/*
 * Copyright 2010 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: jmaessen@google.com (Jan Maessen)

#include "net/instaweb/rewriter/public/image.h"

#include <algorithm>
#include <cstddef>

#include "base/logging.h"
#include "net/instaweb/rewriter/cached_result.pb.h"
#include "net/instaweb/rewriter/public/image_data_lookup.h"
#include "net/instaweb/rewriter/public/image_url_encoder.h"
#include "net/instaweb/rewriter/public/webp_optimizer.h"
#include "pagespeed/kernel/base/annotated_message_handler.h"
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/message_handler.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/statistics.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/http/content_type.h"
#include "pagespeed/kernel/image/gif_reader.h"
#include "pagespeed/kernel/image/image_analysis.h"
#include "pagespeed/kernel/image/image_converter.h"
#include "pagespeed/kernel/image/image_frame_interface.h"
#include "pagespeed/kernel/image/image_resizer.h"
#include "pagespeed/kernel/image/image_util.h"
#include "pagespeed/kernel/image/jpeg_optimizer.h"
#include "pagespeed/kernel/image/jpeg_utils.h"
#include "pagespeed/kernel/image/png_optimizer.h"
#include "pagespeed/kernel/image/read_image.h"
#include "pagespeed/kernel/image/scanline_interface.h"
#include "pagespeed/kernel/image/scanline_status.h"
#include "pagespeed/kernel/image/scanline_utils.h"
#include "pagespeed/kernel/image/webp_optimizer.h"

extern "C" {
#ifdef USE_SYSTEM_LIBWEBP
#include "webp/decode.h"
#else
#include "third_party/libwebp/src/webp/decode.h"
#endif
#ifdef USE_SYSTEM_LIBPNG
#include "png.h"  // NOLINT
#else
#include "third_party/libpng/src/png.h"
#endif
}

using pagespeed::image_compression::AnalyzeImage;
using pagespeed::image_compression::ConversionTimeoutHandler;
using pagespeed::image_compression::CreateScanlineReader;
using pagespeed::image_compression::CreateScanlineWriter;
using pagespeed::image_compression::GifReader;
using pagespeed::image_compression::GRAY_8;
using pagespeed::image_compression::ImageConverter;
using pagespeed::image_compression::ImageFormat;
using pagespeed::image_compression::ImageFormatToString;
using pagespeed::image_compression::JpegCompressionOptions;
using pagespeed::image_compression::JpegScanlineWriter;
using pagespeed::image_compression::JpegUtils;
using pagespeed::image_compression::OptimizeJpegWithOptions;
using pagespeed::image_compression::PixelFormat;
using pagespeed::image_compression::PngCompressParams;
using pagespeed::image_compression::PngOptimizer;
using pagespeed::image_compression::PngReader;
using pagespeed::image_compression::PngReaderInterface;
using pagespeed::image_compression::PngScanlineWriter;
using pagespeed::image_compression::PreferredLibwebpLevel;
using pagespeed::image_compression::RETAIN;
using pagespeed::image_compression::RGB_888;
using pagespeed::image_compression::RGBA_8888;
using pagespeed::image_compression::ScanlineReaderInterface;
using pagespeed::image_compression::ScanlineResizer;
using pagespeed::image_compression::ScanlineWriterInterface;
using pagespeed::image_compression::WebpConfiguration;
using pagespeed::image_compression::WEBP_NONE;
using pagespeed::image_compression::WEBP_LOSSY;
using pagespeed::image_compression::WEBP_LOSSLESS;
using pagespeed::image_compression::WEBP_ANIMATED;

namespace net_instaweb {

namespace ImageHeaders {

const char kPngHeader[] = "\x89PNG\r\n\x1a\n";
const size_t kPngHeaderLength = STATIC_STRLEN(kPngHeader);
const char kPngIHDR[] = "\0\0\0\x0dIHDR";
const size_t kPngIntSize = 4;
const size_t kPngSectionHeaderLength = 2 * kPngIntSize;
const size_t kIHDRDataStart = kPngHeaderLength + kPngSectionHeaderLength;
const size_t kPngSectionMinSize = kPngSectionHeaderLength + kPngIntSize;
const size_t kPngColourTypeOffset = kIHDRDataStart + 2 * kPngIntSize + 1;
const char kPngAlphaChannel = 0x4;  // bit of ColourType set for alpha channel
const char kPngIDAT[] = "IDAT";
const char kPngtRNS[] = "tRNS";

const char kGifHeader[] = "GIF8";
const size_t kGifHeaderLength = STATIC_STRLEN(kGifHeader);
const size_t kGifDimStart = kGifHeaderLength + 2;
const size_t kGifIntSize = 2;

const size_t kJpegIntSize = 2;
const int64 kMaxJpegQuality = 100;
const int64 kQualityForJpegWithUnkownQuality = 85;

}  // namespace ImageHeaders

namespace {

const char kGifString[] = "gif";
const char kPngString[] = "png";
const uint8 kAlphaOpaque = 255;

void UpdateWebpStats(bool ok, bool was_timed_out, int64 time_elapsed_ms,
                     Image::ConversionVariables::VariableType var_type,
                     Image::ConversionVariables* conversion_vars) {
  if (conversion_vars != NULL) {
    Image::ConversionBySourceVariable* the_var = conversion_vars->Get(var_type);
    if (the_var != NULL) {
      if (was_timed_out) {
        the_var->timeout_count->Add(1);
        DCHECK(!ok);
      } else {
        if (ok) {
          the_var->success_ms->Add(time_elapsed_ms);
        } else {
          the_var->failure_ms->Add(time_elapsed_ms);
        }
      }
    }
  }
}

// TODO(huibao): Unify ImageType and ImageFormat.
ImageFormat ImageTypeToImageFormat(ImageType type) {
  ImageFormat format = pagespeed::image_compression::IMAGE_UNKNOWN;
  switch (type) {
    case IMAGE_UNKNOWN:
      format = pagespeed::image_compression::IMAGE_UNKNOWN;
      break;
    case IMAGE_JPEG:
      format = pagespeed::image_compression::IMAGE_JPEG;
      break;
    case IMAGE_PNG:
      format = pagespeed::image_compression::IMAGE_PNG;
      break;
    case IMAGE_GIF:
      format = pagespeed::image_compression::IMAGE_GIF;
      break;
    case IMAGE_WEBP:
    case IMAGE_WEBP_LOSSLESS_OR_ALPHA:
    case IMAGE_WEBP_ANIMATED:
      format = pagespeed::image_compression::IMAGE_WEBP;
      break;
  }
  return format;
}

ImageFormat GetOutputImageFormat(ImageFormat in_format) {
  if (in_format == pagespeed::image_compression::IMAGE_GIF) {
    return pagespeed::image_compression::IMAGE_PNG;
  } else {
    return in_format;
  }
}

ScanlineWriterInterface* CreateUncompressedPngWriter(
    size_t width, size_t height, GoogleString* output,
    MessageHandler* handler, bool use_transparent_for_blank_image) {
  PngCompressParams config(PNG_FILTER_NONE, Z_NO_COMPRESSION, false);
  PixelFormat pixel_format =
      use_transparent_for_blank_image ?
      RGBA_8888 :
      RGB_888;
  return CreateScanlineWriter(
      pagespeed::image_compression::IMAGE_PNG,
      pixel_format, width, height, &config, output, handler);
}

}  // namespace

// TODO(jmaessen): Put ImageImpl into private namespace.

class ImageImpl : public Image {
 public:
  ImageImpl(const StringPiece& original_contents,
            const GoogleString& url,
            const StringPiece& file_prefix,
            CompressionOptions* options,
            Timer* timer,
            MessageHandler* handler);
  ImageImpl(int width, int height, ImageType type,
            const StringPiece& tmp_dir,
            Timer* timer, MessageHandler* handler,
            CompressionOptions* options);

  virtual void Dimensions(ImageDim* natural_dim);
  virtual bool ResizeTo(const ImageDim& new_dim);
  virtual bool DrawImage(Image* image, int x, int y);
  virtual bool EnsureLoaded(bool output_useful);
  virtual bool ShouldConvertToProgressive(int64 quality) const;
  virtual void SetResizedDimensions(const ImageDim& dims) { dims_ = dims; }
  virtual void SetTransformToLowRes();
  virtual const GoogleString& url() { return url_; }
  virtual const GoogleString& debug_message() { return debug_message_; }
  virtual const GoogleString& resize_debug_message() {
    return resize_debug_message_;
  }

  bool GenerateBlankImage();

  StringPiece original_contents() { return original_contents_; }

 private:
  // Maximum number of libpagespeed conversion attempts.
  // TODO(vchudnov): Consider making this tunable.
  static const int kMaxConversionAttempts = 2;

  // Concrete helper methods called by parent class
  virtual void ComputeImageType();
  virtual bool ComputeOutputContents();

  bool ComputeOutputContentsFromGifOrPng(
      const GoogleString& string_for_image,
      const PngReaderInterface* png_reader,
      bool fall_back_to_png,
      const char* dbg_input_format,
      ImageType input_type,
      ConversionVariables::VariableType var_type);

  // Helper methods
  static bool ComputePngTransparency(const StringPiece& buf);

  // Internal methods used only in the implementation
  void UndoChange();
  void FindJpegSize();
  void FindPngSize();
  void FindGifSize();
  void FindWebpSize();

  // Convert the given options object to jpeg compression options.
  void ConvertToJpegOptions(const Image::CompressionOptions& options,
                            JpegCompressionOptions* jpeg_options);

  // Optimizes the png image_data, readable via png_reader.
  bool OptimizePng(
      const PngReaderInterface& png_reader,
      const GoogleString& image_data);

  // Converts image_data, readable via png_reader, to a jpeg if
  // possible or a png if not, using the settings in options_.
  bool OptimizePngOrConvertToJpeg(
      const PngReaderInterface& png_reader,
      const GoogleString& image_data);

  // Converts image_data, readable via png_reader, to a webp using the
  // settings in options_, if allowed by those settings. The alpha channel
  // is always losslessly compressed, while the color may be lossily or
  // or losslessly compressed, depending on 'compress_color_losslessly'.
  bool ConvertPngToWebp(
      const PngReaderInterface& png_reader,
      const GoogleString& image_data,
      bool compress_color_losslessly,
      bool has_transparency,
      ConversionVariables::VariableType var_type);

  // Convert the JPEG in original_jpeg to WebP format in
  // compressed_webp using the quality specified in
  // configured_quality.
  bool ConvertJpegToWebp(
      const GoogleString& original_jpeg, int configured_quality,
      GoogleString* compressed_webp);

  static bool ContinueWebpConversion(
      int percent,
      void* user_data);

  // Determines whether we can attempt a libpagespeed conversion
  // without exceeding kMaxConversionAttempts. If so, increments the
  // number of attempts.
  bool MayConvert() {
    if (options_.get()) {
      VLOG(1) << "Conversions attempted: "
              << options_->conversions_attempted;
      if (options_->conversions_attempted < kMaxConversionAttempts) {
        ++options_->conversions_attempted;
        return true;
      }
    }
    return false;
  }

  int GetJpegQualityFromImage(const StringPiece& contents) {
    const int quality = JpegUtils::GetImageQualityFromImage(contents.data(),
                                                            contents.size(),
                                                            handler_.get());
    return quality;
  }

  // Quality level for compressing the resized image.
  int EstimateQualityForResizedJpeg();

  bool ConvertAnimatedGifToWebp(bool has_transparency);

  const GoogleString file_prefix_;
  scoped_ptr<MessageHandler> handler_;
  bool changed_;
  const GoogleString url_;
  ImageDim dims_;
  ImageDim resized_dimensions_;
  GoogleString resized_image_;
  scoped_ptr<Image::CompressionOptions> options_;
  bool low_quality_enabled_;
  Timer* timer_;
  GoogleString debug_message_;
  GoogleString resize_debug_message_;

  DISALLOW_COPY_AND_ASSIGN(ImageImpl);
};

void ImageImpl::SetTransformToLowRes() {
  // TODO(vchudnov): Deprecate low_quality_enabled_.
  low_quality_enabled_ = true;
  // TODO(vchudnov): All these settings should probably be tunable.
  if (options_->preferred_webp != WEBP_NONE) {
    options_->preferred_webp = WEBP_LOSSY;
  }
  options_->webp_quality = 10;
  options_->webp_animated_quality = 10;
  options_->jpeg_quality = 10;
}

Image::Image(const StringPiece& original_contents)
    : image_type_(IMAGE_UNKNOWN),
      original_contents_(original_contents),
      output_contents_(),
      output_valid_(false),
      rewrite_attempted_(false) { }

ImageImpl::ImageImpl(const StringPiece& original_contents,
                     const GoogleString& url,
                     const StringPiece& file_prefix,
                     CompressionOptions* options,
                     Timer* timer,
                     MessageHandler* handler)
    : Image(original_contents),
      file_prefix_(file_prefix.data(), file_prefix.size()),
      changed_(false),
      url_(url),
      options_(options),
      low_quality_enabled_(false),
      timer_(timer) {
  const GoogleString annotation = StrCat(url, ": ");
  handler_.reset(new AnnotatedMessageHandler(annotation, handler));
}

Image* NewImage(const StringPiece& original_contents,
                const GoogleString& url,
                const StringPiece& file_prefix,
                Image::CompressionOptions* options,
                Timer* timer,
                MessageHandler* handler) {
  return new ImageImpl(original_contents, url, file_prefix, options,
                       timer, handler);
}

Image::Image(ImageType type)
    : image_type_(type),
      original_contents_(),
      output_contents_(),
      output_valid_(false),
      rewrite_attempted_(false) { }

ImageImpl::ImageImpl(int width, int height, ImageType type,
                     const StringPiece& tmp_dir,
                     Timer* timer, MessageHandler* handler,
                     CompressionOptions* options)
    : Image(type),
      file_prefix_(tmp_dir.data(), tmp_dir.size()),
      changed_(false),
      low_quality_enabled_(false),
      timer_(timer) {
  options_.reset(options);
  dims_.set_width(width);
  dims_.set_height(height);
  handler_.reset(new AnnotatedMessageHandler(handler));
}

bool ImageImpl::GenerateBlankImage() {
  DCHECK(image_type_ == IMAGE_PNG) << "Blank image must be a PNG.";

  if (pagespeed::image_compression::GenerateBlankImage(dims_.width(),
      dims_.height(), options_->use_transparent_for_blank_image,
      &output_contents_, handler_.get())) {
    output_valid_ = true;
    return true;
  }
  return false;
}

Image* BlankImageWithOptions(int width, int height, ImageType type,
                             const StringPiece& tmp_dir,
                             Timer* timer, MessageHandler* handler,
                             Image::CompressionOptions* options) {
  scoped_ptr<ImageImpl> image(new ImageImpl(width, height, type, tmp_dir,
                                            timer, handler, options));
  if (image != NULL && image->GenerateBlankImage()) {
    return image.release();
  }
  return NULL;
}

Image::~Image() {
}

// Looks through blocks of jpeg stream to find SOFn block
// indicating encoding and dimensions of image.
// Loosely based on code and FAQs found here:
//    http://www.faqs.org/faqs/jpeg-faq/part1/
void ImageImpl::FindJpegSize() {
  const StringPiece& buf = original_contents_;
  size_t pos = 2;  // Position of first data block after header.
  while (pos < buf.size()) {
    // Read block identifier
    int id = CharToInt(buf[pos++]);
    if (id == 0xff) {  // Padding byte
      continue;
    }
    // At this point pos points to first data byte in block.  In any block,
    // first two data bytes are size (including these 2 bytes).  But first,
    // make sure block wasn't truncated on download.
    if (pos + ImageHeaders::kJpegIntSize > buf.size()) {
      break;
    }
    int length = JpegIntAtPosition(buf, pos);
    // Now check for a SOFn header, which describes image dimensions.
    if (0xc0 <= id && id <= 0xcf &&  // SOFn header
        length >= 8 &&               // Valid SOFn block size
        pos + 1 + 3 * ImageHeaders::kJpegIntSize <= buf.size() &&
        // Above avoids case where dimension data was truncated
        id != 0xc4 && id != 0xc8 && id != 0xcc) {
      // 0xc4, 0xc8, 0xcc aren't actually valid SOFn headers.
      // NOTE: we don't care if we have the whole SOFn block,
      // just that we can fetch both dimensions without trouble.
      // Our image download could be truncated at this point for
      // all we care.
      // We're a bit sloppy about SOFn block size, as it's
      // actually 8 + 3 * buf[pos+2], but for our purposes this
      // will suffice as we don't parse subsequent metadata (which
      // describes the formatting of chunks of image data).
      dims_.set_height(
          JpegIntAtPosition(buf, pos + 1 + ImageHeaders::kJpegIntSize));
      dims_.set_width(
          JpegIntAtPosition(buf, pos + 1 + 2 * ImageHeaders::kJpegIntSize));
      break;
    }
    pos += length;
  }
  if (!ImageUrlEncoder::HasValidDimensions(dims_) ||
      (dims_.height() <= 0) || (dims_.width() <= 0)) {
    dims_.Clear();
    PS_LOG_INFO(handler_, "Couldn't find jpeg dimensions (data truncated?).");
  }
}

// Looks at first (IHDR) block of png stream to find image dimensions.
// See also: http://www.w3.org/TR/PNG/
void ImageImpl::FindPngSize() {
  const StringPiece& buf = original_contents_;
  // Here we make sure that buf contains at least enough data that we'll be able
  // to decipher the image dimensions first, before we actually check for the
  // headers and attempt to decode the dimensions (which are the first two ints
  // after the IHDR section label).
  if ((buf.size() >=  // Not truncated
       ImageHeaders::kIHDRDataStart + 2 * ImageHeaders::kPngIntSize) &&
      (StringPiece(buf.data() + ImageHeaders::kPngHeaderLength,
                   ImageHeaders::kPngSectionHeaderLength) ==
       StringPiece(ImageHeaders::kPngIHDR,
                   ImageHeaders::kPngSectionHeaderLength))) {
    dims_.set_width(PngIntAtPosition(buf, ImageHeaders::kIHDRDataStart));
    dims_.set_height(PngIntAtPosition(
        buf, ImageHeaders::kIHDRDataStart + ImageHeaders::kPngIntSize));
  } else {
    PS_LOG_INFO(handler_, "Couldn't find png dimensions "
                "(data truncated or IHDR missing).");
  }
}

// Looks at header of GIF file to extract image dimensions.
// See also: http://en.wikipedia.org/wiki/Graphics_Interchange_Format
void ImageImpl::FindGifSize() {
  const StringPiece& buf = original_contents_;
  // Make sure that buf contains enough data that we'll be able to
  // decipher the image dimensions before we attempt to do so.
  if (buf.size() >=
      ImageHeaders::kGifDimStart + 2 * ImageHeaders::kGifIntSize) {
    // Not truncated
    dims_.set_width(GifIntAtPosition(buf, ImageHeaders::kGifDimStart));
    dims_.set_height(GifIntAtPosition(
        buf, ImageHeaders::kGifDimStart + ImageHeaders::kGifIntSize));
  } else {
    PS_LOG_INFO(handler_, "Couldn't find gif dimensions (data truncated)");
  }
}

void ImageImpl::FindWebpSize() {
  const uint8* webp = reinterpret_cast<const uint8*>(original_contents_.data());
  const int webp_size = original_contents_.size();
  int width = 0, height = 0;
  if (WebPGetInfo(webp, webp_size, &width, &height) > 0) {
    dims_.set_width(width);
    dims_.set_height(height);
  } else {
    PS_LOG_INFO(handler_, "Couldn't find webp dimensions ");
  }
}

// Looks at image data in order to determine image type, and also fills in any
// dimension information it can (setting image_type_ and dims_).
void ImageImpl::ComputeImageType() {
  image_type_ =
      pagespeed::image_compression::ComputeImageType(original_contents_);

  switch (image_type_) {
    case IMAGE_JPEG:
      FindJpegSize();
      break;
    case IMAGE_PNG:
      FindPngSize();
      break;
    case IMAGE_GIF:
      FindGifSize();
      break;
    case IMAGE_WEBP:
    case IMAGE_WEBP_LOSSLESS_OR_ALPHA:
    case IMAGE_WEBP_ANIMATED:
      FindWebpSize();
      break;
    case IMAGE_UNKNOWN:
      break;
  }
}

const ContentType* Image::TypeToContentType(ImageType image_type) {
  const ContentType* res = NULL;
  switch (image_type) {
    case IMAGE_UNKNOWN:
      break;
    case IMAGE_JPEG:
      res = &kContentTypeJpeg;
      break;
    case IMAGE_PNG:
      res = &kContentTypePng;
      break;
    case IMAGE_GIF:
      res = &kContentTypeGif;
      break;
    case IMAGE_WEBP:
    case IMAGE_WEBP_LOSSLESS_OR_ALPHA:
    case IMAGE_WEBP_ANIMATED:
      res = &kContentTypeWebp;
      break;
  }
  return res;
}

// Compute whether a PNG can have transparent / semi-transparent pixels
// by walking the image data in accordance with the spec:
//   http://www.w3.org/TR/PNG/
// If the colour type (UK spelling from spec) includes an alpha channel, or
// there is a tRNS section with at least one entry before IDAT, then we assume
// the image contains non-opaque pixels and return true.
bool ImageImpl::ComputePngTransparency(const StringPiece& buf) {
  // We assume the image has transparency until we prove otherwise.
  // This allows us to deal conservatively with truncation etc.
  bool has_transparency = true;
  if (buf.size() > ImageHeaders::kPngColourTypeOffset &&
      ((buf[ImageHeaders::kPngColourTypeOffset] &
        ImageHeaders::kPngAlphaChannel) == 0)) {
    // The colour type indicates that there is no dedicated alpha channel.  Now
    // we must look for a tRNS section indicating the existence of transparent
    // colors or palette entries.
    size_t section_start = ImageHeaders::kPngHeaderLength;
    while (section_start + ImageHeaders::kPngSectionHeaderLength < buf.size()) {
      size_t section_size = PngIntAtPosition(buf, section_start);
      if (PngSectionIdIs(ImageHeaders::kPngIDAT, buf, section_start)) {
        // tRNS section must occur before first IDAT.  This image doesn't have a
        // tRNS section, and thus doesn't have transparency.
        has_transparency = false;
        break;
      } else if (PngSectionIdIs(ImageHeaders::kPngtRNS, buf, section_start) &&
                 section_size > 0) {
        // Found a nonempty tRNS section.  This image has_transparency.
        break;
      } else {
        // Move on to next section.
        section_start += section_size + ImageHeaders::kPngSectionMinSize;
      }
    }
  }
  return has_transparency;
}

bool ImageImpl::EnsureLoaded(bool output_useful) {
  return true;
}

// Determine the quality level for compressing the resized image.
// If a JPEG image needs resizing, we decompress it first, then resize it,
// and finally compress it into a new JPEG image. To compress the output image,
// We would like to use the quality level that was used in the input image,
// if such information can be calculated from the input image; otherwise, we
// will use the quality level set in the configuration; otherwise, we will use
// a predefined default quality.
int ImageImpl::EstimateQualityForResizedJpeg() {
  int input_quality = GetJpegQualityFromImage(original_contents_);
  int output_quality = std::min(ImageHeaders::kMaxJpegQuality,
                                options_->jpeg_quality);
  if (input_quality > 0 && output_quality > 0) {
    return std::min(input_quality, output_quality);
  } else if (input_quality > 0) {
    return input_quality;
  } else if (output_quality > 0) {
    return output_quality;
  } else {
    return ImageHeaders::kQualityForJpegWithUnkownQuality;
  }
}

void ImageImpl::Dimensions(ImageDim* natural_dim) {
  if (!ImageUrlEncoder::HasValidDimensions(dims_)) {
    ComputeImageType();
  }
  *natural_dim = dims_;
}

bool ImageImpl::ResizeTo(const ImageDim& new_dim) {
  CHECK(ImageUrlEncoder::HasValidDimensions(new_dim));
  if ((new_dim.width() <= 0) || (new_dim.height() <= 0)) {
    return false;
  }

  if (changed_) {
    // If we already resized, drop data and work with original image.
    UndoChange();
  }

  // TODO(huibao): Enable resizing for WebP and images with alpha channel.
  // We have the tools ready but no tests.
  const ImageFormat original_format = ImageTypeToImageFormat(image_type());
  if (original_format == pagespeed::image_compression::IMAGE_WEBP) {
    return false;
  }

  scoped_ptr<ScanlineReaderInterface> image_reader(
      CreateScanlineReader(original_format,
                           original_contents_.data(),
                           original_contents_.length(),
                           handler_.get()));
  if (image_reader == NULL) {
    resize_debug_message_ = "Cannot resize: Cannot open the image to resize";
    PS_LOG_INFO(handler_, "Cannot open the image to resize.");
    return false;
  }

  ScanlineResizer resizer(handler_.get());
  if (!resizer.Initialize(image_reader.get(), new_dim.width(),
                          new_dim.height())) {
    resize_debug_message_ = "Cannot resize: Unable to initialize resizer";
    return false;
  }

  // Create a writer.
  scoped_ptr<ScanlineWriterInterface> writer;
  const ImageFormat resized_format = GetOutputImageFormat(original_format);
  switch (resized_format) {
    case pagespeed::image_compression::IMAGE_JPEG:
      {
        JpegCompressionOptions jpeg_config;
        jpeg_config.lossy = true;
        jpeg_config.lossy_options.quality = EstimateQualityForResizedJpeg();
        writer.reset(CreateScanlineWriter(resized_format,
                                          resizer.GetPixelFormat(),
                                          resizer.GetImageWidth(),
                                          resizer.GetImageHeight(),
                                          &jpeg_config,
                                          &resized_image_,
                                          handler_.get()));
      }
      break;

    case pagespeed::image_compression::IMAGE_PNG:
      {
        PngCompressParams png_config(PNG_FILTER_NONE, Z_DEFAULT_STRATEGY,
                                     false);
        writer.reset(CreateScanlineWriter(resized_format,
                                          resizer.GetPixelFormat(),
                                          resizer.GetImageWidth(),
                                          resizer.GetImageHeight(),
                                          &png_config,
                                          &resized_image_,
                                          handler_.get()));
      }
      break;

    default:
      resize_debug_message_ = "Cannot resize: Unsupported image format";
      PS_LOG_DFATAL(handler_, "Unsupported image format");
  }

  if (writer == NULL) {
    return false;
  }

  // Resize the image and save the results in 'resized_image_'.
  void* scanline = NULL;
  while (resizer.HasMoreScanLines()) {
    if (!resizer.ReadNextScanline(&scanline)) {
      resize_debug_message_ = "Cannot resize: Reading image failed";
      return false;
    }
    if (!writer->WriteNextScanline(scanline)) {
      resize_debug_message_ = "Cannot resize: Writing image failed";
      return false;
    }
  }
  if (!writer->FinalizeWrite()) {
    resize_debug_message_ = "Cannot resize: Finalizing writing image failed";
    return false;
  }

  changed_ = true;
  output_valid_ = false;
  rewrite_attempted_ = false;
  output_contents_.clear();
  resized_dimensions_ = new_dim;
  resize_debug_message_ = StringPrintf(
      "Resized image from %dx%d to %dx%d", dims_.width(), dims_.height(),
      resized_dimensions_.width(), resized_dimensions_.height());
  return true;
}

void ImageImpl::UndoChange() {
  if (changed_) {
    output_valid_ = false;
    rewrite_attempted_ = false;
    output_contents_.clear();
    resized_image_.clear();
    image_type_ = IMAGE_UNKNOWN;
    changed_ = false;
  }
}

// TODO(huibao): Refactor image rewriting. We may have a centralized
// controller and a set of naive image writers. The controller looks at
// the input image type and the filter settings, and decides which output
// format(s) to try and the configuration for each output format. The writers
// simply write the output based on the specified configurations and should not
// be aware of the input type nor the filters.
//
// Here are some thoughts for the new design.
// 1. Create a scanline reader based on the type of input image.
// 2. If the image is going to be resized, wrap the reader into a resizer, which
//    is also a scanline reader.
// 3. Create a scanline writer or mutliple writers based the filter settings.
//    The parameters for the writer will also be determined by the filters.
//
// Transfer all of the scanlines from the reader to the writer and the image is
// rewritten (and resized)!

// Performs image optimization and output
bool ImageImpl::ComputeOutputContents() {
  if (rewrite_attempted_) {
    return output_valid_;
  }
  rewrite_attempted_ = true;
  if (!output_valid_) {
    StringPiece contents;
    bool resized;

    // Choose appropriate source for image contents.
    // Favor original contents if image unchanged.
    resized = !resized_image_.empty();
    if (resized) {
      contents = resized_image_;
    } else {
      contents = original_contents_;
    }

    // Take image contents and re-compress them.
    // The basic logic is this:
    // * low_quality_enabled_ acts as though convert_gif_to_png and
    //   convert_png_to_webp were both set for this image.
    // * We compute the intended final end state of all the
    //   convert_X_to_Y options, and try to convert to the final
    //   option in one shot. If that fails, we back off by each of the stages.
    // * We return as soon as any applicable conversion succeeds. We
    //   do not compare the sizes of alternative conversions.
    // If we can't optimize the image, we'll fail.
    bool ok = false;
    // We copy the data to a string eagerly as we're very likely to need it
    // (only unrecognized formats don't require it, in which case we probably
    // don't get this far in the first place).
    // TODO(jmarantz): The PageSpeed library should, ideally, take StringPiece
    // args rather than const string&.  We would save lots of string-copying
    // if we made that change.
    GoogleString string_for_image(contents.data(), contents.size());
    scoped_ptr<PngReaderInterface> png_reader;
    switch (image_type()) {
      case IMAGE_UNKNOWN:
        break;
      case IMAGE_WEBP:
      case IMAGE_WEBP_LOSSLESS_OR_ALPHA:
        if (resized || options_->recompress_webp) {
          ok = MayConvert() &&
              ReduceWebpImageQuality(string_for_image,
                                     options_->webp_quality,
                                     &output_contents_);
        }
        // TODO(pulkitg): Convert a webp image to jpeg image if
        // web_preferred_ is false.
        break;
      case IMAGE_WEBP_ANIMATED:
        // TODO(huibao): Recompress animated WebP.
        ok = false;
        break;
      case IMAGE_JPEG:
        if (MayConvert() &&
            options_->convert_jpeg_to_webp &&
            (options_->preferred_webp != WEBP_NONE)) {
          ok = ConvertJpegToWebp(string_for_image, options_->webp_quality,
                                 &output_contents_);
          VLOG(1) << "Image conversion: " << ok << " jpeg->webp for " << url_;
          if (!ok) {
            // Image is not going to be webp-converted!
            PS_LOG_INFO(handler_, "Failed to create webp!");
          }
        }
        if (ok) {
          image_type_ = IMAGE_WEBP;
        } else if (MayConvert() &&
                   (resized || options_->recompress_jpeg)) {
          JpegCompressionOptions jpeg_options;
          ConvertToJpegOptions(*options_.get(), &jpeg_options);
          ok = OptimizeJpegWithOptions(string_for_image, &output_contents_,
                                       jpeg_options, handler_.get());
          VLOG(1) << "Image conversion: " << ok << " jpeg->jpeg for " << url_;
        }
        break;
      case IMAGE_PNG:
        png_reader.reset(new PngReader(handler_.get()));
        ok = ComputeOutputContentsFromGifOrPng(
            string_for_image,
            png_reader.get(),
            (resized || options_->recompress_png) /* fall_back_to_png */,
            kPngString,
            IMAGE_PNG,
            Image::ConversionVariables::FROM_PNG);
        break;
      case IMAGE_GIF:
        ImageType current_image_type = IMAGE_GIF;
        if (resized) {
          // If the GIF image has been resized, it has already been
          // converted to a PNG image.
          png_reader.reset(new PngReader(handler_.get()));
          current_image_type = IMAGE_PNG;
        } else if (options_->convert_gif_to_png || low_quality_enabled_ ||
                   options_->allow_webp_animated) {
          png_reader.reset(new GifReader(handler_.get()));
        } else {
          break;
        }
        ok = ComputeOutputContentsFromGifOrPng(
            string_for_image,
            png_reader.get(),
            options_->convert_gif_to_png /* fall_back_to_png */,
            kGifString,
            current_image_type,
            Image::ConversionVariables::FROM_GIF);
        break;
    }
    output_valid_ = ok;
  }
  return output_valid_;
}

