/*
 * Copyright 2009 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Author: Bryan McQuade

#include "pagespeed/kernel/image/png_optimizer.h"

#include "base/logging.h"
#include "pagespeed/kernel/base/message_handler.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/image/scanline_utils.h"

#ifdef __native_client__
// For some reason that is not yet clear, invoking png_longjmp on
// native client causes a crash. Invoking longjmp on the jump buffer
// directly does not crash. The jump buffer is defined in the
// following libpng private header, so we include it here. See
// http://code.google.com/p/page-speed/issues/detail?id=644 for more
// information.
#include "third_party/libpng/pngstruct.h"
#endif

extern "C" {
#ifdef USE_SYSTEM_ZLIB
#include "zlib.h"  // NOLINT
#else
#include "third_party/zlib/zlib.h"
#endif

#include "third_party/optipng/src/opngreduc/opngreduc.h"
}

using net_instaweb::MessageHandler;
using pagespeed::image_compression::PngCompressParams;

namespace {

// we use these four combinations because different images seem to benefit from
// different parameters and this combination of 4 seems to work best for a large
// set of PNGs from the web.
const PngCompressParams kPngCompressionParams[] = {
  PngCompressParams(PNG_ALL_FILTERS, Z_DEFAULT_STRATEGY, false),
  PngCompressParams(PNG_ALL_FILTERS, Z_FILTERED, false),
  PngCompressParams(PNG_FILTER_NONE, Z_DEFAULT_STRATEGY, false),
  PngCompressParams(PNG_FILTER_NONE, Z_FILTERED, false)
};

const size_t kParamCount = arraysize(kPngCompressionParams);

void ReadPngFromStream(png_structp read_ptr,
                       png_bytep data,
                       png_size_t length) {
  pagespeed::image_compression::ScanlineStreamInput* input =
    reinterpret_cast<pagespeed::image_compression::ScanlineStreamInput*>(
      png_get_io_ptr(read_ptr));

  if (input->offset() + length <= input->length()) {
    memcpy(data, input->data() + input->offset(), length);
    input->set_offset(input->offset() + length);

  } else {
    PS_DLOG_INFO(input->message_handler(), "Unexpected EOF.");

    // We weren't able to satisfy the read, so abort.
#if PNG_LIBPNG_VER >= 10400
  #ifndef __native_client__
    png_longjmp(read_ptr, 1);
  #else
    // On native client, invoking png_longjmp as above causes a
    // crash. Invoking longjmp directly, however, works fine.  For the
    // time being we use this workaround for native client builds. See
    // http://code.google.com/p/page-speed/issues/detail?id=644 for
    // more information.
    longjmp(read_ptr->longjmp_buffer, 1);
  #endif
#else
    longjmp(read_ptr->jmpbuf, 1);
#endif
  }
}

void WritePngToString(png_structp write_ptr,
                      png_bytep data,
                      png_size_t length) {
  GoogleString& buffer =
      *reinterpret_cast<GoogleString*>(png_get_io_ptr(write_ptr));
  buffer.append(reinterpret_cast<char*>(data), length);
}

void PngErrorFn(png_structp png_ptr, png_const_charp msg) {
  PS_DLOG_INFO(static_cast<MessageHandler*>(png_get_error_ptr(png_ptr)), \
               "libpng error: %s", msg);

  // Invoking the error function indicates a terminal failure, which
  // means we must longjmp to abort the libpng invocation.
#if PNG_LIBPNG_VER >= 10400
  #ifndef __native_client__
    png_longjmp(png_ptr, 1);
  #else
    // On native client, invoking png_longjmp as above causes a
    // crash. Invoking longjmp directly, however, works fine.  For the
    // time being we use this workaround for native client builds. See
    // http://code.google.com/p/page-speed/issues/detail?id=644 for
    // more information.
    longjmp(png_ptr->longjmp_buffer, 1);
  #endif

#else
  longjmp(png_ptr->jmpbuf, 1);
#endif
}

void PngWarningFn(png_structp png_ptr, png_const_charp msg) {
  PS_DLOG_INFO(static_cast<MessageHandler*>(png_get_error_ptr(png_ptr)), \
               "libpng warning: %s", msg);
}

// no-op
void PngFlush(png_structp write_ptr) {}

// Helper that reads an unsigned 32-bit integer from a stream of
// big-endian bytes.
inline uint32 ReadUint32FromBigEndianBytes(const unsigned char* read_head) {
  return (static_cast<uint32>(*read_head) << 24) +
      (static_cast<uint32>(*(read_head + 1)) << 16) +
      (static_cast<uint32>(*(read_head + 2)) << 8) +
      static_cast<uint32>(*(read_head + 3));
}

}  // namespace

namespace pagespeed {

namespace image_compression {

PngCompressParams::PngCompressParams(int level, int strategy, bool progressive)
  : filter_level(level),
    compression_strategy(strategy),
    try_best_compression(false),
    is_progressive(progressive) {
}

PngCompressParams::PngCompressParams(bool compression, bool progressive)
  : filter_level(PNG_FILTER_NONE),
    compression_strategy(Z_NO_COMPRESSION),
    try_best_compression(compression),
    is_progressive(progressive) {
}

ScopedPngStruct::ScopedPngStruct(Type type,
    MessageHandler* handler)
  : png_ptr_(NULL),
    info_ptr_(NULL),
    type_(type),
    message_handler_(handler) {
  DCHECK(type == READ || type == WRITE);
  switch (type) {
    case READ:
      png_ptr_ = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                        NULL, NULL, NULL);
      break;
    case WRITE:
      png_ptr_ = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                         NULL, NULL, NULL);
      break;
    default:
      PS_LOG_DFATAL(handler, "Invalid type");
  }
  if (png_ptr_ != NULL) {
    info_ptr_ = png_create_info_struct(png_ptr_);
  }

  png_set_error_fn(png_ptr_, message_handler_, &PngErrorFn, &PngWarningFn);
}

bool ScopedPngStruct::reset() {
  DCHECK(type_ == READ || type_ == WRITE);
  if (type_ == READ) {
    png_destroy_read_struct(&png_ptr_, &info_ptr_, NULL);
    png_ptr_ = png_create_read_struct(PNG_LIBPNG_VER_STRING,
                                      NULL, NULL, NULL);
  } else {
    png_destroy_write_struct(&png_ptr_, &info_ptr_);
    png_ptr_ = png_create_write_struct(PNG_LIBPNG_VER_STRING,
                                       NULL, NULL, NULL);
  }

  if (setjmp(png_jmpbuf(png_ptr_))) {
    PS_LOG_DFATAL(message_handler_, "Failed to initialize libpng.");
    return false;
  }

  if (png_ptr_ != NULL) {
    info_ptr_ = png_create_info_struct(png_ptr_);
  }

  png_set_error_fn(png_ptr_, message_handler_, &PngErrorFn, &PngWarningFn);

  return true;
}

ScopedPngStruct::~ScopedPngStruct() {
  switch (type_) {
    case READ:
      png_destroy_read_struct(&png_ptr_, &info_ptr_, NULL);
      break;
    case WRITE:
      png_destroy_write_struct(&png_ptr_, &info_ptr_);
      break;
    default:
      break;
  }
}

PngReaderInterface::PngReaderInterface() {
}

PngReaderInterface::~PngReaderInterface() {
}

PngOptimizer::PngOptimizer(MessageHandler* handler)
    : read_(ScopedPngStruct::READ, handler),
      write_(ScopedPngStruct::WRITE, handler),
      best_compression_(false),
      message_handler_(handler) {
}

PngOptimizer::~PngOptimizer() {
}

bool PngOptimizer::CreateOptimizedPng(const PngReaderInterface& reader,
                                      const GoogleString& in,
                                      GoogleString* out,
                                      MessageHandler* handler) {
  if (!read_.valid() || !write_.valid()) {
    PS_LOG_DFATAL(handler, "Invalid ScopedPngStruct r: %d, w: %d", \
                  read_.valid(), write_.valid());
    return false;
  }

  out->clear();

  // Configure error handlers.
  if (setjmp(png_jmpbuf(read_.png_ptr()))) {
    PS_LOG_INFO(handler, "libpng failed to decode the input image.");
    return false;
  }

  if (setjmp(png_jmpbuf(write_.png_ptr()))) {
    PS_LOG_INFO(handler, "libpng failed to create the output image.");
    return false;
  }

  if (!reader.ReadPng(in, read_.png_ptr(), read_.info_ptr(),
                      PNG_TRANSFORM_IDENTITY)) {
    return false;
  }

  if (!opng_validate_image(read_.png_ptr(), read_.info_ptr())) {
    return false;
  }

  // Copy the image data from the read structures to the write structures.
  if (!CopyReadToWrite()) {
    return false;
  }

  // Perform all possible lossless image reductions
  // (e.g. RGB->palette, etc).
  opng_reduce_image(write_.png_ptr(), write_.info_ptr(), OPNG_REDUCE_ALL);

  if (best_compression_) {
    return CreateBestOptimizedPngForParams(kPngCompressionParams, kParamCount,
                                           out);
  } else {
    PngCompressParams params(PNG_FILTER_NONE, Z_DEFAULT_STRATEGY, false);
    return CreateOptimizedPngWithParams(&write_, params, out);
  }
}

bool PngOptimizer::CreateBestOptimizedPngForParams(
    const PngCompressParams* param_list, size_t param_list_size,
    GoogleString* out) {
  bool success = false;
  for (size_t idx = 0; idx < param_list_size; ++idx) {
    ScopedPngStruct write(ScopedPngStruct::WRITE, message_handler_);
    GoogleString temp_output;
    // libpng doesn't allow for reuse of the write structs, so we must copy on
    // each iteration of the loop.
    CopyPngStructs(write_, &write);
    if (CreateOptimizedPngWithParams(&write, param_list[idx], &temp_output)) {
      // If this gives better compression update the output.
      if (out->empty() || out->size() > temp_output.size()) {
        out->swap(temp_output);
      }
      success |= true;
    }
  }
  return success;
}

bool PngOptimizer::CreateOptimizedPngWithParams(ScopedPngStruct* write,
    const PngCompressParams& params,
    GoogleString *out) {
  int compression_level =
      best_compression_ ? Z_BEST_COMPRESSION : Z_DEFAULT_COMPRESSION;
  png_set_compression_level(write->png_ptr(), compression_level);
  png_set_compression_mem_level(write->png_ptr(), 8);
  png_set_compression_strategy(write->png_ptr(), params.compression_strategy);
  png_set_filter(write->png_ptr(), PNG_FILTER_TYPE_BASE, params.filter_level);
  png_set_compression_window_bits(write->png_ptr(), 15);
  if (!WritePng(write, out)) {
    return false;
  }
  return true;
}

bool PngOptimizer::OptimizePng(const PngReaderInterface& reader,
                               const GoogleString& in,
                               GoogleString* out,
                               MessageHandler* handler) {
  PngOptimizer o(handler);
  return o.CreateOptimizedPng(reader, in, out, handler);
}

bool PngOptimizer::OptimizePngBestCompression(const PngReaderInterface& reader,
    const GoogleString& in,
    GoogleString* out,
    MessageHandler* handler) {
  PngOptimizer o(handler);
  o.EnableBestCompression();
  return o.CreateOptimizedPng(reader, in, out, handler);
}

PngReader::PngReader(MessageHandler* handler)
  : message_handler_(handler) {
}

PngReader::~PngReader() {
}

bool PngReader::ReadPng(const GoogleString& body,
                        png_structp png_ptr,
                        png_infop info_ptr,
                        int transforms,
                        bool require_opaque) const {
    ScanlineStreamInput input(message_handler_);
    input.Initialize(body);

    if (setjmp(png_jmpbuf(png_ptr))) {
      return false;
    }
    png_set_read_fn(png_ptr, &input, &ReadPngFromStream);
    png_read_png(png_ptr, info_ptr, transforms, NULL);

    if (require_opaque &&
        ((transforms & PNG_TRANSFORM_STRIP_ALPHA) == 0)) {
      // We're not guaranteed that the image is opaque already.

      int color_type = png_get_color_type(png_ptr, info_ptr);
      if ((color_type & PNG_COLOR_MASK_ALPHA) != 0) {
        // Image has an alpha channel. Make sure it's opaque, and
        // strip it.

        if (!IsAlphaChannelOpaque(png_ptr, info_ptr, message_handler_)) {
          return false;
        }
        if ((OPNG_REDUCE_STRIP_ALPHA &
             opng_reduce_image(png_ptr, info_ptr, OPNG_REDUCE_STRIP_ALPHA))
            == 0) {
          return false;
        }
      }
    }
    return true;
}

bool PngReader::GetAttributes(const GoogleString& body,
                              int* out_width,
                              int* out_height,
                              int* out_bit_depth,
                              int* out_color_type) const {
  // We need to read the PNG signature plus the IDAT chunk.
  //
  // Signature is 8 bytes, documentation:
  //  http://www.libpng.org/pub/png/spec/1.2/png-1.2-pdg.html#PNG-file-signature
  //
  // Chunk layout is 4 bytes chunk len + 4 bytes chunk name + chunk +
  // 4 bytes chunk CRC, documentation:
  //  http://www.libpng.org/pub/png/spec/1.2/png-1.2-pdg.html#Chunk-layout
  //
  // IDAT chunk is 13 bytes (see code for details), documentation:
  //  http://www.libpng.org/pub/png/spec/1.2/png-1.2-pdg.html#C.IHDR

  const size_t kPngSigBytesSize = 8;
  const size_t kChunkLenSize = 4;
  const size_t kChunkNameSize = 4;
  const size_t kIHDRChunkSize = 13;
  const size_t kChunkCRCSize = 4;

  const size_t kPngMinHeaderSize =
      kPngSigBytesSize +
      kChunkLenSize +
      kChunkNameSize +
      kIHDRChunkSize +
      kChunkCRCSize;

  if (body.size() < kPngMinHeaderSize) {
    // Not enough bytes for us to read, so abort early.
    return false;
  }

  const unsigned char* read_head =
      reinterpret_cast<const unsigned char*>(body.data());

  // Validate the PNG signature.
  if (png_sig_cmp(
          const_cast<unsigned char*>(read_head), 0, kPngSigBytesSize) != 0) {
    return false;
  }
  read_head += kPngSigBytesSize;

  // The first 4 bytes of the chunk contains the chunk length.
  const uint32 first_chunk_len = ReadUint32FromBigEndianBytes(read_head);
  if (first_chunk_len != kIHDRChunkSize) {
    return false;
  }
  read_head += kChunkLenSize;

  if (strncmp("IHDR", reinterpret_cast<const char*>(read_head), 4) != 0) {
    return false;
  }

  // Compute the CRC for the chunk (using zlib's CRC computer since
  // it's already available to us).
  uint32 computed_crc = crc32(0L, Z_NULL, 0);
  computed_crc =
      crc32(computed_crc, read_head, kChunkNameSize + kIHDRChunkSize);
  read_head += kChunkNameSize;

  // Extract the expected CRC, after the end of the IHDR data.
  uint32 expected_crc =
      ReadUint32FromBigEndianBytes(read_head + kIHDRChunkSize);
  if (expected_crc != computed_crc) {
    // CRC mismatch. Invalid chunk. Abort.
    return false;
  }

  // Now read the IHDR chunk contents. Its layout is:
  // width: 4 bytes
  // height: 4 bytes
  // bit_depth: 1 byte
  // color_type: 1 byte
  // other data: 3 bytes
  *out_width = ReadUint32FromBigEndianBytes(read_head);
  *out_height = ReadUint32FromBigEndianBytes(read_head + 4);
  *out_bit_depth = read_head[8];
  *out_color_type = read_head[9];
  return true;
}

bool PngOptimizer::WritePng(ScopedPngStruct* write, GoogleString* buffer) {
  if (setjmp(png_jmpbuf(write->png_ptr()))) {
    return false;
  }
  png_set_write_fn(write->png_ptr(), buffer, &WritePngToString, &PngFlush);
  png_write_png(
      write->png_ptr(), write->info_ptr(), PNG_TRANSFORM_IDENTITY, NULL);

  return true;
}

bool PngOptimizer::CopyReadToWrite() {
  return CopyPngStructs(read_, &write_);
}

bool PngOptimizer::CopyPngStructs(const ScopedPngStruct& from,
                                  ScopedPngStruct* to) {
  png_uint_32 width, height;
  int bit_depth, color_type, interlace_type, compression_type, filter_type;
  if (setjmp(png_jmpbuf(from.png_ptr()))) {
    return false;
  }
  png_get_IHDR(from.png_ptr(),
               from.info_ptr(),
               &width,
               &height,
               &bit_depth,
               &color_type,
               &interlace_type,
               &compression_type,
               &filter_type);

  if (setjmp(png_jmpbuf(to->png_ptr()))) {
    return false;
  }
  png_set_IHDR(to->png_ptr(),
               to->info_ptr(),
               width,
               height,
               bit_depth,
               color_type,
               interlace_type,
               compression_type,
               filter_type);

  // NOTE: if libpng's free_me capability is not enabled, sharing
  // rowbytes between the read and write structs will lead to a
  // double-free. Thus we test for the PNG_FREE_ME_SUPPORTED define
  // here.
#ifndef PNG_FREE_ME_SUPPORTED
#error PNG_FREE_ME_SUPPORTED is required or double-frees may happen.
#endif
  png_bytepp row_pointers = png_get_rows(from.png_ptr(), from.info_ptr());
  png_set_rows(to->png_ptr(), to->info_ptr(), row_pointers);

  png_colorp palette;
  int num_palette;
  if (png_get_PLTE(from.png_ptr(), from.info_ptr(), &palette, &num_palette) !=
      0) {
    png_set_PLTE(to->png_ptr(), to->info_ptr(), palette, num_palette);
  }

  // Transparency is not considered metadata, although tRNS is
  // ancillary.
  png_bytep trans;
  int num_trans;
  png_color_16p trans_values;
  if (png_get_tRNS(from.png_ptr(), from.info_ptr(), &trans, &num_trans,
                   &trans_values) != 0) {
    png_set_tRNS(to->png_ptr(), to->info_ptr(), trans, num_trans, trans_values);
  }

  double gamma;
  if (png_get_gAMA(from.png_ptr(), from.info_ptr(), &gamma) != 0) {
    png_set_gAMA(to->png_ptr(), to->info_ptr(), gamma);
  }

  // Do not copy bkgd, hist or sbit sections, since they are not
  // supported in most browsers.

  return true;
}

// static
bool PngReaderInterface::IsAlphaChannelOpaque(
    png_structp png_ptr, png_infop info_ptr,
    MessageHandler* handler) {
  png_uint_32 height;
  png_uint_32 width;
  int bit_depth;
  int color_type;
  if (setjmp(png_jmpbuf(png_ptr))) {
    return false;
  }
  png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
               NULL, NULL, NULL);

  if ((color_type & PNG_COLOR_MASK_ALPHA) == 0) {
    // Image doesn't have alpha.
    PS_LOG_DFATAL(handler, \
        "IsAlphaChannelOpaque called for image without alpha channel.");
    return false;
  }

  png_bytep trans;
  int num_trans;
  png_color_16p trans_values;
  if (png_get_tRNS(png_ptr,
                   info_ptr,
                   &trans,
                   &num_trans,
                   &trans_values) != 0) {
    if ((color_type & PNG_COLOR_MASK_PALETTE) != 0) {
      for (int idx = 0; idx < num_trans; ++idx) {
        if (trans[idx] != 0xff) {
          return false;
        }
      }
      return true;
    } else {
      // Non-paletted image with a tRNS block is transparent
      return false;
    }
  } else {
    // There is no tRNS block.
    if ((color_type & PNG_COLOR_MASK_PALETTE) != 0) {
      // If we go this far, we have an image with
      // PNG_COLOR_MASK_ALPHA but no tRNS block. We're confused.
      PS_LOG_INFO(handler, "PNG_COLOR_MASK is set but could not read tRNS.");
      return false;
    }
  }

  int channels = png_get_channels(png_ptr, info_ptr);

  if (color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
    if (channels != 4) {
      PS_LOG_DFATAL(handler, \
          "Encountered unexpected number of channels for RGBA image: %d", \
          channels);
      return false;
    }
  } else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
    if (channels != 2) {
      PS_LOG_DFATAL(handler, \
        "Encountered unexpected number of channels for Gray + Alpha image:" \
        " %d", channels);
      return false;
    }
  } else {
    PS_LOG_DFATAL(handler, \
        "Encountered alpha image of unknown type :%d", color_type);
    return false;
  }

  // We currently detect alpha only for 8/16 bit Gray/TrueColor with Alpha
  // channel. Only 8 or 16 bit depths are supported for these modes.
  if (bit_depth % 8 != 0) {
    PS_DLOG_INFO(handler, "Received unexpected bit_depth: %d", bit_depth);
    return false;
  }

  int bytes_per_channel = bit_depth / 8;
  int bytes_per_pixel = channels * bytes_per_channel;
  png_bytepp row_pointers = png_get_rows(png_ptr, info_ptr);

  // Alpha channel is always the last channel.
  png_uint_32 alpha_byte_offset = (channels - 1) * bytes_per_channel;
  for (png_uint_32 row = 0; row < height; ++row) {
    unsigned char* row_bytes =
        static_cast<unsigned char*>(*(row_pointers + row));
    for (png_uint_32 pixel = 0; pixel < width * bytes_per_pixel;
         pixel += bytes_per_pixel) {
      for (int alpha_byte = 0; alpha_byte < bytes_per_channel;
           ++alpha_byte) {
        if ((row_bytes[pixel + alpha_byte_offset + alpha_byte] & 0xff) !=
            0xff) {
          return false;
        }
      }
    }
  }

  return true;
}

// static
bool PngReaderInterface::GetBackgroundColor(
    png_structp png_ptr, png_infop info_ptr,
    unsigned char *red, unsigned char* green, unsigned char* blue,
    MessageHandler* handler) {
  if (setjmp(png_jmpbuf(png_ptr))) {
    return false;
  }
  if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) {
    return false;
  }
  png_color_16p bg;
  png_get_bKGD(png_ptr, info_ptr, &bg);
  const png_byte bit_depth = png_get_bit_depth(png_ptr, info_ptr);
  const png_byte color_type = png_get_color_type(png_ptr, info_ptr);

  if (bit_depth == 16) {
    // Downsample 16bit to 8bit.
    *red = bg->red >> 8;
    *green = bg->green >> 8;
    *blue = bg->blue >> 8;
  } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
    // Upsample to 8bit.
    const int scale = 255 / ((bit_depth << 1) - 1);
    const unsigned char gray_8bit = bg->gray * scale;
    *red = gray_8bit;
    *green = gray_8bit;
    *blue = gray_8bit;
  } else if (bit_depth == 8) {
    *red = static_cast<unsigned char>(bg->red);
    *green = static_cast<unsigned char>(bg->green);
    *blue = static_cast<unsigned char>(bg->blue);
  } else {
    // TODO(bmcquade): we currently fall through to this case for
    // 1-bit paletted images. Consider adding support.
    PS_DLOG_INFO(handler, \
                 "Unsupported bit_depth: %d color type: %d", \
                 static_cast<int>(bit_depth), static_cast<int>(color_type));
    return false;
  }

  return true;
}

PngScanlineReader::PngScanlineReader(MessageHandler* handler)
    : read_(ScopedPngStruct::READ, handler),
      current_scanline_(0),
      transform_(PNG_TRANSFORM_IDENTITY),
      require_opaque_(false),
      message_handler_(handler) {
}

jmp_buf* PngScanlineReader::GetJmpBuf() {
  jmp_buf& buf = png_jmpbuf(read_.png_ptr());
  return &buf;
}

bool PngScanlineReader::Reset() {
  if (!read_.reset()) {
    return false;
  }
  current_scanline_ = 0;
  transform_ = PNG_TRANSFORM_IDENTITY;
  require_opaque_ = false;
  return true;
}

bool PngScanlineReader::InitializeRead(const PngReaderInterface& reader,
                                       const GoogleString& in) {
  bool is_opaque = false;
  return InitializeRead(reader, in, &is_opaque);
}

bool PngScanlineReader::InitializeRead(const PngReaderInterface& reader,
                                       const GoogleString& in,
                                       bool* is_opaque) {
  if (!read_.valid()) {
    PS_LOG_DFATAL(message_handler_, \
                  "Invalid ScopedPngStruct r: %d", read_.valid());
    return false;
  }

  *is_opaque = require_opaque_;
  if (!reader.ReadPng(in, read_.png_ptr(), read_.info_ptr(), transform_,
                      require_opaque_)) {
    return false;
  }

  if (setjmp(png_jmpbuf(read_.png_ptr()))) {
    return false;
  }
  if (!require_opaque_) {
    int color_type = png_get_color_type(read_.png_ptr(), read_.info_ptr());
    *is_opaque = ((color_type & PNG_COLOR_MASK_ALPHA) == 0);
    if (!(*is_opaque) &&
        PngReaderInterface::IsAlphaChannelOpaque(
            read_.png_ptr(), read_.info_ptr(), message_handler_)) {
      // Clear the read pointers.
      if (!read_.reset()) {
        return false;
      }
      *is_opaque = true;
      return reader.ReadPng(in, read_.png_ptr(), read_.info_ptr(),
                            transform_ | PNG_TRANSFORM_STRIP_ALPHA);
    }
  }

  return true;
}

PngScanlineReader::~PngScanlineReader() {
}

size_t PngScanlineReader::GetBytesPerScanline() {
  return png_get_rowbytes(read_.png_ptr(), read_.info_ptr());
}

bool PngScanlineReader::HasMoreScanLines() {
  size_t height = png_get_image_height(read_.png_ptr(), read_.info_ptr());
  return current_scanline_ < height;
}

ScanlineStatus PngScanlineReader::ReadNextScanlineWithStatus(
    void** out_scanline_bytes) {
  if (!HasMoreScanLines()) {
    return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler_,
                            SCANLINE_STATUS_INVOCATION_ERROR,
                            SCANLINE_PNGREADER,
                            "No more scanlines in the input image.");
  }

  if (setjmp(png_jmpbuf(read_.png_ptr()))) {
    return PS_LOGGED_STATUS(PS_LOG_INFO, message_handler_,
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            SCANLINE_PNGREADER,
                            "libpng failed to decode the image.");
  }
  png_bytepp row_pointers = png_get_rows(read_.png_ptr(), read_.info_ptr());
  *out_scanline_bytes = static_cast<void*>(*(row_pointers + current_scanline_));
  current_scanline_++;
  return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
}

void PngScanlineReader::set_transform(int transform) {
  transform_ = transform;
}

void PngScanlineReader::set_require_opaque(bool require_opaque) {
  require_opaque_ = require_opaque;
}

size_t PngScanlineReader::GetImageHeight() {
  return png_get_image_height(read_.png_ptr(), read_.info_ptr());
}

size_t PngScanlineReader::GetImageWidth() {
  return png_get_image_width(read_.png_ptr(), read_.info_ptr());
}

int PngScanlineReader::GetColorType() {
  return png_get_color_type(read_.png_ptr(), read_.info_ptr());
}

bool PngScanlineReader::IsProgressive() {
  return (png_get_interlace_type(
      read_.png_ptr(), read_.info_ptr()) == PNG_INTERLACE_ADAM7);
}

PixelFormat PngScanlineReader::GetPixelFormat() {
  int bit_depth = png_get_bit_depth(read_.png_ptr(), read_.info_ptr());
  int color_type = png_get_color_type(read_.png_ptr(), read_.info_ptr());
  if (bit_depth == 8 && color_type == PNG_COLOR_TYPE_GRAY) {
    return GRAY_8;
  } else if (bit_depth == 8 && color_type == PNG_COLOR_TYPE_RGB) {
    return RGB_888;
  } else if (bit_depth == 8 && color_type == PNG_COLOR_TYPE_RGB_ALPHA) {
    return RGBA_8888;
  }

  return UNSUPPORTED;
}

bool PngScanlineReader::GetBackgroundColor(
  unsigned char* red, unsigned char* green, unsigned char* blue) {
  return PngReaderInterface::GetBackgroundColor(
      read_.png_ptr(), read_.info_ptr(), red, green, blue, message_handler_);
}

ScanlineStatus PngScanlineReader::InitializeWithStatus(
    const void* /* image_buffer */,
    size_t /* buffer_length */) {
  return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler_,
                          SCANLINE_STATUS_INVOCATION_ERROR,
                          SCANLINE_PNGREADER,
                          "unexpected call to InitializeWithStatus()");
}

