/*
 * 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_encode.h"

#include <vector>

#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 {
// Write PNG data to a vector to simplify memory management.
typedef std::vector<png_byte> PNGByteVector;

void PNGWriteFunction(png_structp png_ptr, png_bytep data, png_size_t length) {
  PNGByteVector* out_buffer =
      reinterpret_cast<PNGByteVector*>(png_get_io_ptr(png_ptr));
  // Append the data to the array using pointers to the beginning and end of the
  // buffer as the first and last iterators.
  out_buffer->insert(out_buffer->end(), data, data + length);
}
}  // namespace

void EncodeRGBAToPNG(const FilePath& png_file_path, const uint8_t* pixel_data,
                     int width, int height, int pitch_in_bytes) {
  // Write the PNG to an in-memory buffer and then write it to disk.
  size_t size;
  scoped_array<uint8> buffer =
      EncodeRGBAToBuffer(pixel_data, width, height, pitch_in_bytes, &size);
  if (!buffer || size == 0) {
    DLOG(ERROR) << "Failed to encode PNG.";
    return;
  }

  int bytes_written = file_util::WriteFile(
      png_file_path, reinterpret_cast<char*>(buffer.get()), size);
  DLOG_IF(ERROR, bytes_written != size) << "Error writing PNG to file.";
}

// Encodes RGBA8 formatted pixel data to an in memory buffer.
scoped_array<uint8> EncodeRGBAToBuffer(const uint8_t* pixel_data, int width,
                                       int height, int pitch_in_bytes,
                                       size_t* out_size) {
  // Initialize png library and headers for writing.
  png_structp png =
      png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
  DCHECK(png);
  png_infop info = png_create_info_struct(png);
  DCHECK(info);

  // if error encountered png will call longjmp(), so we set up a setjmp() here
  // with a failed assert to indicate an error in one of the png functions.
  // yo libpng, 1980 called, they want their longjmp() back....
  if (setjmp(png->jmpbuf)) {
    png_destroy_write_struct(&png, &info);
    NOTREACHED() << "libpng encountered an error during processing.";
    return scoped_array<uint8>();
  }

  // Structure into which png data will be written.
  PNGByteVector png_buffer;

  // Set the write callback. Don't set the flush function, since there's no
  // need for buffered IO when writing to memory.
  png_set_write_fn(png, &png_buffer, &PNGWriteFunction, NULL);

  // Stuff and then write png header.
  png_set_IHDR(png, info, width, height,
               8,  // 8 bits per color channel.
               PNG_COLOR_TYPE_RGBA, PNG_INTERLACE_NONE,
               PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
  png_write_info(png, info);

  // Write image bytes, row by row.
  png_bytep row = (png_bytep)pixel_data;
  for (int i = 0; i < height; ++i) {
    png_write_row(png, row);
    row += pitch_in_bytes;
  }

  png_write_end(png, NULL);
  png_destroy_write_struct(&png, &info);

  size_t num_bytes = png_buffer.size() * sizeof(PNGByteVector::value_type);
  *out_size = num_bytes;

  // Copy the memory from the buffer to a scoped_array to return to the caller.
  scoped_array<uint8> out_buffer(new uint8[num_bytes]);
  memcpy(out_buffer.get(), &(png_buffer[0]), num_bytes);
  return out_buffer.Pass();
}

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