inline bool ImageImpl::ConvertJpegToWebp(
    const GoogleString& original_jpeg, int configured_quality,
    GoogleString* compressed_webp) {
  ConversionTimeoutHandler timeout_handler(options_->webp_conversion_timeout_ms,
                                           timer_, handler_.get());
  timeout_handler.Start(compressed_webp);
  bool ok = OptimizeWebp(original_jpeg, configured_quality,
                         ConversionTimeoutHandler::Continue, &timeout_handler,
                         compressed_webp, handler_.get());
  timeout_handler.Stop();

  bool was_timed_out = timeout_handler.was_timed_out();
  int64 time_elapsed_ms = timeout_handler.time_elapsed_ms();

  UpdateWebpStats(ok, was_timed_out, time_elapsed_ms,
                 Image::ConversionVariables::FROM_JPEG,
                 options_->webp_conversion_variables);

  UpdateWebpStats(ok, was_timed_out, time_elapsed_ms,
                 Image::ConversionVariables::OPAQUE,
                 options_->webp_conversion_variables);
  return ok;
}

bool ImageImpl::ConvertAnimatedGifToWebp(bool has_transparency) {
  ConversionTimeoutHandler timeout_handler(
      options_->webp_conversion_timeout_ms, timer_, handler_.get());
  timeout_handler.Start(&output_contents_);

  // Parameters controlling WebP compression.
  WebpConfiguration webp_config;
  webp_config.quality = options_->webp_animated_quality;
  webp_config.progress_hook = ConversionTimeoutHandler::Continue;
  webp_config.user_data = &timeout_handler;
  // TODO(huibao): Evaluate the following parameters.
  webp_config.method = 3;
  webp_config.kmin = 3;
  webp_config.kmax = 5;
  webp_config.lossless = false;
  webp_config.alpha_quality = 100;
  webp_config.alpha_compression = 1;  // alpha plane compressed losslessly

  pagespeed::image_compression::ScanlineStatus status;
  scoped_ptr<pagespeed::image_compression::MultipleFrameReader> reader(
      CreateImageFrameReader(
          pagespeed::image_compression::IMAGE_GIF,
          original_contents_.data(),
          original_contents_.length(),
          handler_.get(), &status));
  if (!status.Success()) {
    PS_LOG_ERROR(handler_, "Cannot read the animated GIF image.");
    return false;
  }

  scoped_ptr<pagespeed::image_compression::MultipleFrameWriter> writer(
      CreateImageFrameWriter(
          pagespeed::image_compression::IMAGE_WEBP,
          &webp_config,
          &output_contents_,
          handler_.get(), &status));
  if (!status.Success()) {
    PS_LOG_ERROR(handler_, "Cannot create an animated WebP image for output.");
    return false;
  }

  // Copy all pixels in all frames from the reader to the writer. This will do
  // format conversion and compression.
  pagespeed::image_compression::ImageSpec image_spec;
  pagespeed::image_compression::FrameSpec frame_spec;
  const void* scan_row = NULL;
  if (reader->GetImageSpec(&image_spec, &status) &&
      writer->PrepareImage(&image_spec, &status)) {
    while (reader->HasMoreFrames() &&
           reader->PrepareNextFrame(&status) &&
           reader->GetFrameSpec(&frame_spec, &status) &&
           writer->PrepareNextFrame(&frame_spec, &status)) {
      while (reader->HasMoreScanlines() &&
             reader->ReadNextScanline(&scan_row, &status) &&
             writer->WriteNextScanline(scan_row, &status)) {
        // intentional empty loop body
      }
    }
  }
  writer->FinalizeWrite(&status);

  timeout_handler.Stop();
  bool was_timed_out = timeout_handler.was_timed_out();
  int64 time_elapsed_ms = timeout_handler.time_elapsed_ms();
  bool ok = status.Success();

  UpdateWebpStats(ok, was_timed_out, time_elapsed_ms,
                  Image::ConversionVariables::FROM_GIF_ANIMATED,
                  options_->webp_conversion_variables);

  UpdateWebpStats(ok, was_timed_out, time_elapsed_ms,
                  (has_transparency ?
                   Image::ConversionVariables::NONOPAQUE :
                   Image::ConversionVariables::OPAQUE),
                  options_->webp_conversion_variables);

  return ok;
}