PngScanlineReaderRaw::PngScanlineReaderRaw(
    MessageHandler* handler)
  : pixel_format_(UNSUPPORTED),
    is_progressive_(false),
    height_(0),
    width_(0),
    bytes_per_row_(0),
    row_(0),
    was_initialized_(false),
    message_handler_(handler) {
}

PngScanlineReaderRaw::~PngScanlineReaderRaw() {
}

bool PngScanlineReaderRaw::Reset() {
  pixel_format_ = UNSUPPORTED;
  is_progressive_ = false;
  height_ = 0;
  width_ = 0;
  bytes_per_row_ = 0;
  row_ = 0;
  was_initialized_ = false;
  row_pointers_.reset();
  png_struct_.reset();
  png_input_->Reset();
  return true;
}

// Initialize the reader with the given image stream. Note that image_buffer
// must remain unchanged until the last call to ReadNextScanline().
ScanlineStatus PngScanlineReaderRaw::InitializeWithStatus(
    const void* image_buffer,
    size_t buffer_length) {
  // Reset the reader if it has been initialized before.
  if (was_initialized_ && !Reset()) {
    return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler_,
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            SCANLINE_PNGREADERRAW,
                            "Reset()");
  }

  png_struct_.reset(new ScopedPngStruct(ScopedPngStruct::READ,
                                        message_handler_));
  if (png_struct_ == NULL) {
    return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler_,
                            SCANLINE_STATUS_MEMORY_ERROR,
                            SCANLINE_PNGREADERRAW,
                            "Failed to create ScopedPngStruct");
  }

  // Allocate and initialize png_input_, if that has not been done.
  if (png_input_ == NULL) {
    png_input_.reset(new ScanlineStreamInput(message_handler_));
    if (png_input_ == NULL) {
      return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler_,
                              SCANLINE_STATUS_MEMORY_ERROR,
                              SCANLINE_PNGREADERRAW,
                              "new ScanlineStreamInput");
    }
  }

  if (!png_struct_->valid()) {
    return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler_,
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            SCANLINE_PNGREADERRAW,
                            "png_struct_->valid()");
  }

  png_structp png_ptr = png_struct_->png_ptr();
  png_infop info_ptr = png_struct_->info_ptr();

  if (setjmp(png_jmpbuf(png_ptr)) != 0) {
    // Jump to here if any error happens.
    png_struct_.reset();
    return PS_LOGGED_STATUS(PS_LOG_INFO, message_handler_,
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            SCANLINE_PNGREADERRAW,
                            "libpng failed to decode the image.");
  }

  // Set up data feed for libpng.
  png_input_->Initialize(image_buffer, buffer_length);
  png_set_read_fn(png_ptr, png_input_.get(), ReadPngFromStream);

  png_uint_32 width, height;
  int32 bit_depth, color_type, interlace_type;
  png_read_info(png_ptr, info_ptr);
  const int ok = png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth,
                              &color_type, &interlace_type, NULL, NULL);
  if (ok == 0) {
    png_struct_.reset();
    return PS_LOGGED_STATUS(PS_LOG_INFO, message_handler_,
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            SCANLINE_PNGREADERRAW,
                            "png_get_IHDR() failed.");
  }

  // Set up transformations. We will transform the input to one of these
  // formats: GRAY_8, RGB_888, and RGBA_8888.
  //
  // Reference for setting up transformations is in the png_read_png() function
  // in pngread.c.
  //
  // Strip 16 bit per color down to 8 bits per color.
  png_set_strip_16(png_ptr);

  // Expand grayscale images to full 8 bits from 1, 2, or 4 bits per pixel.
  // Expand paletted or RGB images with transparency to full alpha channels
  // so the data will be available as RGBA quartets.
  if ((bit_depth < 8) ||
      (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) {
    png_set_expand(png_ptr);
  }

  // Set up callbacks for interlacing (progressive) image.
  png_set_interlace_handling(png_ptr);

  // Update the reader struct after setting the transformations.
  png_read_update_info(png_ptr, info_ptr);

  // Get the updated color type.
  color_type = png_get_color_type(png_ptr, info_ptr);

  if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
      color_type == PNG_COLOR_TYPE_PALETTE) {
    if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
      // Expand Gray_Alpha to RGBA.
      png_set_gray_to_rgb(png_ptr);
    } else {
      // Expand paletted colors into true RGB triplets.
      png_set_palette_to_rgb(png_ptr);
    }

    // Update the reader struct after modifying the transformations.
    png_read_update_info(png_ptr, info_ptr);

    // Get the updated color type.
    color_type = png_get_color_type(png_ptr, info_ptr);
  }

  // Determine the pixel format and the number of channels.
  switch (color_type) {
    case PNG_COLOR_TYPE_GRAY:
      pixel_format_ = GRAY_8;
      break;
    case PNG_COLOR_TYPE_RGB:
    case PNG_COLOR_TYPE_PALETTE:
      pixel_format_ = RGB_888;
      break;
    case PNG_COLOR_TYPE_RGBA:
      pixel_format_ = RGBA_8888;
      break;
    default:  // Unrecognized format.
      png_struct_.reset();
      return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler_,
                              SCANLINE_STATUS_INTERNAL_ERROR,
                              SCANLINE_PNGREADERRAW,
                              "unrecognized color type");
  }

  // Copy the information to the object properties.
  width_ = width;
  height_ = height;
  bytes_per_row_ = width_ * GetNumChannelsFromPixelFormat(pixel_format_,
                                                          message_handler_);
  row_ = 0;
  is_progressive_ = (interlace_type == PNG_INTERLACE_ADAM7);
  was_initialized_ = true;
  return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
}

