Remove WebKitTestRunner::setClientWindowRect.
[chromium-blink-merge.git] / ui / gfx / codec / png_codec_unittest.cc
blobf1654d9d363bfbf15a5594c6ea3cfa9b66067a2e
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.
5 #include <algorithm>
6 #include <cmath>
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"
19 namespace gfx {
21 namespace {
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
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)
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;
69 for (int y = 0; y < h; y++) {
70 for (int x = 0; x < w; x++) {
71 (*data)[y * w + x] = x; // palette index
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;
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
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
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);
117 // User flush function; goes with WriteImageData, above.
118 void FlushImageData(png_structp /*png_ptr*/) {
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);
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;
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
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);
160 int input_rowbytes = 0;
161 int transforms = PNG_TRANSFORM_IDENTITY;
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;
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;
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]);
208 if (setjmp(png_jmpbuf(png_ptr))) {
209 png_destroy_write_struct(&png_ptr, &info_ptr);
210 return false;
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);
228 png_write_png(png_ptr, info_ptr, transforms, NULL);
230 png_destroy_write_struct(&png_ptr, &info_ptr);
231 return true;
234 } // namespace
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;
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;
252 void MakeTestSkBitmap(int w, int h, SkBitmap* bmp) {
253 bmp->setConfig(SkBitmap::kARGB_8888_Config, w, h);
254 bmp->allocPixels();
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);
262 TEST(PNGCodec, EncodeDecodeRGB) {
263 const int w = 20, h = 20;
265 // create an image with known values
266 std::vector<unsigned char> original;
267 MakeRGBImage(w, h, &original);
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));
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());
286 // Images must be equal
287 ASSERT_TRUE(original == decoded);
290 TEST(PNGCodec, EncodeDecodeRGBA) {
291 const int w = 20, h = 20;
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);
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));
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());
315 // Images must be exactly equal
316 ASSERT_TRUE(original == decoded);
319 TEST(PNGCodec, EncodeDecodeBGRA) {
320 const int w = 20, h = 20;
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);
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));
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());
344 // Images must be exactly equal.
345 ASSERT_TRUE(original == decoded);
348 TEST(PNGCodec, DecodePalette) {
349 const int w = 20, h = 20;
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);
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));
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);
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];
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]);
393 TEST(PNGCodec, DecodePaletteDiscardAlpha) {
394 const int w = 20, h = 20;
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);
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));
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);
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];
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]);
436 TEST(PNGCodec, DecodeInterlacedPalette) {
437 const int w = 20, h = 20;
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);
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));
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);
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];
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]);
481 TEST(PNGCodec, DecodeGrayscale) {
482 const int w = 20, h = 20;
484 // create an image with known values
485 std::vector<unsigned char> original;
486 MakeGrayscaleImage(w, h, &original);
488 // encode
489 std::vector<unsigned char> encoded;
490 ASSERT_TRUE(EncodeImage(original, w, h, COLOR_TYPE_GRAY, &encoded));
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);
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);
514 TEST(PNGCodec, DecodeGrayscaleWithAlpha) {
515 const int w = 20, h = 20;
517 // create an image with known values
518 std::vector<unsigned char> original;
519 MakeGrayscaleAlphaImage(w, h, &original);
521 // encode
522 std::vector<unsigned char> encoded;
523 ASSERT_TRUE(EncodeImage(original,
524 w, h,
525 COLOR_TYPE_GRAY_ALPHA,
526 &encoded));
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);
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]);
551 TEST(PNGCodec, DecodeGrayscaleWithAlphaDiscardAlpha) {
552 const int w = 20, h = 20;
554 // create an image with known values
555 std::vector<unsigned char> original;
556 MakeGrayscaleAlphaImage(w, h, &original);
558 // encode
559 std::vector<unsigned char> encoded;
560 ASSERT_TRUE(EncodeImage(original,
561 w, h,
562 COLOR_TYPE_GRAY_ALPHA,
563 &encoded));
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);
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]);
587 TEST(PNGCodec, DecodeInterlacedGrayscale) {
588 const int w = 20, h = 20;
590 // create an image with known values
591 std::vector<unsigned char> original;
592 MakeGrayscaleImage(w, h, &original);
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));
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);
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);
625 TEST(PNGCodec, DecodeInterlacedGrayscaleWithAlpha) {
626 const int w = 20, h = 20;
628 // create an image with known values
629 std::vector<unsigned char> original;
630 MakeGrayscaleAlphaImage(w, h, &original);
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));
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);
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]);
663 TEST(PNGCodec, DecodeInterlacedRGB) {
664 const int w = 20, h = 20;
666 // create an image with known values
667 std::vector<unsigned char> original;
668 MakeRGBImage(w, h, &original);
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));
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());
688 // Images must be equal
689 ASSERT_EQ(original, decoded);
692 TEST(PNGCodec, DecodeInterlacedRGBA) {
693 const int w = 20, h = 20;
695 // create an image with known values
696 std::vector<unsigned char> original;
697 MakeRGBAImage(w, h, false, &original);
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));
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());
717 // Images must be equal
718 ASSERT_EQ(original, decoded);
721 TEST(PNGCodec, DecodeInterlacedRGBADiscardAlpha) {
722 const int w = 20, h = 20;
724 // create an image with known values
725 std::vector<unsigned char> original;
726 MakeRGBAImage(w, h, false, &original);
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));
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);
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]);
758 TEST(PNGCodec, DecodeInterlacedBGR) {
759 const int w = 20, h = 20;
761 // create an image with known values
762 std::vector<unsigned char> original;
763 MakeRGBImage(w, h, &original);
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));
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);
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]);
795 TEST(PNGCodec, DecodeInterlacedBGRA) {
796 const int w = 20, h = 20;
798 // create an image with known values
799 std::vector<unsigned char> original;
800 MakeRGBAImage(w, h, false, &original);
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));
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());
820 // Images must be equal
821 ASSERT_EQ(original, decoded);
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;
829 // create an image with known values
830 std::vector<unsigned char> original;
831 MakeRGBImage(w, h, &original);
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));
841 // Decode the encoded string.
842 SkBitmap decoded_bitmap;
843 ASSERT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
844 &decoded_bitmap));
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);
859 TEST(PNGCodec, DecodeInterlacedRGBAtoSkBitmap) {
860 const int w = 20, h = 20;
862 // create an image with known values
863 std::vector<unsigned char> original;
864 MakeRGBAImage(w, h, false, &original);
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));
874 // Decode the encoded string.
875 SkBitmap decoded_bitmap;
876 ASSERT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
877 &decoded_bitmap));
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);
892 // Test that corrupted data decompression causes failures.
893 TEST(PNGCodec, DecodeCorrupted) {
894 int w = 20, h = 20;
896 // Make some random data (an uncompressed image).
897 std::vector<unsigned char> original;
898 MakeRGBImage(w, h, &original);
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));
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));
914 // Try decompressing a truncated version.
915 EXPECT_FALSE(PNGCodec::Decode(&compressed[0], compressed.size() / 2,
916 PNGCodec::FORMAT_RGB, &output,
917 &outw, &outh));
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));
927 TEST(PNGCodec, StripAddAlpha) {
928 const int w = 20, h = 20;
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);
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));
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));
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);
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));
962 // Decode the RGBA to RGB.
963 EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
964 PNGCodec::FORMAT_RGB, &decoded,
965 &outw, &outh));
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);
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;
982 SkBitmap original_bitmap;
983 original_bitmap.setConfig(SkBitmap::kARGB_8888_Config,
984 kWidth, kHeight, kRowBytes);
985 original_bitmap.allocPixels();
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);
995 // Encode the bitmap.
996 std::vector<unsigned char> encoded;
997 PNGCodec::EncodeBGRASkBitmap(original_bitmap, false, &encoded);
999 // Decode the encoded string.
1000 SkBitmap decoded_bitmap;
1001 EXPECT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
1002 &decoded_bitmap));
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));
1016 TEST(PNGCodec, EncodeBGRASkBitmap) {
1017 const int w = 20, h = 20;
1019 SkBitmap original_bitmap;
1020 MakeTestSkBitmap(w, h, &original_bitmap);
1022 // Encode the bitmap.
1023 std::vector<unsigned char> encoded;
1024 PNGCodec::EncodeBGRASkBitmap(original_bitmap, false, &encoded);
1026 // Decode the encoded string.
1027 SkBitmap decoded_bitmap;
1028 EXPECT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
1029 &decoded_bitmap));
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));
1043 TEST(PNGCodec, EncodeBGRASkBitmapDiscardTransparency) {
1044 const int w = 20, h = 20;
1046 SkBitmap original_bitmap;
1047 MakeTestSkBitmap(w, h, &original_bitmap);
1049 // Encode the bitmap.
1050 std::vector<unsigned char> encoded;
1051 PNGCodec::EncodeBGRASkBitmap(original_bitmap, true, &encoded);
1053 // Decode the encoded string.
1054 SkBitmap decoded_bitmap;
1055 EXPECT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
1056 &decoded_bitmap));
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);
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) << ")";
1083 TEST(PNGCodec, EncodeWithComment) {
1084 const int w = 10, h = 10;
1086 std::vector<unsigned char> original;
1087 MakeRGBImage(w, h, &original);
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));
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";
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());
1118 TEST(PNGCodec, EncodeDecodeWithVaryingCompressionLevels) {
1119 const int w = 20, h = 20;
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);
1126 // encode
1127 std::vector<unsigned char> encoded_normal;
1128 EXPECT_TRUE(
1129 PNGCodec::EncodeBGRASkBitmap(original_bitmap, false, &encoded_normal));
1131 std::vector<unsigned char> encoded_fast;
1132 EXPECT_TRUE(
1133 PNGCodec::FastEncodeBGRASkBitmap(original_bitmap, false, &encoded_fast));
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());
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));
1145 EXPECT_TRUE(
1146 PNGCodec::Decode(&encoded_fast[0], encoded_fast.size(), &decoded));
1147 EXPECT_TRUE(BitmapsAreEqual(decoded, original_bitmap));
1151 } // namespace gfx