inline bool ImageImpl::ComputeOutputContentsFromGifOrPng(
    const GoogleString& string_for_image,
    const PngReaderInterface* png_reader,
    bool fall_back_to_png,
    const char* dbg_input_format,
    ImageType input_type,
    ConversionVariables::VariableType var_type) {
  // Don't try to optimize empty images, it just messes things up.
  if (dims_.width() <= 0 || dims_.height() <= 0) {
    return false;
  }

  bool ok = false;
  bool is_animated = false;
  bool has_transparency = false;
  bool is_photo = false;
  bool compress_color_losslessly = false;
  ImageType output_type = IMAGE_UNKNOWN;

  AnalyzeImage(ImageTypeToImageFormat(input_type),
               string_for_image.data(), string_for_image.length(),
               NULL /* width */, NULL /* height */, NULL /* is_progressive */,
               &is_animated, &has_transparency, &is_photo,
               NULL /* quality */, NULL /* reader */, handler_.get());

  debug_message_ = StringPrintf("Image has%s transparent pixels,"
                                " is%s sensitive to compression noise, and"
                                " has%s animation.",
                                (has_transparency ? "" : " no"),
                                (is_photo ? " not" : ""),
                                (is_animated ? "" : " no"));

  // By default, a lossless image conversion is eligible for lossless webp
  // conversion.
  if (is_animated) {
    if (options_->preferred_webp == WEBP_ANIMATED &&
        options_->webp_animated_quality > 0) {
      output_type = IMAGE_WEBP_ANIMATED;
    }
    // else we can't recompress this image
  } else if (is_photo && options_->convert_png_to_jpeg &&
             (input_type == IMAGE_PNG ||
              (input_type == IMAGE_GIF && options_->convert_gif_to_png))) {
    // Can be converted to lossy format.
    if (!has_transparency) {
      // No alpha; can be converted to WebP lossy or JPEG.
      if (options_->preferred_webp != WEBP_NONE &&
          options_->convert_jpeg_to_webp &&
          options_->webp_quality > 0) {
        compress_color_losslessly = false;
        output_type = IMAGE_WEBP;
      } else if (options_->jpeg_quality > 0) {
        output_type = IMAGE_JPEG;
      }
    } else {
      if (options_->allow_webp_alpha &&
          options_->convert_jpeg_to_webp &&
          options_->webp_quality > 0) {
        compress_color_losslessly = false;
        output_type = IMAGE_WEBP_LOSSLESS_OR_ALPHA;
      }
    }
  } else {
    // Must be converted to lossless format.
    if (options_->preferred_webp == WEBP_ANIMATED ||
        options_->preferred_webp == WEBP_LOSSLESS) {
      compress_color_losslessly = true;
      output_type = IMAGE_WEBP_LOSSLESS_OR_ALPHA;
    }
  }

  if (output_type == IMAGE_WEBP_ANIMATED) {
    ok = ConvertAnimatedGifToWebp(has_transparency);
  } else {
    if (output_type == IMAGE_WEBP ||
        output_type == IMAGE_WEBP_LOSSLESS_OR_ALPHA) {
      ok = MayConvert() &&
          ConvertPngToWebp(*png_reader, string_for_image,
                           compress_color_losslessly, has_transparency,
                           var_type);
      // TODO(huibao): Re-evaluate why we need to try a different format, if the
      // conversion to WebP failed.
      if (!ok) {
        // If the conversion to WebP failed, we will try converting the image to
        // jpeg or png.
        if (output_type == IMAGE_WEBP) {
          output_type = IMAGE_JPEG;
        } else {
          fall_back_to_png = true;
        }
      }
    }

    if (output_type == IMAGE_JPEG) {
      JpegCompressionOptions jpeg_options;
      ConvertToJpegOptions(*options_.get(), &jpeg_options);
      ok = MayConvert() &&
          ImageConverter::ConvertPngToJpeg(*png_reader, string_for_image,
                                           jpeg_options, &output_contents_,
                                           handler_.get());
    }

    if (!ok && fall_back_to_png) {
      ok = MayConvert() &&
          PngOptimizer::OptimizePngBestCompression(*png_reader,
                                                   string_for_image,
                                                   &output_contents_,
                                                   handler_.get());
      output_type = IMAGE_PNG;
    }
  }

  if (ok) {
    image_type_ = output_type;
  } else {
    image_type_ = input_type;
  }

  VLOG(1) << "Image conversion: " << ok << " " << dbg_input_format << "->"
          << ImageFormatToString(ImageTypeToImageFormat(image_type_)) << " for "
          << url_;

  return ok;
}

