Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Side by Side Diff: ui/gfx/codec/png_codec_unittest.cc

Issue 9496004: Support for interlaced PNGs (in gfx::PNGCodec) (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if defined(USE_SYSTEM_LIBPNG)
6 #include <png.h>
7 #else
8 #include "third_party/libpng/png.h"
9 #endif
Francois 2012/02/28 15:00:36 Required in order to encode interlaced, palette-ba
10
5 #include <algorithm> 11 #include <algorithm>
6 #include <cmath> 12 #include <cmath>
7 13
14 #include "base/logging.h"
8 #include "testing/gtest/include/gtest/gtest.h" 15 #include "testing/gtest/include/gtest/gtest.h"
9 #include "third_party/skia/include/core/SkBitmap.h" 16 #include "third_party/skia/include/core/SkBitmap.h"
17 #include "third_party/skia/include/core/SkColorPriv.h"
10 #include "third_party/skia/include/core/SkUnPreMultiply.h" 18 #include "third_party/skia/include/core/SkUnPreMultiply.h"
11 #include "third_party/zlib/zlib.h" 19 #include "third_party/zlib/zlib.h"
12 #include "ui/gfx/codec/png_codec.h" 20 #include "ui/gfx/codec/png_codec.h"
13 #include "ui/gfx/size.h" 21 #include "ui/gfx/size.h"
14 22
15 namespace gfx { 23 namespace gfx {
16 24
17 static void MakeRGBImage(int w, int h, std::vector<unsigned char>* dat) { 25 namespace {
26
27 void MakeRGBImage(int w, int h, std::vector<unsigned char>* dat) {
18 dat->resize(w * h * 3); 28 dat->resize(w * h * 3);
19 for (int y = 0; y < h; y++) { 29 for (int y = 0; y < h; y++) {
20 for (int x = 0; x < w; x++) { 30 for (int x = 0; x < w; x++) {
21 unsigned char* org_px = &(*dat)[(y * w + x) * 3]; 31 unsigned char* org_px = &(*dat)[(y * w + x) * 3];
22 org_px[0] = x * 3; // r 32 org_px[0] = x * 3; // r
23 org_px[1] = x * 3 + 1; // g 33 org_px[1] = x * 3 + 1; // g
24 org_px[2] = x * 3 + 2; // b 34 org_px[2] = x * 3 + 2; // b
25 } 35 }
26 } 36 }
27 } 37 }
28 38
29 // Set use_transparency to write data into the alpha channel, otherwise it will 39 // Set use_transparency to write data into the alpha channel, otherwise it will
30 // be filled with 0xff. With the alpha channel stripped, this should yield the 40 // be filled with 0xff. With the alpha channel stripped, this should yield the
31 // same image as MakeRGBImage above, so the code below can make reference 41 // same image as MakeRGBImage above, so the code below can make reference
32 // images for conversion testing. 42 // images for conversion testing.
33 static void MakeRGBAImage(int w, int h, bool use_transparency, 43 void MakeRGBAImage(int w, int h, bool use_transparency,
34 std::vector<unsigned char>* dat) { 44 std::vector<unsigned char>* dat) {
35 dat->resize(w * h * 4); 45 dat->resize(w * h * 4);
36 for (int y = 0; y < h; y++) { 46 for (int y = 0; y < h; y++) {
37 for (int x = 0; x < w; x++) { 47 for (int x = 0; x < w; x++) {
38 unsigned char* org_px = &(*dat)[(y * w + x) * 4]; 48 unsigned char* org_px = &(*dat)[(y * w + x) * 4];
39 org_px[0] = x * 3; // r 49 org_px[0] = x * 3; // r
40 org_px[1] = x * 3 + 1; // g 50 org_px[1] = x * 3 + 1; // g
41 org_px[2] = x * 3 + 2; // b 51 org_px[2] = x * 3 + 2; // b
42 if (use_transparency) 52 if (use_transparency)
43 org_px[3] = x*3 + 3; // a 53 org_px[3] = x*3 + 3; // a
44 else 54 else
45 org_px[3] = 0xFF; // a (opaque) 55 org_px[3] = 0xFF; // a (opaque)
46 } 56 }
47 } 57 }
48 } 58 }
49 59
60 // Creates a palette-based image.
61 void MakePaletteImage(int w, int h,
62 std::vector<unsigned char>* dat,
63 std::vector<png_color>* palette,
64 std::vector<unsigned char>* trans_chunk = 0) {
65 dat->resize(w * h);
66 palette->resize(w);
67 for (int i = 0; i < w; ++i) {
68 png_color& color = (*palette)[i];
69 color.red = i * 3;
70 color.green = color.red + 1;
71 color.blue = color.red + 2;
72 }
73 for (int y = 0; y < h; y++) {
74 for (int x = 0; x < w; x++) {
75 (*dat)[y * w + x] = x; // palette index
76 }
77 }
78 if (trans_chunk) {
79 trans_chunk->resize(palette->size());
80 for (std::size_t i = 0; i < trans_chunk->size(); ++i) {
81 (*trans_chunk)[i] = i % 256;
82 }
83 }
84 }
85
86 // Creates a grayscale image without an alpha channel.
87 void MakeGrayscaleImage(int w, int h,
88 std::vector<unsigned char>* dat) {
89 dat->resize(w * h);
90 for (int y = 0; y < h; y++) {
91 for (int x = 0; x < w; x++) {
92 (*dat)[y * w + x] = x; // gray value
93 }
94 }
95 }
96
97 // Creates a grayscale image with an alpha channel.
98 void MakeGrayscaleAlphaImage(int w, int h,
99 std::vector<unsigned char>* dat) {
100 dat->resize(w * h * 2);
101 for (int y = 0; y < h; y++) {
102 for (int x = 0; x < w; x++) {
103 unsigned char* px = &(*dat)[(y * w + x) * 2];
104 px[0] = x; // gray value
105 px[1] = x % 256; // alpha
106 }
107 }
108 }
109
110 // User write function (to be passed to libpng by EncodeImage) which writes
111 // into a buffer instead of to a file.
112 void WriteImageData(png_structp png_ptr,
113 png_bytep data,
114 png_size_t length) {
115 std::vector<unsigned char>& v =
116 *static_cast<std::vector<unsigned char>*>(png_get_io_ptr(png_ptr));
117 v.resize(v.size() + length);
118 memcpy(&v[v.size() - length], data, length);
119 }
120
121 // User flush function; goes with WriteImageData, above.
122 void FlushImageData(png_structp) {}
Francois 2012/02/28 15:00:36 Will change this to void FlushImageData(png_struct
Francois 2012/02/29 09:12:29 Done.
123
124 // Libpng user error function which allows us to print libpng errors using
125 // Chrome's logging facilities instead of stderr.
126 void LogLibPNGError(png_structp png_ptr,
127 png_const_charp error_msg) {
128 DLOG(ERROR) << "libpng encode error: " << error_msg;
129 longjmp(png_jmpbuf(png_ptr), 1);
130 }
131
132 // Goes with LogLibPNGError, above.
133 void LogLibPNGWarning(png_structp png_ptr,
134 png_const_charp warning_msg) {
135 DLOG(ERROR) << "libpng encode warning: " << warning_msg;
136 }
137
138 // Color types supported by EncodeImage. Required because neither libpng nor
139 // PNGCodec::Encode supports all of the required values.
140 enum ColorType {
141 COLOR_TYPE_GRAY = PNG_COLOR_TYPE_GRAY,
142 COLOR_TYPE_GRAY_ALPHA = PNG_COLOR_TYPE_GRAY_ALPHA,
143 COLOR_TYPE_PALETTE = PNG_COLOR_TYPE_PALETTE,
144 COLOR_TYPE_RGB = PNG_COLOR_TYPE_RGB,
145 COLOR_TYPE_RGBA = PNG_COLOR_TYPE_RGBA,
146 COLOR_TYPE_BGR,
147 COLOR_TYPE_BGRA
148 };
149
150 // PNG encoder used for testing. Required because PNGCodec::Encode doesn't do
151 // interlaced, palette-based, or grayscale images, but PNGCodec::Decode is
152 // actually asked to decode these types of images by Chrome.
153 bool EncodeImage(const std::vector<unsigned char>& input,
154 const int width,
155 const int height,
156 ColorType output_color_type,
157 std::vector<unsigned char>* output,
158 const int interlace_type = PNG_INTERLACE_NONE,
159 std::vector<png_color>* palette = 0,
160 std::vector<unsigned char>* palette_alpha = 0) {
161 struct ScopedPNGStructs {
162 ScopedPNGStructs(png_struct** s, png_info** i) : s_(s), i_(i) {}
163 ~ScopedPNGStructs() { png_destroy_write_struct(s_, i_); }
164 png_struct** s_;
165 png_info** i_;
166 };
167
168 DCHECK(output);
169 png_struct* png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
170 NULL, NULL, NULL);
171 if (!png_ptr) return false;
172
173 png_infop info_ptr = png_create_info_struct(png_ptr);
174 if (!info_ptr) {
175 png_destroy_write_struct(&png_ptr, NULL);
176 return false;
177 }
178
179 ScopedPNGStructs scoped_png_structs(&png_ptr, &info_ptr);
180
181 if (setjmp(png_jmpbuf(png_ptr)))
182 return false;
183
184 png_set_error_fn(png_ptr, NULL, LogLibPNGError, LogLibPNGWarning);
185
186 int input_rowbytes = 0;
187 int transforms = PNG_TRANSFORM_IDENTITY;
188
189 switch (output_color_type) {
190 case COLOR_TYPE_GRAY:
191 input_rowbytes = width;
192 break;
193 case COLOR_TYPE_GRAY_ALPHA:
194 input_rowbytes = width * 2;
195 break;
196 case COLOR_TYPE_PALETTE:
197 if (!palette) return false;
198 input_rowbytes = width;
199 break;
200 case COLOR_TYPE_RGB:
201 input_rowbytes = width * 3;
202 break;
203 case COLOR_TYPE_RGBA:
204 input_rowbytes = width * 4;
205 break;
206 case COLOR_TYPE_BGRA:
207 input_rowbytes = width * 4;
208 output_color_type = static_cast<ColorType>(PNG_COLOR_TYPE_RGBA);
209 transforms |= PNG_TRANSFORM_BGR;
210 break;
211 default:
212 return false;
213 break;
214 };
215
216 std::vector<png_bytep> row_pointers(height);
217 for (int y = 0 ; y < height; y++) {
218 row_pointers[y] = const_cast<unsigned char*>(&input[y * input_rowbytes]);
219 }
220 png_set_rows(png_ptr, info_ptr, &row_pointers[0]);
221 png_set_write_fn(png_ptr, output, WriteImageData, FlushImageData);
222 png_set_IHDR(png_ptr, info_ptr, width, height, 8, output_color_type,
223 interlace_type, PNG_COMPRESSION_TYPE_DEFAULT,
224 PNG_FILTER_TYPE_DEFAULT);
225 if (output_color_type == COLOR_TYPE_PALETTE) {
226 png_set_PLTE(png_ptr, info_ptr, &palette->front(), palette->size());
227 if (palette_alpha)
228 png_set_tRNS(png_ptr,
229 info_ptr,
230 &palette_alpha->front(),
231 palette_alpha->size(),
232 NULL);
233 }
234
235 png_write_png(png_ptr, info_ptr, transforms, NULL);
236
237 return true;
238 }
239
240 } // namespace
241
50 // Returns true if each channel of the given two colors are "close." This is 242 // Returns true if each channel of the given two colors are "close." This is
51 // used for comparing colors where rounding errors may cause off-by-one. 243 // used for comparing colors where rounding errors may cause off-by-one.
52 bool ColorsClose(uint32_t a, uint32_t b) { 244 bool ColorsClose(uint32_t a, uint32_t b) {
53 return abs(static_cast<int>(SkColorGetB(a) - SkColorGetB(b))) < 2 && 245 return abs(static_cast<int>(SkColorGetB(a) - SkColorGetB(b))) < 2 &&
54 abs(static_cast<int>(SkColorGetG(a) - SkColorGetG(b))) < 2 && 246 abs(static_cast<int>(SkColorGetG(a) - SkColorGetG(b))) < 2 &&
55 abs(static_cast<int>(SkColorGetR(a) - SkColorGetR(b))) < 2 && 247 abs(static_cast<int>(SkColorGetR(a) - SkColorGetR(b))) < 2 &&
56 abs(static_cast<int>(SkColorGetA(a) - SkColorGetA(b))) < 2; 248 abs(static_cast<int>(SkColorGetA(a) - SkColorGetA(b))) < 2;
57 } 249 }
58 250
59 // Returns true if the RGB components are "close." 251 // Returns true if the RGB components are "close."
(...skipping 15 matching lines...) Expand all
75 267
76 TEST(PNGCodec, EncodeDecodeRGB) { 268 TEST(PNGCodec, EncodeDecodeRGB) {
77 const int w = 20, h = 20; 269 const int w = 20, h = 20;
78 270
79 // create an image with known values 271 // create an image with known values
80 std::vector<unsigned char> original; 272 std::vector<unsigned char> original;
81 MakeRGBImage(w, h, &original); 273 MakeRGBImage(w, h, &original);
82 274
83 // encode 275 // encode
84 std::vector<unsigned char> encoded; 276 std::vector<unsigned char> encoded;
85 EXPECT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGB, 277 ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGB,
86 Size(w, h), w * 3, false, 278 Size(w, h), w * 3, false,
87 std::vector<PNGCodec::Comment>(), 279 std::vector<PNGCodec::Comment>(),
88 &encoded)); 280 &encoded));
89 281
90 // decode, it should have the same size as the original 282 // decode, it should have the same size as the original
91 std::vector<unsigned char> decoded; 283 std::vector<unsigned char> decoded;
92 int outw, outh; 284 int outw, outh;
93 EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(), 285 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
94 PNGCodec::FORMAT_RGB, &decoded, 286 PNGCodec::FORMAT_RGB, &decoded,
95 &outw, &outh)); 287 &outw, &outh));
96 ASSERT_EQ(w, outw); 288 ASSERT_EQ(w, outw);
97 ASSERT_EQ(h, outh); 289 ASSERT_EQ(h, outh);
98 ASSERT_EQ(original.size(), decoded.size()); 290 ASSERT_EQ(original.size(), decoded.size());
99 291
100 // Images must be equal 292 // Images must be equal
101 ASSERT_TRUE(original == decoded); 293 ASSERT_TRUE(original == decoded);
102 } 294 }
103 295
104 TEST(PNGCodec, EncodeDecodeRGBA) { 296 TEST(PNGCodec, EncodeDecodeRGBA) {
105 const int w = 20, h = 20; 297 const int w = 20, h = 20;
106 298
107 // create an image with known values, a must be opaque because it will be 299 // create an image with known values, a must be opaque because it will be
108 // lost during encoding 300 // lost during encoding
109 std::vector<unsigned char> original; 301 std::vector<unsigned char> original;
110 MakeRGBAImage(w, h, true, &original); 302 MakeRGBAImage(w, h, true, &original);
111 303
112 // encode 304 // encode
113 std::vector<unsigned char> encoded; 305 std::vector<unsigned char> encoded;
114 EXPECT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGBA, 306 ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGBA,
115 Size(w, h), w * 4, false, 307 Size(w, h), w * 4, false,
116 std::vector<PNGCodec::Comment>(), 308 std::vector<PNGCodec::Comment>(),
117 &encoded)); 309 &encoded));
118 310
119 // decode, it should have the same size as the original 311 // decode, it should have the same size as the original
120 std::vector<unsigned char> decoded; 312 std::vector<unsigned char> decoded;
121 int outw, outh; 313 int outw, outh;
122 EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(), 314 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
123 PNGCodec::FORMAT_RGBA, &decoded, 315 PNGCodec::FORMAT_RGBA, &decoded,
124 &outw, &outh)); 316 &outw, &outh));
125 ASSERT_EQ(w, outw); 317 ASSERT_EQ(w, outw);
126 ASSERT_EQ(h, outh); 318 ASSERT_EQ(h, outh);
127 ASSERT_EQ(original.size(), decoded.size()); 319 ASSERT_EQ(original.size(), decoded.size());
128 320
129 // Images must be exactly equal 321 // Images must be exactly equal
130 ASSERT_TRUE(original == decoded); 322 ASSERT_TRUE(original == decoded);
131 } 323 }
132 324
325 TEST(PNGCodec, EncodeDecodeBGRA) {
326 const int w = 20, h = 20;
327
328 // Create an image with known values, alpha must be opaque because it will be
329 // lost during encoding.
330 std::vector<unsigned char> original;
331 MakeRGBAImage(w, h, true, &original);
332
333 // Encode.
334 std::vector<unsigned char> encoded;
335 ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_BGRA,
336 Size(w, h), w * 4, false,
337 std::vector<PNGCodec::Comment>(),
338 &encoded));
339
340 // Decode, it should have the same size as the original.
341 std::vector<unsigned char> decoded;
342 int outw, outh;
343 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
344 PNGCodec::FORMAT_BGRA, &decoded,
345 &outw, &outh));
346 ASSERT_EQ(w, outw);
347 ASSERT_EQ(h, outh);
348 ASSERT_EQ(original.size(), decoded.size());
349
350 // Images must be exactly equal.
351 ASSERT_TRUE(original == decoded);
352 }
Francois 2012/02/28 15:00:36 Old code moved from further down.
353
354 TEST(PNGCodec, DecodePalette) {
355 const int w = 20, h = 20;
356
357 // create an image with known values
358 std::vector<unsigned char> original;
359 std::vector<png_color> original_palette;
360 std::vector<unsigned char> original_trans_chunk;
361 MakePaletteImage(w, h, &original, &original_palette, &original_trans_chunk);
362
363 // encode
364 std::vector<unsigned char> encoded;
365 ASSERT_TRUE(EncodeImage(original,
366 w, h,
367 COLOR_TYPE_PALETTE,
368 &encoded,
369 PNG_INTERLACE_NONE,
370 &original_palette,
371 &original_trans_chunk));
372
373 // decode
374 std::vector<unsigned char> decoded;
375 int outw, outh;
376 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
377 PNGCodec::FORMAT_RGBA, &decoded,
378 &outw, &outh));
379 ASSERT_EQ(w, outw);
380 ASSERT_EQ(h, outh);
381 ASSERT_EQ(decoded.size(), w * h * 4U);
382
383 // Images must be equal
384 for (int y = 0; y < h; ++y) {
385 for (int x = 0; x < w; ++x) {
386 unsigned char palette_pixel = original[y * w + x];
387 png_color& palette_color = original_palette[palette_pixel];
388 int alpha = original_trans_chunk[palette_pixel];
389 unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
390
391 ASSERT_EQ(palette_color.red, rgba_pixel[0]);
392 ASSERT_EQ(palette_color.green, rgba_pixel[1]);
393 ASSERT_EQ(palette_color.blue, rgba_pixel[2]);
394 ASSERT_EQ(alpha, rgba_pixel[3]);
395 }
396 }
397 }
398
399 TEST(PNGCodec, DecodePaletteDiscardAlpha) {
400 const int w = 20, h = 20;
401
402 // create an image with known values
403 std::vector<unsigned char> original;
404 std::vector<png_color> original_palette;
405 std::vector<unsigned char> original_trans_chunk;
406 MakePaletteImage(w, h, &original, &original_palette, &original_trans_chunk);
407
408 // encode
409 std::vector<unsigned char> encoded;
410 ASSERT_TRUE(EncodeImage(original,
411 w, h,
412 COLOR_TYPE_PALETTE,
413 &encoded,
414 PNG_INTERLACE_NONE,
415 &original_palette,
416 &original_trans_chunk));
417
418 // decode
419 std::vector<unsigned char> decoded;
420 int outw, outh;
421 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
422 PNGCodec::FORMAT_RGB, &decoded,
423 &outw, &outh));
424 ASSERT_EQ(w, outw);
425 ASSERT_EQ(h, outh);
426 ASSERT_EQ(decoded.size(), w * h * 3U);
427
428 // Images must be equal
429 for (int y = 0; y < h; ++y) {
430 for (int x = 0; x < w; ++x) {
431 unsigned char palette_pixel = original[y * w + x];
432 png_color& palette_color = original_palette[palette_pixel];
433 unsigned char* rgba_pixel = &decoded[(y * w + x) * 3];
434
435 ASSERT_EQ(palette_color.red, rgba_pixel[0]);
436 ASSERT_EQ(palette_color.green, rgba_pixel[1]);
437 ASSERT_EQ(palette_color.blue, rgba_pixel[2]);
438 }
439 }
440 }
441
442 TEST(PNGCodec, DecodeInterlacedPalette) {
443 const int w = 20, h = 20;
444
445 // create an image with known values
446 std::vector<unsigned char> original;
447 std::vector<png_color> original_palette;
448 std::vector<unsigned char> original_trans_chunk;
449 MakePaletteImage(w, h, &original, &original_palette, &original_trans_chunk);
450
451 // encode
452 std::vector<unsigned char> encoded;
453 ASSERT_TRUE(EncodeImage(original,
454 w, h,
455 COLOR_TYPE_PALETTE,
456 &encoded,
457 PNG_INTERLACE_ADAM7,
458 &original_palette,
459 &original_trans_chunk));
460
461 // decode
462 std::vector<unsigned char> decoded;
463 int outw, outh;
464 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
465 PNGCodec::FORMAT_RGBA, &decoded,
466 &outw, &outh));
467 ASSERT_EQ(w, outw);
468 ASSERT_EQ(h, outh);
469 ASSERT_EQ(decoded.size(), w * h * 4U);
470
471 // Images must be equal
472 for (int y = 0; y < h; ++y) {
473 for (int x = 0; x < w; ++x) {
474 unsigned char palette_pixel = original[y * w + x];
475 png_color& palette_color = original_palette[palette_pixel];
476 int alpha = original_trans_chunk[palette_pixel];
477 unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
478
479 ASSERT_EQ(palette_color.red, rgba_pixel[0]);
480 ASSERT_EQ(palette_color.green, rgba_pixel[1]);
481 ASSERT_EQ(palette_color.blue, rgba_pixel[2]);
482 ASSERT_EQ(alpha, rgba_pixel[3]);
483 }
484 }
485 }
486
487 TEST(PNGCodec, DecodeGrayscale) {
488 const int w = 20, h = 20;
489
490 // create an image with known values
491 std::vector<unsigned char> original;
492 MakeGrayscaleImage(w, h, &original);
493
494 // encode
495 std::vector<unsigned char> encoded;
496 ASSERT_TRUE(EncodeImage(original, w, h, COLOR_TYPE_GRAY, &encoded));
497
498 // decode
499 std::vector<unsigned char> decoded;
500 int outw, outh;
501 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
502 PNGCodec::FORMAT_RGB, &decoded,
503 &outw, &outh));
504 ASSERT_EQ(w, outw);
505 ASSERT_EQ(h, outh);
506 ASSERT_EQ(decoded.size(), original.size() * 3);
507
508 // Images must be equal
509 for (int y = 0; y < h; ++y) {
510 for (int x = 0; x < w; ++x) {
511 unsigned char gray_pixel = original[(y * w + x)];
512 unsigned char* rgba_pixel = &decoded[(y * w + x) * 3];
513 ASSERT_EQ(rgba_pixel[0], gray_pixel);
514 ASSERT_EQ(rgba_pixel[1], gray_pixel);
515 ASSERT_EQ(rgba_pixel[2], gray_pixel);
516 }
517 }
518 }
519
520 TEST(PNGCodec, DecodeGrayscaleWithAlpha) {
521 const int w = 20, h = 20;
522
523 // create an image with known values
524 std::vector<unsigned char> original;
525 MakeGrayscaleAlphaImage(w, h, &original);
526
527 // encode
528 std::vector<unsigned char> encoded;
529 ASSERT_TRUE(EncodeImage(original,
530 w, h,
531 COLOR_TYPE_GRAY_ALPHA,
532 &encoded));
533
534 // decode
535 std::vector<unsigned char> decoded;
536 int outw, outh;
537 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
538 PNGCodec::FORMAT_RGBA, &decoded,
539 &outw, &outh));
540 ASSERT_EQ(w, outw);
541 ASSERT_EQ(h, outh);
542 ASSERT_EQ(decoded.size(), original.size() * 2);
543
544 // Images must be equal
545 for (int y = 0; y < h; ++y) {
546 for (int x = 0; x < w; ++x) {
547 unsigned char* gray_pixel = &original[(y * w + x) * 2];
548 unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
549 ASSERT_EQ(rgba_pixel[0], gray_pixel[0]);
550 ASSERT_EQ(rgba_pixel[1], gray_pixel[0]);
551 ASSERT_EQ(rgba_pixel[2], gray_pixel[0]);
552 ASSERT_EQ(rgba_pixel[3], gray_pixel[1]);
553 }
554 }
555 }
556
557 TEST(PNGCodec, DecodeGrayscaleWithAlphaDiscardAlpha) {
558 const int w = 20, h = 20;
559
560 // create an image with known values
561 std::vector<unsigned char> original;
562 MakeGrayscaleAlphaImage(w, h, &original);
563
564 // encode
565 std::vector<unsigned char> encoded;
566 ASSERT_TRUE(EncodeImage(original,
567 w, h,
568 COLOR_TYPE_GRAY_ALPHA,
569 &encoded));
570
571 // decode
572 std::vector<unsigned char> decoded;
573 int outw, outh;
574 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
575 PNGCodec::FORMAT_RGB, &decoded,
576 &outw, &outh));
577 ASSERT_EQ(w, outw);
578 ASSERT_EQ(h, outh);
579 ASSERT_EQ(decoded.size(), w * h * 3U);
580
581 // Images must be equal
582 for (int y = 0; y < h; ++y) {
583 for (int x = 0; x < w; ++x) {
584 unsigned char* gray_pixel = &original[(y * w + x) * 2];
585 unsigned char* rgba_pixel = &decoded[(y * w + x) * 3];
586 ASSERT_EQ(rgba_pixel[0], gray_pixel[0]);
587 ASSERT_EQ(rgba_pixel[1], gray_pixel[0]);
588 ASSERT_EQ(rgba_pixel[2], gray_pixel[0]);
589 }
590 }
591 }
592
593 TEST(PNGCodec, DecodeInterlacedGrayscale) {
594 const int w = 20, h = 20;
595
596 // create an image with known values
597 std::vector<unsigned char> original;
598 MakeGrayscaleImage(w, h, &original);
599
600 // encode
601 std::vector<unsigned char> encoded;
602 ASSERT_TRUE(EncodeImage(original,
603 w, h,
604 COLOR_TYPE_GRAY,
605 &encoded,
606 PNG_INTERLACE_ADAM7));
607
608 // decode
609 std::vector<unsigned char> decoded;
610 int outw, outh;
611 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
612 PNGCodec::FORMAT_RGBA, &decoded,
613 &outw, &outh));
614 ASSERT_EQ(w, outw);
615 ASSERT_EQ(h, outh);
616 ASSERT_EQ(decoded.size(), original.size() * 4);
617
618 // Images must be equal
619 for (int y = 0; y < h; ++y) {
620 for (int x = 0; x < w; ++x) {
621 unsigned char gray_pixel = original[(y * w + x)];
622 unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
623 ASSERT_EQ(rgba_pixel[0], gray_pixel);
624 ASSERT_EQ(rgba_pixel[1], gray_pixel);
625 ASSERT_EQ(rgba_pixel[2], gray_pixel);
626 ASSERT_EQ(rgba_pixel[3], 0xFF);
627 }
628 }
629 }
630
631 TEST(PNGCodec, DecodeInterlacedGrayscaleWithAlpha) {
632 const int w = 20, h = 20;
633
634 // create an image with known values
635 std::vector<unsigned char> original;
636 MakeGrayscaleAlphaImage(w, h, &original);
637
638 // encode
639 std::vector<unsigned char> encoded;
640 ASSERT_TRUE(EncodeImage(original,
641 w, h,
642 COLOR_TYPE_GRAY_ALPHA,
643 &encoded,
644 PNG_INTERLACE_ADAM7));
645
646 // decode
647 std::vector<unsigned char> decoded;
648 int outw, outh;
649 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
650 PNGCodec::FORMAT_RGBA, &decoded,
651 &outw, &outh));
652 ASSERT_EQ(w, outw);
653 ASSERT_EQ(h, outh);
654 ASSERT_EQ(decoded.size(), original.size() * 2);
655
656 // Images must be equal
657 for (int y = 0; y < h; ++y) {
658 for (int x = 0; x < w; ++x) {
659 unsigned char* gray_pixel = &original[(y * w + x) * 2];
660 unsigned char* rgba_pixel = &decoded[(y * w + x) * 4];
661 ASSERT_EQ(rgba_pixel[0], gray_pixel[0]);
662 ASSERT_EQ(rgba_pixel[1], gray_pixel[0]);
663 ASSERT_EQ(rgba_pixel[2], gray_pixel[0]);
664 ASSERT_EQ(rgba_pixel[3], gray_pixel[1]);
665 }
666 }
667 }
668
669 TEST(PNGCodec, DecodeInterlacedRGB) {
670 const int w = 20, h = 20;
671
672 // create an image with known values
673 std::vector<unsigned char> original;
674 MakeRGBImage(w, h, &original);
675
676 // encode
677 std::vector<unsigned char> encoded;
678 ASSERT_TRUE(EncodeImage(original,
679 w, h,
680 COLOR_TYPE_RGB,
681 &encoded,
682 PNG_INTERLACE_ADAM7));
683
684 // decode, it should have the same size as the original
685 std::vector<unsigned char> decoded;
686 int outw, outh;
687 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
688 PNGCodec::FORMAT_RGB, &decoded,
689 &outw, &outh));
690 ASSERT_EQ(w, outw);
691 ASSERT_EQ(h, outh);
692 ASSERT_EQ(original.size(), decoded.size());
693
694 // Images must be equal
695 ASSERT_EQ(original, decoded);
696 }
697
698 TEST(PNGCodec, DecodeInterlacedRGBA) {
699 const int w = 20, h = 20;
700
701 // create an image with known values
702 std::vector<unsigned char> original;
703 MakeRGBAImage(w, h, false, &original);
704
705 // encode
706 std::vector<unsigned char> encoded;
707 ASSERT_TRUE(EncodeImage(original,
708 w, h,
709 COLOR_TYPE_RGBA,
710 &encoded,
711 PNG_INTERLACE_ADAM7));
712
713 // decode, it should have the same size as the original
714 std::vector<unsigned char> decoded;
715 int outw, outh;
716 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
717 PNGCodec::FORMAT_RGBA, &decoded,
718 &outw, &outh));
719 ASSERT_EQ(w, outw);
720 ASSERT_EQ(h, outh);
721 ASSERT_EQ(original.size(), decoded.size());
722
723 // Images must be equal
724 ASSERT_EQ(original, decoded);
725 }
726
727 TEST(PNGCodec, DecodeInterlacedBGRA) {
728 const int w = 20, h = 20;
729
730 // create an image with known values
731 std::vector<unsigned char> original;
732 MakeRGBAImage(w, h, false, &original);
733
734 // encode
735 std::vector<unsigned char> encoded;
736 ASSERT_TRUE(EncodeImage(original,
737 w, h,
738 COLOR_TYPE_BGRA,
739 &encoded,
740 PNG_INTERLACE_ADAM7));
741
742 // decode, it should have the same size as the original
743 std::vector<unsigned char> decoded;
744 int outw, outh;
745 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
746 PNGCodec::FORMAT_BGRA, &decoded,
747 &outw, &outh));
748 ASSERT_EQ(w, outw);
749 ASSERT_EQ(h, outh);
750 ASSERT_EQ(original.size(), decoded.size());
751
752 // Images must be equal
753 ASSERT_EQ(original, decoded);
754 }
755
756 // Not encoding an interlaced PNG from SkBitmap because we don't do it
757 // anywhere, and the ability to do that requires more code changes.
758 TEST(PNGCodec, DecodeInterlacedRGBtoSkBitmap) {
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_RGB,
770 &encoded,
771 PNG_INTERLACE_ADAM7));
772
773 // Decode the encoded string.
774 SkBitmap decoded_bitmap;
775 ASSERT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
776 &decoded_bitmap));
777
778 for (int x = 0; x < w; x++) {
779 for (int y = 0; y < h; y++) {
780 const unsigned char* original_pixel = &original[(y * w + x) * 3];
781 const uint32_t original_pixel_sk = SkPackARGB32(0xFF,
782 original_pixel[0],
783 original_pixel[1],
784 original_pixel[2]);
785 const uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
786 ASSERT_EQ(original_pixel_sk, decoded_pixel);
787 }
788 }
789 }
790
791 TEST(PNGCodec, DecodeInterlacedRGBAtoSkBitmap) {
792 const int w = 20, h = 20;
793
794 // create an image with known values
795 std::vector<unsigned char> original;
796 MakeRGBAImage(w, h, false, &original);
797
798 // encode
799 std::vector<unsigned char> encoded;
800 ASSERT_TRUE(EncodeImage(original,
801 w, h,
802 COLOR_TYPE_RGBA,
803 &encoded,
804 PNG_INTERLACE_ADAM7));
805
806 // Decode the encoded string.
807 SkBitmap decoded_bitmap;
808 ASSERT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
809 &decoded_bitmap));
810
811 for (int x = 0; x < w; x++) {
812 for (int y = 0; y < h; y++) {
813 const unsigned char* original_pixel = &original[(y * w + x) * 4];
814 const uint32_t original_pixel_sk = SkPackARGB32(original_pixel[3],
815 original_pixel[0],
816 original_pixel[1],
817 original_pixel[2]);
818 const uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
819 ASSERT_EQ(original_pixel_sk, decoded_pixel);
820 }
821 }
822 }
823
133 // Test that corrupted data decompression causes failures. 824 // Test that corrupted data decompression causes failures.
134 TEST(PNGCodec, DecodeCorrupted) { 825 TEST(PNGCodec, DecodeCorrupted) {
135 int w = 20, h = 20; 826 int w = 20, h = 20;
136 827
137 // Make some random data (an uncompressed image). 828 // Make some random data (an uncompressed image).
138 std::vector<unsigned char> original; 829 std::vector<unsigned char> original;
139 MakeRGBImage(w, h, &original); 830 MakeRGBImage(w, h, &original);
140 831
141 // It should fail when given non-JPEG compressed data. 832 // It should fail when given non-JPEG compressed data.
142 std::vector<unsigned char> output; 833 std::vector<unsigned char> output;
143 int outw, outh; 834 int outw, outh;
144 EXPECT_FALSE(PNGCodec::Decode(&original[0], original.size(), 835 EXPECT_FALSE(PNGCodec::Decode(&original[0], original.size(),
145 PNGCodec::FORMAT_RGB, &output, 836 PNGCodec::FORMAT_RGB, &output,
146 &outw, &outh)); 837 &outw, &outh));
147 838
148 // Make some compressed data. 839 // Make some compressed data.
149 std::vector<unsigned char> compressed; 840 std::vector<unsigned char> compressed;
150 EXPECT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGB, 841 ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGB,
151 Size(w, h), w * 3, false, 842 Size(w, h), w * 3, false,
152 std::vector<PNGCodec::Comment>(), 843 std::vector<PNGCodec::Comment>(),
153 &compressed)); 844 &compressed));
154 845
155 // Try decompressing a truncated version. 846 // Try decompressing a truncated version.
156 EXPECT_FALSE(PNGCodec::Decode(&compressed[0], compressed.size() / 2, 847 EXPECT_FALSE(PNGCodec::Decode(&compressed[0], compressed.size() / 2,
157 PNGCodec::FORMAT_RGB, &output, 848 PNGCodec::FORMAT_RGB, &output,
158 &outw, &outh)); 849 &outw, &outh));
159 850
160 // Corrupt it and try decompressing that. 851 // Corrupt it and try decompressing that.
161 for (int i = 10; i < 30; i++) 852 for (int i = 10; i < 30; i++)
162 compressed[i] = i; 853 compressed[i] = i;
163 EXPECT_FALSE(PNGCodec::Decode(&compressed[0], compressed.size(), 854 EXPECT_FALSE(PNGCodec::Decode(&compressed[0], compressed.size(),
164 PNGCodec::FORMAT_RGB, &output, 855 PNGCodec::FORMAT_RGB, &output,
165 &outw, &outh)); 856 &outw, &outh));
166 } 857 }
167 858
168 TEST(PNGCodec, EncodeDecodeBGRA) {
169 const int w = 20, h = 20;
170
171 // Create an image with known values, alpha must be opaque because it will be
172 // lost during encoding.
173 std::vector<unsigned char> original;
174 MakeRGBAImage(w, h, true, &original);
175
176 // Encode.
177 std::vector<unsigned char> encoded;
178 EXPECT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_BGRA,
179 Size(w, h), w * 4, false,
180 std::vector<PNGCodec::Comment>(),
181 &encoded));
182
183 // Decode, it should have the same size as the original.
184 std::vector<unsigned char> decoded;
185 int outw, outh;
186 EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
187 PNGCodec::FORMAT_BGRA, &decoded,
188 &outw, &outh));
189 ASSERT_EQ(w, outw);
190 ASSERT_EQ(h, outh);
191 ASSERT_EQ(original.size(), decoded.size());
192
193 // Images must be exactly equal.
194 ASSERT_TRUE(original == decoded);
Francois 2012/02/28 15:00:36 This function was moved further up.
195 }
196
197 TEST(PNGCodec, StripAddAlpha) { 859 TEST(PNGCodec, StripAddAlpha) {
198 const int w = 20, h = 20; 860 const int w = 20, h = 20;
199 861
200 // These should be the same except one has a 0xff alpha channel. 862 // These should be the same except one has a 0xff alpha channel.
201 std::vector<unsigned char> original_rgb; 863 std::vector<unsigned char> original_rgb;
202 MakeRGBImage(w, h, &original_rgb); 864 MakeRGBImage(w, h, &original_rgb);
203 std::vector<unsigned char> original_rgba; 865 std::vector<unsigned char> original_rgba;
204 MakeRGBAImage(w, h, false, &original_rgba); 866 MakeRGBAImage(w, h, false, &original_rgba);
205 867
206 // Encode RGBA data as RGB. 868 // Encode RGBA data as RGB.
207 std::vector<unsigned char> encoded; 869 std::vector<unsigned char> encoded;
208 EXPECT_TRUE(PNGCodec::Encode(&original_rgba[0], PNGCodec::FORMAT_RGBA, 870 EXPECT_TRUE(PNGCodec::Encode(&original_rgba[0], PNGCodec::FORMAT_RGBA,
209 Size(w, h), w * 4, true, 871 Size(w, h), w * 4, true,
210 std::vector<PNGCodec::Comment>(), 872 std::vector<PNGCodec::Comment>(),
211 &encoded)); 873 &encoded));
212 874
213 // Decode the RGB to RGBA. 875 // Decode the RGB to RGBA.
214 std::vector<unsigned char> decoded; 876 std::vector<unsigned char> decoded;
215 int outw, outh; 877 int outw, outh;
216 EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(), 878 EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
217 PNGCodec::FORMAT_RGBA, &decoded, 879 PNGCodec::FORMAT_RGBA, &decoded,
218 &outw, &outh)); 880 &outw, &outh));
219 881
220 // Decoded and reference should be the same (opaque alpha). 882 // Decoded and reference should be the same (opaque alpha).
221 ASSERT_EQ(w, outw); 883 ASSERT_EQ(w, outw);
222 ASSERT_EQ(h, outh); 884 ASSERT_EQ(h, outh);
223 ASSERT_EQ(original_rgba.size(), decoded.size()); 885 ASSERT_EQ(original_rgba.size(), decoded.size());
224 ASSERT_TRUE(original_rgba == decoded); 886 ASSERT_EQ(original_rgba, decoded);
225 887
226 // Encode RGBA to RGBA. 888 // Encode RGBA to RGBA.
227 EXPECT_TRUE(PNGCodec::Encode(&original_rgba[0], PNGCodec::FORMAT_RGBA, 889 EXPECT_TRUE(PNGCodec::Encode(&original_rgba[0], PNGCodec::FORMAT_RGBA,
228 Size(w, h), w * 4, false, 890 Size(w, h), w * 4, false,
229 std::vector<PNGCodec::Comment>(), 891 std::vector<PNGCodec::Comment>(),
230 &encoded)); 892 &encoded));
231 893
232 // Decode the RGBA to RGB. 894 // Decode the RGBA to RGB.
233 EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(), 895 EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
234 PNGCodec::FORMAT_RGB, &decoded, 896 PNGCodec::FORMAT_RGB, &decoded,
235 &outw, &outh)); 897 &outw, &outh));
236 898
237 // It should be the same as our non-alpha-channel reference. 899 // It should be the same as our non-alpha-channel reference.
238 ASSERT_EQ(w, outw); 900 ASSERT_EQ(w, outw);
239 ASSERT_EQ(h, outh); 901 ASSERT_EQ(h, outh);
240 ASSERT_EQ(original_rgb.size(), decoded.size()); 902 ASSERT_EQ(original_rgb.size(), decoded.size());
241 ASSERT_TRUE(original_rgb == decoded); 903 ASSERT_EQ(original_rgb, decoded);
242 } 904 }
243 905
244 TEST(PNGCodec, EncodeBGRASkBitmap) { 906 TEST(PNGCodec, EncodeBGRASkBitmap) {
245 const int w = 20, h = 20; 907 const int w = 20, h = 20;
246 908
247 SkBitmap original_bitmap; 909 SkBitmap original_bitmap;
248 MakeTestSkBitmap(w, h, &original_bitmap); 910 MakeTestSkBitmap(w, h, &original_bitmap);
249 911
250 // Encode the bitmap. 912 // Encode the bitmap.
251 std::vector<unsigned char> encoded; 913 std::vector<unsigned char> encoded;
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 ASSERT_EQ(w, outw); 1041 ASSERT_EQ(w, outw);
380 ASSERT_EQ(h, outh); 1042 ASSERT_EQ(h, outh);
381 ASSERT_EQ(original.size(), decoded.size()); 1043 ASSERT_EQ(original.size(), decoded.size());
382 1044
383 // Images must be exactly equal 1045 // Images must be exactly equal
384 ASSERT_TRUE(original == decoded); 1046 ASSERT_TRUE(original == decoded);
385 } 1047 }
386 1048
387 1049
388 } // namespace gfx 1050 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698