ScanlineStatus PngScanlineReaderRaw::ReadNextScanlineWithStatus(
    void** out_scanline_bytes) {
  if (!was_initialized_ || !HasMoreScanLines()) {
    return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler_,
                            SCANLINE_STATUS_INVOCATION_ERROR,
                            SCANLINE_PNGREADERRAW,
                            "The reader was not initialized or the image "
                            "does not have any more scanlines.");
  }

  png_structp png_ptr = png_struct_->png_ptr();

  // In case libpng has an error, program will jump to the following 'setjmp',
  // which will have value of non-zero. To clean up memory properly, we have
  // to define row_pointers before 'setjmp' and clean it up when error happens.
  if (setjmp(png_jmpbuf(png_ptr)) != 0) {
    Reset();
    return PS_LOGGED_STATUS(PS_LOG_INFO, message_handler_,
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            SCANLINE_PNGREADERRAW,
                            "libpng failed to decode the image.");
  }

  // At the first time when ReadNextScanline() is called, we allocate buffer
  // to store the decoded pixels. For non-progressive (non-interlacing)
  // image, we need buffer to store a row of pixels. For progressive image,
  // we need buffer to store the entire image. For progressive image, we
  // also decode the entire image at the first call.
  if (row_ == 0) {
    if (!is_progressive_) {
      image_buffer_.reset(new png_byte[bytes_per_row_]);
    } else {
      image_buffer_.reset(new png_byte[bytes_per_row_ * height_]);
      // For a progressive PNG, we have to decode the entire image before
      // rendering any row. So at the first time when ReadNextScanline()
      // is called, we decode the entire image into image_buffer_.
      if (image_buffer_ != NULL) {
        // Initialize an array of pointers, which specify the address of rows.
        row_pointers_.reset(new png_bytep[height_]);
        if (row_pointers_ == NULL) {
          Reset();
          return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler_,
                                  SCANLINE_STATUS_MEMORY_ERROR,
                                  SCANLINE_PNGREADERRAW,
                                  "Failed to allocate memory.");
        }
        for (size_t i = 0; i < height_; ++i) {
          row_pointers_[i] = image_buffer_.get() + i * bytes_per_row_;
        }

        // Decode the entire image. The results are stored in image_buffer_.
        png_read_image(png_ptr, row_pointers_.get());
      }
    }
    if (image_buffer_ == NULL) {
      Reset();
      return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler_,
                              SCANLINE_STATUS_MEMORY_ERROR,
                              SCANLINE_PNGREADERRAW,
                              "Failed to allocate memory.");
    }
  }

  if (!is_progressive_) {
    // For a non-progressive PNG, we decode the image a row at a time.
    png_read_row(png_ptr, image_buffer_.get(), NULL);
    *out_scanline_bytes = static_cast<void*>(image_buffer_.get());
  } else {
    // For a progressive PNG, we simply point the output to the corresponding
    // row, because the image has already been decoded.
    *out_scanline_bytes =
      static_cast<void*>(image_buffer_.get() + row_ * bytes_per_row_);
  }

  ++row_;
  row_pointers_.reset();
  return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
}