bool ImageImpl::ConvertPngToWebp(
      const PngReaderInterface& png_reader,
      const GoogleString& input_image,
      bool compress_color_losslessly,
      bool has_transparency,
      ConversionVariables::VariableType var_type) {
  ConversionTimeoutHandler timeout_handler(options_->webp_conversion_timeout_ms,
                                           timer_, handler_.get());
  WebpConfiguration webp_config;

  // Quality/speed trade-off (0=fast, 6=slower-better).
  // This is the default value in libpagespeed. We should evaluate
  // whether this is the optimal value, and consider making it
  // tunable.
  webp_config.method = 3;
  webp_config.quality = options_->webp_quality;
  webp_config.progress_hook = ConversionTimeoutHandler::Continue;
  webp_config.user_data = &timeout_handler;

  ImageType target_image_type = IMAGE_WEBP_LOSSLESS_OR_ALPHA;
  if (compress_color_losslessly) {
    // Note that webp_config.alpha_quality and
    // webp_config.alpha_compression are only meaningful in the
    // lossy compression case.
    webp_config.lossless = true;
  } else {
    webp_config.lossless = false;
    if (has_transparency) {
      webp_config.alpha_quality = 100;
      webp_config.alpha_compression = 1;
    } else {
      webp_config.alpha_quality = 0;
      webp_config.alpha_compression = 0;
      image_type_ = IMAGE_WEBP;
    }
  }

  // TODO(huibao): Remove "is_opaque" from the returned arguments in
  // ConvertPngToWebp() and PngScanlineReader::InitializeRead().
  // The technique they use can only detect some of the opaque images.
  // PixelFormatOptimizer has a more expensive, but comprehensive solution.
  bool not_used;
  timeout_handler.Start(&output_contents_);
  bool ok = ImageConverter::ConvertPngToWebp(
      png_reader, input_image, webp_config,
      &output_contents_, &not_used, handler_.get());

  if (ok) {
    image_type_ = target_image_type;
  }
  timeout_handler.Stop();

  bool was_timed_out = timeout_handler.was_timed_out();
  int64 time_elapsed_ms = timeout_handler.time_elapsed_ms();

  UpdateWebpStats(ok, was_timed_out, time_elapsed_ms, var_type,
                  options_->webp_conversion_variables);

  UpdateWebpStats(ok, was_timed_out, time_elapsed_ms,
                  (has_transparency ?
                   Image::ConversionVariables::NONOPAQUE :
                   Image::ConversionVariables::OPAQUE),
                  options_->webp_conversion_variables);

  return ok;
}

