/*
 * 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: Victor Chudnovsky

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

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

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

namespace pagespeed {

namespace image_compression {

using image_compression::GetNumChannelsFromPixelFormat;
using net_instaweb::MessageHandler;

// Copied from libwebp/v0_2/examples/cwebp.c
static const char* const kWebPErrorMessages[] = {
  "OK",
  "OUT_OF_MEMORY: Out of memory allocating objects",
  "BITSTREAM_OUT_OF_MEMORY: Out of memory re-allocating byte buffer",
  "NULL_PARAMETER: NULL parameter passed to function",
  "INVALID_CONFIGURATION: configuration is invalid",
  "BAD_DIMENSION: Bad picture dimension. Maximum width and height "
  "allowed is 16383 pixels.",
  "PARTITION0_OVERFLOW: Partition #0 is too big to fit 512k.\n"
  "To reduce the size of this partition, try using less segments "
  "with the -segments option, and eventually reduce the number of "
  "header bits using -partition_limit. More details are available "
  "in the manual (`man cwebp`)",
  "PARTITION_OVERFLOW: Partition is too big to fit 16M",
  "BAD_WRITE: Picture writer returned an I/O error",
  "FILE_TOO_BIG: File would be too big to fit in 4G",
  "USER_ABORT: encoding abort requested by user"
};

// The libwebp error code returned in case of timeouts.
static const int kWebPErrorTimeout = VP8_ENC_ERROR_USER_ABORT;

void WebpConfiguration::CopyTo(WebPConfig* webp_config) const {
  webp_config->lossless = lossless;
  webp_config->quality = quality;
  webp_config->method = method;
  webp_config->target_size = target_size;
  webp_config->alpha_compression = alpha_compression;
  webp_config->alpha_filtering = alpha_filtering;
  webp_config->alpha_quality = alpha_quality;
}

WebpFrameWriter::WebpFrameWriter(MessageHandler* handler) :
    MultipleFrameWriter(handler), image_spec_(NULL), next_frame_(0),
    next_scanline_(0), empty_frame_(false), frame_stride_px_(0),
    frame_position_px_(NULL), frame_bytes_per_pixel_(0), webp_image_(NULL),
    webp_frame_cache_(NULL), webp_mux_(NULL), output_image_(NULL),
    has_alpha_(false), image_prepared_(false), progress_hook_(NULL),
    progress_hook_data_(NULL) {
}

WebpFrameWriter::~WebpFrameWriter() {
  FreeWebpStructs();
}

void WebpFrameWriter::FreeWebpStructs() {
  // Shortcut the initial case, which will happen every time this
  // class is used.
  if ((webp_frame_cache_ == NULL) &&
      (webp_image_ == NULL) &&
      (webp_mux_ == NULL)) {
    return;
  }

  WebPFrameCacheDelete(webp_frame_cache_);
  webp_frame_cache_ = NULL;

  WebPPictureFree(webp_image_);
  delete webp_image_;
  webp_image_ = NULL;

  WebPMuxDelete(webp_mux_);
  webp_mux_ = NULL;
}


ScanlineStatus WebpFrameWriter::Initialize(const void* config,
                                           GoogleString* out) {
  FreeWebpStructs();
  webp_mux_ = WebPMuxNew();
  if (webp_mux_ == NULL) {
    return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            FRAME_WEBPWRITER,
                            "WebPMuxNew() failure");
  }

  if (config == NULL) {
    return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler(),
                            SCANLINE_STATUS_INVOCATION_ERROR,
                            FRAME_WEBPWRITER,
                            "missing WebpConfiguration*");
  }

  const WebpConfiguration* webp_config =
      static_cast<const WebpConfiguration*>(config);

  if (!WebPConfigInit(&libwebp_config_)) {
    return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            FRAME_WEBPWRITER, "WebPConfigInit()");
  }

  webp_config->CopyTo(&libwebp_config_);

  if (!WebPValidateConfig(&libwebp_config_)) {
    return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            FRAME_WEBPWRITER, "WebPValidateConfig()");
  }

  if (webp_config->progress_hook) {
    progress_hook_ = webp_config->progress_hook;
    progress_hook_data_ = webp_config->user_data;
  }

  kmin_ = webp_config->kmin;
  kmax_ = webp_config->kmax;

  output_image_ = out;

  return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
}

int WebpFrameWriter::ProgressHook(int percent, const WebPPicture* picture) {
  const WebpFrameWriter* webp_writer =
      static_cast<WebpFrameWriter*>(picture->user_data);
  return webp_writer->progress_hook_(percent, webp_writer->progress_hook_data_);
}

ScanlineStatus WebpFrameWriter::PrepareImage(const ImageSpec* image_spec) {
  DVLOG(1) << image_spec->ToString();
  if (image_prepared_) {
    return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler(),
                            SCANLINE_STATUS_INVOCATION_ERROR,
                            FRAME_WEBPWRITER, "image already prepared");
  }

  DVLOG(1) << "PrepareImage: num_frames: " << image_spec->num_frames;

  if ((image_spec->height > WEBP_MAX_DIMENSION) ||
      (image_spec->width > WEBP_MAX_DIMENSION)) {
    return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                            SCANLINE_STATUS_UNSUPPORTED_FEATURE,
                            FRAME_WEBPWRITER,
                            "each image dimension must be at most %d",
                            WEBP_MAX_DIMENSION);
  }

  if ((image_spec->height < 1) || (image_spec->width < 1)) {
    return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                            SCANLINE_STATUS_UNSUPPORTED_FEATURE,
                            FRAME_WEBPWRITER,
                            "each image dimension must be at least 1");
  }

  webp_image_ = new WebPPicture();

  if (!WebPPictureInit(webp_image_)) {
    return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            FRAME_WEBPWRITER, "WebPPictureInit()");
  }

  webp_image_->width = image_spec->width;
  webp_image_->height = image_spec->height;
  webp_image_->use_argb = true;
#ifndef NDEBUG
  webp_image_->stats = &stats_;
#endif

  if (!WebPPictureAlloc(webp_image_)) {
    return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            FRAME_WEBPWRITER, "WebPPictureAlloc()");
  }
  WebPUtilClearPic(webp_image_, NULL);

  webp_image_->user_data = this;
  if (progress_hook_) {
    webp_image_->progress_hook = ProgressHook;
  }

  image_spec_ = image_spec;
  next_frame_ = 0;
  image_prepared_ = true;

  // Key frame parameters.
  static size_t kMax;
  static size_t kMin;
  if (kmin_ > 0) {
    if (kmin_ >= kmax_) {
      return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler(),
                        SCANLINE_STATUS_INVOCATION_ERROR,
                        FRAME_WEBPWRITER,
                        "Keyframe parameters error: kmin >= kmax");
    } else if (kmin_ < (kmax_ / 2 + 1)) {
      return PS_LOGGED_STATUS(
                        PS_LOG_DFATAL,
                        message_handler(),
                        SCANLINE_STATUS_INVOCATION_ERROR,
                        FRAME_WEBPWRITER,
                        "Keyframe parameters error: kmin < (kmax / 2 + 1)");
    } else {
      kMax = kmax_;
      kMin = kmin_;
    }
  } else {
    kMax = ~0;
    kMin = kMax - 1;
  }

  webp_frame_cache_ = WebPFrameCacheNew(
      image_spec->width, image_spec->height, kMin, kMax,
      false /* don't allow mixing lossy and lossless frames */);

  if (webp_frame_cache_ == NULL) {
    return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                            SCANLINE_STATUS_MEMORY_ERROR,
                            FRAME_WEBPWRITER, "WebPFrameCacheNew()");
  }

  frame_position_px_ = NULL;
  frame_stride_px_ = 0;
  next_scanline_ = 0;

  return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
}

