Upstream version 9.38.198.0
[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 // Returns true if the BGRA 32-bit SkColor specified by |a| is equivalent to the
253 // 8-bit Gray color specified by |b|.
254 bool BGRAGrayEqualsA8Gray(uint32_t a, uint8_t b) {
255   return SkColorGetB(a) == b && SkColorGetG(a) ==  b &&
256          SkColorGetR(a) == b && SkColorGetA(a) == 255;
257 }
258
259 void MakeTestBGRASkBitmap(int w, int h, SkBitmap* bmp) {
260   bmp->allocN32Pixels(w, h);
261
262   uint32_t* src_data = bmp->getAddr32(0, 0);
263   for (int i = 0; i < w * h; i++)
264     src_data[i] = SkPreMultiplyARGB(i % 255, i % 250, i % 245, i % 240);
265 }
266
267 void MakeTestA8SkBitmap(int w, int h, SkBitmap* bmp) {
268   bmp->allocPixels(SkImageInfo::MakeA8(w, h));
269
270   uint8_t* src_data = bmp->getAddr8(0, 0);
271   for (int i = 0; i < w * h; i++)
272     src_data[i] = i % 255;
273 }
274
275 TEST(PNGCodec, EncodeDecodeRGB) {
276   const int w = 20, h = 20;
277
278   // create an image with known values
279   std::vector<unsigned char> original;
280   MakeRGBImage(w, h, &original);
281
282   // encode
283   std::vector<unsigned char> encoded;
284   ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGB,
285                                Size(w, h), w * 3, false,
286                                std::vector<PNGCodec::Comment>(),
287                                &encoded));
288
289   // decode, it should have the same size as the original
290   std::vector<unsigned char> decoded;
291   int outw, outh;
292   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
293                                PNGCodec::FORMAT_RGB, &decoded,
294                                &outw, &outh));
295   ASSERT_EQ(w, outw);
296   ASSERT_EQ(h, outh);
297   ASSERT_EQ(original.size(), decoded.size());
298
299   // Images must be equal
300   ASSERT_TRUE(original == decoded);
301 }
302
303 TEST(PNGCodec, EncodeDecodeRGBA) {
304   const int w = 20, h = 20;
305
306   // create an image with known values, a must be opaque because it will be
307   // lost during encoding
308   std::vector<unsigned char> original;
309   MakeRGBAImage(w, h, true, &original);
310
311   // encode
312   std::vector<unsigned char> encoded;
313   ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGBA,
314                                Size(w, h), w * 4, false,
315                                std::vector<PNGCodec::Comment>(),
316                                &encoded));
317
318   // decode, it should have the same size as the original
319   std::vector<unsigned char> decoded;
320   int outw, outh;
321   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
322                                PNGCodec::FORMAT_RGBA, &decoded,
323                                &outw, &outh));
324   ASSERT_EQ(w, outw);
325   ASSERT_EQ(h, outh);
326   ASSERT_EQ(original.size(), decoded.size());
327
328   // Images must be exactly equal
329   ASSERT_TRUE(original == decoded);
330 }
331
332 TEST(PNGCodec, EncodeDecodeBGRA) {
333   const int w = 20, h = 20;
334
335   // Create an image with known values, alpha must be opaque because it will be
336   // lost during encoding.
337   std::vector<unsigned char> original;
338   MakeRGBAImage(w, h, true, &original);
339
340   // Encode.
341   std::vector<unsigned char> encoded;
342   ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_BGRA,
343                                Size(w, h), w * 4, false,
344                                std::vector<PNGCodec::Comment>(),
345                                &encoded));
346
347   // Decode, it should have the same size as the original.
348   std::vector<unsigned char> decoded;
349   int outw, outh;
350   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
351                                PNGCodec::FORMAT_BGRA, &decoded,
352                                &outw, &outh));
353   ASSERT_EQ(w, outw);
354   ASSERT_EQ(h, outh);
355   ASSERT_EQ(original.size(), decoded.size());
356
357   // Images must be exactly equal.
358   ASSERT_TRUE(original == decoded);
359 }
360
361 TEST(PNGCodec, DecodePalette) {
362   const int w = 20, h = 20;
363
364   // create an image with known values
365   std::vector<unsigned char> original;
366   std::vector<png_color> original_palette;
367   std::vector<unsigned char> original_trans_chunk;
368   MakePaletteImage(w, h, &original, &original_palette, &original_trans_chunk);
369
370   // encode
371   std::vector<unsigned char> encoded;
372   ASSERT_TRUE(EncodeImage(original,
373                           w, h,
374                           COLOR_TYPE_PALETTE,
375                           &encoded,
376                           PNG_INTERLACE_NONE,
377                           &original_palette,
378                           &original_trans_chunk));
379
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,
385                                &outw, &outh));
386   ASSERT_EQ(w, outw);
387   ASSERT_EQ(h, outh);
388   ASSERT_EQ(decoded.size(), w * h * 4U);
389
390   // Images must be equal
391   for (int y = 0; y < h; ++y) {
392     for (int x = 0; x < w; ++x) {
393       unsigned char palette_pixel = original[y * w + x];
394       png_color& palette_color = original_palette[palette_pixel];
395       int alpha = original_trans_chunk[palette_pixel];
396       unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
397
398       EXPECT_EQ(palette_color.red, rgba_pixel[0]);
399       EXPECT_EQ(palette_color.green, rgba_pixel[1]);
400       EXPECT_EQ(palette_color.blue, rgba_pixel[2]);
401       EXPECT_EQ(alpha, rgba_pixel[3]);
402     }
403   }
404 }
405
406 TEST(PNGCodec, DecodePaletteDiscardAlpha) {
407   const int w = 20, h = 20;
408
409   // create an image with known values
410   std::vector<unsigned char> original;
411   std::vector<png_color> original_palette;
412   std::vector<unsigned char> original_trans_chunk;
413   MakePaletteImage(w, h, &original, &original_palette, &original_trans_chunk);
414
415   // encode
416   std::vector<unsigned char> encoded;
417   ASSERT_TRUE(EncodeImage(original,
418                           w, h,
419                           COLOR_TYPE_PALETTE,
420                           &encoded,
421                           PNG_INTERLACE_NONE,
422                           &original_palette,
423                           &original_trans_chunk));
424
425   // decode
426   std::vector<unsigned char> decoded;
427   int outw, outh;
428   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
429                                PNGCodec::FORMAT_RGB, &decoded,
430                                &outw, &outh));
431   ASSERT_EQ(w, outw);
432   ASSERT_EQ(h, outh);
433   ASSERT_EQ(decoded.size(), w * h * 3U);
434
435   // Images must be equal
436   for (int y = 0; y < h; ++y) {
437     for (int x = 0; x < w; ++x) {
438       unsigned char palette_pixel = original[y * w + x];
439       png_color& palette_color = original_palette[palette_pixel];
440       unsigned char* rgba_pixel = &decoded[(y * w + x) * 3];
441
442       EXPECT_EQ(palette_color.red, rgba_pixel[0]);
443       EXPECT_EQ(palette_color.green, rgba_pixel[1]);
444       EXPECT_EQ(palette_color.blue, rgba_pixel[2]);
445     }
446   }
447 }
448
449 TEST(PNGCodec, DecodeInterlacedPalette) {
450   const int w = 20, h = 20;
451
452   // create an image with known values
453   std::vector<unsigned char> original;
454   std::vector<png_color> original_palette;
455   std::vector<unsigned char> original_trans_chunk;
456   MakePaletteImage(w, h, &original, &original_palette, &original_trans_chunk);
457
458   // encode
459   std::vector<unsigned char> encoded;
460   ASSERT_TRUE(EncodeImage(original,
461                           w, h,
462                           COLOR_TYPE_PALETTE,
463                           &encoded,
464                           PNG_INTERLACE_ADAM7,
465                           &original_palette,
466                           &original_trans_chunk));
467
468   // decode
469   std::vector<unsigned char> decoded;
470   int outw, outh;
471   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
472                                PNGCodec::FORMAT_RGBA, &decoded,
473                                &outw, &outh));
474   ASSERT_EQ(w, outw);
475   ASSERT_EQ(h, outh);
476   ASSERT_EQ(decoded.size(), w * h * 4U);
477
478   // Images must be equal
479   for (int y = 0; y < h; ++y) {
480     for (int x = 0; x < w; ++x) {
481       unsigned char palette_pixel = original[y * w + x];
482       png_color& palette_color = original_palette[palette_pixel];
483       int alpha = original_trans_chunk[palette_pixel];
484       unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
485
486       EXPECT_EQ(palette_color.red, rgba_pixel[0]);
487       EXPECT_EQ(palette_color.green, rgba_pixel[1]);
488       EXPECT_EQ(palette_color.blue, rgba_pixel[2]);
489       EXPECT_EQ(alpha, rgba_pixel[3]);
490     }
491   }
492 }
493
494 TEST(PNGCodec, DecodeGrayscale) {
495   const int w = 20, h = 20;
496
497   // create an image with known values
498   std::vector<unsigned char> original;
499   MakeGrayscaleImage(w, h, &original);
500
501   // encode
502   std::vector<unsigned char> encoded;
503   ASSERT_TRUE(EncodeImage(original, w, h, COLOR_TYPE_GRAY, &encoded));
504
505   // decode
506   std::vector<unsigned char> decoded;
507   int outw, outh;
508   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
509                                PNGCodec::FORMAT_RGB, &decoded,
510                                &outw, &outh));
511   ASSERT_EQ(w, outw);
512   ASSERT_EQ(h, outh);
513   ASSERT_EQ(decoded.size(), original.size() * 3);
514
515   // Images must be equal
516   for (int y = 0; y < h; ++y) {
517     for (int x = 0; x < w; ++x) {
518       unsigned char gray_pixel = original[(y * w + x)];
519       unsigned char* rgba_pixel = &decoded[(y * w + x) * 3];
520       EXPECT_EQ(rgba_pixel[0], gray_pixel);
521       EXPECT_EQ(rgba_pixel[1], gray_pixel);
522       EXPECT_EQ(rgba_pixel[2], gray_pixel);
523     }
524   }
525 }
526
527 TEST(PNGCodec, DecodeGrayscaleWithAlpha) {
528   const int w = 20, h = 20;
529
530   // create an image with known values
531   std::vector<unsigned char> original;
532   MakeGrayscaleAlphaImage(w, h, &original);
533
534   // encode
535   std::vector<unsigned char> encoded;
536   ASSERT_TRUE(EncodeImage(original,
537                           w, h,
538                           COLOR_TYPE_GRAY_ALPHA,
539                           &encoded));
540
541   // decode
542   std::vector<unsigned char> decoded;
543   int outw, outh;
544   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
545                                PNGCodec::FORMAT_RGBA, &decoded,
546                                &outw, &outh));
547   ASSERT_EQ(w, outw);
548   ASSERT_EQ(h, outh);
549   ASSERT_EQ(decoded.size(), original.size() * 2);
550
551   // Images must be equal
552   for (int y = 0; y < h; ++y) {
553     for (int x = 0; x < w; ++x) {
554       unsigned char* gray_pixel = &original[(y * w + x) * 2];
555       unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
556       EXPECT_EQ(rgba_pixel[0], gray_pixel[0]);
557       EXPECT_EQ(rgba_pixel[1], gray_pixel[0]);
558       EXPECT_EQ(rgba_pixel[2], gray_pixel[0]);
559       EXPECT_EQ(rgba_pixel[3], gray_pixel[1]);
560     }
561   }
562 }
563
564 TEST(PNGCodec, DecodeGrayscaleWithAlphaDiscardAlpha) {
565   const int w = 20, h = 20;
566
567   // create an image with known values
568   std::vector<unsigned char> original;
569   MakeGrayscaleAlphaImage(w, h, &original);
570
571   // encode
572   std::vector<unsigned char> encoded;
573   ASSERT_TRUE(EncodeImage(original,
574                           w, h,
575                           COLOR_TYPE_GRAY_ALPHA,
576                           &encoded));
577
578   // decode
579   std::vector<unsigned char> decoded;
580   int outw, outh;
581   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
582                                PNGCodec::FORMAT_RGB, &decoded,
583                                &outw, &outh));
584   ASSERT_EQ(w, outw);
585   ASSERT_EQ(h, outh);
586   ASSERT_EQ(decoded.size(), w * h * 3U);
587
588   // Images must be equal
589   for (int y = 0; y < h; ++y) {
590     for (int x = 0; x < w; ++x) {
591       unsigned char* gray_pixel = &original[(y * w + x) * 2];
592       unsigned char* rgba_pixel = &decoded[(y * w + x) * 3];
593       EXPECT_EQ(rgba_pixel[0], gray_pixel[0]);
594       EXPECT_EQ(rgba_pixel[1], gray_pixel[0]);
595       EXPECT_EQ(rgba_pixel[2], gray_pixel[0]);
596     }
597   }
598 }
599
600 TEST(PNGCodec, DecodeInterlacedGrayscale) {
601   const int w = 20, h = 20;
602
603   // create an image with known values
604   std::vector<unsigned char> original;
605   MakeGrayscaleImage(w, h, &original);
606
607   // encode
608   std::vector<unsigned char> encoded;
609   ASSERT_TRUE(EncodeImage(original,
610                           w, h,
611                           COLOR_TYPE_GRAY,
612                           &encoded,
613                           PNG_INTERLACE_ADAM7));
614
615   // decode
616   std::vector<unsigned char> decoded;
617   int outw, outh;
618   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
619                                PNGCodec::FORMAT_RGBA, &decoded,
620                                &outw, &outh));
621   ASSERT_EQ(w, outw);
622   ASSERT_EQ(h, outh);
623   ASSERT_EQ(decoded.size(), original.size() * 4);
624
625   // Images must be equal
626   for (int y = 0; y < h; ++y) {
627     for (int x = 0; x < w; ++x) {
628       unsigned char gray_pixel = original[(y * w + x)];
629       unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
630       EXPECT_EQ(rgba_pixel[0], gray_pixel);
631       EXPECT_EQ(rgba_pixel[1], gray_pixel);
632       EXPECT_EQ(rgba_pixel[2], gray_pixel);
633       EXPECT_EQ(rgba_pixel[3], 0xFF);
634     }
635   }
636 }
637
638 TEST(PNGCodec, DecodeInterlacedGrayscaleWithAlpha) {
639   const int w = 20, h = 20;
640
641   // create an image with known values
642   std::vector<unsigned char> original;
643   MakeGrayscaleAlphaImage(w, h, &original);
644
645   // encode
646   std::vector<unsigned char> encoded;
647   ASSERT_TRUE(EncodeImage(original,
648                           w, h,
649                           COLOR_TYPE_GRAY_ALPHA,
650                           &encoded,
651                           PNG_INTERLACE_ADAM7));
652
653   // decode
654   std::vector<unsigned char> decoded;
655   int outw, outh;
656   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
657                                PNGCodec::FORMAT_RGBA, &decoded,
658                                &outw, &outh));
659   ASSERT_EQ(w, outw);
660   ASSERT_EQ(h, outh);
661   ASSERT_EQ(decoded.size(), original.size() * 2);
662
663   // Images must be equal
664   for (int y = 0; y < h; ++y) {
665     for (int x = 0; x < w; ++x) {
666       unsigned char* gray_pixel = &original[(y * w + x) * 2];
667       unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
668       EXPECT_EQ(rgba_pixel[0], gray_pixel[0]);
669       EXPECT_EQ(rgba_pixel[1], gray_pixel[0]);
670       EXPECT_EQ(rgba_pixel[2], gray_pixel[0]);
671       EXPECT_EQ(rgba_pixel[3], gray_pixel[1]);
672     }
673   }
674 }
675
676 TEST(PNGCodec, DecodeInterlacedRGB) {
677   const int w = 20, h = 20;
678
679   // create an image with known values
680   std::vector<unsigned char> original;
681   MakeRGBImage(w, h, &original);
682
683   // encode
684   std::vector<unsigned char> encoded;
685   ASSERT_TRUE(EncodeImage(original,
686                           w, h,
687                           COLOR_TYPE_RGB,
688                           &encoded,
689                           PNG_INTERLACE_ADAM7));
690
691   // decode, it should have the same size as the original
692   std::vector<unsigned char> decoded;
693   int outw, outh;
694   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
695                                PNGCodec::FORMAT_RGB, &decoded,
696                                &outw, &outh));
697   ASSERT_EQ(w, outw);
698   ASSERT_EQ(h, outh);
699   ASSERT_EQ(original.size(), decoded.size());
700
701   // Images must be equal
702   ASSERT_EQ(original, decoded);
703 }
704
705 TEST(PNGCodec, DecodeInterlacedRGBA) {
706   const int w = 20, h = 20;
707
708   // create an image with known values
709   std::vector<unsigned char> original;
710   MakeRGBAImage(w, h, false, &original);
711
712   // encode
713   std::vector<unsigned char> encoded;
714   ASSERT_TRUE(EncodeImage(original,
715                           w, h,
716                           COLOR_TYPE_RGBA,
717                           &encoded,
718                           PNG_INTERLACE_ADAM7));
719
720   // decode, it should have the same size as the original
721   std::vector<unsigned char> decoded;
722   int outw, outh;
723   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
724                                PNGCodec::FORMAT_RGBA, &decoded,
725                                &outw, &outh));
726   ASSERT_EQ(w, outw);
727   ASSERT_EQ(h, outh);
728   ASSERT_EQ(original.size(), decoded.size());
729
730   // Images must be equal
731   ASSERT_EQ(original, decoded);
732 }
733
734 TEST(PNGCodec, DecodeInterlacedRGBADiscardAlpha) {
735   const int w = 20, h = 20;
736
737   // create an image with known values
738   std::vector<unsigned char> original;
739   MakeRGBAImage(w, h, false, &original);
740
741   // encode
742   std::vector<unsigned char> encoded;
743   ASSERT_TRUE(EncodeImage(original,
744                           w, h,
745                           COLOR_TYPE_RGBA,
746                           &encoded,
747                           PNG_INTERLACE_ADAM7));
748
749   // decode
750   std::vector<unsigned char> decoded;
751   int outw, outh;
752   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
753                                PNGCodec::FORMAT_RGB, &decoded,
754                                &outw, &outh));
755   ASSERT_EQ(w, outw);
756   ASSERT_EQ(h, outh);
757   ASSERT_EQ(decoded.size(), w * h * 3U);
758
759   // Images must be equal
760   for (int x = 0; x < w; x++) {
761     for (int y = 0; y < h; y++) {
762       unsigned char* orig_px = &original[(y * w + x) * 4];
763       unsigned char* dec_px = &decoded[(y * w + x) * 3];
764       EXPECT_EQ(dec_px[0], orig_px[0]);
765       EXPECT_EQ(dec_px[1], orig_px[1]);
766       EXPECT_EQ(dec_px[2], orig_px[2]);
767     }
768   }
769 }
770
771 TEST(PNGCodec, DecodeInterlacedBGR) {
772   const int w = 20, h = 20;
773
774   // create an image with known values
775   std::vector<unsigned char> original;
776   MakeRGBImage(w, h, &original);
777
778   // encode
779   std::vector<unsigned char> encoded;
780   ASSERT_TRUE(EncodeImage(original,
781                           w, h,
782                           COLOR_TYPE_BGR,
783                           &encoded,
784                           PNG_INTERLACE_ADAM7));
785
786   // decode, it should have the same size as the original
787   std::vector<unsigned char> decoded;
788   int outw, outh;
789   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
790                                PNGCodec::FORMAT_BGRA, &decoded,
791                                &outw, &outh));
792   ASSERT_EQ(w, outw);
793   ASSERT_EQ(h, outh);
794   ASSERT_EQ(decoded.size(), w * h * 4U);
795
796   // Images must be equal
797   for (int x = 0; x < w; x++) {
798     for (int y = 0; y < h; y++) {
799       unsigned char* orig_px = &original[(y * w + x) * 3];
800       unsigned char* dec_px = &decoded[(y * w + x) * 4];
801       EXPECT_EQ(dec_px[0], orig_px[0]);
802       EXPECT_EQ(dec_px[1], orig_px[1]);
803       EXPECT_EQ(dec_px[2], orig_px[2]);
804     }
805   }
806 }
807
808 TEST(PNGCodec, DecodeInterlacedBGRA) {
809   const int w = 20, h = 20;
810
811   // create an image with known values
812   std::vector<unsigned char> original;
813   MakeRGBAImage(w, h, false, &original);
814
815   // encode
816   std::vector<unsigned char> encoded;
817   ASSERT_TRUE(EncodeImage(original,
818                           w, h,
819                           COLOR_TYPE_BGRA,
820                           &encoded,
821                           PNG_INTERLACE_ADAM7));
822
823   // decode, it should have the same size as the original
824   std::vector<unsigned char> decoded;
825   int outw, outh;
826   ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
827                                PNGCodec::FORMAT_BGRA, &decoded,
828                                &outw, &outh));
829   ASSERT_EQ(w, outw);
830   ASSERT_EQ(h, outh);
831   ASSERT_EQ(original.size(), decoded.size());
832
833   // Images must be equal
834   ASSERT_EQ(original, decoded);
835 }
836
837 // Not encoding an interlaced PNG from SkBitmap because we don't do it
838 // anywhere, and the ability to do that requires more code changes.
839 TEST(PNGCodec, DecodeInterlacedRGBtoSkBitmap) {
840   const int w = 20, h = 20;
841
842   // create an image with known values
843   std::vector<unsigned char> original;
844   MakeRGBImage(w, h, &original);
845
846   // encode
847   std::vector<unsigned char> encoded;
848   ASSERT_TRUE(EncodeImage(original,
849                           w, h,
850                           COLOR_TYPE_RGB,
851                           &encoded,
852                           PNG_INTERLACE_ADAM7));
853
854   // Decode the encoded string.
855   SkBitmap decoded_bitmap;
856   ASSERT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
857                                &decoded_bitmap));
858
859   for (int x = 0; x < w; x++) {
860     for (int y = 0; y < h; y++) {
861       const unsigned char* original_pixel = &original[(y * w + x) * 3];
862       const uint32_t original_pixel_sk = SkPackARGB32(0xFF,
863                                                       original_pixel[0],
864                                                       original_pixel[1],
865                                                       original_pixel[2]);
866       const uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
867       EXPECT_EQ(original_pixel_sk, decoded_pixel);
868     }
869   }
870 }
871
872 TEST(PNGCodec, DecodeInterlacedRGBAtoSkBitmap) {
873   const int w = 20, h = 20;
874
875   // create an image with known values
876   std::vector<unsigned char> original;
877   MakeRGBAImage(w, h, false, &original);
878
879   // encode
880   std::vector<unsigned char> encoded;
881   ASSERT_TRUE(EncodeImage(original,
882                           w, h,
883                           COLOR_TYPE_RGBA,
884                           &encoded,
885                           PNG_INTERLACE_ADAM7));
886
887   // Decode the encoded string.
888   SkBitmap decoded_bitmap;
889   ASSERT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
890                                &decoded_bitmap));
891
892   for (int x = 0; x < w; x++) {
893     for (int y = 0; y < h; y++) {
894       const unsigned char* original_pixel = &original[(y * w + x) * 4];
895       const uint32_t original_pixel_sk = SkPackARGB32(original_pixel[3],
896                                                       original_pixel[0],
897                                                       original_pixel[1],
898                                                       original_pixel[2]);
899       const uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
900       EXPECT_EQ(original_pixel_sk, decoded_pixel);
901     }
902   }
903 }
904
905 // Test that corrupted data decompression causes failures.
906 TEST(PNGCodec, DecodeCorrupted) {
907   int w = 20, h = 20;
908
909   // Make some random data (an uncompressed image).
910   std::vector<unsigned char> original;
911   MakeRGBImage(w, h, &original);
912
913   // It should fail when given non-JPEG compressed data.
914   std::vector<unsigned char> output;
915   int outw, outh;
916   EXPECT_FALSE(PNGCodec::Decode(&original[0], original.size(),
917                                 PNGCodec::FORMAT_RGB, &output,
918                                 &outw, &outh));
919
920   // Make some compressed data.
921   std::vector<unsigned char> compressed;
922   ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGB,
923                                Size(w, h), w * 3, false,
924                                std::vector<PNGCodec::Comment>(),
925                                &compressed));
926
927   // Try decompressing a truncated version.
928   EXPECT_FALSE(PNGCodec::Decode(&compressed[0], compressed.size() / 2,
929                                 PNGCodec::FORMAT_RGB, &output,
930                                 &outw, &outh));
931
932   // Corrupt it and try decompressing that.
933   for (int i = 10; i < 30; i++)
934     compressed[i] = i;
935   EXPECT_FALSE(PNGCodec::Decode(&compressed[0], compressed.size(),
936                                 PNGCodec::FORMAT_RGB, &output,
937                                 &outw, &outh));
938 }
939
940 TEST(PNGCodec, StripAddAlpha) {
941   const int w = 20, h = 20;
942
943   // These should be the same except one has a 0xff alpha channel.
944   std::vector<unsigned char> original_rgb;
945   MakeRGBImage(w, h, &original_rgb);
946   std::vector<unsigned char> original_rgba;
947   MakeRGBAImage(w, h, false, &original_rgba);
948
949   // Encode RGBA data as RGB.
950   std::vector<unsigned char> encoded;
951   EXPECT_TRUE(PNGCodec::Encode(&original_rgba[0], PNGCodec::FORMAT_RGBA,
952                                Size(w, h), w * 4, true,
953                                std::vector<PNGCodec::Comment>(),
954                                &encoded));
955
956   // Decode the RGB to RGBA.
957   std::vector<unsigned char> decoded;
958   int outw, outh;
959   EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
960                                PNGCodec::FORMAT_RGBA, &decoded,
961                                &outw, &outh));
962
963   // Decoded and reference should be the same (opaque alpha).
964   ASSERT_EQ(w, outw);
965   ASSERT_EQ(h, outh);
966   ASSERT_EQ(original_rgba.size(), decoded.size());
967   ASSERT_EQ(original_rgba, decoded);
968
969   // Encode RGBA to RGBA.
970   EXPECT_TRUE(PNGCodec::Encode(&original_rgba[0], PNGCodec::FORMAT_RGBA,
971                                Size(w, h), w * 4, false,
972                                std::vector<PNGCodec::Comment>(),
973                                &encoded));
974
975   // Decode the RGBA to RGB.
976   EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
977                                PNGCodec::FORMAT_RGB, &decoded,
978                                &outw, &outh));
979
980   // It should be the same as our non-alpha-channel reference.
981   ASSERT_EQ(w, outw);
982   ASSERT_EQ(h, outh);
983   ASSERT_EQ(original_rgb.size(), decoded.size());
984   ASSERT_EQ(original_rgb, decoded);
985 }
986
987 TEST(PNGCodec, EncodeBGRASkBitmapStridePadded) {
988   const int kWidth = 20;
989   const int kHeight = 20;
990   const int kPaddedWidth = 32;
991   const int kBytesPerPixel = 4;
992   const int kPaddedSize = kPaddedWidth * kHeight;
993   const int kRowBytes = kPaddedWidth * kBytesPerPixel;
994
995   SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
996   SkBitmap original_bitmap;
997   original_bitmap.setInfo(info, kRowBytes);
998   original_bitmap.allocPixels();
999
1000   // Write data over the source bitmap.
1001   // We write on the pad area here too.
1002   // The encoder should ignore the pad area.
1003   uint32_t* src_data = original_bitmap.getAddr32(0, 0);
1004   for (int i = 0; i < kPaddedSize; i++) {
1005     src_data[i] = SkPreMultiplyARGB(i % 255, i % 250, i % 245, i % 240);
1006   }
1007
1008   // Encode the bitmap.
1009   std::vector<unsigned char> encoded;
1010   PNGCodec::EncodeBGRASkBitmap(original_bitmap, false, &encoded);
1011
1012   // Decode the encoded string.
1013   SkBitmap decoded_bitmap;
1014   EXPECT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
1015                                &decoded_bitmap));
1016
1017   // Compare the original bitmap and the output bitmap. We use ColorsClose
1018   // as SkBitmaps are considered to be pre-multiplied, the unpremultiplication
1019   // (in Encode) and repremultiplication (in Decode) can be lossy.
1020   for (int x = 0; x < kWidth; x++) {
1021     for (int y = 0; y < kHeight; y++) {
1022       uint32_t original_pixel = original_bitmap.getAddr32(0, y)[x];
1023       uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
1024       EXPECT_TRUE(ColorsClose(original_pixel, decoded_pixel));
1025     }
1026   }
1027 }
1028
1029 TEST(PNGCodec, EncodeBGRASkBitmap) {
1030   const int w = 20, h = 20;
1031
1032   SkBitmap original_bitmap;
1033   MakeTestBGRASkBitmap(w, h, &original_bitmap);
1034
1035   // Encode the bitmap.
1036   std::vector<unsigned char> encoded;
1037   PNGCodec::EncodeBGRASkBitmap(original_bitmap, false, &encoded);
1038
1039   // Decode the encoded string.
1040   SkBitmap decoded_bitmap;
1041   EXPECT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
1042                                &decoded_bitmap));
1043
1044   // Compare the original bitmap and the output bitmap. We use ColorsClose
1045   // as SkBitmaps are considered to be pre-multiplied, the unpremultiplication
1046   // (in Encode) and repremultiplication (in Decode) can be lossy.
1047   for (int x = 0; x < w; x++) {
1048     for (int y = 0; y < h; y++) {
1049       uint32_t original_pixel = original_bitmap.getAddr32(0, y)[x];
1050       uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
1051       EXPECT_TRUE(ColorsClose(original_pixel, decoded_pixel));
1052     }
1053   }
1054 }
1055
1056 TEST(PNGCodec, EncodeA8SkBitmap) {
1057   const int w = 20, h = 20;
1058
1059   SkBitmap original_bitmap;
1060   MakeTestA8SkBitmap(w, h, &original_bitmap);
1061
1062   // Encode the bitmap.
1063   std::vector<unsigned char> encoded;
1064   EXPECT_TRUE(PNGCodec::EncodeA8SkBitmap(original_bitmap, &encoded));
1065
1066   // Decode the encoded string.
1067   SkBitmap decoded_bitmap;
1068   EXPECT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
1069                                &decoded_bitmap));
1070
1071   for (int x = 0; x < w; x++) {
1072     for (int y = 0; y < h; y++) {
1073       uint8_t original_pixel = *original_bitmap.getAddr8(x, y);
1074       uint32_t decoded_pixel = *decoded_bitmap.getAddr32(x, y);
1075       EXPECT_TRUE(BGRAGrayEqualsA8Gray(decoded_pixel, original_pixel));
1076     }
1077   }
1078 }
1079
1080 TEST(PNGCodec, EncodeBGRASkBitmapDiscardTransparency) {
1081   const int w = 20, h = 20;
1082
1083   SkBitmap original_bitmap;
1084   MakeTestBGRASkBitmap(w, h, &original_bitmap);
1085
1086   // Encode the bitmap.
1087   std::vector<unsigned char> encoded;
1088   PNGCodec::EncodeBGRASkBitmap(original_bitmap, true, &encoded);
1089
1090   // Decode the encoded string.
1091   SkBitmap decoded_bitmap;
1092   EXPECT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
1093                                &decoded_bitmap));
1094
1095   // Compare the original bitmap and the output bitmap. We need to
1096   // unpremultiply original_pixel, as the decoded bitmap doesn't have an alpha
1097   // channel.
1098   for (int x = 0; x < w; x++) {
1099     for (int y = 0; y < h; y++) {
1100       uint32_t original_pixel = original_bitmap.getAddr32(0, y)[x];
1101       uint32_t unpremultiplied =
1102           SkUnPreMultiply::PMColorToColor(original_pixel);
1103       uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
1104       uint32_t unpremultiplied_decoded =
1105           SkUnPreMultiply::PMColorToColor(decoded_pixel);
1106
1107       EXPECT_TRUE(NonAlphaColorsClose(unpremultiplied, unpremultiplied_decoded))
1108           << "Original_pixel: ("
1109           << SkColorGetR(unpremultiplied) << ", "
1110           << SkColorGetG(unpremultiplied) << ", "
1111           << SkColorGetB(unpremultiplied) << "), "
1112           << "Decoded pixel: ("
1113           << SkColorGetR(unpremultiplied_decoded) << ", "
1114           << SkColorGetG(unpremultiplied_decoded) << ", "
1115           << SkColorGetB(unpremultiplied_decoded) << ")";
1116     }
1117   }
1118 }
1119
1120 TEST(PNGCodec, EncodeWithComment) {
1121   const int w = 10, h = 10;
1122
1123   std::vector<unsigned char> original;
1124   MakeRGBImage(w, h, &original);
1125
1126   std::vector<unsigned char> encoded;
1127   std::vector<PNGCodec::Comment> comments;
1128   comments.push_back(PNGCodec::Comment("key", "text"));
1129   comments.push_back(PNGCodec::Comment("test", "something"));
1130   comments.push_back(PNGCodec::Comment("have some", "spaces in both"));
1131   EXPECT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGB,
1132                                Size(w, h), w * 3, false, comments, &encoded));
1133
1134   // Each chunk is of the form length (4 bytes), chunk type (tEXt), data,
1135   // checksum (4 bytes).  Make sure we find all of them in the encoded
1136   // results.
1137   const unsigned char kExpected1[] =
1138       "\x00\x00\x00\x08tEXtkey\x00text\x9e\xe7\x66\x51";
1139   const unsigned char kExpected2[] =
1140       "\x00\x00\x00\x0etEXttest\x00something\x29\xba\xef\xac";
1141   const unsigned char kExpected3[] =
1142       "\x00\x00\x00\x18tEXthave some\x00spaces in both\x8d\x69\x34\x2d";
1143
1144   EXPECT_NE(std::search(encoded.begin(), encoded.end(), kExpected1,
1145                         kExpected1 + arraysize(kExpected1)),
1146             encoded.end());
1147   EXPECT_NE(std::search(encoded.begin(), encoded.end(), kExpected2,
1148                         kExpected2 + arraysize(kExpected2)),
1149             encoded.end());
1150   EXPECT_NE(std::search(encoded.begin(), encoded.end(), kExpected3,
1151                         kExpected3 + arraysize(kExpected3)),
1152             encoded.end());
1153 }
1154
1155 TEST(PNGCodec, EncodeDecodeWithVaryingCompressionLevels) {
1156   const int w = 20, h = 20;
1157
1158   // create an image with known values, a must be opaque because it will be
1159   // lost during encoding
1160   SkBitmap original_bitmap;
1161   MakeTestBGRASkBitmap(w, h, &original_bitmap);
1162
1163   // encode
1164   std::vector<unsigned char> encoded_normal;
1165   EXPECT_TRUE(
1166       PNGCodec::EncodeBGRASkBitmap(original_bitmap, false, &encoded_normal));
1167
1168   std::vector<unsigned char> encoded_fast;
1169   EXPECT_TRUE(
1170       PNGCodec::FastEncodeBGRASkBitmap(original_bitmap, false, &encoded_fast));
1171
1172   // Make sure the different compression settings actually do something; the
1173   // sizes should be different.
1174   EXPECT_NE(encoded_normal.size(), encoded_fast.size());
1175
1176   // decode, they should be identical to the original.
1177   SkBitmap decoded;
1178   EXPECT_TRUE(
1179       PNGCodec::Decode(&encoded_normal[0], encoded_normal.size(), &decoded));
1180   EXPECT_TRUE(BitmapsAreEqual(decoded, original_bitmap));
1181
1182   EXPECT_TRUE(
1183       PNGCodec::Decode(&encoded_fast[0], encoded_fast.size(), &decoded));
1184   EXPECT_TRUE(BitmapsAreEqual(decoded, original_bitmap));
1185 }
1186
1187
1188 }  // namespace gfx