Home | History | Annotate | Download | only in codec
      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