PngScanlineWriter::PngScanlineWriter(MessageHandler* handler) :
  width_(0),
  height_(0),
  row_(0),
  pixel_format_(UNSUPPORTED),
  was_initialized_(false),
  message_handler_(handler) {
}

PngScanlineWriter::~PngScanlineWriter() {
}

bool PngScanlineWriter::Reset() {
  width_ = 0;
  height_ = 0;
  row_ = 0;
  pixel_format_ = UNSUPPORTED;
  png_struct_.reset();
  was_initialized_ = false;
  return true;
}

bool PngScanlineWriter::Validate(const PngCompressParams* params,
                                 GoogleString* png_image) {
  if (params != NULL) {
    // PNG_NO_FILTERS == 0
    // PNG_ALL_FILTERS == (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP |
    //                     PNG_FILTER_AVG | PNG_FILTER_PAETH)
    if (params->filter_level & (~PNG_ALL_FILTERS)) {
      PS_LOG_DFATAL(message_handler_, \
          "Filter level must be one of the following values, " \
          "or bitwise OR of some of them: PNG_NO_FILTERS, PNG_FILTER_NONE, " \
          "PNG_FILTER_SUB, PNG_FILTER_UP, PNG_FILTER_AVG, PNG_FILTER_PAETH.");
    }

    switch (params->compression_strategy) {
      case Z_DEFAULT_STRATEGY:
      case Z_FILTERED:
      case Z_HUFFMAN_ONLY:
      case Z_RLE:
      case Z_FIXED:
        break;
      default:
        PS_LOG_DFATAL(message_handler_, \
            "Compression strategy must be one of the following values: " \
            "Z_DEFAULT_STRATEGY, Z_FILTERED, Z_HUFFMAN_ONLY, Z_RLE, Z_FIXED.");
        return false;
    }
  }

  if (png_image == NULL) {
    PS_LOG_DFATAL(message_handler_, "Ouput PNG image cannot be NULL.");
    return false;
  }
  return true;
}

