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

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
« no previous file with comments | « ui/gfx/codec/png_codec.cc ('k') | ui/ui_unittests.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
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 // User write function (to be passed to libpng by EncodeImage) which writes
61 // into a buffer instead of to a file.
62 void WriteImageData(png_structp png_ptr,
63 png_bytep data,
64 png_size_t length) {
65 std::vector<unsigned char>& v =
66 *static_cast<std::vector<unsigned char>*>(png_get_io_ptr(png_ptr));
67 v.resize(v.size() + length);
68 memcpy(&v[v.size() - length], data, length);
69 }
70
71 // User flush function; goes with WriteImageData, above.
72 void FlushImageData(png_structp /*png_ptr*/) {
73 }
74
75 // Libpng user error function which allows us to print libpng errors using
76 // Chrome's logging facilities instead of stderr.
77 void LogLibPNGError(png_structp png_ptr,
78 png_const_charp error_msg) {
79 DLOG(ERROR) << "libpng encode error: " << error_msg;
80 longjmp(png_jmpbuf(png_ptr), 1);
81 }
82
83 // Goes with LogLibPNGError, above.
84 void LogLibPNGWarning(png_structp png_ptr,
85 png_const_charp warning_msg) {
86 DLOG(ERROR) << "libpng encode warning: " << warning_msg;
87 }
88
89 // Color types supported by EncodeImage. Required because neither libpng nor
90 // PNGCodec::Encode supports all of the required values.
91 enum ColorType {
92 COLOR_TYPE_GRAY = PNG_COLOR_TYPE_GRAY,
93 COLOR_TYPE_GRAY_ALPHA = PNG_COLOR_TYPE_GRAY_ALPHA,
94 COLOR_TYPE_PALETTE = PNG_COLOR_TYPE_PALETTE,
95 COLOR_TYPE_RGB = PNG_COLOR_TYPE_RGB,
96 COLOR_TYPE_RGBA = PNG_COLOR_TYPE_RGBA,
97 COLOR_TYPE_BGR,
98 COLOR_TYPE_BGRA
99 };
100
101 // PNG encoder used for testing. Required because PNGCodec::Encode doesn't do
102 // interlaced, palette-based, or grayscale images, but PNGCodec::Decode is
103 // actually asked to decode these types of images by Chrome.
104 bool EncodeImage(const std::vector<unsigned char>& input,
105 const int width,
106 const int height,
107 ColorType output_color_type,
108 std::vector<unsigned char>* output,
109 const int interlace_type = PNG_INTERLACE_NONE,
110 std::vector<png_color>* palette = 0,
111 std::vector<unsigned char>* palette_alpha = 0) {
112 struct ScopedPNGStructs {
113 ScopedPNGStructs(png_struct** s, png_info** i) : s_(s), i_(i) {}
114 ~ScopedPNGStructs() { png_destroy_write_struct(s_, i_); }
115 png_struct** s_;
116 png_info** i_;
117 };
118
119 DCHECK(output);
120 png_struct* png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
121 NULL, NULL, NULL);
122 if (!png_ptr)
123 return false;
124
125 png_infop info_ptr = png_create_info_struct(png_ptr);
126 if (!info_ptr) {
127 png_destroy_write_struct(&png_ptr, NULL);
128 return false;
129 }
130
131 ScopedPNGStructs scoped_png_structs(&png_ptr, &info_ptr);
132
133 if (setjmp(png_jmpbuf(png_ptr)))
134 return false;
135
136 png_set_error_fn(png_ptr, NULL, LogLibPNGError, LogLibPNGWarning);
137
138 int input_rowbytes = 0;
139 int transforms = PNG_TRANSFORM_IDENTITY;
140
141 switch (output_color_type) {
142 case COLOR_TYPE_GRAY:
143 input_rowbytes = width;
144 break;
145 case COLOR_TYPE_GRAY_ALPHA:
146 input_rowbytes = width * 2;
147 break;
148 case COLOR_TYPE_PALETTE:
149 if (!palette)
150 return false;
151 input_rowbytes = width;
152 break;
153 case COLOR_TYPE_RGB:
154 input_rowbytes = width * 3;
155 break;
156 case COLOR_TYPE_RGBA:
157 input_rowbytes = width * 4;
158 break;
159 case COLOR_TYPE_BGR:
160 input_rowbytes = width * 3;
161 output_color_type = static_cast<ColorType>(PNG_COLOR_TYPE_RGB);
162 transforms |= PNG_TRANSFORM_BGR;
163 break;
164 case COLOR_TYPE_BGRA:
165 input_rowbytes = width * 4;
166 output_color_type = static_cast<ColorType>(PNG_COLOR_TYPE_RGBA);
167 transforms |= PNG_TRANSFORM_BGR;
168 break;
169 };
170
171 std::vector<png_bytep> row_pointers(height);
172 for (int y = 0 ; y < height; y++) {
173 row_pointers[y] = const_cast<unsigned char*>(&input[y * input_rowbytes]);
174 }
175 png_set_rows(png_ptr, info_ptr, &row_pointers[0]);
176 png_set_write_fn(png_ptr, output, WriteImageData, FlushImageData);
177 png_set_IHDR(png_ptr, info_ptr, width, height, 8, output_color_type,
178 interlace_type, PNG_COMPRESSION_TYPE_DEFAULT,
179 PNG_FILTER_TYPE_DEFAULT);
180 if (output_color_type == COLOR_TYPE_PALETTE) {
181 png_set_PLTE(png_ptr, info_ptr, &palette->front(), palette->size());
182 if (palette_alpha) {
183 png_set_tRNS(png_ptr,
184 info_ptr,
185 &palette_alpha->front(),
186 palette_alpha->size(),
187 NULL);
188 }
189 }
190
191 png_write_png(png_ptr, info_ptr, transforms, NULL);
192
193 return true;
194 }
195
196 } // namespace
197
50 // Returns true if each channel of the given two colors are "close." This is 198 // 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. 199 // used for comparing colors where rounding errors may cause off-by-one.
52 bool ColorsClose(uint32_t a, uint32_t b) { 200 bool ColorsClose(uint32_t a, uint32_t b) {
53 return abs(static_cast<int>(SkColorGetB(a) - SkColorGetB(b))) < 2 && 201 return abs(static_cast<int>(SkColorGetB(a) - SkColorGetB(b))) < 2 &&
54 abs(static_cast<int>(SkColorGetG(a) - SkColorGetG(b))) < 2 && 202 abs(static_cast<int>(SkColorGetG(a) - SkColorGetG(b))) < 2 &&
55 abs(static_cast<int>(SkColorGetR(a) - SkColorGetR(b))) < 2 && 203 abs(static_cast<int>(SkColorGetR(a) - SkColorGetR(b))) < 2 &&
56 abs(static_cast<int>(SkColorGetA(a) - SkColorGetA(b))) < 2; 204 abs(static_cast<int>(SkColorGetA(a) - SkColorGetA(b))) < 2;
57 } 205 }
58 206
59 // Returns true if the RGB components are "close." 207 // Returns true if the RGB components are "close."
(...skipping 15 matching lines...) Expand all
75 223
76 TEST(PNGCodec, EncodeDecodeRGB) { 224 TEST(PNGCodec, EncodeDecodeRGB) {
77 const int w = 20, h = 20; 225 const int w = 20, h = 20;
78 226
79 // create an image with known values 227 // create an image with known values
80 std::vector<unsigned char> original; 228 std::vector<unsigned char> original;
81 MakeRGBImage(w, h, &original); 229 MakeRGBImage(w, h, &original);
82 230
83 // encode 231 // encode
84 std::vector<unsigned char> encoded; 232 std::vector<unsigned char> encoded;
85 EXPECT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGB, 233 ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGB,
86 Size(w, h), w * 3, false, 234 Size(w, h), w * 3, false,
87 std::vector<PNGCodec::Comment>(), 235 std::vector<PNGCodec::Comment>(),
88 &encoded)); 236 &encoded));
89 237
90 // decode, it should have the same size as the original 238 // decode, it should have the same size as the original
91 std::vector<unsigned char> decoded; 239 std::vector<unsigned char> decoded;
92 int outw, outh; 240 int outw, outh;
93 EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(), 241 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
94 PNGCodec::FORMAT_RGB, &decoded, 242 PNGCodec::FORMAT_RGB, &decoded,
95 &outw, &outh)); 243 &outw, &outh));
96 ASSERT_EQ(w, outw); 244 ASSERT_EQ(w, outw);
97 ASSERT_EQ(h, outh); 245 ASSERT_EQ(h, outh);
98 ASSERT_EQ(original.size(), decoded.size()); 246 ASSERT_EQ(original.size(), decoded.size());
99 247
100 // Images must be equal 248 // Images must be equal
101 ASSERT_TRUE(original == decoded); 249 ASSERT_TRUE(original == decoded);
102 } 250 }
103 251
104 TEST(PNGCodec, EncodeDecodeRGBA) { 252 TEST(PNGCodec, EncodeDecodeRGBA) {
105 const int w = 20, h = 20; 253 const int w = 20, h = 20;
106 254
107 // create an image with known values, a must be opaque because it will be 255 // create an image with known values, a must be opaque because it will be
108 // lost during encoding 256 // lost during encoding
109 std::vector<unsigned char> original; 257 std::vector<unsigned char> original;
110 MakeRGBAImage(w, h, true, &original); 258 MakeRGBAImage(w, h, true, &original);
111 259
112 // encode 260 // encode
113 std::vector<unsigned char> encoded; 261 std::vector<unsigned char> encoded;
114 EXPECT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGBA, 262 ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGBA,
115 Size(w, h), w * 4, false, 263 Size(w, h), w * 4, false,
116 std::vector<PNGCodec::Comment>(), 264 std::vector<PNGCodec::Comment>(),
117 &encoded)); 265 &encoded));
118 266
119 // decode, it should have the same size as the original 267 // decode, it should have the same size as the original
120 std::vector<unsigned char> decoded; 268 std::vector<unsigned char> decoded;
121 int outw, outh; 269 int outw, outh;
122 EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(), 270 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
123 PNGCodec::FORMAT_RGBA, &decoded, 271 PNGCodec::FORMAT_RGBA, &decoded,
124 &outw, &outh)); 272 &outw, &outh));
125 ASSERT_EQ(w, outw); 273 ASSERT_EQ(w, outw);
126 ASSERT_EQ(h, outh); 274 ASSERT_EQ(h, outh);
127 ASSERT_EQ(original.size(), decoded.size()); 275 ASSERT_EQ(original.size(), decoded.size());
128 276
129 // Images must be exactly equal 277 // Images must be exactly equal
130 ASSERT_TRUE(original == decoded); 278 ASSERT_TRUE(original == decoded);
131 } 279 }
132 280
281 TEST(PNGCodec, EncodeDecodeBGRA) {
282 const int w = 20, h = 20;
283
284 // Create an image with known values, alpha must be opaque because it will be
285 // lost during encoding.
286 std::vector<unsigned char> original;
287 MakeRGBAImage(w, h, true, &original);
288
289 // Encode.
290 std::vector<unsigned char> encoded;
291 ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_BGRA,
292 Size(w, h), w * 4, false,
293 std::vector<PNGCodec::Comment>(),
294 &encoded));
295
296 // Decode, it should have the same size as the original.
297 std::vector<unsigned char> decoded;
298 int outw, outh;
299 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
300 PNGCodec::FORMAT_BGRA, &decoded,
301 &outw, &outh));
302 ASSERT_EQ(w, outw);
303 ASSERT_EQ(h, outh);
304 ASSERT_EQ(original.size(), decoded.size());
305
306 // Images must be exactly equal.
307 ASSERT_TRUE(original == decoded);
308 }
309
310 TEST(PNGCodec, DecodeInterlacedRGB) {
311 const int w = 20, h = 20;
312
313 // create an image with known values
314 std::vector<unsigned char> original;
315 MakeRGBImage(w, h, &original);
316
317 // encode
318 std::vector<unsigned char> encoded;
319 ASSERT_TRUE(EncodeImage(original,
320 w, h,
321 COLOR_TYPE_RGB,
322 &encoded,
323 PNG_INTERLACE_ADAM7));
324
325 // decode, it should have the same size as the original
326 std::vector<unsigned char> decoded;
327 int outw, outh;
328 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
329 PNGCodec::FORMAT_RGB, &decoded,
330 &outw, &outh));
331 ASSERT_EQ(w, outw);
332 ASSERT_EQ(h, outh);
333 ASSERT_EQ(original.size(), decoded.size());
334
335 // Images must be equal
336 ASSERT_EQ(original, decoded);
337 }
338
339 TEST(PNGCodec, DecodeInterlacedRGBA) {
340 const int w = 20, h = 20;
341
342 // create an image with known values
343 std::vector<unsigned char> original;
344 MakeRGBAImage(w, h, false, &original);
345
346 // encode
347 std::vector<unsigned char> encoded;
348 ASSERT_TRUE(EncodeImage(original,
349 w, h,
350 COLOR_TYPE_RGBA,
351 &encoded,
352 PNG_INTERLACE_ADAM7));
353
354 // decode, it should have the same size as the original
355 std::vector<unsigned char> decoded;
356 int outw, outh;
357 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
358 PNGCodec::FORMAT_RGBA, &decoded,
359 &outw, &outh));
360 ASSERT_EQ(w, outw);
361 ASSERT_EQ(h, outh);
362 ASSERT_EQ(original.size(), decoded.size());
363
364 // Images must be equal
365 ASSERT_EQ(original, decoded);
366 }
367
368 TEST(PNGCodec, DecodeInterlacedRGBADiscardAlpha) {
369 const int w = 20, h = 20;
370
371 // create an image with known values
372 std::vector<unsigned char> original;
373 MakeRGBAImage(w, h, false, &original);
374
375 // encode
376 std::vector<unsigned char> encoded;
377 ASSERT_TRUE(EncodeImage(original,
378 w, h,
379 COLOR_TYPE_RGBA,
380 &encoded,
381 PNG_INTERLACE_ADAM7));
382
383 // decode
384 std::vector<unsigned char> decoded;
385 int outw, outh;
386 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
387 PNGCodec::FORMAT_RGB, &decoded,
388 &outw, &outh));
389 ASSERT_EQ(w, outw);
390 ASSERT_EQ(h, outh);
391 ASSERT_EQ(decoded.size(), w * h * 3U);
392
393 // Images must be equal
394 for (int x = 0; x < w; x++) {
395 for (int y = 0; y < h; y++) {
396 unsigned char* orig_px = &original[(y * w + x) * 4];
397 unsigned char* dec_px = &decoded[(y * w + x) * 3];
398 ASSERT_EQ(dec_px[0], orig_px[0]);
399 ASSERT_EQ(dec_px[1], orig_px[1]);
400 ASSERT_EQ(dec_px[2], orig_px[2]);
401 }
402 }
403 }
404
405 TEST(PNGCodec, DecodeInterlacedBGR) {
406 const int w = 20, h = 20;
407
408 // create an image with known values
409 std::vector<unsigned char> original;
410 MakeRGBImage(w, h, &original);
411
412 // encode
413 std::vector<unsigned char> encoded;
414 ASSERT_TRUE(EncodeImage(original,
415 w, h,
416 COLOR_TYPE_BGR,
417 &encoded,
418 PNG_INTERLACE_ADAM7));
419
420 // decode, it should have the same size as the original
421 std::vector<unsigned char> decoded;
422 int outw, outh;
423 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
424 PNGCodec::FORMAT_BGRA, &decoded,
425 &outw, &outh));
426 ASSERT_EQ(w, outw);
427 ASSERT_EQ(h, outh);
428 ASSERT_EQ(decoded.size(), w * h * 4U);
429
430 // Images must be equal
431 for (int x = 0; x < w; x++) {
432 for (int y = 0; y < h; y++) {
433 unsigned char* orig_px = &original[(y * w + x) * 3];
434 unsigned char* dec_px = &decoded[(y * w + x) * 4];
435 ASSERT_EQ(dec_px[0], orig_px[0]);
436 ASSERT_EQ(dec_px[1], orig_px[1]);
437 ASSERT_EQ(dec_px[2], orig_px[2]);
438 }
439 }
440 }
441
442 TEST(PNGCodec, DecodeInterlacedBGRA) {
443 const int w = 20, h = 20;
444
445 // create an image with known values
446 std::vector<unsigned char> original;
447 MakeRGBAImage(w, h, false, &original);
448
449 // encode
450 std::vector<unsigned char> encoded;
451 ASSERT_TRUE(EncodeImage(original,
452 w, h,
453 COLOR_TYPE_BGRA,
454 &encoded,
455 PNG_INTERLACE_ADAM7));
456
457 // decode, it should have the same size as the original
458 std::vector<unsigned char> decoded;
459 int outw, outh;
460 ASSERT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
461 PNGCodec::FORMAT_BGRA, &decoded,
462 &outw, &outh));
463 ASSERT_EQ(w, outw);
464 ASSERT_EQ(h, outh);
465 ASSERT_EQ(original.size(), decoded.size());
466
467 // Images must be equal
468 ASSERT_EQ(original, decoded);
469 }
470
471 // Not encoding an interlaced PNG from SkBitmap because we don't do it
472 // anywhere, and the ability to do that requires more code changes.
473 TEST(PNGCodec, DecodeInterlacedRGBtoSkBitmap) {
474 const int w = 20, h = 20;
475
476 // create an image with known values
477 std::vector<unsigned char> original;
478 MakeRGBImage(w, h, &original);
479
480 // encode
481 std::vector<unsigned char> encoded;
482 ASSERT_TRUE(EncodeImage(original,
483 w, h,
484 COLOR_TYPE_RGB,
485 &encoded,
486 PNG_INTERLACE_ADAM7));
487
488 // Decode the encoded string.
489 SkBitmap decoded_bitmap;
490 ASSERT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
491 &decoded_bitmap));
492
493 for (int x = 0; x < w; x++) {
494 for (int y = 0; y < h; y++) {
495 const unsigned char* original_pixel = &original[(y * w + x) * 3];
496 const uint32_t original_pixel_sk = SkPackARGB32(0xFF,
497 original_pixel[0],
498 original_pixel[1],
499 original_pixel[2]);
500 const uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
501 ASSERT_EQ(original_pixel_sk, decoded_pixel);
502 }
503 }
504 }
505
506 TEST(PNGCodec, DecodeInterlacedRGBAtoSkBitmap) {
507 const int w = 20, h = 20;
508
509 // create an image with known values
510 std::vector<unsigned char> original;
511 MakeRGBAImage(w, h, false, &original);
512
513 // encode
514 std::vector<unsigned char> encoded;
515 ASSERT_TRUE(EncodeImage(original,
516 w, h,
517 COLOR_TYPE_RGBA,
518 &encoded,
519 PNG_INTERLACE_ADAM7));
520
521 // Decode the encoded string.
522 SkBitmap decoded_bitmap;
523 ASSERT_TRUE(PNGCodec::Decode(&encoded.front(), encoded.size(),
524 &decoded_bitmap));
525
526 for (int x = 0; x < w; x++) {
527 for (int y = 0; y < h; y++) {
528 const unsigned char* original_pixel = &original[(y * w + x) * 4];
529 const uint32_t original_pixel_sk = SkPackARGB32(original_pixel[3],
530 original_pixel[0],
531 original_pixel[1],
532 original_pixel[2]);
533 const uint32_t decoded_pixel = decoded_bitmap.getAddr32(0, y)[x];
534 ASSERT_EQ(original_pixel_sk, decoded_pixel);
535 }
536 }
537 }
538
133 // Test that corrupted data decompression causes failures. 539 // Test that corrupted data decompression causes failures.
134 TEST(PNGCodec, DecodeCorrupted) { 540 TEST(PNGCodec, DecodeCorrupted) {
135 int w = 20, h = 20; 541 int w = 20, h = 20;
136 542
137 // Make some random data (an uncompressed image). 543 // Make some random data (an uncompressed image).
138 std::vector<unsigned char> original; 544 std::vector<unsigned char> original;
139 MakeRGBImage(w, h, &original); 545 MakeRGBImage(w, h, &original);
140 546
141 // It should fail when given non-JPEG compressed data. 547 // It should fail when given non-JPEG compressed data.
142 std::vector<unsigned char> output; 548 std::vector<unsigned char> output;
143 int outw, outh; 549 int outw, outh;
144 EXPECT_FALSE(PNGCodec::Decode(&original[0], original.size(), 550 EXPECT_FALSE(PNGCodec::Decode(&original[0], original.size(),
145 PNGCodec::FORMAT_RGB, &output, 551 PNGCodec::FORMAT_RGB, &output,
146 &outw, &outh)); 552 &outw, &outh));
147 553
148 // Make some compressed data. 554 // Make some compressed data.
149 std::vector<unsigned char> compressed; 555 std::vector<unsigned char> compressed;
150 EXPECT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGB, 556 ASSERT_TRUE(PNGCodec::Encode(&original[0], PNGCodec::FORMAT_RGB,
151 Size(w, h), w * 3, false, 557 Size(w, h), w * 3, false,
152 std::vector<PNGCodec::Comment>(), 558 std::vector<PNGCodec::Comment>(),
153 &compressed)); 559 &compressed));
154 560
155 // Try decompressing a truncated version. 561 // Try decompressing a truncated version.
156 EXPECT_FALSE(PNGCodec::Decode(&compressed[0], compressed.size() / 2, 562 EXPECT_FALSE(PNGCodec::Decode(&compressed[0], compressed.size() / 2,
157 PNGCodec::FORMAT_RGB, &output, 563 PNGCodec::FORMAT_RGB, &output,
158 &outw, &outh)); 564 &outw, &outh));
159 565
160 // Corrupt it and try decompressing that. 566 // Corrupt it and try decompressing that.
161 for (int i = 10; i < 30; i++) 567 for (int i = 10; i < 30; i++)
162 compressed[i] = i; 568 compressed[i] = i;
163 EXPECT_FALSE(PNGCodec::Decode(&compressed[0], compressed.size(), 569 EXPECT_FALSE(PNGCodec::Decode(&compressed[0], compressed.size(),
164 PNGCodec::FORMAT_RGB, &output, 570 PNGCodec::FORMAT_RGB, &output,
165 &outw, &outh)); 571 &outw, &outh));
166 } 572 }
167 573
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);
195 }
196
197 TEST(PNGCodec, StripAddAlpha) { 574 TEST(PNGCodec, StripAddAlpha) {
198 const int w = 20, h = 20; 575 const int w = 20, h = 20;
199 576
200 // These should be the same except one has a 0xff alpha channel. 577 // These should be the same except one has a 0xff alpha channel.
201 std::vector<unsigned char> original_rgb; 578 std::vector<unsigned char> original_rgb;
202 MakeRGBImage(w, h, &original_rgb); 579 MakeRGBImage(w, h, &original_rgb);
203 std::vector<unsigned char> original_rgba; 580 std::vector<unsigned char> original_rgba;
204 MakeRGBAImage(w, h, false, &original_rgba); 581 MakeRGBAImage(w, h, false, &original_rgba);
205 582
206 // Encode RGBA data as RGB. 583 // Encode RGBA data as RGB.
207 std::vector<unsigned char> encoded; 584 std::vector<unsigned char> encoded;
208 EXPECT_TRUE(PNGCodec::Encode(&original_rgba[0], PNGCodec::FORMAT_RGBA, 585 EXPECT_TRUE(PNGCodec::Encode(&original_rgba[0], PNGCodec::FORMAT_RGBA,
209 Size(w, h), w * 4, true, 586 Size(w, h), w * 4, true,
210 std::vector<PNGCodec::Comment>(), 587 std::vector<PNGCodec::Comment>(),
211 &encoded)); 588 &encoded));
212 589
213 // Decode the RGB to RGBA. 590 // Decode the RGB to RGBA.
214 std::vector<unsigned char> decoded; 591 std::vector<unsigned char> decoded;
215 int outw, outh; 592 int outw, outh;
216 EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(), 593 EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
217 PNGCodec::FORMAT_RGBA, &decoded, 594 PNGCodec::FORMAT_RGBA, &decoded,
218 &outw, &outh)); 595 &outw, &outh));
219 596
220 // Decoded and reference should be the same (opaque alpha). 597 // Decoded and reference should be the same (opaque alpha).
221 ASSERT_EQ(w, outw); 598 ASSERT_EQ(w, outw);
222 ASSERT_EQ(h, outh); 599 ASSERT_EQ(h, outh);
223 ASSERT_EQ(original_rgba.size(), decoded.size()); 600 ASSERT_EQ(original_rgba.size(), decoded.size());
224 ASSERT_TRUE(original_rgba == decoded); 601 ASSERT_EQ(original_rgba, decoded);
225 602
226 // Encode RGBA to RGBA. 603 // Encode RGBA to RGBA.
227 EXPECT_TRUE(PNGCodec::Encode(&original_rgba[0], PNGCodec::FORMAT_RGBA, 604 EXPECT_TRUE(PNGCodec::Encode(&original_rgba[0], PNGCodec::FORMAT_RGBA,
228 Size(w, h), w * 4, false, 605 Size(w, h), w * 4, false,
229 std::vector<PNGCodec::Comment>(), 606 std::vector<PNGCodec::Comment>(),
230 &encoded)); 607 &encoded));
231 608
232 // Decode the RGBA to RGB. 609 // Decode the RGBA to RGB.
233 EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(), 610 EXPECT_TRUE(PNGCodec::Decode(&encoded[0], encoded.size(),
234 PNGCodec::FORMAT_RGB, &decoded, 611 PNGCodec::FORMAT_RGB, &decoded,
235 &outw, &outh)); 612 &outw, &outh));
236 613
237 // It should be the same as our non-alpha-channel reference. 614 // It should be the same as our non-alpha-channel reference.
238 ASSERT_EQ(w, outw); 615 ASSERT_EQ(w, outw);
239 ASSERT_EQ(h, outh); 616 ASSERT_EQ(h, outh);
240 ASSERT_EQ(original_rgb.size(), decoded.size()); 617 ASSERT_EQ(original_rgb.size(), decoded.size());
241 ASSERT_TRUE(original_rgb == decoded); 618 ASSERT_EQ(original_rgb, decoded);
242 } 619 }
243 620
244 TEST(PNGCodec, EncodeBGRASkBitmap) { 621 TEST(PNGCodec, EncodeBGRASkBitmap) {
245 const int w = 20, h = 20; 622 const int w = 20, h = 20;
246 623
247 SkBitmap original_bitmap; 624 SkBitmap original_bitmap;
248 MakeTestSkBitmap(w, h, &original_bitmap); 625 MakeTestSkBitmap(w, h, &original_bitmap);
249 626
250 // Encode the bitmap. 627 // Encode the bitmap.
251 std::vector<unsigned char> encoded; 628 std::vector<unsigned char> encoded;
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 ASSERT_EQ(w, outw); 756 ASSERT_EQ(w, outw);
380 ASSERT_EQ(h, outh); 757 ASSERT_EQ(h, outh);
381 ASSERT_EQ(original.size(), decoded.size()); 758 ASSERT_EQ(original.size(), decoded.size());
382 759
383 // Images must be exactly equal 760 // Images must be exactly equal
384 ASSERT_TRUE(original == decoded); 761 ASSERT_TRUE(original == decoded);
385 } 762 }
386 763
387 764
388 } // namespace gfx 765 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/codec/png_codec.cc ('k') | ui/ui_unittests.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698