- add sources.
[platform/framework/web/crosswalk.git] / src / ui / gfx / codec / png_codec_unittest.cc
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
5 #include <algorithm>
6 #include <cmath>
7
8 #include "base/logging.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10 #include "third_party/libpng/png.h"
11 #include "third_party/skia/include/core/SkBitmap.h"
12 #include "third_party/skia/include/core/SkColorPriv.h"
13 #include "third_party/skia/include/core/SkUnPreMultiply.h"
14 #include "third_party/zlib/zlib.h"
15 #include "ui/gfx/codec/png_codec.h"
16 #include "ui/gfx/size.h"
17 #include "ui/gfx/skia_util.h"
18
19 namespace gfx {
20
21 namespace {
22
23 void MakeRGBImage(int w, int h, std::vector<unsigned char>* data) {
24   data->resize(w * h * 3);
25   for (int y = 0; y < h; y++) {
26     for (int x = 0; x < w; x++) {
27       unsigned char* org_px = &(*data)[(y * w + x) * 3];
28       org_px[0] = x * 3;      // r
29       org_px[1] = x * 3 + 1;  // g
30       org_px[2] = x * 3 + 2;  // b
31     }
32   }
33 }
34
35 // Set use_transparency to write data into the alpha channel, otherwise it will
36 // be filled with 0xff. With the alpha channel stripped, this should yield the
37 // same image as MakeRGBImage above, so the code below can make reference
38 // images for conversion testing.
39 void MakeRGBAImage(int w, int h, bool use_transparency,
40                    std::vector<unsigned char>* data) {
41   data->resize(w * h * 4);
42   for (int y = 0; y < h; y++) {
43     for (int x = 0; x < w; x++) {
44       unsigned char* org_px = &(*data)[(y * w + x) * 4];
45       org_px[0] = x * 3;      // r
46       org_px[1] = x * 3 + 1;  // g
47       org_px[2] = x * 3 + 2;  // b
48       if (use_transparency)
49         org_px[3] = x*3 + 3;  // a
50       else
51         org_px[3] = 0xFF;     // a (opaque)
52     }
53   }
54 }
55
56 // Creates a palette-based image.
57 void MakePaletteImage(int w, int h,
58                       std::vector<unsigned char>* data,
59                       std::vector<png_color>* palette,
60                       std::vector<unsigned char>* trans_chunk = 0) {
61   data->resize(w * h);
62   palette->resize(w);
63   for (int i = 0; i < w; ++i) {
64     png_color& color = (*palette)[i];
65     color.red = i * 3;
66     color.green = color.red + 1;
67     color.blue = color.red + 2;
68   }
69   for (int y = 0; y < h; y++) {
70     for (int x = 0; x < w; x++) {
71       (*data)[y * w + x] = x;  // palette index
72     }
73   }
74   if (trans_chunk) {
75     trans_chunk->resize(palette->size());
76     for (std::size_t i = 0; i < trans_chunk->size(); ++i) {
77       (*trans_chunk)[i] = i % 256;
78     }
79   }
80 }
81
82 // Creates a grayscale image without an alpha channel.
83 void MakeGrayscaleImage(int w, int h,
84                         std::vector<unsigned char>* data) {
85   data->resize(w * h);
86   for (int y = 0; y < h; y++) {
87     for (int x = 0; x < w; x++) {
88       (*data)[y * w + x] = x;  // gray value
89     }
90   }
91 }
92
93 // Creates a grayscale image with an alpha channel.
94 void MakeGrayscaleAlphaImage(int w, int h,
95                              std::vector<unsigned char>* data) {
96   data->resize(w * h * 2);
97   for (int y = 0; y < h; y++) {
98     for (int x = 0; x < w; x++) {
99       unsigned char* px = &(*data)[(y * w + x) * 2];
100       px[0] = x;        // gray value
101       px[1] = x % 256;  // alpha
102     }
103   }
104 }
105
106 // User write function (to be passed to libpng by EncodeImage) which writes
107 // into a buffer instead of to a file.
108 void WriteImageData(png_structp png_ptr,
109                     png_bytep data,
110                     png_size_t length) {
111   std::vector<unsigned char>& v =
112       *static_cast<std::vector<unsigned char>*>(png_get_io_ptr(png_ptr));
113   v.resize(v.size() + length);
114   memcpy(&v[v.size() - length], data, length);
115 }
116
117 // User flush function; goes with WriteImageData, above.
118 void FlushImageData(png_structp /*png_ptr*/) {
119 }
120
121 // Libpng user error function which allows us to print libpng errors using
122 // Chrome's logging facilities instead of stderr.
123 void LogLibPNGError(png_structp png_ptr,
124                     png_const_charp error_msg) {
125   DLOG(ERROR) << "libpng encode error: " << error_msg;
126   longjmp(png_jmpbuf(png_ptr), 1);
127 }
128
129 // Goes with LogLibPNGError, above.
130 void LogLibPNGWarning(png_structp png_ptr,
131                       png_const_charp warning_msg) {
132   DLOG(ERROR) << "libpng encode warning: " << warning_msg;
133 }
134
135 // Color types supported by EncodeImage. Required because neither libpng nor
136 // PNGCodec::Encode supports all of the required values.
137 enum ColorType {
138   COLOR_TYPE_GRAY = PNG_COLOR_TYPE_GRAY,
139   COLOR_TYPE_GRAY_ALPHA = PNG_COLOR_TYPE_GRAY_ALPHA,
140   COLOR_TYPE_PALETTE = PNG_COLOR_TYPE_PALETTE,
141   COLOR_TYPE_RGB = PNG_COLOR_TYPE_RGB,
142   COLOR_TYPE_RGBA = PNG_COLOR_TYPE_RGBA,
143   COLOR_TYPE_BGR,
144   COLOR_TYPE_BGRA
145 };
146
147 // PNG encoder used for testing. Required because PNGCodec::Encode doesn't do
148 // interlaced, palette-based, or grayscale images, but PNGCodec::Decode is
149 // actually asked to decode these types of images by Chrome.
150 bool EncodeImage(const std::vector<unsigned char>& input,
151                  const int width,
152                  const int height,
153                  ColorType output_color_type,
154                  std::vector<unsigned char>* output,
155                  const int interlace_type = PNG_INTERLACE_NONE,
156                  std::vector<png_color>* palette = 0,
157                  std::vector<unsigned char>* palette_alpha = 0) {
158   DCHECK(output);
159
160   int input_rowbytes = 0;
161   int transforms = PNG_TRANSFORM_IDENTITY;
162
163   switch (output_color_type) {
164     case COLOR_TYPE_GRAY:
165       input_rowbytes = width;
166       break;
167     case COLOR_TYPE_GRAY_ALPHA:
168       input_rowbytes = width * 2;
169       break;
170     case COLOR_TYPE_PALETTE:
171       if (!palette)
172         return false;
173       input_rowbytes = width;
174       break;
175     case COLOR_TYPE_RGB:
176       input_rowbytes = width * 3;
177       break;
178     case COLOR_TYPE_RGBA:
179       input_rowbytes = width * 4;
180       break;
181     case COLOR_TYPE_BGR:
182       input_rowbytes = width * 3;
183       output_color_type = static_cast<ColorType>(PNG_COLOR_TYPE_RGB);
184       transforms |= PNG_TRANSFORM_BGR;
185       break;
186     case COLOR_TYPE_BGRA:
187       input_rowbytes = width * 4;
188       output_color_type = static_cast<ColorType>(PNG_COLOR_TYPE_RGBA);
189       transforms |= PNG_TRANSFORM_BGR;
190       break;
191   };
192
193   png_struct* png_ptr =
194       png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
195   if (!png_ptr)
196     return false;
197   png_infop info_ptr = png_create_info_struct(png_ptr);
198   if (!info_ptr) {
199     png_destroy_write_struct(&png_ptr, NULL);
200     return false;
201   }
202
203   std::vector<png_bytep> row_pointers(height);
204   for (int y = 0 ; y < height; ++y) {
205     row_pointers[y] = const_cast<unsigned char*>(&input[y * input_rowbytes]);
206   }
207
208   if (setjmp(png_jmpbuf(png_ptr))) {
209     png_destroy_write_struct(&png_ptr, &info_ptr);
210     return false;
211   }
212
213   png_set_error_fn(png_ptr, NULL, LogLibPNGError, LogLibPNGWarning);
214   png_set_rows(png_ptr, info_ptr, &row_pointers[0]);
215   png_set_write_fn(png_ptr, output, WriteImageData, FlushImageData);
216   png_set_IHDR(png_ptr, info_ptr, width, height, 8, output_color_type,
217                interlace_type, PNG_COMPRESSION_TYPE_DEFAULT,
218                PNG_FILTER_TYPE_DEFAULT);
219   if (output_color_type == COLOR_TYPE_PALETTE) {
220     png_set_PLTE(png_ptr, info_ptr, &palette->front(), palette->size());
221     if (palette_alpha) {
222       unsigned char* alpha_data = &palette_alpha->front();
223       size_t alpha_size = palette_alpha->size();
224       png_set_tRNS(png_ptr, info_ptr, alpha_data, alpha_size, NULL);
225     }
226   }
227
228   png_write_png(png_ptr, info_ptr, transforms, NULL);
229
230   png_destroy_write_struct(&png_ptr, &info_ptr);
231   return true;
232 }
233
234 }  // namespace
235
236 // Returns true if each channel of the given two colors are "close." This is
237 // used for comparing colors where rounding errors may cause off-by-one.
238 bool ColorsClose(uint32_t a, uint32_t b) {
239   return abs(static_cast<int>(SkColorGetB(a) - SkColorGetB(b))) < 2 &&
240          abs(static_cast<int>(SkColorGetG(a) - SkColorGetG(b))) < 2 &&
241          abs(static_cast<int>(SkColorGetR(a) - SkColorGetR(b))) < 2 &&
242          abs(static_cast<int>(SkColorGetA(a) - SkColorGetA(b))) < 2;
243 }
244
245 // Returns true if the RGB components are "close."
246 bool NonAlphaColorsClose(uint32_t a, uint32_t b) {
247   return abs(static_cast<int>(SkColorGetB(a) - SkColorGetB(b))) < 2 &&
248          abs(static_cast<int>(SkColorGetG(a) - SkColorGetG(b))) < 2 &&
249          abs(static_cast<int>(SkColorGetR(a) - SkColorGetR(b))) < 2;
250 }
251
252 void MakeTestSkBitmap(int w, int h, SkBitmap* bmp) {
253   bmp->setConfig(SkBitmap::kARGB_8888_Config, w, h);
254   bmp->allocPixels();
255
256   uint32_t* src_data = bmp->getAddr32(0, 0);
257   for (int i = 0; i < w * h; i++) {
258     src_data[i] = SkPreMultiplyARGB(i % 255, i % 250, i % 245, i % 240);
259   }
260 }
261
262 TEST(PNGCodec, EncodeDecodeRGB) {
263   const int w = 20, h = 20;
264
265   // create an image with known values
266   std::vector<unsigned char> original;
267   MakeRGBImage(w, h, &original);
268
269   // encode
270   std::vector<unsigned char> encoded;
271   ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGB,
272                                Size(w, h), w * 3, false,
273                                std::vector<PNGCodec::Comment>(),
274                                &encoded));
275
276   // decode, it should have the same size as the original
277   std::vector<unsigned char> decoded;
278   int outw, outh;
279   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
280                                PNGCodec::FORMAT_RGB, &decoded,
281                                &outw, &outh));
282   ASSERT_EQ(w, outw);
283   ASSERT_EQ(h, outh);
284   ASSERT_EQ(original.size(), decoded.size());
285
286   // Images must be equal
287   ASSERT_TRUE(original == decoded);
288 }
289
290 TEST(PNGCodec, EncodeDecodeRGBA) {
291   const int w = 20, h = 20;
292
293   // create an image with known values, a must be opaque because it will be
294   // lost during encoding
295   std::vector<unsigned char> original;
296   MakeRGBAImage(w, h, true, &original);
297
298   // encode
299   std::vector<unsigned char> encoded;
300   ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGBA,
301                                Size(w, h), w * 4, false,
302                                std::vector<PNGCodec::Comment>(),
303                                &encoded));
304
305   // decode, it should have the same size as the original
306   std::vector<unsigned char> decoded;
307   int outw, outh;
308   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
309                                PNGCodec::FORMAT_RGBA, &decoded,
310                                &outw, &outh));
311   ASSERT_EQ(w, outw);
312   ASSERT_EQ(h, outh);
313   ASSERT_EQ(original.size(), decoded.size());
314
315   // Images must be exactly equal
316   ASSERT_TRUE(original == decoded);
317 }
318
319 TEST(PNGCodec, EncodeDecodeBGRA) {
320   const int w = 20, h = 20;
321
322   // Create an image with known values, alpha must be opaque because it will be
323   // lost during encoding.
324   std::vector<unsigned char> original;
325   MakeRGBAImage(w, h, true, &original);
326
327   // Encode.
328   std::vector<unsigned char> encoded;
329   ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_BGRA,
330                                Size(w, h), w * 4, false,
331                                std::vector<PNGCodec::Comment>(),
332                                &encoded));
333
334   // Decode, it should have the same size as the original.
335   std::vector<unsigned char> decoded;
336   int outw, outh;
337   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
338                                PNGCodec::FORMAT_BGRA, &decoded,
339                                &outw, &outh));
340   ASSERT_EQ(w, outw);
341   ASSERT_EQ(h, outh);
342   ASSERT_EQ(original.size(), decoded.size());
343
344   // Images must be exactly equal.
345   ASSERT_TRUE(original == decoded);
346 }
347
348 TEST(PNGCodec, DecodePalette) {
349   const int w = 20, h = 20;
350
351   // create an image with known values
352   std::vector<unsigned char> original;
353   std::vector<png_color> original_palette;
354   std::vector<unsigned char> original_trans_chunk;
355   MakePaletteImage(w, h, &original, &original_palette, &original_trans_chunk);
356
357   // encode
358   std::vector<unsigned char> encoded;
359   ASSERT_TRUE(EncodeImage(original,
360                           w, h,
361                           COLOR_TYPE_PALETTE,
362                           &encoded,
363                           PNG_INTERLACE_NONE,
364                           &original_palette,
365                           &original_trans_chunk));
366
367   // decode
368   std::vector<unsigned char> decoded;
369   int outw, outh;
370   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
371                                PNGCodec::FORMAT_RGBA, &decoded,
372                                &outw, &outh));
373   ASSERT_EQ(w, outw);
374   ASSERT_EQ(h, outh);
375   ASSERT_EQ(decoded.size(), w * h * 4U);
376
377   // Images must be equal
378   for (int y = 0; y < h; ++y) {
379     for (int x = 0; x < w; ++x) {
380       unsigned char palette_pixel = original[y * w + x];
381       png_color& palette_color = original_palette[palette_pixel];
382       int alpha = original_trans_chunk[palette_pixel];
383       unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
384
385       EXPECT_EQ(palette_color.red, rgba_pixel[0]);
386       EXPECT_EQ(palette_color.green, rgba_pixel[1]);
387       EXPECT_EQ(palette_color.blue, rgba_pixel[2]);
388       EXPECT_EQ(alpha, rgba_pixel[3]);
389     }
390   }
391 }
392
393 TEST(PNGCodec, DecodePaletteDiscardAlpha) {
394   const int w = 20, h = 20;
395
396   // create an image with known values
397   std::vector<unsigned char> original;
398   std::vector<png_color> original_palette;
399   std::vector<unsigned char> original_trans_chunk;
400   MakePaletteImage(w, h, &original, &original_palette, &original_trans_chunk);
401
402   // encode
403   std::vector<unsigned char> encoded;
404   ASSERT_TRUE(EncodeImage(original,
405                           w, h,
406                           COLOR_TYPE_PALETTE,
407                           &encoded,
408                           PNG_INTERLACE_NONE,
409                           &original_palette,
410                           &original_trans_chunk));
411
412   // decode
413   std::vector<unsigned char> decoded;
414   int outw, outh;
415   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
416                                PNGCodec::FORMAT_RGB, &decoded,
417                                &outw, &outh));
418   ASSERT_EQ(w, outw);
419   ASSERT_EQ(h, outh);
420   ASSERT_EQ(decoded.size(), w * h * 3U);
421
422   // Images must be equal
423   for (int y = 0; y < h; ++y) {
424     for (int x = 0; x < w; ++x) {
425       unsigned char palette_pixel = original[y * w + x];
426       png_color& palette_color = original_palette[palette_pixel];
427       unsigned char* rgba_pixel = &decoded[(y * w + x) * 3];
428
429       EXPECT_EQ(palette_color.red, rgba_pixel[0]);
430       EXPECT_EQ(palette_color.green, rgba_pixel[1]);
431       EXPECT_EQ(palette_color.blue, rgba_pixel[2]);
432     }
433   }
434 }
435
436 TEST(PNGCodec, DecodeInterlacedPalette) {
437   const int w = 20, h = 20;
438
439   // create an image with known values
440   std::vector<unsigned char> original;
441   std::vector<png_color> original_palette;
442   std::vector<unsigned char> original_trans_chunk;
443   MakePaletteImage(w, h, &original, &original_palette, &original_trans_chunk);
444
445   // encode
446   std::vector<unsigned char> encoded;
447   ASSERT_TRUE(EncodeImage(original,
448                           w, h,
449                           COLOR_TYPE_PALETTE,
450                           &encoded,
451                           PNG_INTERLACE_ADAM7,
452                           &original_palette,
453                           &original_trans_chunk));
454
455   // decode
456   std::vector<unsigned char> decoded;
457   int outw, outh;
458   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
459                                PNGCodec::FORMAT_RGBA, &decoded,
460                                &outw, &outh));
461   ASSERT_EQ(w, outw);
462   ASSERT_EQ(h, outh);
463   ASSERT_EQ(decoded.size(), w * h * 4U);
464
465   // Images must be equal
466   for (int y = 0; y < h; ++y) {
467     for (int x = 0; x < w; ++x) {
468       unsigned char palette_pixel = original[y * w + x];
469       png_color& palette_color = original_palette[palette_pixel];
470       int alpha = original_trans_chunk[palette_pixel];
471       unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
472
473       EXPECT_EQ(palette_color.red, rgba_pixel[0]);
474       EXPECT_EQ(palette_color.green, rgba_pixel[1]);
475       EXPECT_EQ(palette_color.blue, rgba_pixel[2]);
476       EXPECT_EQ(alpha, rgba_pixel[3]);
477     }
478   }
479 }
480
481 TEST(PNGCodec, DecodeGrayscale) {
482   const int w = 20, h = 20;
483
484   // create an image with known values
485   std::vector<unsigned char> original;
486   MakeGrayscaleImage(w, h, &original);
487
488   // encode
489   std::vector<unsigned char> encoded;
490   ASSERT_TRUE(EncodeImage(original, w, h, COLOR_TYPE_GRAY, &encoded));
491
492   // decode
493   std::vector<unsigned char> decoded;
494   int outw, outh;
495   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
496                                PNGCodec::FORMAT_RGB, &decoded,
497                                &outw, &outh));
498   ASSERT_EQ(w, outw);
499   ASSERT_EQ(h, outh);
500   ASSERT_EQ(decoded.size(), original.size() * 3);
501
502   // Images must be equal
503   for (int y = 0; y < h; ++y) {
504     for (int x = 0; x < w; ++x) {
505       unsigned char gray_pixel = original[(y * w + x)];
506       unsigned char* rgba_pixel = &decoded[(y * w + x) * 3];
507       EXPECT_EQ(rgba_pixel[0], gray_pixel);
508       EXPECT_EQ(rgba_pixel[1], gray_pixel);
509       EXPECT_EQ(rgba_pixel[2], gray_pixel);
510     }
511   }
512 }
513
514 TEST(PNGCodec, DecodeGrayscaleWithAlpha) {
515   const int w = 20, h = 20;
516
517   // create an image with known values
518   std::vector<unsigned char> original;
519   MakeGrayscaleAlphaImage(w, h, &original);
520
521   // encode
522   std::vector<unsigned char> encoded;
523   ASSERT_TRUE(EncodeImage(original,
524                           w, h,
525                           COLOR_TYPE_GRAY_ALPHA,
526                           &encoded));
527
528   // decode
529   std::vector<unsigned char> decoded;
530   int outw, outh;
531   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
532                                PNGCodec::FORMAT_RGBA, &decoded,
533                                &outw, &outh));
534   ASSERT_EQ(w, outw);
535   ASSERT_EQ(h, outh);
536   ASSERT_EQ(decoded.size(), original.size() * 2);
537
538   // Images must be equal
539   for (int y = 0; y < h; ++y) {
540     for (int x = 0; x < w; ++x) {
541       unsigned char* gray_pixel = &original[(y * w + x) * 2];
542       unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
543       EXPECT_EQ(rgba_pixel[0], gray_pixel[0]);
544       EXPECT_EQ(rgba_pixel[1], gray_pixel[0]);
545       EXPECT_EQ(rgba_pixel[2], gray_pixel[0]);
546       EXPECT_EQ(rgba_pixel[3], gray_pixel[1]);
547     }
548   }
549 }
550
551 TEST(PNGCodec, DecodeGrayscaleWithAlphaDiscardAlpha) {
552   const int w = 20, h = 20;
553
554   // create an image with known values
555   std::vector<unsigned char> original;
556   MakeGrayscaleAlphaImage(w, h, &original);
557
558   // encode
559   std::vector<unsigned char> encoded;
560   ASSERT_TRUE(EncodeImage(original,
561                           w, h,
562                           COLOR_TYPE_GRAY_ALPHA,
563                           &encoded));
564
565   // decode
566   std::vector<unsigned char> decoded;
567   int outw, outh;
568   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
569                                PNGCodec::FORMAT_RGB, &decoded,
570                                &outw, &outh));
571   ASSERT_EQ(w, outw);
572   ASSERT_EQ(h, outh);
573   ASSERT_EQ(decoded.size(), w * h * 3U);
574
575   // Images must be equal
576   for (int y = 0; y < h; ++y) {
577     for (int x = 0; x < w; ++x) {
578       unsigned char* gray_pixel = &original[(y * w + x) * 2];
579       unsigned char* rgba_pixel = &decoded[(y * w + x) * 3];
580       EXPECT_EQ(rgba_pixel[0], gray_pixel[0]);
581       EXPECT_EQ(rgba_pixel[1], gray_pixel[0]);
582       EXPECT_EQ(rgba_pixel[2], gray_pixel[0]);
583     }
584   }
585 }
586
587 TEST(PNGCodec, DecodeInterlacedGrayscale) {
588   const int w = 20, h = 20;
589
590   // create an image with known values
591   std::vector<unsigned char> original;
592   MakeGrayscaleImage(w, h, &original);
593
594   // encode
595   std::vector<unsigned char> encoded;
596   ASSERT_TRUE(EncodeImage(original,
597                           w, h,
598                           COLOR_TYPE_GRAY,
599                           &encoded,
600                           PNG_INTERLACE_ADAM7));
601
602   // decode
603   std::vector<unsigned char> decoded;
604   int outw, outh;
605   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
606                                PNGCodec::FORMAT_RGBA, &decoded,
607                                &outw, &outh));
608   ASSERT_EQ(w, outw);
609   ASSERT_EQ(h, outh);
610   ASSERT_EQ(decoded.size(), original.size() * 4);
611
612   // Images must be equal
613   for (int y = 0; y < h; ++y) {
614     for (int x = 0; x < w; ++x) {
615       unsigned char gray_pixel = original[(y * w + x)];
616       unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
617       EXPECT_EQ(rgba_pixel[0], gray_pixel);
618       EXPECT_EQ(rgba_pixel[1], gray_pixel);
619       EXPECT_EQ(rgba_pixel[2], gray_pixel);
620       EXPECT_EQ(rgba_pixel[3], 0xFF);
621     }
622   }
623 }
624
625 TEST(PNGCodec, DecodeInterlacedGrayscaleWithAlpha) {
626   const int w = 20, h = 20;
627
628   // create an image with known values
629   std::vector<unsigned char> original;
630   MakeGrayscaleAlphaImage(w, h, &original);
631
632   // encode
633   std::vector<unsigned char> encoded;
634   ASSERT_TRUE(EncodeImage(original,
635                           w, h,
636                           COLOR_TYPE_GRAY_ALPHA,
637                           &encoded,
638                           PNG_INTERLACE_ADAM7));
639
640   // decode
641   std::vector<unsigned char> decoded;
642   int outw, outh;
643   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
644                                PNGCodec::FORMAT_RGBA, &decoded,
645                                &outw, &outh));
646   ASSERT_EQ(w, outw);
647   ASSERT_EQ(h, outh);
648   ASSERT_EQ(decoded.size(), original.size() * 2);
649
650   // Images must be equal
651   for (int y = 0; y < h; ++y) {
652     for (int x = 0; x < w; ++x) {
653       unsigned char* gray_pixel = &original[(y * w + x) * 2];
654       unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
655       EXPECT_EQ(rgba_pixel[0], gray_pixel[0]);
656       EXPECT_EQ(rgba_pixel[1], gray_pixel[0]);
657       EXPECT_EQ(rgba_pixel[2], gray_pixel[0]);
658       EXPECT_EQ(rgba_pixel[3], gray_pixel[1]);
659     }
660   }
661 }
662
663 TEST(PNGCodec, DecodeInterlacedRGB) {
664   const int w = 20, h = 20;
665
666   // create an image with known values
667   std::vector<unsigned char> original;
668   MakeRGBImage(w, h, &original);
669
670   // encode
671   std::vector<unsigned char> encoded;
672   ASSERT_TRUE(EncodeImage(original,
673                           w, h,
674                           COLOR_TYPE_RGB,
675                           &encoded,
676                           PNG_INTERLACE_ADAM7));
677
678   // decode, it should have the same size as the original
679   std::vector<unsigned char> decoded;
680   int outw, outh;
681   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
682                                PNGCodec::FORMAT_RGB, &decoded,
683                                &outw, &outh));
684   ASSERT_EQ(w, outw);
685   ASSERT_EQ(h, outh);
686   ASSERT_EQ(original.size(), decoded.size());
687
688   // Images must be equal
689   ASSERT_EQ(original, decoded);
690 }
691
692 TEST(PNGCodec, DecodeInterlacedRGBA) {
693   const int w = 20, h = 20;
694
695   // create an image with known values
696   std::vector<unsigned char> original;
697   MakeRGBAImage(w, h, false, &original);
698
699   // encode
700   std::vector<unsigned char> encoded;
701   ASSERT_TRUE(EncodeImage(original,
702                           w, h,
703                           COLOR_TYPE_RGBA,
704                           &encoded,
705                           PNG_INTERLACE_ADAM7));
706
707   // decode, it should have the same size as the original
708   std::vector<unsigned char> decoded;
709   int outw, outh;
710   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
711                                PNGCodec::FORMAT_RGBA, &decoded,
712                                &outw, &outh));
713   ASSERT_EQ(w, outw);
714   ASSERT_EQ(h, outh);
715   ASSERT_EQ(original.size(), decoded.size());
716
717   // Images must be equal
718   ASSERT_EQ(original, decoded);
719 }
720
721 TEST(PNGCodec, DecodeInterlacedRGBADiscardAlpha) {
722   const int w = 20, h = 20;
723
724   // create an image with known values
725   std::vector<unsigned char> original;
726   MakeRGBAImage(w, h, false, &original);
727
728   // encode
729   std::vector<unsigned char> encoded;
730   ASSERT_TRUE(EncodeImage(original,
731                           w, h,
732                           COLOR_TYPE_RGBA,
733                           &encoded,
734                           PNG_INTERLACE_ADAM7));
735
736   // decode
737   std::vector<unsigned char> decoded;
738   int outw, outh;
739   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
740                                PNGCodec::FORMAT_RGB, &decoded,
741                                &outw, &outh));
742   ASSERT_EQ(w, outw);
743   ASSERT_EQ(h, outh);
744   ASSERT_EQ(decoded.size(), w * h * 3U);
745
746   // Images must be equal
747   for (int x = 0; x < w; x++) {
748     for (int y = 0; y < h; y++) {
749       unsigned char* orig_px = &original[(y * w + x) * 4];
750       unsigned char* dec_px = &decoded[(y * w + x) * 3];
751       EXPECT_EQ(dec_px[0], orig_px[0]);
752       EXPECT_EQ(dec_px[1], orig_px[1]);
753       EXPECT_EQ(dec_px[2], orig_px[2]);
754     }
755   }
756 }
757
758 TEST(PNGCodec, DecodeInterlacedBGR) {
759   const int w = 20, h = 20;
760
761   // create an image with known values
762   std::vector<unsigned char> original;
763   MakeRGBImage(w, h, &original);
764
765   // encode
766   std::vector<unsigned char> encoded;
767   ASSERT_TRUE(EncodeImage(original,
768                           w, h,
769                           COLOR_TYPE_BGR,
770                           &encoded,
771                           PNG_INTERLACE_ADAM7));
772
773   // decode, it should have the same size as the original
774   std::vector<unsigned char> decoded;
775   int outw, outh;
776   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
777                                PNGCodec::FORMAT_BGRA, &decoded,
778                                &outw, &outh));
779   ASSERT_EQ(w, outw);
780   ASSERT_EQ(h, outh);
781   ASSERT_EQ(decoded.size(), w * h * 4U);
782
783   // Images must be equal
784   for (int x = 0; x < w; x++) {
785     for (int y = 0; y < h; y++) {
786       unsigned char* orig_px = &original[(y * w + x) * 3];
787       unsigned char* dec_px = &decoded[(y * w + x) * 4];
788       EXPECT_EQ(dec_px[0], orig_px[0]);
789       EXPECT_EQ(dec_px[1], orig_px[1]);
790       EXPECT_EQ(dec_px[2], orig_px[2]);
791     }
792   }
793 }
794
795 TEST(PNGCodec, DecodeInterlacedBGRA) {
796   const int w = 20, h = 20;
797
798   // create an image with known values
799   std::vector<unsigned char> original;
800   MakeRGBAImage(w, h, false, &original);
801
802   // encode
803   std::vector<unsigned char> encoded;
804   ASSERT_TRUE(EncodeImage(original,
805                           w, h,
806                           COLOR_TYPE_BGRA,
807                           &encoded,
808                           PNG_INTERLACE_ADAM7));
809
810   // decode, it should have the same size as the original
811   std::vector<unsigned char> decoded;
812   int outw, outh;
813   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
814                                PNGCodec::FORMAT_BGRA, &decoded,
815                                &outw, &outh));
816   ASSERT_EQ(w, outw);
817   ASSERT_EQ(h, outh);
818   ASSERT_EQ(original.size(), decoded.size());
819
820   // Images must be equal
821   ASSERT_EQ(original, decoded);
822 }
823
824 // Not encoding an interlaced PNG from SkBitmap because we don't do it
825 // anywhere, and the ability to do that requires more code changes.
826 TEST(PNGCodec, DecodeInterlacedRGBtoSkBitmap) {
827   const int w = 20, h = 20;
828
829   // create an image with known values
830   std::vector<unsigned char> original;
831   MakeRGBImage(w, h, &original);
832
833   // encode
834   std::vector<unsigned char> encoded;
835   ASSERT_TRUE(EncodeImage(original,
836                           w, h,
837                           COLOR_TYPE_RGB,
838                           &encoded,
839                           PNG_INTERLACE_ADAM7));
840
841   // Decode the encoded string.
842   SkBitmap decoded_bitmap;
843   ASSERT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
844                                &decoded_bitmap));
845
846   for (int x = 0; x < w; x++) {
847     for (int y = 0; y < h; y++) {
848       const unsigned char* original_pixel = &original[(y * w + x) * 3];
849       const uint32_t original_pixel_sk = SkPackARGB32(0xFF,
850                                                       original_pixel[0],
851                                                       original_pixel[1],
852                                                       original_pixel[2]);
853       const uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
854       EXPECT_EQ(original_pixel_sk, decoded_pixel);
855     }
856   }
857 }
858
859 TEST(PNGCodec, DecodeInterlacedRGBAtoSkBitmap) {
860   const int w = 20, h = 20;
861
862   // create an image with known values
863   std::vector<unsigned char> original;
864   MakeRGBAImage(w, h, false, &original);
865
866   // encode
867   std::vector<unsigned char> encoded;
868   ASSERT_TRUE(EncodeImage(original,
869                           w, h,
870                           COLOR_TYPE_RGBA,
871                           &encoded,
872                           PNG_INTERLACE_ADAM7));
873
874   // Decode the encoded string.
875   SkBitmap decoded_bitmap;
876   ASSERT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
877                                &decoded_bitmap));
878
879   for (int x = 0; x < w; x++) {
880     for (int y = 0; y < h; y++) {
881       const unsigned char* original_pixel = &original[(y * w + x) * 4];
882       const uint32_t original_pixel_sk = SkPackARGB32(original_pixel[3],
883                                                       original_pixel[0],
884                                                       original_pixel[1],
885                                                       original_pixel[2]);
886       const uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
887       EXPECT_EQ(original_pixel_sk, decoded_pixel);
888     }
889   }
890 }
891
892 // Test that corrupted data decompression causes failures.
893 TEST(PNGCodec, DecodeCorrupted) {
894   int w = 20, h = 20;
895
896   // Make some random data (an uncompressed image).
897   std::vector<unsigned char> original;
898   MakeRGBImage(w, h, &original);
899
900   // It should fail when given non-JPEG compressed data.
901   std::vector<unsigned char> output;
902   int outw, outh;
903   EXPECT_FALSE(PNGCodec::Decode(&original[0], original.size(),
904                                 PNGCodec::FORMAT_RGB, &output,
905                                 &outw, &outh));
906
907   // Make some compressed data.
908   std::vector<unsigned char> compressed;
909   ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGB,
910                                Size(w, h), w * 3, false,
911                                std::vector<PNGCodec::Comment>(),
912                                &compressed));
913
914   // Try decompressing a truncated version.
915   EXPECT_FALSE(PNGCodec::Decode(&compressed[0], compressed.size() / 2,
916                                 PNGCodec::FORMAT_RGB, &output,
917                                 &outw, &outh));
918
919   // Corrupt it and try decompressing that.
920   for (int i = 10; i < 30; i++)
921     compressed[i] = i;
922   EXPECT_FALSE(PNGCodec::Decode(&compressed[0], compressed.size(),
923                                 PNGCodec::FORMAT_RGB, &output,
924                                 &outw, &outh));
925 }
926
927 TEST(PNGCodec, StripAddAlpha) {
928   const int w = 20, h = 20;
929
930   // These should be the same except one has a 0xff alpha channel.
931   std::vector<unsigned char> original_rgb;
932   MakeRGBImage(w, h, &original_rgb);
933   std::vector<unsigned char> original_rgba;
934   MakeRGBAImage(w, h, false, &original_rgba);
935
936   // Encode RGBA data as RGB.
937   std::vector<unsigned char> encoded;
938   EXPECT_TRUE(PNGCodec::Encode(&original_rgba[0], PNGCodec::FORMAT_RGBA,
939                                Size(w, h), w * 4, true,
940                                std::vector<PNGCodec::Comment>(),
941                                &encoded));
942
943   // Decode the RGB to RGBA.
944   std::vector<unsigned char> decoded;
945   int outw, outh;
946   EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
947                                PNGCodec::FORMAT_RGBA, &decoded,
948                                &outw, &outh));
949
950   // Decoded and reference should be the same (opaque alpha).
951   ASSERT_EQ(w, outw);
952   ASSERT_EQ(h, outh);
953   ASSERT_EQ(original_rgba.size(), decoded.size());
954   ASSERT_EQ(original_rgba, decoded);
955
956   // Encode RGBA to RGBA.
957   EXPECT_TRUE(PNGCodec::Encode(&original_rgba[0], PNGCodec::FORMAT_RGBA,
958                                Size(w, h), w * 4, false,
959                                std::vector<PNGCodec::Comment>(),
960                                &encoded));
961
962   // Decode the RGBA to RGB.
963   EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
964                                PNGCodec::FORMAT_RGB, &decoded,
965                                &outw, &outh));
966
967   // It should be the same as our non-alpha-channel reference.
968   ASSERT_EQ(w, outw);
969   ASSERT_EQ(h, outh);
970   ASSERT_EQ(original_rgb.size(), decoded.size());
971   ASSERT_EQ(original_rgb, decoded);
972 }
973
974 TEST(PNGCodec, EncodeBGRASkBitmapStridePadded) {
975   const int kWidth = 20;
976   const int kHeight = 20;
977   const int kPaddedWidth = 32;
978   const int kBytesPerPixel = 4;
979   const int kPaddedSize = kPaddedWidth * kHeight;
980   const int kRowBytes = kPaddedWidth * kBytesPerPixel;
981
982   SkBitmap original_bitmap;
983   original_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
984                             kWidth, kHeight, kRowBytes);
985   original_bitmap.allocPixels();
986
987   // Write data over the source bitmap.
988   // We write on the pad area here too.
989   // The encoder should ignore the pad area.
990   uint32_t* src_data = original_bitmap.getAddr32(0, 0);
991   for (int i = 0; i < kPaddedSize; i++) {
992     src_data[i] = SkPreMultiplyARGB(i % 255, i % 250, i % 245, i % 240);
993   }
994
995   // Encode the bitmap.
996   std::vector<unsigned char> encoded;
997   PNGCodec::EncodeBGRASkBitmap(original_bitmap, false, &encoded);
998
999   // Decode the encoded string.
1000   SkBitmap decoded_bitmap;
1001   EXPECT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
1002                                &decoded_bitmap));
1003
1004   // Compare the original bitmap and the output bitmap. We use ColorsClose
1005   // as SkBitmaps are considered to be pre-multiplied, the unpremultiplication
1006   // (in Encode) and repremultiplication (in Decode) can be lossy.
1007   for (int x = 0; x < kWidth; x++) {
1008     for (int y = 0; y < kHeight; y++) {
1009       uint32_t original_pixel = original_bitmap.getAddr32(0, y)[x];
1010       uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
1011       EXPECT_TRUE(ColorsClose(original_pixel, decoded_pixel));
1012     }
1013   }
1014 }
1015
1016 TEST(PNGCodec, EncodeBGRASkBitmap) {
1017   const int w = 20, h = 20;
1018
1019   SkBitmap original_bitmap;
1020   MakeTestSkBitmap(w, h, &original_bitmap);
1021
1022   // Encode the bitmap.
1023   std::vector<unsigned char> encoded;
1024   PNGCodec::EncodeBGRASkBitmap(original_bitmap, false, &encoded);
1025
1026   // Decode the encoded string.
1027   SkBitmap decoded_bitmap;
1028   EXPECT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
1029                                &decoded_bitmap));
1030
1031   // Compare the original bitmap and the output bitmap. We use ColorsClose
1032   // as SkBitmaps are considered to be pre-multiplied, the unpremultiplication
1033   // (in Encode) and repremultiplication (in Decode) can be lossy.
1034   for (int x = 0; x < w; x++) {
1035     for (int y = 0; y < h; y++) {
1036       uint32_t original_pixel = original_bitmap.getAddr32(0, y)[x];
1037       uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
1038       EXPECT_TRUE(ColorsClose(original_pixel, decoded_pixel));
1039     }
1040   }
1041 }
1042
1043 TEST(PNGCodec, EncodeBGRASkBitmapDiscardTransparency) {
1044   const int w = 20, h = 20;
1045
1046   SkBitmap original_bitmap;
1047   MakeTestSkBitmap(w, h, &original_bitmap);
1048
1049   // Encode the bitmap.
1050   std::vector<unsigned char> encoded;
1051   PNGCodec::EncodeBGRASkBitmap(original_bitmap, true, &encoded);
1052
1053   // Decode the encoded string.
1054   SkBitmap decoded_bitmap;
1055   EXPECT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
1056                                &decoded_bitmap));
1057
1058   // Compare the original bitmap and the output bitmap. We need to
1059   // unpremultiply original_pixel, as the decoded bitmap doesn't have an alpha
1060   // channel.
1061   for (int x = 0; x < w; x++) {
1062     for (int y = 0; y < h; y++) {
1063       uint32_t original_pixel = original_bitmap.getAddr32(0, y)[x];
1064       uint32_t unpremultiplied =
1065           SkUnPreMultiply::PMColorToColor(original_pixel);
1066       uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
1067       uint32_t unpremultiplied_decoded =
1068           SkUnPreMultiply::PMColorToColor(decoded_pixel);
1069
1070       EXPECT_TRUE(NonAlphaColorsClose(unpremultiplied, unpremultiplied_decoded))
1071           << "Original_pixel: ("
1072           << SkColorGetR(unpremultiplied) << ", "
1073           << SkColorGetG(unpremultiplied) << ", "
1074           << SkColorGetB(unpremultiplied) << "), "
1075           << "Decoded pixel: ("
1076           << SkColorGetR(unpremultiplied_decoded) << ", "
1077           << SkColorGetG(unpremultiplied_decoded) << ", "
1078           << SkColorGetB(unpremultiplied_decoded) << ")";
1079     }
1080   }
1081 }
1082
1083 TEST(PNGCodec, EncodeWithComment) {
1084   const int w = 10, h = 10;
1085
1086   std::vector<unsigned char> original;
1087   MakeRGBImage(w, h, &original);
1088
1089   std::vector<unsigned char> encoded;
1090   std::vector<PNGCodec::Comment> comments;
1091   comments.push_back(PNGCodec::Comment("key", "text"));
1092   comments.push_back(PNGCodec::Comment("test", "something"));
1093   comments.push_back(PNGCodec::Comment("have some", "spaces in both"));
1094   EXPECT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGB,
1095                                Size(w, h), w * 3, false, comments, &encoded));
1096
1097   // Each chunk is of the form length (4 bytes), chunk type (tEXt), data,
1098   // checksum (4 bytes).  Make sure we find all of them in the encoded
1099   // results.
1100   const unsigned char kExpected1[] =
1101       "\x00\x00\x00\x08tEXtkey\x00text\x9e\xe7\x66\x51";
1102   const unsigned char kExpected2[] =
1103       "\x00\x00\x00\x0etEXttest\x00something\x29\xba\xef\xac";
1104   const unsigned char kExpected3[] =
1105       "\x00\x00\x00\x18tEXthave some\x00spaces in both\x8d\x69\x34\x2d";
1106
1107   EXPECT_NE(std::search(encoded.begin(), encoded.end(), kExpected1,
1108                         kExpected1 + arraysize(kExpected1)),
1109             encoded.end());
1110   EXPECT_NE(std::search(encoded.begin(), encoded.end(), kExpected2,
1111                         kExpected2 + arraysize(kExpected2)),
1112             encoded.end());
1113   EXPECT_NE(std::search(encoded.begin(), encoded.end(), kExpected3,
1114                         kExpected3 + arraysize(kExpected3)),
1115             encoded.end());
1116 }
1117
1118 TEST(PNGCodec, EncodeDecodeWithVaryingCompressionLevels) {
1119   const int w = 20, h = 20;
1120
1121   // create an image with known values, a must be opaque because it will be
1122   // lost during encoding
1123   SkBitmap original_bitmap;
1124   MakeTestSkBitmap(w, h, &original_bitmap);
1125
1126   // encode
1127   std::vector<unsigned char> encoded_normal;
1128   EXPECT_TRUE(
1129       PNGCodec::EncodeBGRASkBitmap(original_bitmap, false, &encoded_normal));
1130
1131   std::vector<unsigned char> encoded_fast;
1132   EXPECT_TRUE(
1133       PNGCodec::FastEncodeBGRASkBitmap(original_bitmap, false, &encoded_fast));
1134
1135   // Make sure the different compression settings actually do something; the
1136   // sizes should be different.
1137   EXPECT_NE(encoded_normal.size(), encoded_fast.size());
1138
1139   // decode, they should be identical to the original.
1140   SkBitmap decoded;
1141   EXPECT_TRUE(
1142       PNGCodec::Decode(&encoded_normal[0], encoded_normal.size(), &decoded));
1143   EXPECT_TRUE(BitmapsAreEqual(decoded, original_bitmap));
1144
1145   EXPECT_TRUE(
1146       PNGCodec::Decode(&encoded_fast[0], encoded_fast.size(), &decoded));
1147   EXPECT_TRUE(BitmapsAreEqual(decoded, original_bitmap));
1148 }
1149
1150
1151 }  // namespace gfx