png_codec_unittest.cc 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/gfx/codec/png_codec.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <algorithm>
  8. #include <cmath>
  9. #include "base/check.h"
  10. #include "base/logging.h"
  11. #include "testing/gtest/include/gtest/gtest.h"
  12. #include "third_party/libpng/png.h"
  13. #include "third_party/skia/include/core/SkBitmap.h"
  14. #include "third_party/skia/include/core/SkColorPriv.h"
  15. #include "third_party/skia/include/core/SkUnPreMultiply.h"
  16. #include "third_party/zlib/zlib.h"
  17. #include "ui/gfx/geometry/size.h"
  18. #include "ui/gfx/skia_util.h"
  19. namespace gfx {
  20. namespace {
  21. void MakeRGBImage(int w, int h, std::vector<unsigned char>* data) {
  22. data->resize(w * h * 3);
  23. for (int y = 0; y < h; y++) {
  24. for (int x = 0; x < w; x++) {
  25. unsigned char* org_px = &(*data)[(y * w + x) * 3];
  26. org_px[0] = x * 3; // r
  27. org_px[1] = x * 3 + 1; // g
  28. org_px[2] = x * 3 + 2; // b
  29. }
  30. }
  31. }
  32. // Set use_transparency to write data into the alpha channel, otherwise it will
  33. // be filled with 0xff. With the alpha channel stripped, this should yield the
  34. // same image as MakeRGBImage above, so the code below can make reference
  35. // images for conversion testing.
  36. void MakeRGBAImage(int w, int h, bool use_transparency,
  37. std::vector<unsigned char>* data) {
  38. data->resize(w * h * 4);
  39. for (int y = 0; y < h; y++) {
  40. for (int x = 0; x < w; x++) {
  41. unsigned char* org_px = &(*data)[(y * w + x) * 4];
  42. org_px[0] = x * 3; // r
  43. org_px[1] = x * 3 + 1; // g
  44. org_px[2] = x * 3 + 2; // b
  45. if (use_transparency)
  46. org_px[3] = x*3 + 3; // a
  47. else
  48. org_px[3] = 0xFF; // a (opaque)
  49. }
  50. }
  51. }
  52. // Creates a palette-based image.
  53. void MakePaletteImage(int w, int h,
  54. std::vector<unsigned char>* data,
  55. std::vector<png_color>* palette,
  56. std::vector<unsigned char>* trans_chunk = 0) {
  57. data->resize(w * h);
  58. palette->resize(w);
  59. for (int i = 0; i < w; ++i) {
  60. png_color& color = (*palette)[i];
  61. color.red = i * 3;
  62. color.green = color.red + 1;
  63. color.blue = color.red + 2;
  64. }
  65. for (int y = 0; y < h; y++) {
  66. for (int x = 0; x < w; x++) {
  67. (*data)[y * w + x] = x; // palette index
  68. }
  69. }
  70. if (trans_chunk) {
  71. trans_chunk->resize(palette->size());
  72. for (std::size_t i = 0; i < trans_chunk->size(); ++i) {
  73. (*trans_chunk)[i] = i % 256;
  74. }
  75. }
  76. }
  77. // Creates a grayscale image without an alpha channel.
  78. void MakeGrayscaleImage(int w, int h,
  79. std::vector<unsigned char>* data) {
  80. data->resize(w * h);
  81. for (int y = 0; y < h; y++) {
  82. for (int x = 0; x < w; x++) {
  83. (*data)[y * w + x] = x; // gray value
  84. }
  85. }
  86. }
  87. // Creates a grayscale image with an alpha channel.
  88. void MakeGrayscaleAlphaImage(int w, int h,
  89. std::vector<unsigned char>* data) {
  90. data->resize(w * h * 2);
  91. for (int y = 0; y < h; y++) {
  92. for (int x = 0; x < w; x++) {
  93. unsigned char* px = &(*data)[(y * w + x) * 2];
  94. px[0] = x; // gray value
  95. px[1] = x % 256; // alpha
  96. }
  97. }
  98. }
  99. // User write function (to be passed to libpng by EncodeImage) which writes
  100. // into a buffer instead of to a file.
  101. void WriteImageData(png_structp png_ptr,
  102. png_bytep data,
  103. png_size_t length) {
  104. std::vector<unsigned char>& v =
  105. *static_cast<std::vector<unsigned char>*>(png_get_io_ptr(png_ptr));
  106. v.resize(v.size() + length);
  107. memcpy(&v[v.size() - length], data, length);
  108. }
  109. // User flush function; goes with WriteImageData, above.
  110. void FlushImageData(png_structp /*png_ptr*/) {
  111. }
  112. // Libpng user error function which allows us to print libpng errors using
  113. // Chrome's logging facilities instead of stderr.
  114. void LogLibPNGError(png_structp png_ptr,
  115. png_const_charp error_msg) {
  116. DLOG(ERROR) << "libpng encode error: " << error_msg;
  117. longjmp(png_jmpbuf(png_ptr), 1);
  118. }
  119. // Goes with LogLibPNGError, above.
  120. void LogLibPNGWarning(png_structp png_ptr,
  121. png_const_charp warning_msg) {
  122. DLOG(ERROR) << "libpng encode warning: " << warning_msg;
  123. }
  124. // Color types supported by EncodeImage. Required because neither libpng nor
  125. // PNGCodec::Encode supports all of the required values.
  126. enum ColorType {
  127. COLOR_TYPE_GRAY = PNG_COLOR_TYPE_GRAY,
  128. COLOR_TYPE_GRAY_ALPHA = PNG_COLOR_TYPE_GRAY_ALPHA,
  129. COLOR_TYPE_PALETTE = PNG_COLOR_TYPE_PALETTE,
  130. COLOR_TYPE_RGB = PNG_COLOR_TYPE_RGB,
  131. COLOR_TYPE_RGBA = PNG_COLOR_TYPE_RGBA,
  132. COLOR_TYPE_BGR,
  133. COLOR_TYPE_BGRA
  134. };
  135. // PNG encoder used for testing. Required because PNGCodec::Encode doesn't do
  136. // interlaced, palette-based, or grayscale images, but PNGCodec::Decode is
  137. // actually asked to decode these types of images by Chrome.
  138. bool EncodeImage(const std::vector<unsigned char>& input,
  139. const int width,
  140. const int height,
  141. ColorType output_color_type,
  142. std::vector<unsigned char>* output,
  143. const int interlace_type = PNG_INTERLACE_NONE,
  144. std::vector<png_color>* palette = 0,
  145. std::vector<unsigned char>* palette_alpha = 0) {
  146. DCHECK(output);
  147. int input_rowbytes = 0;
  148. int transforms = PNG_TRANSFORM_IDENTITY;
  149. switch (output_color_type) {
  150. case COLOR_TYPE_GRAY:
  151. input_rowbytes = width;
  152. break;
  153. case COLOR_TYPE_GRAY_ALPHA:
  154. input_rowbytes = width * 2;
  155. break;
  156. case COLOR_TYPE_PALETTE:
  157. if (!palette)
  158. return false;
  159. input_rowbytes = width;
  160. break;
  161. case COLOR_TYPE_RGB:
  162. input_rowbytes = width * 3;
  163. break;
  164. case COLOR_TYPE_RGBA:
  165. input_rowbytes = width * 4;
  166. break;
  167. case COLOR_TYPE_BGR:
  168. input_rowbytes = width * 3;
  169. output_color_type = static_cast<ColorType>(PNG_COLOR_TYPE_RGB);
  170. transforms |= PNG_TRANSFORM_BGR;
  171. break;
  172. case COLOR_TYPE_BGRA:
  173. input_rowbytes = width * 4;
  174. output_color_type = static_cast<ColorType>(PNG_COLOR_TYPE_RGBA);
  175. transforms |= PNG_TRANSFORM_BGR;
  176. break;
  177. };
  178. png_struct* png_ptr =
  179. png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  180. if (!png_ptr)
  181. return false;
  182. png_infop info_ptr = png_create_info_struct(png_ptr);
  183. if (!info_ptr) {
  184. png_destroy_write_struct(&png_ptr, NULL);
  185. return false;
  186. }
  187. std::vector<png_bytep> row_pointers(height);
  188. for (int y = 0 ; y < height; ++y) {
  189. row_pointers[y] = const_cast<unsigned char*>(&input[y * input_rowbytes]);
  190. }
  191. if (setjmp(png_jmpbuf(png_ptr))) {
  192. png_destroy_write_struct(&png_ptr, &info_ptr);
  193. return false;
  194. }
  195. png_set_error_fn(png_ptr, NULL, LogLibPNGError, LogLibPNGWarning);
  196. png_set_rows(png_ptr, info_ptr, &row_pointers[0]);
  197. png_set_write_fn(png_ptr, output, WriteImageData, FlushImageData);
  198. png_set_IHDR(png_ptr, info_ptr, width, height, 8, output_color_type,
  199. interlace_type, PNG_COMPRESSION_TYPE_DEFAULT,
  200. PNG_FILTER_TYPE_DEFAULT);
  201. if (output_color_type == COLOR_TYPE_PALETTE) {
  202. png_set_PLTE(png_ptr, info_ptr, &palette->front(), palette->size());
  203. if (palette_alpha) {
  204. unsigned char* alpha_data = &palette_alpha->front();
  205. size_t alpha_size = palette_alpha->size();
  206. png_set_tRNS(png_ptr, info_ptr, alpha_data, alpha_size, NULL);
  207. }
  208. }
  209. png_write_png(png_ptr, info_ptr, transforms, NULL);
  210. png_destroy_write_struct(&png_ptr, &info_ptr);
  211. return true;
  212. }
  213. } // namespace
  214. // Returns true if each channel of the given two colors are "close." This is
  215. // used for comparing colors where rounding errors may cause off-by-one.
  216. bool ColorsClose(uint32_t a, uint32_t b) {
  217. return abs(static_cast<int>(SkColorGetB(a) - SkColorGetB(b))) < 2 &&
  218. abs(static_cast<int>(SkColorGetG(a) - SkColorGetG(b))) < 2 &&
  219. abs(static_cast<int>(SkColorGetR(a) - SkColorGetR(b))) < 2 &&
  220. abs(static_cast<int>(SkColorGetA(a) - SkColorGetA(b))) < 2;
  221. }
  222. // Returns true if the RGB components are "close."
  223. bool NonAlphaColorsClose(uint32_t a, uint32_t b) {
  224. return abs(static_cast<int>(SkColorGetB(a) - SkColorGetB(b))) < 2 &&
  225. abs(static_cast<int>(SkColorGetG(a) - SkColorGetG(b))) < 2 &&
  226. abs(static_cast<int>(SkColorGetR(a) - SkColorGetR(b))) < 2;
  227. }
  228. // Returns true if the BGRA 32-bit SkColor specified by |a| is equivalent to the
  229. // 8-bit Gray color specified by |b|.
  230. bool BGRAGrayEqualsA8Gray(uint32_t a, uint8_t b) {
  231. return SkColorGetB(a) == b && SkColorGetG(a) == b &&
  232. SkColorGetR(a) == b && SkColorGetA(a) == 255;
  233. }
  234. void MakeTestBGRASkBitmap(int w, int h, SkBitmap* bmp) {
  235. bmp->allocN32Pixels(w, h);
  236. uint32_t* src_data = bmp->getAddr32(0, 0);
  237. for (int i = 0; i < w * h; i++)
  238. src_data[i] = SkPreMultiplyARGB(i % 255, i % 250, i % 245, i % 240);
  239. }
  240. void MakeTestA8SkBitmap(int w, int h, SkBitmap* bmp) {
  241. bmp->allocPixels(SkImageInfo::MakeA8(w, h));
  242. uint8_t* src_data = bmp->getAddr8(0, 0);
  243. for (int i = 0; i < w * h; i++)
  244. src_data[i] = i % 255;
  245. }
  246. TEST(PNGCodec, EncodeDecodeRGBA) {
  247. const int w = 20, h = 20;
  248. // create an image with known values, a must be opaque because it will be
  249. // lost during encoding
  250. std::vector<unsigned char> original;
  251. MakeRGBAImage(w, h, true, &original);
  252. // encode
  253. std::vector<unsigned char> encoded;
  254. ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGBA,
  255. Size(w, h), w * 4, false,
  256. std::vector<PNGCodec::Comment>(),
  257. &encoded));
  258. // decode, it should have the same size as the original
  259. std::vector<unsigned char> decoded;
  260. int outw, outh;
  261. ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
  262. PNGCodec::FORMAT_RGBA, &decoded,
  263. &outw, &outh));
  264. ASSERT_EQ(w, outw);
  265. ASSERT_EQ(h, outh);
  266. ASSERT_EQ(original.size(), decoded.size());
  267. // Images must be exactly equal
  268. ASSERT_TRUE(original == decoded);
  269. }
  270. TEST(PNGCodec, EncodeDecodeBGRA) {
  271. const int w = 20, h = 20;
  272. // Create an image with known values, alpha must be opaque because it will be
  273. // lost during encoding.
  274. std::vector<unsigned char> original;
  275. MakeRGBAImage(w, h, true, &original);
  276. // Encode.
  277. std::vector<unsigned char> encoded;
  278. ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_BGRA,
  279. Size(w, h), w * 4, false,
  280. std::vector<PNGCodec::Comment>(),
  281. &encoded));
  282. // Decode, it should have the same size as the original.
  283. std::vector<unsigned char> decoded;
  284. int outw, outh;
  285. ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
  286. PNGCodec::FORMAT_BGRA, &decoded,
  287. &outw, &outh));
  288. ASSERT_EQ(w, outw);
  289. ASSERT_EQ(h, outh);
  290. ASSERT_EQ(original.size(), decoded.size());
  291. // Images must be exactly equal.
  292. ASSERT_TRUE(original == decoded);
  293. }
  294. TEST(PNGCodec, DecodePalette) {
  295. const int w = 20, h = 20;
  296. // create an image with known values
  297. std::vector<unsigned char> original;
  298. std::vector<png_color> original_palette;
  299. std::vector<unsigned char> original_trans_chunk;
  300. MakePaletteImage(w, h, &original, &original_palette, &original_trans_chunk);
  301. // encode
  302. std::vector<unsigned char> encoded;
  303. ASSERT_TRUE(EncodeImage(original,
  304. w, h,
  305. COLOR_TYPE_PALETTE,
  306. &encoded,
  307. PNG_INTERLACE_NONE,
  308. &original_palette,
  309. &original_trans_chunk));
  310. // decode
  311. std::vector<unsigned char> decoded;
  312. int outw, outh;
  313. ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
  314. PNGCodec::FORMAT_RGBA, &decoded,
  315. &outw, &outh));
  316. ASSERT_EQ(w, outw);
  317. ASSERT_EQ(h, outh);
  318. ASSERT_EQ(decoded.size(), w * h * 4U);
  319. // Images must be equal
  320. for (int y = 0; y < h; ++y) {
  321. for (int x = 0; x < w; ++x) {
  322. unsigned char palette_pixel = original[y * w + x];
  323. png_color& palette_color = original_palette[palette_pixel];
  324. int alpha = original_trans_chunk[palette_pixel];
  325. unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
  326. EXPECT_EQ(palette_color.red, rgba_pixel[0]);
  327. EXPECT_EQ(palette_color.green, rgba_pixel[1]);
  328. EXPECT_EQ(palette_color.blue, rgba_pixel[2]);
  329. EXPECT_EQ(alpha, rgba_pixel[3]);
  330. }
  331. }
  332. }
  333. TEST(PNGCodec, DecodeInterlacedPalette) {
  334. const int w = 20, h = 20;
  335. // create an image with known values
  336. std::vector<unsigned char> original;
  337. std::vector<png_color> original_palette;
  338. std::vector<unsigned char> original_trans_chunk;
  339. MakePaletteImage(w, h, &original, &original_palette, &original_trans_chunk);
  340. // encode
  341. std::vector<unsigned char> encoded;
  342. ASSERT_TRUE(EncodeImage(original,
  343. w, h,
  344. COLOR_TYPE_PALETTE,
  345. &encoded,
  346. PNG_INTERLACE_ADAM7,
  347. &original_palette,
  348. &original_trans_chunk));
  349. // decode
  350. std::vector<unsigned char> decoded;
  351. int outw, outh;
  352. ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
  353. PNGCodec::FORMAT_RGBA, &decoded,
  354. &outw, &outh));
  355. ASSERT_EQ(w, outw);
  356. ASSERT_EQ(h, outh);
  357. ASSERT_EQ(decoded.size(), w * h * 4U);
  358. // Images must be equal
  359. for (int y = 0; y < h; ++y) {
  360. for (int x = 0; x < w; ++x) {
  361. unsigned char palette_pixel = original[y * w + x];
  362. png_color& palette_color = original_palette[palette_pixel];
  363. int alpha = original_trans_chunk[palette_pixel];
  364. unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
  365. EXPECT_EQ(palette_color.red, rgba_pixel[0]);
  366. EXPECT_EQ(palette_color.green, rgba_pixel[1]);
  367. EXPECT_EQ(palette_color.blue, rgba_pixel[2]);
  368. EXPECT_EQ(alpha, rgba_pixel[3]);
  369. }
  370. }
  371. }
  372. TEST(PNGCodec, DecodeGrayscale) {
  373. const int w = 20, h = 20;
  374. // create an image with known values
  375. std::vector<unsigned char> original;
  376. MakeGrayscaleImage(w, h, &original);
  377. // encode
  378. std::vector<unsigned char> encoded;
  379. ASSERT_TRUE(EncodeImage(original, w, h, COLOR_TYPE_GRAY, &encoded));
  380. // decode
  381. std::vector<unsigned char> decoded;
  382. int outw, outh;
  383. ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
  384. PNGCodec::FORMAT_RGBA, &decoded, &outw, &outh));
  385. ASSERT_EQ(w, outw);
  386. ASSERT_EQ(h, outh);
  387. ASSERT_EQ(decoded.size(), original.size() * 4);
  388. // Images must be equal
  389. for (int y = 0; y < h; ++y) {
  390. for (int x = 0; x < w; ++x) {
  391. unsigned char gray_pixel = original[(y * w + x)];
  392. unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
  393. EXPECT_EQ(rgba_pixel[0], gray_pixel);
  394. EXPECT_EQ(rgba_pixel[1], gray_pixel);
  395. EXPECT_EQ(rgba_pixel[2], gray_pixel);
  396. EXPECT_EQ(rgba_pixel[3], 0xff);
  397. }
  398. }
  399. }
  400. TEST(PNGCodec, DecodeGrayscaleWithAlpha) {
  401. const int w = 20, h = 20;
  402. // create an image with known values
  403. std::vector<unsigned char> original;
  404. MakeGrayscaleAlphaImage(w, h, &original);
  405. // encode
  406. std::vector<unsigned char> encoded;
  407. ASSERT_TRUE(EncodeImage(original,
  408. w, h,
  409. COLOR_TYPE_GRAY_ALPHA,
  410. &encoded));
  411. // decode
  412. std::vector<unsigned char> decoded;
  413. int outw, outh;
  414. ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
  415. PNGCodec::FORMAT_RGBA, &decoded,
  416. &outw, &outh));
  417. ASSERT_EQ(w, outw);
  418. ASSERT_EQ(h, outh);
  419. ASSERT_EQ(decoded.size(), original.size() * 2);
  420. // Images must be equal
  421. for (int y = 0; y < h; ++y) {
  422. for (int x = 0; x < w; ++x) {
  423. unsigned char* gray_pixel = &original[(y * w + x) * 2];
  424. unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
  425. EXPECT_EQ(rgba_pixel[0], gray_pixel[0]);
  426. EXPECT_EQ(rgba_pixel[1], gray_pixel[0]);
  427. EXPECT_EQ(rgba_pixel[2], gray_pixel[0]);
  428. EXPECT_EQ(rgba_pixel[3], gray_pixel[1]);
  429. }
  430. }
  431. }
  432. TEST(PNGCodec, DecodeInterlacedGrayscale) {
  433. const int w = 20, h = 20;
  434. // create an image with known values
  435. std::vector<unsigned char> original;
  436. MakeGrayscaleImage(w, h, &original);
  437. // encode
  438. std::vector<unsigned char> encoded;
  439. ASSERT_TRUE(EncodeImage(original,
  440. w, h,
  441. COLOR_TYPE_GRAY,
  442. &encoded,
  443. PNG_INTERLACE_ADAM7));
  444. // decode
  445. std::vector<unsigned char> decoded;
  446. int outw, outh;
  447. ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
  448. PNGCodec::FORMAT_RGBA, &decoded,
  449. &outw, &outh));
  450. ASSERT_EQ(w, outw);
  451. ASSERT_EQ(h, outh);
  452. ASSERT_EQ(decoded.size(), original.size() * 4);
  453. // Images must be equal
  454. for (int y = 0; y < h; ++y) {
  455. for (int x = 0; x < w; ++x) {
  456. unsigned char gray_pixel = original[(y * w + x)];
  457. unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
  458. EXPECT_EQ(rgba_pixel[0], gray_pixel);
  459. EXPECT_EQ(rgba_pixel[1], gray_pixel);
  460. EXPECT_EQ(rgba_pixel[2], gray_pixel);
  461. EXPECT_EQ(rgba_pixel[3], 0xFF);
  462. }
  463. }
  464. }
  465. TEST(PNGCodec, DecodeInterlacedGrayscaleWithAlpha) {
  466. const int w = 20, h = 20;
  467. // create an image with known values
  468. std::vector<unsigned char> original;
  469. MakeGrayscaleAlphaImage(w, h, &original);
  470. // encode
  471. std::vector<unsigned char> encoded;
  472. ASSERT_TRUE(EncodeImage(original,
  473. w, h,
  474. COLOR_TYPE_GRAY_ALPHA,
  475. &encoded,
  476. PNG_INTERLACE_ADAM7));
  477. // decode
  478. std::vector<unsigned char> decoded;
  479. int outw, outh;
  480. ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
  481. PNGCodec::FORMAT_RGBA, &decoded,
  482. &outw, &outh));
  483. ASSERT_EQ(w, outw);
  484. ASSERT_EQ(h, outh);
  485. ASSERT_EQ(decoded.size(), original.size() * 2);
  486. // Images must be equal
  487. for (int y = 0; y < h; ++y) {
  488. for (int x = 0; x < w; ++x) {
  489. unsigned char* gray_pixel = &original[(y * w + x) * 2];
  490. unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
  491. EXPECT_EQ(rgba_pixel[0], gray_pixel[0]);
  492. EXPECT_EQ(rgba_pixel[1], gray_pixel[0]);
  493. EXPECT_EQ(rgba_pixel[2], gray_pixel[0]);
  494. EXPECT_EQ(rgba_pixel[3], gray_pixel[1]);
  495. }
  496. }
  497. }
  498. TEST(PNGCodec, DecodeInterlacedRGBA) {
  499. const int w = 20, h = 20;
  500. // create an image with known values
  501. std::vector<unsigned char> original;
  502. MakeRGBAImage(w, h, false, &original);
  503. // encode
  504. std::vector<unsigned char> encoded;
  505. ASSERT_TRUE(EncodeImage(original,
  506. w, h,
  507. COLOR_TYPE_RGBA,
  508. &encoded,
  509. PNG_INTERLACE_ADAM7));
  510. // decode, it should have the same size as the original
  511. std::vector<unsigned char> decoded;
  512. int outw, outh;
  513. ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
  514. PNGCodec::FORMAT_RGBA, &decoded,
  515. &outw, &outh));
  516. ASSERT_EQ(w, outw);
  517. ASSERT_EQ(h, outh);
  518. ASSERT_EQ(original.size(), decoded.size());
  519. // Images must be equal
  520. ASSERT_EQ(original, decoded);
  521. }
  522. TEST(PNGCodec, DecodeInterlacedBGR) {
  523. const int w = 20, h = 20;
  524. // create an image with known values
  525. std::vector<unsigned char> original;
  526. MakeRGBImage(w, h, &original);
  527. // encode
  528. std::vector<unsigned char> encoded;
  529. ASSERT_TRUE(EncodeImage(original,
  530. w, h,
  531. COLOR_TYPE_BGR,
  532. &encoded,
  533. PNG_INTERLACE_ADAM7));
  534. // decode, it should have the same size as the original
  535. std::vector<unsigned char> decoded;
  536. int outw, outh;
  537. ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
  538. PNGCodec::FORMAT_BGRA, &decoded,
  539. &outw, &outh));
  540. ASSERT_EQ(w, outw);
  541. ASSERT_EQ(h, outh);
  542. ASSERT_EQ(decoded.size(), w * h * 4U);
  543. // Images must be equal
  544. for (int x = 0; x < w; x++) {
  545. for (int y = 0; y < h; y++) {
  546. unsigned char* orig_px = &original[(y * w + x) * 3];
  547. unsigned char* dec_px = &decoded[(y * w + x) * 4];
  548. EXPECT_EQ(dec_px[0], orig_px[0]);
  549. EXPECT_EQ(dec_px[1], orig_px[1]);
  550. EXPECT_EQ(dec_px[2], orig_px[2]);
  551. }
  552. }
  553. }
  554. TEST(PNGCodec, DecodeInterlacedBGRA) {
  555. const int w = 20, h = 20;
  556. // create an image with known values
  557. std::vector<unsigned char> original;
  558. MakeRGBAImage(w, h, false, &original);
  559. // encode
  560. std::vector<unsigned char> encoded;
  561. ASSERT_TRUE(EncodeImage(original,
  562. w, h,
  563. COLOR_TYPE_BGRA,
  564. &encoded,
  565. PNG_INTERLACE_ADAM7));
  566. // decode, it should have the same size as the original
  567. std::vector<unsigned char> decoded;
  568. int outw, outh;
  569. ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
  570. PNGCodec::FORMAT_BGRA, &decoded,
  571. &outw, &outh));
  572. ASSERT_EQ(w, outw);
  573. ASSERT_EQ(h, outh);
  574. ASSERT_EQ(original.size(), decoded.size());
  575. // Images must be equal
  576. ASSERT_EQ(original, decoded);
  577. }
  578. // Not encoding an interlaced PNG from SkBitmap because we don't do it
  579. // anywhere, and the ability to do that requires more code changes.
  580. TEST(PNGCodec, DecodeInterlacedRGBtoSkBitmap) {
  581. const int w = 20, h = 20;
  582. // create an image with known values
  583. std::vector<unsigned char> original;
  584. MakeRGBImage(w, h, &original);
  585. // encode
  586. std::vector<unsigned char> encoded;
  587. ASSERT_TRUE(EncodeImage(original,
  588. w, h,
  589. COLOR_TYPE_RGB,
  590. &encoded,
  591. PNG_INTERLACE_ADAM7));
  592. // Decode the encoded string.
  593. SkBitmap decoded_bitmap;
  594. ASSERT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
  595. &decoded_bitmap));
  596. for (int x = 0; x < w; x++) {
  597. for (int y = 0; y < h; y++) {
  598. const unsigned char* original_pixel = &original[(y * w + x) * 3];
  599. const uint32_t original_pixel_sk = SkPackARGB32(0xFF,
  600. original_pixel[0],
  601. original_pixel[1],
  602. original_pixel[2]);
  603. const uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
  604. EXPECT_EQ(original_pixel_sk, decoded_pixel);
  605. }
  606. }
  607. }
  608. TEST(PNGCodec, DecodeInterlacedRGBAtoSkBitmap) {
  609. const int w = 20, h = 20;
  610. // create an image with known values
  611. std::vector<unsigned char> original;
  612. MakeRGBAImage(w, h, false, &original);
  613. // encode
  614. std::vector<unsigned char> encoded;
  615. ASSERT_TRUE(EncodeImage(original,
  616. w, h,
  617. COLOR_TYPE_RGBA,
  618. &encoded,
  619. PNG_INTERLACE_ADAM7));
  620. // Decode the encoded string.
  621. SkBitmap decoded_bitmap;
  622. ASSERT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
  623. &decoded_bitmap));
  624. for (int x = 0; x < w; x++) {
  625. for (int y = 0; y < h; y++) {
  626. const unsigned char* original_pixel = &original[(y * w + x) * 4];
  627. const uint32_t original_pixel_sk = SkPackARGB32(original_pixel[3],
  628. original_pixel[0],
  629. original_pixel[1],
  630. original_pixel[2]);
  631. const uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
  632. EXPECT_EQ(original_pixel_sk, decoded_pixel);
  633. }
  634. }
  635. }
  636. // Test that corrupted data decompression causes failures.
  637. TEST(PNGCodec, DecodeCorrupted) {
  638. int w = 20, h = 20;
  639. // Make some random data (an uncompressed image).
  640. std::vector<unsigned char> original;
  641. MakeRGBAImage(w, h, false, &original);
  642. // It should fail when given non-PNG compressed data.
  643. std::vector<unsigned char> output;
  644. int outw, outh;
  645. EXPECT_FALSE(PNGCodec::Decode(&original[0], original.size(),
  646. PNGCodec::FORMAT_RGBA, &output, &outw, &outh));
  647. // Make some compressed data.
  648. std::vector<unsigned char> compressed;
  649. ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGBA, Size(w, h),
  650. w * 4, false, std::vector<PNGCodec::Comment>(),
  651. &compressed));
  652. // Try decompressing a truncated version.
  653. EXPECT_FALSE(PNGCodec::Decode(&compressed[0], compressed.size() / 2,
  654. PNGCodec::FORMAT_RGBA, &output, &outw, &outh));
  655. // Corrupt it and try decompressing that.
  656. for (int i = 10; i < 30; i++)
  657. compressed[i] = i;
  658. EXPECT_FALSE(PNGCodec::Decode(&compressed[0], compressed.size(),
  659. PNGCodec::FORMAT_RGBA, &output, &outw, &outh));
  660. }
  661. TEST(PNGCodec, EncodeBGRASkBitmapStridePadded) {
  662. const int kWidth = 20;
  663. const int kHeight = 20;
  664. const int kPaddedWidth = 32;
  665. const int kBytesPerPixel = 4;
  666. const int kRowBytes = kPaddedWidth * kBytesPerPixel;
  667. SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
  668. SkBitmap original_bitmap;
  669. original_bitmap.setInfo(info, kRowBytes);
  670. original_bitmap.allocPixels();
  671. // Write data over the source bitmap.
  672. // We write on the pad area here too.
  673. // The encoder should ignore the pad area.
  674. uint32_t* src_data = original_bitmap.getAddr32(0, 0);
  675. const int count =
  676. original_bitmap.computeByteSize() / original_bitmap.bytesPerPixel();
  677. for (int i = 0; i < count; i++) {
  678. src_data[i] = SkPreMultiplyARGB(i % 255, i % 250, i % 245, i % 240);
  679. }
  680. // Encode the bitmap.
  681. std::vector<unsigned char> encoded;
  682. PNGCodec::EncodeBGRASkBitmap(original_bitmap, false, &encoded);
  683. // Decode the encoded string.
  684. SkBitmap decoded_bitmap;
  685. EXPECT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
  686. &decoded_bitmap));
  687. // Compare the original bitmap and the output bitmap. We use ColorsClose
  688. // as SkBitmaps are considered to be pre-multiplied, the unpremultiplication
  689. // (in Encode) and repremultiplication (in Decode) can be lossy.
  690. for (int x = 0; x < kWidth; x++) {
  691. for (int y = 0; y < kHeight; y++) {
  692. uint32_t original_pixel = original_bitmap.getAddr32(0, y)[x];
  693. uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
  694. EXPECT_TRUE(ColorsClose(original_pixel, decoded_pixel));
  695. }
  696. }
  697. }
  698. TEST(PNGCodec, EncodeBGRASkBitmap) {
  699. const int w = 20, h = 20;
  700. SkBitmap original_bitmap;
  701. MakeTestBGRASkBitmap(w, h, &original_bitmap);
  702. // Encode the bitmap.
  703. std::vector<unsigned char> encoded;
  704. PNGCodec::EncodeBGRASkBitmap(original_bitmap, false, &encoded);
  705. // Decode the encoded string.
  706. SkBitmap decoded_bitmap;
  707. EXPECT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
  708. &decoded_bitmap));
  709. // Compare the original bitmap and the output bitmap. We use ColorsClose
  710. // as SkBitmaps are considered to be pre-multiplied, the unpremultiplication
  711. // (in Encode) and repremultiplication (in Decode) can be lossy.
  712. for (int x = 0; x < w; x++) {
  713. for (int y = 0; y < h; y++) {
  714. uint32_t original_pixel = original_bitmap.getAddr32(0, y)[x];
  715. uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
  716. EXPECT_TRUE(ColorsClose(original_pixel, decoded_pixel));
  717. }
  718. }
  719. }
  720. TEST(PNGCodec, EncodeA8SkBitmap) {
  721. const int w = 20, h = 20;
  722. SkBitmap original_bitmap;
  723. MakeTestA8SkBitmap(w, h, &original_bitmap);
  724. // Encode the bitmap.
  725. std::vector<unsigned char> encoded;
  726. EXPECT_TRUE(PNGCodec::EncodeA8SkBitmap(original_bitmap, &encoded));
  727. // Decode the encoded string.
  728. SkBitmap decoded_bitmap;
  729. EXPECT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
  730. &decoded_bitmap));
  731. for (int x = 0; x < w; x++) {
  732. for (int y = 0; y < h; y++) {
  733. uint8_t original_pixel = *original_bitmap.getAddr8(x, y);
  734. uint32_t decoded_pixel = *decoded_bitmap.getAddr32(x, y);
  735. EXPECT_TRUE(BGRAGrayEqualsA8Gray(decoded_pixel, original_pixel));
  736. }
  737. }
  738. }
  739. TEST(PNGCodec, EncodeBGRASkBitmapDiscardTransparency) {
  740. const int w = 20, h = 20;
  741. SkBitmap original_bitmap;
  742. MakeTestBGRASkBitmap(w, h, &original_bitmap);
  743. // Encode the bitmap.
  744. std::vector<unsigned char> encoded;
  745. PNGCodec::EncodeBGRASkBitmap(original_bitmap, true, &encoded);
  746. // Decode the encoded string.
  747. SkBitmap decoded_bitmap;
  748. EXPECT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
  749. &decoded_bitmap));
  750. // Compare the original bitmap and the output bitmap. We need to
  751. // unpremultiply original_pixel, as the decoded bitmap doesn't have an alpha
  752. // channel.
  753. for (int x = 0; x < w; x++) {
  754. for (int y = 0; y < h; y++) {
  755. uint32_t original_pixel = original_bitmap.getAddr32(0, y)[x];
  756. uint32_t unpremultiplied =
  757. SkUnPreMultiply::PMColorToColor(original_pixel);
  758. uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
  759. uint32_t unpremultiplied_decoded =
  760. SkUnPreMultiply::PMColorToColor(decoded_pixel);
  761. EXPECT_TRUE(NonAlphaColorsClose(unpremultiplied, unpremultiplied_decoded))
  762. << "Original_pixel: ("
  763. << SkColorGetR(unpremultiplied) << ", "
  764. << SkColorGetG(unpremultiplied) << ", "
  765. << SkColorGetB(unpremultiplied) << "), "
  766. << "Decoded pixel: ("
  767. << SkColorGetR(unpremultiplied_decoded) << ", "
  768. << SkColorGetG(unpremultiplied_decoded) << ", "
  769. << SkColorGetB(unpremultiplied_decoded) << ")";
  770. }
  771. }
  772. }
  773. TEST(PNGCodec, EncodeWithComment) {
  774. const int w = 10, h = 10;
  775. std::vector<unsigned char> original;
  776. MakeRGBAImage(w, h, true, &original);
  777. std::vector<unsigned char> encoded;
  778. std::vector<PNGCodec::Comment> comments;
  779. comments.push_back(PNGCodec::Comment("key", "text"));
  780. comments.push_back(PNGCodec::Comment("test", "something"));
  781. comments.push_back(PNGCodec::Comment("have some", "spaces in both"));
  782. EXPECT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGBA, Size(w, h),
  783. w * 4, false, comments, &encoded));
  784. // Each chunk is of the form length (4 bytes), chunk type (tEXt), data,
  785. // checksum (4 bytes). Make sure we find all of them in the encoded
  786. // results.
  787. const unsigned char kExpected1[] =
  788. "\x00\x00\x00\x08tEXtkey\x00text\x9e\xe7\x66\x51";
  789. const unsigned char kExpected2[] =
  790. "\x00\x00\x00\x0etEXttest\x00something\x29\xba\xef\xac";
  791. const unsigned char kExpected3[] =
  792. "\x00\x00\x00\x18tEXthave some\x00spaces in both\x8d\x69\x34\x2d";
  793. EXPECT_NE(std::search(encoded.begin(), encoded.end(), kExpected1,
  794. kExpected1 + std::size(kExpected1)),
  795. encoded.end());
  796. EXPECT_NE(std::search(encoded.begin(), encoded.end(), kExpected2,
  797. kExpected2 + std::size(kExpected2)),
  798. encoded.end());
  799. EXPECT_NE(std::search(encoded.begin(), encoded.end(), kExpected3,
  800. kExpected3 + std::size(kExpected3)),
  801. encoded.end());
  802. }
  803. TEST(PNGCodec, EncodeDecodeWithVaryingCompressionLevels) {
  804. const int w = 20, h = 20;
  805. // create an image with known values, a must be opaque because it will be
  806. // lost during encoding
  807. SkBitmap original_bitmap;
  808. MakeTestBGRASkBitmap(w, h, &original_bitmap);
  809. // encode
  810. std::vector<unsigned char> encoded_normal;
  811. EXPECT_TRUE(
  812. PNGCodec::EncodeBGRASkBitmap(original_bitmap, false, &encoded_normal));
  813. std::vector<unsigned char> encoded_fast;
  814. EXPECT_TRUE(
  815. PNGCodec::FastEncodeBGRASkBitmap(original_bitmap, false, &encoded_fast));
  816. // Make sure the different compression settings actually do something; the
  817. // sizes should be different.
  818. EXPECT_NE(encoded_normal.size(), encoded_fast.size());
  819. // decode, they should be identical to the original.
  820. SkBitmap decoded;
  821. EXPECT_TRUE(
  822. PNGCodec::Decode(&encoded_normal[0], encoded_normal.size(), &decoded));
  823. EXPECT_TRUE(BitmapsAreEqual(decoded, original_bitmap));
  824. EXPECT_TRUE(
  825. PNGCodec::Decode(&encoded_fast[0], encoded_fast.size(), &decoded));
  826. EXPECT_TRUE(BitmapsAreEqual(decoded, original_bitmap));
  827. }
  828. } // namespace gfx