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