bool ImageImpl::OptimizePng(
    const PngReaderInterface& png_reader,
    const GoogleString& image_data) {
  bool ok = MayConvert() &&
      PngOptimizer::OptimizePngBestCompression(png_reader,
                                               image_data,
                                               &output_contents_,
                                               handler_.get());
  if (ok) {
    image_type_ = IMAGE_PNG;
  }
  return ok;
}

bool ImageImpl::OptimizePngOrConvertToJpeg(
    const PngReaderInterface& png_reader,
    const GoogleString& image_data) {
  bool is_png;
  JpegCompressionOptions jpeg_options;
  ConvertToJpegOptions(*options_.get(), &jpeg_options);
  bool ok = MayConvert() &&
      ImageConverter::OptimizePngOrConvertToJpeg(
          png_reader, image_data, jpeg_options,
          &output_contents_, &is_png, handler_.get());
  if (ok) {
    if (is_png) {
      image_type_ = IMAGE_PNG;
    } else {
      image_type_ = IMAGE_JPEG;
    }
  }
  return ok;
}

void ImageImpl::ConvertToJpegOptions(const Image::CompressionOptions& options,
                                     JpegCompressionOptions* jpeg_options) {
  int input_quality = GetJpegQualityFromImage(original_contents_);
  jpeg_options->retain_color_profile = options.retain_color_profile;
  jpeg_options->retain_exif_data = options.retain_exif_data;
  int output_quality = EstimateQualityForResizedJpeg();

  if (options.jpeg_quality > 0) {
    // If the source image is JPEG we want to fallback to lossless if the input
    // quality is less than the quality we want to set for final compression and
    // num progressive scans is not set. Incase we are not able to decode the
    // input image quality, then we use lossless path.
    if (image_type() != IMAGE_JPEG ||
        options.jpeg_num_progressive_scans > 0 ||
        input_quality > output_quality) {
      jpeg_options->lossy = true;
      jpeg_options->lossy_options.quality = output_quality;
      if (options.progressive_jpeg) {
        jpeg_options->lossy_options.num_scans =
            options.jpeg_num_progressive_scans;
      }

      if (options.retain_color_sampling) {
        jpeg_options->lossy_options.color_sampling = RETAIN;
      }
    }
  }

  jpeg_options->progressive = options.progressive_jpeg &&
      ShouldConvertToProgressive(output_quality);
}

