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 
     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