/*
 * 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: Bryan McQuade, Matthew Steele

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

#include <setjmp.h>
#include <stdlib.h>

#include "pagespeed/kernel/base/message_handler.h"
#include "pagespeed/kernel/base/string.h"

extern "C" {
#ifdef USE_SYSTEM_LIBJPEG
#include "jerror.h"                                                 // NOLINT
#include "jpeglib.h"                                                // NOLINT
#else
#include "third_party/libjpeg_turbo/src/jerror.h"
#include "third_party/libjpeg_turbo/src/jpeglib.h"
#endif
}

namespace {

// Unfortunately, libjpeg normally only supports reading images from C FILE
// pointers, wheras we want to read from a C++ string.  Fortunately, libjpeg
// also provides an extension mechanism.  Below, we define a new kind of
// jpeg_source_mgr for reading from strings.

// The below code was adapted from the JPEGMemoryReader class that can be found
// in src/o3d/core/cross/bitmap_jpg.cc in the Chromium source tree (r29423).
// That code is Copyright 2009, Google Inc.

METHODDEF(void) InitSource(j_decompress_ptr cinfo) {}

METHODDEF(boolean) FillInputBuffer(j_decompress_ptr cinfo) {
  // Should not be called because we already have all the data
  ERREXIT(cinfo, JERR_INPUT_EOF);
  return TRUE;
}

METHODDEF(void) SkipInputData(j_decompress_ptr cinfo,
                              long num_bytes) {              // NOLINT
  jpeg_source_mgr &mgr = *(cinfo->src);
  const int bytes_remaining = mgr.bytes_in_buffer - num_bytes;
  mgr.bytes_in_buffer = bytes_remaining < 0 ? 0 : bytes_remaining;
  mgr.next_input_byte += num_bytes;
}

METHODDEF(void) TermSource(j_decompress_ptr cinfo) {}

// Call this function on a j_decompress_ptr to install a reader that will read
// from the given string.
void JpegStringReader(j_decompress_ptr cinfo,
                      const void* image_data,
                      size_t image_length) {
  if (cinfo->src == NULL) {
    cinfo->src = (struct jpeg_source_mgr*)
      (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
                                  sizeof(jpeg_source_mgr));
  }
  struct jpeg_source_mgr &src = *(cinfo->src);

  src.init_source = InitSource;
  src.fill_input_buffer = FillInputBuffer;
  src.skip_input_data = SkipInputData;
  src.resync_to_restart = jpeg_resync_to_restart;  // default method
  src.term_source = TermSource;

  src.bytes_in_buffer = image_length;
  src.next_input_byte = static_cast<const JOCTET*>(image_data);
}

// ErrorExit() is installed as a callback, called on errors
// encountered within libjpeg.  The longjmp jumps back
// to the setjmp in JpegOptimizer::CreateOptimizedJpeg().
void ErrorExit(j_common_ptr jpeg_state_struct) {
  jmp_buf *env = static_cast<jmp_buf *>(jpeg_state_struct->client_data);
  (*jpeg_state_struct->err->output_message)(jpeg_state_struct);
  if (env)
    longjmp(*env, 1);
}

// OutputMessageFromReader is called by libjpeg code on an error when reading.
// Without this function, a default function would print to standard error.
void OutputMessage(j_common_ptr jpeg_decompress) {
  // The following code is handy for debugging.
  /*
  char buf[JMSG_LENGTH_MAX];
  (*jpeg_decompress->err->format_message)(jpeg_decompress, buf);
  DLOG(INFO) << "JPEG Reader Error: " << buf;
  */
}

}  // namespace