ScanlineStatus PngScanlineWriter::InitWithStatus(const size_t width,
                                                 const size_t height,
                                                 PixelFormat pixel_format) {
  // Reset the writer if it has been initialized before.
  if (was_initialized_ && !Reset()) {
    return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler_,
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            SCANLINE_PNGWRITER, "Reset()");
  }

  if (png_struct_ == NULL) {
    png_struct_.reset(new ScopedPngStruct(ScopedPngStruct::WRITE,
                                          message_handler_));
    if (png_struct_ == NULL) {
      return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler_,
                              SCANLINE_STATUS_MEMORY_ERROR,
                              SCANLINE_PNGWRITER,
                              "Failed to create ScopedPngStruct");
    }
  }

  if (!png_struct_->valid()) {
    return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler_,
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            SCANLINE_PNGWRITER,
                            "png_struct_->valid()");
  }

  if (width < 1 || height < 1) {
    return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler_,
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            SCANLINE_PNGWRITER,
                            "dimensions are not positive");
  }

  switch (pixel_format) {
    case GRAY_8:
    case RGB_888:
    case RGBA_8888:
      break;
    default:
      return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler_,
                              SCANLINE_STATUS_INTERNAL_ERROR,
                              SCANLINE_PNGWRITER,
                              "unknown pixel format: %d",
                              pixel_format);
  }

  width_ = width;
  height_ = height;
  pixel_format_ = pixel_format;
  bytes_per_row_ = width * GetBytesPerPixel(pixel_format);
  return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
}

