// Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#include "libcef/browser/image_impl.h"

#include <algorithm>

#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/image/image_png_rep.h"
#include "ui/gfx/image/image_skia.h"

namespace {

SkColorType GetSkColorType(cef_color_type_t color_type) {
  switch (color_type) {
    case CEF_COLOR_TYPE_RGBA_8888:
      return kRGBA_8888_SkColorType;
    case CEF_COLOR_TYPE_BGRA_8888:
      return kBGRA_8888_SkColorType;
    default:
      break;
  }

  NOTREACHED();
  return kUnknown_SkColorType;
}

SkAlphaType GetSkAlphaType(cef_alpha_type_t alpha_type) {
  switch (alpha_type) {
    case CEF_ALPHA_TYPE_OPAQUE:
      return kOpaque_SkAlphaType;
    case CEF_ALPHA_TYPE_PREMULTIPLIED:
      return kPremul_SkAlphaType;
    case CEF_ALPHA_TYPE_POSTMULTIPLIED:
      return kUnpremul_SkAlphaType;
    default:
      break;
  }

  NOTREACHED();
  return kUnknown_SkAlphaType;
}

// Compress as PNG. Requires post-multiplied alpha.
bool PNGMethod(bool with_transparency,
               const SkBitmap& bitmap,
               std::vector<unsigned char>* compressed) {
  return gfx::PNGCodec::Encode(
      reinterpret_cast<unsigned char*>(bitmap.getPixels()),
      bitmap.colorType() == kBGRA_8888_SkColorType ? gfx::PNGCodec::FORMAT_BGRA
                                                   : gfx::PNGCodec::FORMAT_RGBA,
      gfx::Size(bitmap.width(), bitmap.height()),
      static_cast<int>(bitmap.rowBytes()),
      bitmap.alphaType() == kOpaque_SkAlphaType || !with_transparency,
      std::vector<gfx::PNGCodec::Comment>(), compressed);
}

// Compress as JPEG. This internally uses JCS_EXT_RGBX or JCS_EXT_BGRX which
// causes the alpha channel to be ignored. Requires post-multiplied alpha.
bool JPEGMethod(int quality,
                const SkBitmap& bitmap,
                std::vector<unsigned char>* compressed) {
  return gfx::JPEGCodec::Encode(bitmap, quality, compressed);
}

}  // namespace

// static
CefRefPtr<CefImage> CefImage::CreateImage() {
  return new CefImageImpl();
}

CefImageImpl::CefImageImpl(const gfx::ImageSkia& image_skia)
    : image_(image_skia) {}

bool CefImageImpl::IsEmpty() {
  base::AutoLock lock_scope(lock_);
  return image_.IsEmpty();
}

bool CefImageImpl::IsSame(CefRefPtr<CefImage> that) {
  CefImageImpl* that_impl = static_cast<CefImageImpl*>(that.get());
  if (!that_impl)
    return false;

  // Quick check for the same object.
  if (this == that_impl)
    return true;

  base::AutoLock lock_scope(lock_);
  return image_.AsImageSkia().BackedBySameObjectAs(
      that_impl->image_.AsImageSkia());
}

bool CefImageImpl::AddBitmap(float scale_factor,
                             int pixel_width,
                             int pixel_height,
                             cef_color_type_t color_type,
                             cef_alpha_type_t alpha_type,
                             const void* pixel_data,
                             size_t pixel_data_size) {
  const SkColorType ct = GetSkColorType(color_type);
  const SkAlphaType at = GetSkAlphaType(alpha_type);

  // Make sure the client passed in the expected values.
  if (ct != kBGRA_8888_SkColorType && ct != kRGBA_8888_SkColorType)
    return false;
  if (pixel_data_size != pixel_width * pixel_height * 4U)
    return false;

  SkBitmap bitmap;
  if (!bitmap.tryAllocPixels(
          SkImageInfo::Make(pixel_width, pixel_height, ct, at))) {
    return false;
  }

  DCHECK_EQ(pixel_data_size, bitmap.computeByteSize());
  memcpy(bitmap.getPixels(), pixel_data, pixel_data_size);

  return AddBitmap(scale_factor, bitmap);
}

bool CefImageImpl::AddPNG(float scale_factor,
                          const void* png_data,
                          size_t png_data_size) {
  SkBitmap bitmap;
  if (!gfx::PNGCodec::Decode(static_cast<const unsigned char*>(png_data),
                             png_data_size, &bitmap)) {
    return false;
  }

  return AddBitmap(scale_factor, bitmap);
}

bool CefImageImpl::AddJPEG(float scale_factor,
                           const void* jpeg_data,
                           size_t jpeg_data_size) {
  std::unique_ptr<SkBitmap> bitmap(gfx::JPEGCodec::Decode(
      static_cast<const unsigned char*>(jpeg_data), jpeg_data_size));
  if (!bitmap.get())
    return false;

  return AddBitmap(scale_factor, *bitmap);
}

