/*
 * Copyright 2015 Google Inc. All Rights Reserved.
 *
 * 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.
 */

#include "cobalt/renderer/test/png_utils/png_decode.h"

#include <vector>

#include "base/debug/trace_event.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "third_party/libpng/png.h"

namespace cobalt {
namespace renderer {
namespace test {
namespace png_utils {

namespace {

class PNGFileReadContext {
 public:
  explicit PNGFileReadContext(const FilePath& file_path,
                              render_tree::PixelFormat pixel_format,
                              render_tree::AlphaFormat alpha_format);
  ~PNGFileReadContext();

  void DecodeImageTo(const std::vector<png_bytep>& rows);

  int width() const { return width_; }
  int height() const { return height_; }

 private:
  base::PlatformFile file_;
  png_structp png_;
  png_infop png_metadata_;

  int width_;
  int height_;
};

uint8_t PremultiplyAlpha(uint8_t alpha_value, uint8_t component_value) {
  // The following code divides by 255 and rounds without explicitly using
  // a division instruction.
  // For more information read:
  // http://answers.google.com/answers/threadview/id/502016.html
  uint32_t product = component_value * alpha_value + 128;
  return (product + (product >> 8)) >> 8;
}

template <bool premultiply, int r, int g, int b, int a>
void TransformPixelRow(png_structp ptr, png_row_infop row_info,
                       png_bytep data) {
  for (unsigned int i = 0; i < row_info->width; ++i) {
    uint8_t* color_bytes = data + i * 4;
    uint8_t pixel[4];
    for (int i = 0; i < 4; ++i) {
      pixel[i] = color_bytes[i];
    }
    uint8_t alpha_value = pixel[3];
    color_bytes[r] =
        premultiply ? PremultiplyAlpha(alpha_value, pixel[0]) : pixel[0];
    color_bytes[g] =
        premultiply ? PremultiplyAlpha(alpha_value, pixel[1]) : pixel[1];
    color_bytes[b] =
        premultiply ? PremultiplyAlpha(alpha_value, pixel[2]) : pixel[2];
    color_bytes[a] = pixel[3];
  }
}

void PNGReadPlatformFile(png_structp png, png_bytep buffer,
                         png_size_t buffer_size) {
#if defined(OS_STARBOARD)
  // Casting between two pointer types.
  base::PlatformFile file =
      reinterpret_cast<base::PlatformFile>(png_get_io_ptr(png));
#else
  // Casting from a pointer to an int type.
  intptr_t temp = reinterpret_cast<intptr_t>(png_get_io_ptr(png));
  base::PlatformFile file = static_cast<base::PlatformFile>(temp);
#endif
  int count = base::ReadPlatformFileAtCurrentPos(
      file, reinterpret_cast<char*>(buffer), buffer_size);
  DCHECK_EQ(count, buffer_size);
}

PNGFileReadContext::PNGFileReadContext(const FilePath& file_path,
                                       render_tree::PixelFormat pixel_format,
                                       render_tree::AlphaFormat alpha_format) {
  TRACE_EVENT0("renderer::test::png_utils",
               "PNGFileReadContext::PNGFileReadContext()");

  // Much of this PNG loading code is based on a section from the libpng manual:
  // http://www.libpng.org/pub/png/libpng-1.2.5-manual.html#section-3

  file_ = base::CreatePlatformFile(
      file_path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, NULL,
      NULL);
  DCHECK_NE(base::kInvalidPlatformFileValue, file_) << "Unable to open: "
                                                    << file_path.value();

  uint8_t header[8];
  int count = base::ReadPlatformFileAtCurrentPos(
      file_, reinterpret_cast<char*>(header), sizeof(header));
  DCHECK_EQ(sizeof(header), count) << "Invalid file size.";
  DCHECK(!png_sig_cmp(header, 0, 8)) << "Invalid PNG header.";

  // Set up a libpng context for reading images.
  png_ = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  DCHECK(png_);

  // Create a structure to contain metadata about the image.
  png_metadata_ = png_create_info_struct(png_);
  DCHECK(png_metadata_);

  // libpng expects to longjump to png_->jmpbuf if it encounters an error.
  // According to longjmp's documentation, this implies that stack unwinding
  // will occur in that case, though C++ objects with non-trivial destructors
  // will not be called.  This is fine though, since we abort upon errors here.
  // If alternative behavior is desired, custom error and warning handler
  // functions can be passed into the png_create_read_struct() call above.
  if (setjmp(png_->jmpbuf)) {
    LOG(FATAL) << "libpng returned error reading " << file_path.value();
  }

  // Set up for file i/o.
  png_set_read_fn(png_, reinterpret_cast<void*>(file_), &PNGReadPlatformFile);
  // Tell png we already read 8 bytes.
  png_set_sig_bytes(png_, 8);
  // Read the image info.
  png_read_info(png_, png_metadata_);

  // Transform PNGs into a canonical RGBA form, in order to simplify the process
  // of reading png files of varying formats.  Of course, if we would like to
  // maintain data in formats other than RGBA, this logic should be adjusted.
  {
    if (png_get_bit_depth(png_, png_metadata_) == 16) {
      png_set_strip_16(png_);
    }

    png_byte color = png_get_color_type(png_, png_metadata_);

    if (color == PNG_COLOR_TYPE_GRAY &&
        png_get_bit_depth(png_, png_metadata_) < 8) {
      png_set_expand_gray_1_2_4_to_8(png_);
    }

    // Convert from grayscale or palette to color.
    if (!(color & PNG_COLOR_MASK_COLOR)) {
      png_set_gray_to_rgb(png_);
    } else if (color == PNG_COLOR_TYPE_PALETTE) {
      png_set_palette_to_rgb(png_);
    }

    // Add an alpha channel if missing.
    if (!(color & PNG_COLOR_MASK_ALPHA)) {
      png_set_add_alpha(png_, 0xff /* opaque */, PNG_FILLER_AFTER);
    }
  }

  switch (alpha_format) {
    case render_tree::kAlphaFormatPremultiplied: {
      switch (pixel_format) {
        case render_tree::kPixelFormatRGBA8: {
          png_set_read_user_transform_fn(png_,
                                         &TransformPixelRow<true, 0, 1, 2, 3>);
        } break;
        case render_tree::kPixelFormatBGRA8: {
          png_set_read_user_transform_fn(png_,
                                         &TransformPixelRow<true, 2, 1, 0, 3>);
        } break;
        case render_tree::kPixelFormatY8:
        case render_tree::kPixelFormatU8:
        case render_tree::kPixelFormatV8:
        case render_tree::kPixelFormatUV8:
        case render_tree::kPixelFormatInvalid: {
          NOTREACHED();
        }
      }
    } break;
    case render_tree::kAlphaFormatUnpremultiplied: {
      switch (pixel_format) {
        case render_tree::kPixelFormatRGBA8: {
          // No need to set a transform in this case, this is how the data
          // is coming out anyway.
        } break;
        case render_tree::kPixelFormatBGRA8: {
          png_set_read_user_transform_fn(png_,
                                         &TransformPixelRow<true, 2, 1, 0, 3>);
        } break;
        case render_tree::kPixelFormatY8:
        case render_tree::kPixelFormatU8:
        case render_tree::kPixelFormatV8:
        case render_tree::kPixelFormatUV8:
        case render_tree::kPixelFormatInvalid: {
          NOTREACHED();
        }
      }
    } break;
    case render_tree::kAlphaFormatOpaque: {
      NOTREACHED() << "kAlphaFormatOpaque not supported.";
    } break;
  }

  // End transformations. Get the updated info, and then verify.
  png_read_update_info(png_, png_metadata_);
  DCHECK_EQ(PNG_COLOR_TYPE_RGBA, png_get_color_type(png_, png_metadata_));
  DCHECK_EQ(8, png_get_bit_depth(png_, png_metadata_));

  width_ = png_get_image_width(png_, png_metadata_);
  height_ = png_get_image_height(png_, png_metadata_);
}

PNGFileReadContext::~PNGFileReadContext() {
  // Time to clean up.  First create a structure to read image metadata (like
  // comments) from the end of the png file, then read the remaining data in
  // the png file, and then finally release our context and close the file.
  png_infop end = png_create_info_struct(png_);
  DCHECK(end);

  // Read the end data in the png file.
  png_read_end(png_, end);

  // Release our png reading context and associated info structs.
  png_destroy_read_struct(&png_, &png_metadata_, &end);

  base::ClosePlatformFile(file_);
}

void PNGFileReadContext::DecodeImageTo(const std::vector<png_bytep>& rows) {
  TRACE_EVENT0("renderer::test::png_utils",
               "PNGFileReadContext::DecodeImageTo()");
  // Execute the read of png image data.
  png_read_image(png_, const_cast<png_bytep*>(&rows[0]));
}

scoped_array<uint8_t> DecodePNGToRGBAInternal(
    const FilePath& png_file_path, int* width, int* height,
    render_tree::AlphaFormat alpha_format) {
  PNGFileReadContext png_read_context(
      png_file_path, render_tree::kPixelFormatRGBA8, alpha_format);

  // Setup pointers to the rows in which libpng should read out the decoded png
  // image data to.

  // We set bpp to 4 because we know that we're dealing with RGBA.
  const int bytes_per_pixel = 4;
  int pitch = png_read_context.width() * 4;
  scoped_array<uint8_t> data(new uint8_t[pitch * png_read_context.height()]);
  std::vector<png_bytep> rows(png_read_context.height());
  uint8_t* row = data.get();
  for (int i = 0; i < png_read_context.height(); ++i) {
    rows[i] = row;
    row += pitch;
  }

  png_read_context.DecodeImageTo(rows);

  // And finally return the output decoded PNG data.
  DCHECK(width);
  DCHECK(height);
  *width = png_read_context.width();
  *height = png_read_context.height();

  return data.Pass();
}

}  // namespace

scoped_array<uint8_t> DecodePNGToRGBA(const FilePath& png_file_path, int* width,
                                      int* height) {
  TRACE_EVENT0("renderer::test::png_utils", "DecodePNGToRGBA()");
  return DecodePNGToRGBAInternal(png_file_path, width, height,
                                 render_tree::kAlphaFormatUnpremultiplied);
}

scoped_array<uint8_t> DecodePNGToPremultipliedAlphaRGBA(
    const FilePath& png_file_path, int* width, int* height) {
  TRACE_EVENT0("renderer::test::png_utils",
               "DecodePNGToPremultipliedAlphaRGBA()");
  return DecodePNGToRGBAInternal(png_file_path, width, height,
                                 render_tree::kAlphaFormatPremultiplied);
}

namespace {
render_tree::PixelFormat ChoosePixelFormat(
    render_tree::ResourceProvider* resource_provider) {
  if (resource_provider->PixelFormatSupported(render_tree::kPixelFormatRGBA8)) {
    return render_tree::kPixelFormatRGBA8;
  } else if (resource_provider->PixelFormatSupported(
                 render_tree::kPixelFormatBGRA8)) {
    return render_tree::kPixelFormatBGRA8;
  } else {
    NOTREACHED() << "Invalid pixel format.";
    return render_tree::kPixelFormatInvalid;
  }
}
}  // namespace

scoped_refptr<cobalt::render_tree::Image> DecodePNGToRenderTreeImage(
    const FilePath& png_file_path,
    render_tree::ResourceProvider* resource_provider) {
  TRACE_EVENT0("renderer::test::png_utils", "DecodePNGToRenderTreeImage()");

  render_tree::PixelFormat pixel_format = ChoosePixelFormat(resource_provider);
  PNGFileReadContext png_read_context(png_file_path, pixel_format,
                                      render_tree::kAlphaFormatPremultiplied);

  // Setup pointers to the rows in which libpng should read out the decoded png
  // image data to.
  // Currently, we decode all images to RGBA and load those.
  scoped_ptr<render_tree::ImageData> data =
      resource_provider->AllocateImageData(
          math::Size(png_read_context.width(), png_read_context.height()),
          pixel_format, render_tree::kAlphaFormatPremultiplied);
  std::vector<png_bytep> rows(png_read_context.height());
  uint8_t* row = data->GetMemory();
  for (int i = 0; i < png_read_context.height(); ++i) {
    rows[i] = row;
    row += data->GetDescriptor().pitch_in_bytes;
  }

  png_read_context.DecodeImageTo(rows);

  // And now create a texture out of the image data.
  return resource_provider->CreateImage(data.Pass());
}

}  // namespace png_utils
}  // namespace test
}  // namespace renderer
}  // namespace cobalt
