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