// Initialize the basic parameter for writing the image. To use the default
// compression parameters, set 'params' to NULL.
ScanlineStatus PngScanlineWriter::InitializeWriteWithStatus(
    const void* const params,
    GoogleString* const png_image) {
  const PngCompressParams* png_params =
      static_cast<const PngCompressParams*>(params);

  // Validate input arguments.
  if (!Validate(png_params, png_image)) {
    return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler_,
                            SCANLINE_STATUS_INVOCATION_ERROR,
                            SCANLINE_PNGWRITER,
                            "Validate()");
  }

  png_image->clear();

  const int bit_depth = 8;
  int color_type = -1;
  switch (pixel_format_) {
    case GRAY_8:
      color_type = PNG_COLOR_TYPE_GRAY;
      break;
    case RGB_888:
      color_type = PNG_COLOR_TYPE_RGB;
      break;
    default:  // RGBA_8888. Init() has filtered out invalid values.
      color_type = PNG_COLOR_TYPE_RGB_ALPHA;
  }

  png_structp png_ptr = png_struct_->png_ptr();
  png_infop info_ptr = png_struct_->info_ptr();

  if (setjmp(png_jmpbuf(png_ptr)) != 0) {
    // Jump to here if any error happens.
    Reset();
    return PS_LOGGED_STATUS(PS_LOG_INFO, message_handler_,
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            SCANLINE_PNGWRITER,
                            "libpng failed to compress the image.");
  }

  png_set_compression_strategy(png_ptr, png_params->compression_strategy);
  png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, png_params->filter_level);
  png_set_write_fn(png_ptr, png_image, &WritePngToString, &PngFlush);

  int interlace_type = (png_params->is_progressive ?
                        PNG_INTERLACE_ADAM7 :
                        PNG_INTERLACE_NONE);
  png_set_IHDR(png_ptr, info_ptr, width_, height_, bit_depth, color_type,
               interlace_type, PNG_COMPRESSION_TYPE_DEFAULT,
               PNG_FILTER_TYPE_DEFAULT);

  png_write_info(png_ptr, info_ptr);
  try_best_compression_ = png_params->try_best_compression;
  pixel_buffer_.reset(new unsigned char[height_ * bytes_per_row_]);
  was_initialized_ = true;
  return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
}