WebPMuxAnimDispose FrameDisposalToWebPDisposal(
    FrameSpec::DisposalMethod frame_disposal) {
  switch (frame_disposal) {
    case FrameSpec::DISPOSAL_UNKNOWN:
    case FrameSpec::DISPOSAL_NONE:
      return WEBP_MUX_DISPOSE_NONE;
    case FrameSpec::DISPOSAL_BACKGROUND:
    case FrameSpec::DISPOSAL_RESTORE:
      return WEBP_MUX_DISPOSE_BACKGROUND;
  }
  return WEBP_MUX_DISPOSE_NONE;
}

ScanlineStatus WebpFrameWriter::CacheCurrentFrame() {
  // If we're not even on the first frame, no-op.
  if (next_frame_ < 1) {
    return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
  }

  // Don't add empty frames.
  if (empty_frame_) {
    return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
  }

  // All scanlines must be written before caching a frame.
  if (next_scanline_ < frame_spec_.height) {
    return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler(),
                            SCANLINE_STATUS_INVOCATION_ERROR,
                            FRAME_WEBPWRITER,
                            "CacheCurrentFrame: not all scanlines written");
  }

  // We need to pass image to add frame.
  WebPFrameRect frame_rect = {
    static_cast<int>(frame_spec_.left),
    static_cast<int>(frame_spec_.top),
    static_cast<int>(frame_spec_.width),
    static_cast<int>(frame_spec_.height)
  };

  if (progress_hook_) {
    CHECK(webp_image_->progress_hook == ProgressHook);
    CHECK(webp_image_->user_data == this);
  }

  struct WebPMuxFrameInfo webp_frame_info;
  memset(&webp_frame_info, 0, sizeof(webp_frame_info));
  webp_frame_info.id = WEBP_CHUNK_ANMF;
  webp_frame_info.dispose_method =
      FrameDisposalToWebPDisposal(frame_spec_.disposal);
  webp_frame_info.blend_method = WEBP_MUX_BLEND;
  webp_frame_info.duration = frame_spec_.duration_ms;
  if (!WebPFrameCacheAddFrame(webp_frame_cache_, &libwebp_config_, &frame_rect,
                              webp_image_, &webp_frame_info)) {
    if (webp_image_->error_code == kWebPErrorTimeout) {
      return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                              SCANLINE_STATUS_TIMEOUT_ERROR,
                              FRAME_WEBPWRITER,
                              "WebPFrameCacheAddFrame(): %s",
                              kWebPErrorMessages[webp_image_->error_code]);
    } else {
      return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                              SCANLINE_STATUS_INTERNAL_ERROR,
                              FRAME_WEBPWRITER,
                              "WebPFrameCacheAddFrame(): %s\n%s\n%s",
                              kWebPErrorMessages[webp_image_->error_code],
                              image_spec_->ToString().c_str(),
                              frame_spec_.ToString().c_str());
    }
  }

  if (WebPFrameCacheFlush(webp_frame_cache_, false /*verbose*/, webp_mux_) !=
      WEBP_MUX_OK) {
    return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            FRAME_WEBPWRITER,
                            "WebPFrameCacheFlush() error");
  }

  return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
}