size_t CefImageImpl::GetWidth() {
  base::AutoLock lock_scope(lock_);
  return image_.Width();
}

size_t CefImageImpl::GetHeight() {
  base::AutoLock lock_scope(lock_);
  return image_.Height();
}

bool CefImageImpl::HasRepresentation(float scale_factor) {
  base::AutoLock lock_scope(lock_);
  return image_.AsImageSkia().HasRepresentation(scale_factor);
}

bool CefImageImpl::RemoveRepresentation(float scale_factor) {
  base::AutoLock lock_scope(lock_);
  gfx::ImageSkia image_skia = image_.AsImageSkia();
  if (image_skia.HasRepresentation(scale_factor)) {
    image_skia.RemoveRepresentation(scale_factor);
    return true;
  }
  return false;
}

bool CefImageImpl::GetRepresentationInfo(float scale_factor,
                                         float& actual_scale_factor,
                                         int& pixel_width,
                                         int& pixel_height) {
  base::AutoLock lock_scope(lock_);
  gfx::ImageSkia image_skia = image_.AsImageSkia();
  if (image_skia.isNull())
    return false;

  const gfx::ImageSkiaRep& rep = image_skia.GetRepresentation(scale_factor);
  if (rep.is_null())
    return false;

  actual_scale_factor = rep.scale();
  pixel_width = rep.GetBitmap().width();
  pixel_height = rep.GetBitmap().height();
  return true;
}

CefRefPtr<CefBinaryValue> CefImageImpl::GetAsBitmap(float scale_factor,
                                                    cef_color_type_t color_type,
                                                    cef_alpha_type_t alpha_type,
                                                    int& pixel_width,
                                                    int& pixel_height) {
  const SkColorType desired_ct = GetSkColorType(color_type);
  const SkAlphaType desired_at = GetSkAlphaType(alpha_type);

  base::AutoLock lock_scope(lock_);
  const SkBitmap* bitmap = GetBitmap(scale_factor);
  if (!bitmap)
    return nullptr;

  DCHECK(bitmap->readyToDraw());

  pixel_width = bitmap->width();
  pixel_height = bitmap->height();

  if (bitmap->colorType() == desired_ct && bitmap->alphaType() == desired_at) {
    // No conversion necessary.
    return CefBinaryValue::Create(bitmap->getPixels(),
                                  bitmap->computeByteSize());
  } else {
    SkBitmap desired_bitmap;
    if (!ConvertBitmap(*bitmap, &desired_bitmap, desired_ct, desired_at))
      return nullptr;
    DCHECK(desired_bitmap.readyToDraw());
    return CefBinaryValue::Create(desired_bitmap.getPixels(),
                                  desired_bitmap.computeByteSize());
  }
}

CefRefPtr<CefBinaryValue> CefImageImpl::GetAsPNG(float scale_factor,
                                                 bool with_transparency,
                                                 int& pixel_width,
                                                 int& pixel_height) {
  base::AutoLock lock_scope(lock_);
  const SkBitmap* bitmap = GetBitmap(scale_factor);
  if (!bitmap)
    return nullptr;

  std::vector<unsigned char> compressed;
  if (!WritePNG(*bitmap, &compressed, with_transparency))
    return nullptr;

  pixel_width = bitmap->width();
  pixel_height = bitmap->height();

  return CefBinaryValue::Create(&compressed.front(), compressed.size());
}

CefRefPtr<CefBinaryValue> CefImageImpl::GetAsJPEG(float scale_factor,
                                                  int quality,
                                                  int& pixel_width,
                                                  int& pixel_height) {
  base::AutoLock lock_scope(lock_);
  const SkBitmap* bitmap = GetBitmap(scale_factor);
  if (!bitmap)
    return nullptr;

  std::vector<unsigned char> compressed;
  if (!WriteJPEG(*bitmap, &compressed, quality))
    return nullptr;

  pixel_width = bitmap->width();
  pixel_height = bitmap->height();

  return CefBinaryValue::Create(&compressed.front(), compressed.size());
}

void CefImageImpl::AddBitmaps(int32_t scale_1x_size,
                              const std::vector<SkBitmap>& bitmaps) {
  if (scale_1x_size == 0) {
    // Set the scale 1x size to the smallest bitmap pixel size.
    int32_t min_size = std::numeric_limits<int32_t>::max();
    for (const SkBitmap& bitmap : bitmaps) {
      const int32_t size = std::max(bitmap.width(), bitmap.height());
      if (size < min_size)
        min_size = size;
    }
    scale_1x_size = min_size;
  }

  for (const SkBitmap& bitmap : bitmaps) {
    const int32_t size = std::max(bitmap.width(), bitmap.height());
    const float scale_factor =
        static_cast<float>(size) / static_cast<float>(scale_1x_size);
    AddBitmap(scale_factor, bitmap);
  }
}