bool ImageImpl::ShouldConvertToProgressive(int64 quality) const {
  bool progressive = false;
  const ImageDim* expected_dimensions = &dims_;
  if (ImageUrlEncoder::HasValidDimensions(resized_dimensions_)) {
    expected_dimensions = &resized_dimensions_;
  }
  if (ImageUrlEncoder::HasValidDimensions(*expected_dimensions)) {
    progressive = pagespeed::image_compression::ShouldConvertToProgressive(
        quality, options_->progressive_jpeg_min_bytes,
        original_contents_.size(), expected_dimensions->width(),
        expected_dimensions->height());
  } else {
    progressive = (static_cast<int64>(original_contents_.size()) >=
                   options_->progressive_jpeg_min_bytes);
  }
  return progressive;
}

StringPiece Image::Contents() {
  StringPiece contents;
  if (this->image_type() != IMAGE_UNKNOWN) {
    contents = original_contents_;
    if (output_valid_ || ComputeOutputContents()) {
      contents = output_contents_;
    }
  }
  return contents;
}

bool ImageImpl::DrawImage(Image* image, int x, int y) {
  // Create a reader for reading the original canvas image.
  scoped_ptr<ScanlineReaderInterface> canvas_reader(CreateScanlineReader(
      pagespeed::image_compression::IMAGE_PNG,
      output_contents_.data(),
      output_contents_.length(),
      handler_.get()));
  if (canvas_reader == NULL) {
    PS_LOG_ERROR(handler_, "Cannot open canvas image.");
    return false;
  }

  // Get the size and pixel format of the original canvas image.
  const size_t canvas_width = canvas_reader->GetImageWidth();
  const size_t canvas_height = canvas_reader->GetImageHeight();
  const PixelFormat canvas_pixel_format = canvas_reader->GetPixelFormat();

  // Initialize a reader for reading the image which will be sprited.
  ImageImpl* impl = static_cast<ImageImpl*>(image);
  scoped_ptr<ScanlineReaderInterface> image_reader(CreateScanlineReader(
      ImageTypeToImageFormat(impl->image_type()),
                             impl->original_contents().data(),
                             impl->original_contents().length(),
                             handler_.get()));
  if (image_reader == NULL) {
    PS_LOG_INFO(handler_, "Cannot open the image which will be sprited.");
    return false;
  }

  // Get the size of the image which will be sprited.
  const size_t image_width = image_reader->GetImageWidth();
  const size_t image_height = image_reader->GetImageHeight();
  const PixelFormat image_pixel_format = image_reader->GetPixelFormat();

  if (x + image_width > canvas_width || y + image_height > canvas_height) {
    PS_LOG_INFO(handler_, "The new image cannot fit into the canvas.");
    return false;
  }

  bool has_transparency = false;
  PixelFormat output_pixel_format = RGB_888;
  if (image_pixel_format == RGBA_8888 ||
      canvas_pixel_format == RGBA_8888) {
    has_transparency = true;
    output_pixel_format = RGBA_8888;
  }

  const size_t bytes_per_pixel =
      GetNumChannelsFromPixelFormat(output_pixel_format, handler_.get());
  const size_t bytes_per_scanline = canvas_width * bytes_per_pixel;
  scoped_array<uint8> scanline(new uint8[bytes_per_scanline]);

  // Create a writer for writing the new canvas image.
  GoogleString canvas_image;
  scoped_ptr<ScanlineWriterInterface> canvas_writer(
      CreateUncompressedPngWriter(canvas_width, canvas_height,
                                  &canvas_image, handler_.get(),
                                  has_transparency));
  if (canvas_writer == NULL) {
    PS_LOG_ERROR(handler_, "Failed to create canvas writer.");
    return false;
  }

  // Overlay the new image onto the canvas image.
  for (int row = 0; row < static_cast<int>(canvas_height); ++row) {
    uint8* canvas_line = NULL;
    if (!canvas_reader->ReadNextScanline(
        reinterpret_cast<void**>(&canvas_line))) {
      PS_LOG_ERROR(handler_, "Failed to read canvas image.");
      return false;
    }

    if (row >= y && row < y + static_cast<int>(image_height)) {
      uint8* image_line = NULL;
      if (!image_reader->ReadNextScanline(
          reinterpret_cast<void**>(&image_line))) {
        PS_LOG_INFO(handler_,
                     "Failed to read the image which will be sprited.");
        return false;
      }

      // Set the entire scanline to white. This operation has no effect
      // on the webpage; it just gives a clean background to the
      // sprite image.
      memset(scanline.get(), kAlphaOpaque, x * bytes_per_pixel);
      memset(scanline.get() + (x + image_width) * bytes_per_pixel,
             kAlphaOpaque,
             (canvas_width - image_width - x) * bytes_per_pixel);

      ExpandPixelFormat(image_width, image_pixel_format, 0, image_line,
                        output_pixel_format, x, scanline.get(), handler_.get());
    } else {
      ExpandPixelFormat(canvas_width, canvas_pixel_format, 0, canvas_line,
                        output_pixel_format, 0, scanline.get(), handler_.get());
    }

    if (!canvas_writer->WriteNextScanline(
        reinterpret_cast<void*>(scanline.get()))) {
      PS_LOG_ERROR(handler_, "Failed to write canvas image.");
      return false;
    }
  }

  if (!canvas_writer->FinalizeWrite()) {
    PS_LOG_ERROR(handler_, "Failed to close canvas file.");
    return false;
  }

  output_contents_ = canvas_image;
  output_valid_ = true;
  return true;
}

}  // namespace net_instaweb