ScanlineStatus WebpFrameWriter::PrepareNextFrame(const FrameSpec* frame_spec) {
  if (!image_prepared_) {
    return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler(),
                            SCANLINE_STATUS_INVOCATION_ERROR,
                            FRAME_WEBPWRITER,
                            "PrepareNextFrame: image not prepared");
  }

  if (next_frame_ >= image_spec_->num_frames) {
    return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler(),
                            SCANLINE_STATUS_INVOCATION_ERROR,
                            FRAME_WEBPWRITER,
                            "PrepareNextFrame: no next frame");
  }

  ScanlineStatus status = CacheCurrentFrame();
  if (!status.Success()) {
    return status;
  }

  // Bounds-check the frame.
  if (!image_spec_->CanContainFrame(*frame_spec)) {
    return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                            SCANLINE_STATUS_INVOCATION_ERROR,
                            FRAME_WEBPWRITER,
                            "PrepareNextFrame: frame does not fit in image:\n"
                            "%s\n%s",
                            image_spec_->ToString().c_str(),
                            frame_spec->ToString().c_str());
  }

  ++next_frame_;
  frame_spec_ = *frame_spec;

  should_expand_gray_to_rgb_ = false;
  PixelFormat new_pixel_format = frame_spec_.pixel_format;
  switch (new_pixel_format) {
    case RGB_888:
      has_alpha_ = false;
      break;
    case RGBA_8888:
      has_alpha_ = true;
      break;
    case GRAY_8:
      // GRAY_8 will be expanded to RGB_888.
      has_alpha_ = false;
      should_expand_gray_to_rgb_ = true;
      new_pixel_format = RGB_888;
      break;
    default:
      return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                              SCANLINE_STATUS_INTERNAL_ERROR,
                              FRAME_WEBPWRITER,
                              "unknown pixel format: %d",
                              new_pixel_format);
  }
  DVLOG(1) << "Pixel format:" << GetPixelFormatString(frame_spec_.pixel_format);

  empty_frame_ = (frame_spec_.width < 1) || (frame_spec_.height < 1);
  if (empty_frame_) {
    frame_stride_px_ = frame_spec_.width;
    frame_position_px_ = NULL;
  } else {
    if (!WebPPictureView(webp_image_,
                         frame_spec_.left, frame_spec_.top,
                         frame_spec_.width, frame_spec_.height,
                         &webp_frame_)) {
      return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                              SCANLINE_STATUS_INTERNAL_ERROR,
                              FRAME_WEBPWRITER,
                              "WebPPictureView() failure: %s",
                              frame_spec_.ToString().c_str());
    }
    frame_stride_px_ = webp_frame_.argb_stride;
    frame_position_px_ = webp_frame_.argb;
  }

  frame_bytes_per_pixel_ = GetBytesPerPixel(frame_spec_.pixel_format);
  next_scanline_ = 0;

  return status;
}