// Write a scanline with the data provided. Return false in case of error.
ScanlineStatus PngScanlineWriter::WriteNextScanlineWithStatus(
    const void* const scanline_bytes) {
  if (was_initialized_ && row_ < height_) {
    // Buffer the scanlines.
    memcpy(pixel_buffer_.get() + row_ * bytes_per_row_, scanline_bytes,
           bytes_per_row_);
    ++row_;
    return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
  }
  return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler_,
                          SCANLINE_STATUS_INVOCATION_ERROR,
                          SCANLINE_PNGWRITER,
                          "failed preconditions to write scanline");
}

// Finalize write structure once all scanlines are written.
ScanlineStatus PngScanlineWriter::FinalizeWriteWithStatus() {
  if (!was_initialized_ || row_ != height_) {
    Reset();
    return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler_,
                            SCANLINE_STATUS_INVOCATION_ERROR,
                            SCANLINE_PNGWRITER,
                            "not initialized or not all rows written");
  }

  net_instaweb::scoped_array<unsigned char*> row_pointers(
      new unsigned char*[height_]);
  for (size_t row = 0; row < height_; ++row) {
    row_pointers[row] = pixel_buffer_.get() + row * bytes_per_row_;
  }
  png_set_rows(png_struct_->png_ptr(), png_struct_->info_ptr(),
               row_pointers.get());
  png_write_png(png_struct_->png_ptr(), png_struct_->info_ptr(),
                PNG_TRANSFORM_IDENTITY, NULL);

  if (try_best_compression_) {
    if (!DoBestCompression()) {
      Reset();
      return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler_,
                              SCANLINE_STATUS_INTERNAL_ERROR,
                              SCANLINE_PNGWRITER,
                              "Failed to do the best compression");
    }
  }
  return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
}

