/*
 * Copyright 2013 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: Huibao Lin

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

#include <setjmp.h>
#include <stdlib.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/frame_interface_optimizer.h"
#include "pagespeed/kernel/image/gif_reader.h"
#include "pagespeed/kernel/image/image_frame_interface.h"
#include "pagespeed/kernel/image/jpeg_optimizer.h"
#include "pagespeed/kernel/image/jpeg_reader.h"
#include "pagespeed/kernel/image/png_optimizer.h"
#include "pagespeed/kernel/image/scanline_interface.h"
#include "pagespeed/kernel/image/scanline_interface_frame_adapter.h"
#include "pagespeed/kernel/image/scanline_utils.h"
#include "pagespeed/kernel/image/webp_optimizer.h"

namespace pagespeed {

namespace image_compression {

using net_instaweb::MessageHandler;

////////// Scanline API

// Forward declaration
MultipleFrameReader* InstantiateImageFrameReader(
    ImageFormat image_type,
    MessageHandler* handler,
    ScanlineStatus* status);

// Instantiates an uninitialized scanline image reader.
ScanlineReaderInterface* InstantiateScanlineReader(
    ImageFormat image_type,
    MessageHandler* handler,
    ScanlineStatus* status) {
  ScanlineReaderInterface* reader = NULL;
  const char* which = NULL;

  *status = ScanlineStatus(SCANLINE_STATUS_SUCCESS);
  switch (image_type) {
    case IMAGE_PNG:
      reader = new PngScanlineReaderRaw(handler);
      which = "PngScanlineReaderRaw";
      break;

    case IMAGE_JPEG:
      reader = new JpegScanlineReader(handler);
      which = "JpegScanlineReader";
      break;

    case IMAGE_WEBP:
      reader = new WebpScanlineReader(handler);
      which = "WebpScanlineReader";
      break;

    case IMAGE_GIF: {
      which = "FrameToScanlineReaderAdapter(GifFrameReader)";
      net_instaweb::scoped_ptr<MultipleFrameReader> mf_reader(
          InstantiateImageFrameReader(image_type, handler, status));
      if (!mf_reader->set_quirks_mode(QUIRKS_CHROME, status)) {
        return NULL;
      }
      reader =
          new FrameToScanlineReaderAdapter(
              new MultipleFramePaddingReader(mf_reader.release()));
      break;
    }

    case IMAGE_UNKNOWN:
      break;

    // No default so compiler will complain if any enum is not processed.
  }

  if (which == NULL) {
      *status = PS_LOGGED_STATUS(PS_LOG_DFATAL, handler,
                                 SCANLINE_STATUS_UNSUPPORTED_FORMAT,
                                 SCANLINE_UTIL,
                                 "invalid image type for reader: %d",
                                 image_type);
  } else if (reader == NULL) {
    *status = PS_LOGGED_STATUS(PS_LOG_ERROR, handler,
                               SCANLINE_STATUS_MEMORY_ERROR,
                               SCANLINE_UTIL,
                               "failed to allocate %s", which);
  }

  return reader;
}

// Returns an initialized scanline image reader.
ScanlineReaderInterface* CreateScanlineReader(
    ImageFormat image_type,
    const void* image_buffer,
    size_t buffer_length,
    MessageHandler* handler,
    ScanlineStatus* status) {
  net_instaweb::scoped_ptr<ScanlineReaderInterface> reader(
      InstantiateScanlineReader(image_type, handler, status));
  if (status->Success()) {
    *status = reader->InitializeWithStatus(image_buffer, buffer_length);
  }
  return status->Success() ? reader.release() : NULL;
}

// Forward declaration.
MultipleFrameWriter* InstantiateImageFrameWriter(
    ImageFormat image_type,
    MessageHandler* handler,
    ScanlineStatus* status);

// Instantiates an uninitialized scanline image writer.
ScanlineWriterInterface* InstantiateScanlineWriter(
    ImageFormat image_type,
    MessageHandler* handler,
    ScanlineStatus* status) {
  ScanlineWriterInterface* writer = NULL;
  const char* which = NULL;

  *status = ScanlineStatus(SCANLINE_STATUS_SUCCESS);
  switch (image_type) {
    case pagespeed::image_compression::IMAGE_JPEG:
      {
        net_instaweb::scoped_ptr<JpegScanlineWriter> jpeg_writer(
            new JpegScanlineWriter(handler));
        if (jpeg_writer != NULL) {
          // TODO(huibao): Set up error handling inside JpegScanlineWriter.
          // Remove 'setjmp' from the clients and remove the 'SetJmpBufEnv'
          // method.
          jmp_buf env;
          if (setjmp(env)) {
            // This code is run only when libjpeg hit an error, and
            // called longjmp(env). Note that this only works for as
            // long as this stack frame is valid.
            jpeg_writer->AbortWrite();
            return NULL;
          }

          jpeg_writer->SetJmpBufEnv(&env);
          writer = jpeg_writer.release();
        }
        which  = "JpegScanlineWriter";
      }
      break;

    case pagespeed::image_compression::IMAGE_PNG:
      writer = new PngScanlineWriter(handler);
      which = "PngScanlineWriter";
      break;

    case pagespeed::image_compression::IMAGE_WEBP:
      which = "FrameToScanlineWriterAdapter(WebpFrameWriter)";
      writer = new FrameToScanlineWriterAdapter(
          InstantiateImageFrameWriter(image_type, handler, status));
      break;

    case IMAGE_GIF:
      // This library does not implement a GIF writer; intentional
      // fall-through.
    case IMAGE_UNKNOWN:
      break;

    // No default so compiler will complain if any enum is not processed.
  }

  if (which == NULL) {
        *status = PS_LOGGED_STATUS(PS_LOG_DFATAL, handler,
                                   SCANLINE_STATUS_UNSUPPORTED_FORMAT,
                                   SCANLINE_UTIL,
                                   "invalid image type for writer: %d",
                                   image_type);
  } else if (writer == NULL) {
    *status = PS_LOGGED_STATUS(PS_LOG_ERROR, handler,
                               SCANLINE_STATUS_MEMORY_ERROR,
                               SCANLINE_UTIL,
                               "failed to allocate %s", which);
  }

  return writer;
}


// Returns an initialized scanline image writer.
ScanlineWriterInterface* CreateScanlineWriter(
    ImageFormat image_type,
    PixelFormat pixel_format,
    size_t width,
    size_t height,
    const void* config,
    GoogleString* image_data,
    MessageHandler* handler,
    ScanlineStatus* status) {
  net_instaweb::scoped_ptr<ScanlineWriterInterface> writer(
      InstantiateScanlineWriter(image_type, handler, status));
  if (status->Success()) {
    *status = writer->InitWithStatus(width, height, pixel_format);
  }
  if (status->Success()) {
    *status = writer->InitializeWriteWithStatus(config, image_data);
  }
  return status->Success() ? writer.release() : NULL;
}


////////// ImageFrame API

// Instantiates an uninitialized image frame reader.
MultipleFrameReader* InstantiateImageFrameReader(
    ImageFormat image_type,
    MessageHandler* handler,
    ScanlineStatus* status) {
  MultipleFrameReader* reader = NULL;

  *status = ScanlineStatus(SCANLINE_STATUS_SUCCESS);
  if (image_type == IMAGE_GIF) {
    // Native ImageFrame implementation
    reader = new GifFrameReader(handler);
    if (reader == NULL) {
      *status = PS_LOGGED_STATUS(
          PS_LOG_ERROR, handler,
          SCANLINE_STATUS_MEMORY_ERROR,
          SCANLINE_UTIL,
          "failed to allocate GifFrameReader");
    }
  } else {
    // Image formats for which we do not have an ImageFrame
    // implementation result in a wrapper around the corresponding
    // Scanline object.
    net_instaweb::scoped_ptr<ScanlineReaderInterface> scanline_reader(
        InstantiateScanlineReader(image_type, handler, status));
    if (status->Success()) {
      reader = new ScanlineToFrameReaderAdapter(
          scanline_reader.release(), handler);
      if (reader == NULL) {
        *status = PS_LOGGED_STATUS(
            PS_LOG_ERROR, handler,
            SCANLINE_STATUS_MEMORY_ERROR,
            SCANLINE_UTIL,
            "failed to allocate ScanlineToFrameReaderAdapter");
      }
    }
  }

  return reader;
}

// Returns an initialized image frame reader.
MultipleFrameReader* CreateImageFrameReader(
    ImageFormat image_type,
    const void* image_buffer,
    size_t buffer_length,
    QuirksMode quirks_mode,
    MessageHandler* handler,
    ScanlineStatus* status) {
  net_instaweb::scoped_ptr<MultipleFrameReader> reader(
      InstantiateImageFrameReader(image_type, handler, status));
  return (status->Success() &&
          reader->set_quirks_mode(quirks_mode, status) &&
          reader->Initialize(image_buffer, buffer_length, status)) ?
          reader.release() : NULL;
}

// Instantiates an uninitialized image frame writer.
MultipleFrameWriter* InstantiateImageFrameWriter(
    ImageFormat image_type,
    MessageHandler* handler,
    ScanlineStatus* status) {
  MultipleFrameWriter* allocated_writer = NULL;
  *status = ScanlineStatus(SCANLINE_STATUS_SUCCESS);

  if (image_type == IMAGE_WEBP) {
    // Native ImageFrame implementation
    allocated_writer = new WebpFrameWriter(handler);
    if (allocated_writer == NULL) {
      *status = PS_LOGGED_STATUS(
          PS_LOG_ERROR, handler,
          SCANLINE_STATUS_MEMORY_ERROR,
          SCANLINE_UTIL,
          "failed to allocate WebpFrameReader");
    }
  } else {
    // Image formats for which we do not have an ImageFrame
    // implementation result in a wrapper around the corresponding
    // Scanline object.
    net_instaweb::scoped_ptr<ScanlineWriterInterface> scanline_writer(
        InstantiateScanlineWriter(image_type, handler, status));
    if (status->Success()) {
      allocated_writer = new ScanlineToFrameWriterAdapter(
          scanline_writer.release(), handler);
      if (allocated_writer == NULL) {
        *status = PS_LOGGED_STATUS(
            PS_LOG_ERROR, handler,
            SCANLINE_STATUS_MEMORY_ERROR,
            SCANLINE_UTIL,
            "failed to allocate ScanlineToFrameWriterAdapter");
      }
    }
  }
  return allocated_writer;
}

// Returns an initialized image frame writer.
MultipleFrameWriter* CreateImageFrameWriter(
    ImageFormat image_type,
    const void* config,
    GoogleString* image_data,
    MessageHandler* handler,
    ScanlineStatus* status) {
  net_instaweb::scoped_ptr<MultipleFrameWriter> writer(
      InstantiateImageFrameWriter(image_type, handler, status));
  return (status->Success() &&
          writer->Initialize(config, image_data, status)) ?
      writer.release() : NULL;
}

////////// Utilities

bool ReadImage(ImageFormat image_type,
               const void* image_buffer,
               size_t buffer_length,
               void** pixels,
               PixelFormat* pixel_format,
               size_t* width,
               size_t* height,
               size_t* stride,
               MessageHandler* handler) {
  // Instantiate and initialize the reader based on image type.
  net_instaweb::scoped_ptr<ScanlineReaderInterface> reader;
  reader.reset(CreateScanlineReader(image_type, image_buffer, buffer_length,
                                    handler));
  if (reader.get() == NULL) {
    return false;
  }

  // The following information is available after the reader is initialized.
  // Copy them to the outputs if they are requested.
  if (pixel_format != NULL) {
    *pixel_format = reader->GetPixelFormat();
  }
  if (width != NULL) {
    *width = reader->GetImageWidth();
  }
  if (height != NULL) {
    *height = reader->GetImageHeight();
  }

  // Round up stride to a multiplier of 4.
  size_t bytes_per_row4 = (((reader->GetBytesPerScanline() + 3) >> 2) << 2);
  if (stride != NULL) {
    *stride = bytes_per_row4;
  }

  // Decode the image data (pixels) if it has been requested.
  if (pixels == NULL) {
    return true;
  }
  *pixels = NULL;
  const size_t data_length = reader->GetImageHeight() * bytes_per_row4;
  unsigned char* image_data = static_cast<unsigned char*>(malloc(data_length));
  if (image_data == NULL) {
    return false;
  }

  unsigned char* row_data = image_data;
  unsigned char* scanline = NULL;
  while (reader->HasMoreScanLines()) {
    if (!reader->ReadNextScanline(reinterpret_cast<void**>(&scanline))) {
      free(image_data);
      return false;
    }
    memcpy(row_data, scanline, reader->GetBytesPerScanline());
    row_data += bytes_per_row4;
  }

  *pixels = static_cast<void*>(image_data);
  return true;
}

}  // namespace image_compression

}  // namespace pagespeed