gfx::ImageSkia CefImageImpl::GetForced1xScaleRepresentation(
    float scale_factor) const {
  base::AutoLock lock_scope(lock_);
  if (scale_factor == 1.0f) {
    // We can use the existing image without modification.
    return image_.AsImageSkia();
  }

  const SkBitmap* bitmap = GetBitmap(scale_factor);
  gfx::ImageSkia image_skia;
  if (bitmap)
    image_skia.AddRepresentation(gfx::ImageSkiaRep(*bitmap, 1.0f));
  return image_skia;
}

gfx::ImageSkia CefImageImpl::AsImageSkia() const {
  base::AutoLock lock_scope(lock_);
  return image_.AsImageSkia();
}

bool CefImageImpl::AddBitmap(float scale_factor, const SkBitmap& bitmap) {
#if DCHECK_IS_ON()
  DCHECK(bitmap.readyToDraw());
#endif
  DCHECK(bitmap.colorType() == kBGRA_8888_SkColorType ||
         bitmap.colorType() == kRGBA_8888_SkColorType);

  gfx::ImageSkiaRep skia_rep(bitmap, scale_factor);
  base::AutoLock lock_scope(lock_);
  if (image_.IsEmpty()) {
    image_ = gfx::Image(gfx::ImageSkia(skia_rep));
  } else {
    image_.AsImageSkia().AddRepresentation(skia_rep);
  }
  return true;
}

const SkBitmap* CefImageImpl::GetBitmap(float scale_factor) const {
  lock_.AssertAcquired();
  gfx::ImageSkia image_skia = image_.AsImageSkia();
  if (image_skia.isNull())
    return nullptr;

  const gfx::ImageSkiaRep& rep = image_skia.GetRepresentation(scale_factor);
  if (rep.is_null())
    return nullptr;

  return &rep.GetBitmap();
}

// static
bool CefImageImpl::ConvertBitmap(const SkBitmap& src_bitmap,
                                 SkBitmap* target_bitmap,
                                 SkColorType target_ct,
                                 SkAlphaType target_at) {
  DCHECK(src_bitmap.readyToDraw());
  DCHECK(src_bitmap.colorType() != target_ct ||
         src_bitmap.alphaType() != target_at);
  DCHECK(target_bitmap);

  SkImageInfo target_info = SkImageInfo::Make(
      src_bitmap.width(), src_bitmap.height(), target_ct, target_at);
  if (!target_bitmap->tryAllocPixels(target_info))
    return false;

  if (!src_bitmap.readPixels(target_info, target_bitmap->getPixels(),
                             target_bitmap->rowBytes(), 0, 0)) {
    return false;
  }

  DCHECK(target_bitmap->readyToDraw());
  return true;
}

// static
bool CefImageImpl::WriteCompressedFormat(const SkBitmap& bitmap,
                                         std::vector<unsigned char>* compressed,
                                         const CompressionMethod& method) {
  const SkBitmap* bitmap_ptr = nullptr;
  SkBitmap bitmap_postalpha;
  if (bitmap.alphaType() == kPremul_SkAlphaType) {
    // Compression methods require post-multiplied alpha values.
    if (!ConvertBitmap(bitmap, &bitmap_postalpha, bitmap.colorType(),
                       kUnpremul_SkAlphaType)) {
      return false;
    }
    bitmap_ptr = &bitmap_postalpha;
  } else {
    bitmap_ptr = &bitmap;
  }

  DCHECK(bitmap_ptr->readyToDraw());
  DCHECK(bitmap_ptr->colorType() == kBGRA_8888_SkColorType ||
         bitmap_ptr->colorType() == kRGBA_8888_SkColorType);
  DCHECK(bitmap_ptr->alphaType() == kOpaque_SkAlphaType ||
         bitmap_ptr->alphaType() == kUnpremul_SkAlphaType);

  return method.Run(*bitmap_ptr, compressed);
}

// static
bool CefImageImpl::WritePNG(const SkBitmap& bitmap,
                            std::vector<unsigned char>* compressed,
                            bool with_transparency) {
  return WriteCompressedFormat(bitmap, compressed,
                               base::Bind(PNGMethod, with_transparency));
}

// static
bool CefImageImpl::WriteJPEG(const SkBitmap& bitmap,
                             std::vector<unsigned char>* compressed,
                             int quality) {
  return WriteCompressedFormat(bitmap, compressed,
                               base::Bind(JPEGMethod, quality));
}