bool PngScanlineWriter::DoBestCompression() {
  GoogleString* png_image = static_cast<GoogleString*>(
      png_get_io_ptr(png_struct_->png_ptr()));
  ScanlineStreamInput png_input(message_handler_);
  png_input.Initialize(*png_image);
  ScopedPngStruct png_read(ScopedPngStruct::READ, message_handler_);

  if (setjmp(png_jmpbuf(png_read.png_ptr())) != 0) {
    // Jump to here if any error happens.
    Reset();
    return false;
  }

  png_set_read_fn(png_read.png_ptr(), &png_input, &ReadPngFromStream);
  png_read_png(png_read.png_ptr(), png_read.info_ptr(), PNG_TRANSFORM_IDENTITY,
               NULL);
  opng_reduce_image(png_read.png_ptr(), png_read.info_ptr(), OPNG_REDUCE_ALL);

  int min_size = png_image->length();
  for (size_t i = 0; i < kParamCount; ++i) {
    ScopedPngStruct png_write(ScopedPngStruct::WRITE, message_handler_);
    PngOptimizer::CopyPngStructs(png_read, &png_write);

    if (setjmp(png_jmpbuf(png_write.png_ptr())) != 0) {
      // Jump to here if any error happens.
      Reset();
      return false;
    }

    png_set_compression_level(png_write.png_ptr(), Z_BEST_COMPRESSION);
    png_set_compression_mem_level(png_write.png_ptr(), 8);
    png_set_compression_window_bits(png_write.png_ptr(), 15);
    png_set_compression_strategy(png_write.png_ptr(),
                                 kPngCompressionParams[i].compression_strategy);
    png_set_filter(png_write.png_ptr(), PNG_FILTER_TYPE_BASE,
                   kPngCompressionParams[i].filter_level);

    GoogleString recompressed_image;
    png_set_write_fn(png_write.png_ptr(), &recompressed_image,
                     &WritePngToString, &PngFlush);
    png_write_png(png_write.png_ptr(), png_write.info_ptr(),
                  PNG_TRANSFORM_IDENTITY, NULL);

    int recompressed_length = recompressed_image.length();
    if (min_size > recompressed_length) {
      min_size = recompressed_length;
      swap(*png_image, recompressed_image);
    }
  }

  return true;
}

}  // namespace image_compression

}  // namespace pagespeed