namespace pagespeed {

namespace image_compression {

using net_instaweb::MessageHandler;

struct JpegEnv {
  jpeg_decompress_struct jpeg_decompress_;
  jpeg_error_mgr decompress_error_;
  jmp_buf jmp_buf_env_;
};

JpegReader::JpegReader(MessageHandler* handler)
  : message_handler_(handler) {
  jpeg_decompress_ = static_cast<jpeg_decompress_struct*>(
      malloc(sizeof(jpeg_decompress_struct)));
  decompress_error_ = static_cast<jpeg_error_mgr*>(
      malloc(sizeof(jpeg_error_mgr)));
  memset(jpeg_decompress_, 0, sizeof(jpeg_decompress_struct));
  memset(decompress_error_, 0, sizeof(jpeg_error_mgr));

  jpeg_decompress_->err = jpeg_std_error(decompress_error_);
  decompress_error_->error_exit = &ErrorExit;
  decompress_error_->output_message = &OutputMessage;
  jpeg_create_decompress(jpeg_decompress_);
}

JpegReader::~JpegReader() {
  jpeg_destroy_decompress(jpeg_decompress_);
  free(decompress_error_);
  free(jpeg_decompress_);
}

void JpegReader::PrepareForRead(const void* image_data, size_t image_length) {
  // Prepare to read from a string.
  JpegStringReader(jpeg_decompress_, image_data, image_length);
}

JpegScanlineReader::JpegScanlineReader(MessageHandler* handler) :
  jpeg_env_(NULL),
  pixel_format_(UNSUPPORTED),
  height_(0),
  width_(0),
  row_(0),
  bytes_per_row_(0),
  was_initialized_(false),
  is_progressive_(false),
  message_handler_(handler) {
  row_pointer_[0] = NULL;
}

JpegScanlineReader::~JpegScanlineReader() {
  if (was_initialized_) {
    Reset();
  }
  free(jpeg_env_);
}

bool JpegScanlineReader::Reset() {
  pixel_format_ = UNSUPPORTED;
  height_ = 0;
  width_ = 0;
  row_ = 0;
  bytes_per_row_ = 0;
  was_initialized_ = false;

  jpeg_destroy_decompress(&(jpeg_env_->jpeg_decompress_));
  memset(jpeg_env_, 0, sizeof(JpegEnv));
  free(row_pointer_[0]);
  row_pointer_[0] = NULL;
  return true;
}

ScanlineStatus JpegScanlineReader::InitializeWithStatus(const void* image_data,
                                                        size_t image_length) {
  if (was_initialized_) {
    // Reset the reader if it has been initialized before.
    Reset();
  } else if (jpeg_env_ == NULL) {
    jpeg_env_ = static_cast<JpegEnv*>(malloc(sizeof(JpegEnv)));
    memset(jpeg_env_, 0, sizeof(JpegEnv));
  }

  // libjpeg's error handling mechanism requires that longjmp be used
  // to get control after an error.
  if (setjmp(jpeg_env_->jmp_buf_env_)) {
    // This code is run only when libjpeg hit an error and called
    // longjmp(env). It will reset the object to a state where it can be used
    // again.
    Reset();
    return PS_LOGGED_STATUS(PS_LOG_INFO, message_handler_,
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            SCANLINE_JPEGREADER,
                            "libjpeg failed to decode the image.");
  }

  jpeg_error_mgr* decompress_error = &(jpeg_env_->decompress_error_);
  jpeg_decompress_struct* jpeg_decompress = &(jpeg_env_->jpeg_decompress_);
  jpeg_decompress->err = jpeg_std_error(decompress_error);
  decompress_error->error_exit = &ErrorExit;
  decompress_error->output_message = &OutputMessage;
  jpeg_create_decompress(jpeg_decompress);

  // Need to install env so that it will be longjmp()ed to on error.
  jpeg_decompress->client_data = static_cast<void *>(jpeg_env_->jmp_buf_env_);

  // Prepare to read from a string.
  JpegStringReader(jpeg_decompress, image_data, image_length);

  // Read jpeg data into the decompression struct.
  jpeg_read_header(jpeg_decompress, TRUE);

  width_ = jpeg_decompress->image_width;
  height_ = jpeg_decompress->image_height;

  // Decode the image to GRAY_8 if it was in gray scale, or to RGB_888
  // otherwise.
  if (jpeg_decompress->jpeg_color_space == JCS_GRAYSCALE) {
    jpeg_decompress->out_color_space = JCS_GRAYSCALE;
    pixel_format_ = GRAY_8;
    bytes_per_row_ = width_;
  } else {
    jpeg_decompress->out_color_space = JCS_RGB;
    pixel_format_ = RGB_888;
    bytes_per_row_ = 3 * width_;
  }
  is_progressive_ = jpeg_decompress->progressive_mode;

  was_initialized_ = true;
  return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
}

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

  if (setjmp(jpeg_env_->jmp_buf_env_)) {
    // This code is run only when libjpeg hit an error and called
    // longjmp(env). It will reset the object to a state where it can be used
    // again.
    Reset();
    return PS_LOGGED_STATUS(PS_LOG_INFO, message_handler_,
                            SCANLINE_STATUS_INTERNAL_ERROR,
                            SCANLINE_JPEGREADER,
                            "libjpeg failed to decode the image.");
  }

  // At the time when ReadNextScanline is called, allocate buffer for holding
  // a row of pixels, and initiate decompression.
  jpeg_decompress_struct* jpeg_decompress = &(jpeg_env_->jpeg_decompress_);
  if (row_ == 0) {
    row_pointer_[0] = static_cast<JSAMPLE*>(malloc(bytes_per_row_));
    jpeg_start_decompress(jpeg_decompress);
  }

  // Try to read a scanline.
  const JDIMENSION num_scanlines_read =
      jpeg_read_scanlines(jpeg_decompress, row_pointer_, 1);
  if (num_scanlines_read != 1) {
    Reset();
    return PS_LOGGED_STATUS(PS_LOG_INFO, message_handler_,
                            SCANLINE_STATUS_PARSE_ERROR,
                            SCANLINE_JPEGREADER,
                            "libjpeg failed to read a scanline.");
  }
  *out_scanline_bytes = row_pointer_[0];
  ++row_;

  // At the last row, ask libjpeg to finish decompression.
  if (!HasMoreScanLines()) {
    jpeg_finish_decompress(jpeg_decompress);
  }
  return ScanlineStatus(SCANLINE_STATUS_SUCCESS);
}

}  // namespace image_compression

}  // namespace pagespeed