ScanlineStatus WebpFrameWriter::WriteNextScanline(const void *scanline_bytes) {
  if (next_scanline_ >= frame_spec_.height) {
      return PS_LOGGED_STATUS(PS_LOG_DFATAL, message_handler(),
                              SCANLINE_STATUS_INVOCATION_ERROR,
                              FRAME_WEBPWRITER,
                              "WriteNextScanline: too many scanlines");
  }
  if (!empty_frame_) {
    if (should_expand_gray_to_rgb_) {
      // Replicate the luminance to RGB.
      const uint8_t* const in_bytes =
          reinterpret_cast<const uint8_t*>(scanline_bytes);
      for (int idx = 0; idx < webp_frame_.width; ++idx) {
        frame_position_px_[idx] = GrayscaleToPackedArgb(in_bytes[idx]);
      }
    } else if (has_alpha_) {
      // Note: this branch and the next only differ in the packing
      // function used. It is tempting to assign a function pointer
      // based on has_alpha_ and then implement the loop only
      // once. However, since this is an "inner loop" iterating over a
      // series of pixels, we want to take advantage of the inline
      // forms of the packing functions for speed.
      for (size_t px_col = 0, byte_col = 0;
           px_col < frame_spec_.width;
           ++px_col, byte_col += frame_bytes_per_pixel_) {
        frame_position_px_[px_col] =
            RgbaToPackedArgb(static_cast<const uint8_t*>(scanline_bytes) +
                             byte_col);
      }
    } else {
      for (size_t px_col = 0, byte_col = 0;
           px_col < frame_spec_.width;
           ++px_col, byte_col += frame_bytes_per_pixel_) {
        frame_position_px_[px_col] =
            RgbToPackedArgb(static_cast<const uint8_t*>(scanline_bytes) +
                            byte_col);
      }
    }
    frame_position_px_ += frame_stride_px_;
  }

  ++next_scanline_;
  return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
}

ScanlineStatus WebpFrameWriter::FinalizeWrite() {
  ScanlineStatus status = CacheCurrentFrame();
  if (!status.Success()) {
    return status;
  }

  if (WebPFrameCacheFlushAll(webp_frame_cache_, false /*verbose*/, webp_mux_) !=
      WEBP_MUX_OK) {
    return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            FRAME_WEBPWRITER,
                            "WebPFrameCacheFlushAll error");
  }

  if (next_frame_ > 1) {
    // This was an animated image.
    WebPMuxAnimParams anim = {
      RgbaToPackedArgb(image_spec_->bg_color),
      static_cast<int>(image_spec_->loop_count - 1)
    };
    if (WebPMuxSetAnimationParams(webp_mux_, &anim) != WEBP_MUX_OK) {
      return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                              SCANLINE_STATUS_INTERNAL_ERROR,
                              FRAME_WEBPWRITER,
                              "WebPMuxSetAnimationParams error");
    }
  }

  WebPData webp_data = { NULL, 0 };
  WebPMuxError muxerr = WebPMuxAssemble(webp_mux_, &webp_data);
  if (muxerr != WEBP_MUX_OK) {
    if (webp_image_->error_code == kWebPErrorTimeout) {
      return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                              SCANLINE_STATUS_TIMEOUT_ERROR,
                              FRAME_WEBPWRITER,
                              "WebPMuxAssemble: (%d) %d",
                              webp_image_->error_code,
                              muxerr);
    } else {
      return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler(),
                              SCANLINE_STATUS_INTERNAL_ERROR,
                              FRAME_WEBPWRITER,
                              "WebPMuxAssemble: (%d) %d",
                              webp_image_->error_code,
                              muxerr);
    }
  }

  output_image_->append(reinterpret_cast<const char *>(webp_data.bytes),
                        webp_data.size);
  WebPDataClear(&webp_data);

  PS_DLOG_INFO(message_handler(), \
      "Stats: coded_size: %d; lossless_size: %d; alpha size: %d;",
      stats_.coded_size, stats_.lossless_size, stats_.alpha_data_size);

  return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
}

WebpScanlineReader::WebpScanlineReader(MessageHandler* handler)
  : image_buffer_(NULL),
    buffer_length_(0),
    pixel_format_(UNSUPPORTED),
    height_(0),
    width_(0),
    bytes_per_row_(0),
    row_(0),
    was_initialized_(false),
    message_handler_(handler) {
}

WebpScanlineReader::~WebpScanlineReader() {
  Reset();
}

bool WebpScanlineReader::Reset() {
  image_buffer_ = NULL;
  buffer_length_ = 0;
  pixel_format_ = UNSUPPORTED;
  height_ = 0;
  width_ = 0;
  bytes_per_row_ = 0;
  row_ = 0;
  pixels_.reset();
  was_initialized_ = false;
  return true;
}

// Initialize the reader with the given image stream. Note that image_buffer
// must remain unchanged until the *first* call to ReadNextScanline().
ScanlineStatus WebpScanlineReader::InitializeWithStatus(
    const void* image_buffer,
    size_t buffer_length) {
  if (was_initialized_) {
    Reset();
  }

  WebPBitstreamFeatures features;
  if (WebPGetFeatures(reinterpret_cast<const uint8_t*>(image_buffer),
                      buffer_length, &features)
        != VP8_STATUS_OK) {
    return PS_LOGGED_STATUS(PS_LOG_INFO, message_handler_,
                            SCANLINE_STATUS_PARSE_ERROR,
                            SCANLINE_WEBPREADER, "WebPGetFeatures()");
  }


  // Determine the pixel format and the number of channels.
  if (features.has_alpha) {
    pixel_format_ = RGBA_8888;
  } else {
    pixel_format_ = RGB_888;
  }

  // Copy the information to the object properties.
  image_buffer_ = reinterpret_cast<const uint8_t*>(image_buffer);
  buffer_length_ = buffer_length;
  width_ = features.width;
  height_ = features.height;
  bytes_per_row_ = width_ * GetNumChannelsFromPixelFormat(pixel_format_,
                                                          message_handler_);
  row_ = 0;
  was_initialized_ = true;

  return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
}

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

  // The first time ReadNextScanline() is called, we decode the entire image.
  if (row_ == 0) {
    pixels_.reset(new uint8_t[bytes_per_row_ * height_]);
    if (pixels_ == NULL) {
      Reset();
      return PS_LOGGED_STATUS(PS_LOG_ERROR, message_handler_,
                              SCANLINE_STATUS_MEMORY_ERROR,
                              SCANLINE_WEBPREADER,
                              "Failed to allocate memory.");
    }

     WebPDecoderConfig config;
     CHECK(WebPInitDecoderConfig(&config));

     // Specify the desired output colorspace:
     if (pixel_format_ == RGB_888) {
       config.output.colorspace = MODE_RGB;
     } else {
       config.output.colorspace = MODE_RGBA;
     }

     // Have config.output point to an external buffer:
     config.output.u.RGBA.rgba = pixels_.get();
     config.output.u.RGBA.stride = bytes_per_row_;
     config.output.u.RGBA.size = bytes_per_row_ * height_;
     config.output.is_external_memory = true;

     bool decode_ok = (WebPDecode(image_buffer_, buffer_length_, &config)
                       == VP8_STATUS_OK);

     // Clean up WebP decoder because it is not needed any more,
     // regardless of whether whether decoding was successful or not.
     WebPFreeDecBuffer(&config.output);

     if (!decode_ok) {
       Reset();
       return PS_LOGGED_STATUS(PS_LOG_INFO, message_handler_,
                               SCANLINE_STATUS_INTERNAL_ERROR,
                               SCANLINE_WEBPREADER,
                               "Failed to decode the WebP image.");
     }
  }

  // Point output to the corresponding row of the already decoded image.
  *out_scanline_bytes =
      static_cast<void*>(pixels_.get() + row_ * bytes_per_row_);

  ++row_;
  return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
}

}  // namespace image_compression

}  // namespace pagespeed
