// Copyright 2016 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#include "core/fpdfapi/page/cpdf_image.h"

#include <stdint.h>

#include <algorithm>
#include <array>
#include <memory>
#include <utility>

#include "constants/stream_dict_common.h"
#include "core/fpdfapi/page/cpdf_dib.h"
#include "core/fpdfapi/page/cpdf_page.h"
#include "core/fpdfapi/page/cpdf_pageimagecache.h"
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_boolean.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
#include "core/fpdfapi/parser/cpdf_document.h"
#include "core/fpdfapi/parser/cpdf_name.h"
#include "core/fpdfapi/parser/cpdf_number.h"
#include "core/fpdfapi/parser/cpdf_reference.h"
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fpdfapi/parser/cpdf_string.h"
#include "core/fxcodec/jpeg/jpegmodule.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/compiler_specific.h"
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/fx_2d_size.h"
#include "core/fxcrt/fx_stream.h"
#include "core/fxcrt/numerics/safe_conversions.h"
#include "core/fxcrt/span_util.h"
#include "core/fxcrt/stl_util.h"
#include "core/fxge/dib/cfx_dibitmap.h"
#include "core/fxge/dib/fx_dib.h"

// static
bool CPDF_Image::IsValidJpegComponent(int32_t comps) {
  return comps == 1 || comps == 3 || comps == 4;
}

// static
bool CPDF_Image::IsValidJpegBitsPerComponent(int32_t bpc) {
  return bpc == 1 || bpc == 2 || bpc == 4 || bpc == 8 || bpc == 16;
}

CPDF_Image::CPDF_Image(CPDF_Document* doc) : document_(doc) {
  DCHECK(document_);
}

CPDF_Image::CPDF_Image(CPDF_Document* doc, RetainPtr<CPDF_Stream> pStream)
    : is_inline_(true), document_(doc), stream_(std::move(pStream)) {
  DCHECK(document_);
  FinishInitialization();
}

CPDF_Image::CPDF_Image(CPDF_Document* doc, uint32_t dwStreamObjNum)
    : document_(doc),
      stream_(ToStream(doc->GetMutableIndirectObject(dwStreamObjNum))) {
  DCHECK(document_);
  FinishInitialization();
}

CPDF_Image::~CPDF_Image() = default;

void CPDF_Image::FinishInitialization() {
  RetainPtr<const CPDF_Dictionary> pStreamDict = stream_->GetDict();
  oc_ = pStreamDict->GetDictFor("OC");
  is_mask_ = !pStreamDict->KeyExist("ColorSpace") ||
             pStreamDict->GetBooleanFor("ImageMask", /*bDefault=*/false);
  interpolate_ = !!pStreamDict->GetIntegerFor("Interpolate");
  height_ = pStreamDict->GetIntegerFor("Height");
  width_ = pStreamDict->GetIntegerFor("Width");
}

void CPDF_Image::ConvertStreamToIndirectObject() {
  CHECK(stream_->IsInline());
  document_->AddIndirectObject(stream_);
}

RetainPtr<const CPDF_Dictionary> CPDF_Image::GetDict() const {
  return stream_ ? stream_->GetDict() : nullptr;
}

RetainPtr<const CPDF_Stream> CPDF_Image::GetStream() const {
  return stream_;
}

RetainPtr<const CPDF_Dictionary> CPDF_Image::GetOC() const {
  return oc_;
}

RetainPtr<CPDF_Dictionary> CPDF_Image::InitJPEG(
    pdfium::span<uint8_t> src_span) {
  std::optional<JpegModule::ImageInfo> info_opt =
      JpegModule::LoadInfo(src_span);
  if (!info_opt.has_value()) {
    return nullptr;
  }

  const JpegModule::ImageInfo& info = info_opt.value();
  if (!IsValidJpegComponent(info.num_components) ||
      !IsValidJpegBitsPerComponent(info.bits_per_components)) {
    return nullptr;
  }

  RetainPtr<CPDF_Dictionary> dict =
      CreateXObjectImageDict(info.width, info.height);
  const char* csname = nullptr;
  if (info.num_components == 1) {
    csname = "DeviceGray";
  } else if (info.num_components == 3) {
    csname = "DeviceRGB";
  } else if (info.num_components == 4) {
    csname = "DeviceCMYK";
    auto pDecode = dict->SetNewFor<CPDF_Array>("Decode");
    for (int n = 0; n < 4; n++) {
      pDecode->AppendNew<CPDF_Number>(1);
      pDecode->AppendNew<CPDF_Number>(0);
    }
  }
  dict->SetNewFor<CPDF_Name>("ColorSpace", csname);
  dict->SetNewFor<CPDF_Number>("BitsPerComponent", info.bits_per_components);
  dict->SetNewFor<CPDF_Name>("Filter", "DCTDecode");
  if (!info.color_transform) {
    auto pParms =
        dict->SetNewFor<CPDF_Dictionary>(pdfium::stream::kDecodeParms);
    pParms->SetNewFor<CPDF_Number>("ColorTransform", 0);
  }
  is_mask_ = false;
  width_ = info.width;
  height_ = info.height;
  return dict;
}

void CPDF_Image::SetJpegImage(RetainPtr<IFX_SeekableReadStream> pFile) {
  uint32_t size = pdfium::checked_cast<uint32_t>(pFile->GetSize());
  if (!size) {
    return;
  }

  uint32_t dwEstimateSize = std::min(size, 8192U);
  DataVector<uint8_t> data(dwEstimateSize);
  if (!pFile->ReadBlockAtOffset(data, 0)) {
    return;
  }

  RetainPtr<CPDF_Dictionary> dict = InitJPEG(data);
  if (!dict && size > dwEstimateSize) {
    data.resize(size);
    if (pFile->ReadBlockAtOffset(data, 0)) {
      dict = InitJPEG(data);
    }
  }
  if (!dict) {
    return;
  }

  stream_ = pdfium::MakeRetain<CPDF_Stream>(std::move(pFile), std::move(dict));
}

void CPDF_Image::SetJpegImageInline(RetainPtr<IFX_SeekableReadStream> pFile) {
  uint32_t size = pdfium::checked_cast<uint32_t>(pFile->GetSize());
  if (!size) {
    return;
  }

  DataVector<uint8_t> data(size);
  if (!pFile->ReadBlockAtOffset(data, 0)) {
    return;
  }

  RetainPtr<CPDF_Dictionary> dict = InitJPEG(data);
  if (!dict) {
    return;
  }

  stream_ = pdfium::MakeRetain<CPDF_Stream>(std::move(data), std::move(dict));
}

void CPDF_Image::SetImage(const RetainPtr<CFX_DIBitmap>& pBitmap) {
  int32_t BitmapWidth = pBitmap->GetWidth();
  int32_t BitmapHeight = pBitmap->GetHeight();
  if (BitmapWidth < 1 || BitmapHeight < 1) {
    return;
  }

  RetainPtr<CPDF_Dictionary> dict =
      CreateXObjectImageDict(BitmapWidth, BitmapHeight);
  const int32_t bpp = pBitmap->GetBPP();
  size_t dest_pitch = 0;
  bool bCopyWithoutAlpha = true;
  if (bpp == 1) {
    FX_BGRA_STRUCT<uint8_t> reset_bgra;
    FX_BGRA_STRUCT<uint8_t> set_bgra;
    if (!pBitmap->IsMaskFormat()) {
      reset_bgra = ArgbToBGRAStruct(pBitmap->GetPaletteArgb(0));
      set_bgra = ArgbToBGRAStruct(pBitmap->GetPaletteArgb(1));
    }
    if (set_bgra.alpha == 0 || reset_bgra.alpha == 0) {
      dict->SetNewFor<CPDF_Boolean>("ImageMask", true);
      if (reset_bgra.alpha == 0) {
        auto pArray = dict->SetNewFor<CPDF_Array>("Decode");
        pArray->AppendNew<CPDF_Number>(1);
        pArray->AppendNew<CPDF_Number>(0);
      }
    } else {
      auto pCS = dict->SetNewFor<CPDF_Array>("ColorSpace");
      pCS->AppendNew<CPDF_Name>("Indexed");
      pCS->AppendNew<CPDF_Name>("DeviceRGB");
      pCS->AppendNew<CPDF_Number>(1);
      const uint8_t ct[6] = {reset_bgra.red, reset_bgra.green, reset_bgra.blue,
                             set_bgra.red,   set_bgra.green,   set_bgra.blue};
      pCS->AppendNew<CPDF_String>(ct, CPDF_String::DataType::kIsHex);
    }
    dict->SetNewFor<CPDF_Number>("BitsPerComponent", 1);
    dest_pitch = (BitmapWidth + 7) / 8;
  } else if (bpp == 8) {
    size_t palette_size = pBitmap->GetRequiredPaletteSize();
    if (palette_size > 0) {
      DCHECK(palette_size <= 256);
      auto pCS = document_->NewIndirect<CPDF_Array>();
      pCS->AppendNew<CPDF_Name>("Indexed");
      pCS->AppendNew<CPDF_Name>("DeviceRGB");
      pCS->AppendNew<CPDF_Number>(static_cast<int>(palette_size - 1));
      DataVector<uint8_t> color_table(Fx2DSizeOrDie(palette_size, 3));
      auto color_table_span = pdfium::span(color_table);
      for (size_t i = 0; i < palette_size; i++) {
        uint32_t argb = pBitmap->GetPaletteArgb(i);
        color_table_span[0] = FXARGB_R(argb);
        color_table_span[1] = FXARGB_G(argb);
        color_table_span[2] = FXARGB_B(argb);
        color_table_span = color_table_span.subspan<3u>();
      }
      auto pNewDict = document_->New<CPDF_Dictionary>();
      auto pCTS = document_->NewIndirect<CPDF_Stream>(std::move(color_table),
                                                      std::move(pNewDict));
      pCS->AppendNew<CPDF_Reference>(document_, pCTS->GetObjNum());
      dict->SetNewFor<CPDF_Reference>("ColorSpace", document_,
                                      pCS->GetObjNum());
    } else {
      dict->SetNewFor<CPDF_Name>("ColorSpace", "DeviceGray");
    }
    dict->SetNewFor<CPDF_Number>("BitsPerComponent", 8);
    dest_pitch = BitmapWidth;
  } else {
    dict->SetNewFor<CPDF_Name>("ColorSpace", "DeviceRGB");
    dict->SetNewFor<CPDF_Number>("BitsPerComponent", 8);
    dest_pitch = BitmapWidth * 3;
    bCopyWithoutAlpha = false;
  }

  RetainPtr<CFX_DIBitmap> pMaskBitmap;
  if (pBitmap->IsAlphaFormat()) {
    pMaskBitmap = pBitmap->CloneAlphaMask();
  }

  if (pMaskBitmap) {
    const int32_t mask_width = pMaskBitmap->GetWidth();
    const int32_t mask_height = pMaskBitmap->GetHeight();
    DataVector<uint8_t> mask_buf;
    RetainPtr<CPDF_Dictionary> pMaskDict =
        CreateXObjectImageDict(mask_width, mask_height);
    pMaskDict->SetNewFor<CPDF_Name>("ColorSpace", "DeviceGray");
    pMaskDict->SetNewFor<CPDF_Number>("BitsPerComponent", 8);
    if (pMaskBitmap->GetFormat() != FXDIB_Format::k1bppMask) {
      mask_buf.resize(Fx2DSizeOrDie(mask_width, mask_height));
      for (int32_t a = 0; a < mask_height; a++) {
        fxcrt::Copy(
            pMaskBitmap->GetScanline(a).first(static_cast<size_t>(mask_width)),
            pdfium::span(mask_buf).subspan(
                static_cast<size_t>(a * mask_width)));
      }
    }
    pMaskDict->SetNewFor<CPDF_Number>(
        "Length", pdfium::checked_cast<int>(mask_buf.size()));
    auto pNewStream = document_->NewIndirect<CPDF_Stream>(std::move(mask_buf),
                                                          std::move(pMaskDict));
    dict->SetNewFor<CPDF_Reference>("SMask", document_,
                                    pNewStream->GetObjNum());
  }

  DataVector<uint8_t> dest_buf(Fx2DSizeOrDie(dest_pitch, BitmapHeight));
  pdfium::span<uint8_t> dest_span = pdfium::span(dest_buf);
  pdfium::span<const uint8_t> src_span = pBitmap->GetBuffer();
  const int32_t src_pitch = pBitmap->GetPitch();
  if (bCopyWithoutAlpha) {
    for (int32_t i = 0; i < BitmapHeight; i++) {
      dest_span = fxcrt::spancpy(dest_span, src_span.first(dest_pitch));
      src_span = src_span.subspan(static_cast<size_t>(src_pitch));
    }
  } else {
    const size_t src_step = bpp == 24 ? 3 : 4;
    for (int32_t row = 0; row < BitmapHeight; row++) {
      uint8_t* dest_ptr = dest_span.data();
      const uint8_t* src_ptr = src_span.data();
      for (int32_t column = 0; column < BitmapWidth; column++) {
        UNSAFE_TODO({
          dest_ptr[0] = src_ptr[2];
          dest_ptr[1] = src_ptr[1];
          dest_ptr[2] = src_ptr[0];
          dest_ptr += 3;
          src_ptr += src_step;
        });
      }
      dest_span = dest_span.subspan(dest_pitch);
      src_span = src_span.subspan(static_cast<size_t>(src_pitch));
    }
  }

  stream_ =
      pdfium::MakeRetain<CPDF_Stream>(std::move(dest_buf), std::move(dict));
  is_mask_ = pBitmap->IsMaskFormat();
  width_ = BitmapWidth;
  height_ = BitmapHeight;
}

void CPDF_Image::ResetCache(CPDF_Page* pPage) {
  RetainPtr<CPDF_Image> pHolder(this);
  pPage->GetPageImageCache()->ResetBitmapForImage(std::move(pHolder));
}

void CPDF_Image::WillBeDestroyed() {
  will_be_destroyed_ = true;
}

RetainPtr<CPDF_DIB> CPDF_Image::CreateNewDIB() const {
  return pdfium::MakeRetain<CPDF_DIB>(GetDocument(), GetStream());
}

RetainPtr<CFX_DIBBase> CPDF_Image::LoadDIBBase() const {
  RetainPtr<CPDF_DIB> source = CreateNewDIB();
  if (!source->Load()) {
    return nullptr;
  }

  if (!source->IsJBigImage()) {
    return source;
  }

  CPDF_DIB::LoadState ret = CPDF_DIB::LoadState::kContinue;
  while (ret == CPDF_DIB::LoadState::kContinue) {
    ret = source->ContinueLoadDIBBase(nullptr);
  }
  return ret == CPDF_DIB::LoadState::kSuccess ? source : nullptr;
}

RetainPtr<CFX_DIBBase> CPDF_Image::DetachBitmap() {
  return std::move(dibbase_);
}

RetainPtr<CFX_DIBBase> CPDF_Image::DetachMask() {
  return std::move(mask_);
}

bool CPDF_Image::StartLoadDIBBase(const CPDF_Dictionary* pFormResource,
                                  const CPDF_Dictionary* pPageResource,
                                  bool bStdCS,
                                  CPDF_ColorSpace::Family GroupFamily,
                                  bool bLoadMask,
                                  const CFX_Size& max_size_required) {
  RetainPtr<CPDF_DIB> source = CreateNewDIB();
  CPDF_DIB::LoadState ret =
      source->StartLoadDIBBase(true, pFormResource, pPageResource, bStdCS,
                               GroupFamily, bLoadMask, max_size_required);
  if (ret == CPDF_DIB::LoadState::kFail) {
    dibbase_.Reset();
    return false;
  }
  dibbase_ = source;
  if (ret == CPDF_DIB::LoadState::kContinue) {
    return true;
  }

  mask_ = source->DetachMask();
  matte_color_ = source->GetMatteColor();
  return false;
}

bool CPDF_Image::Continue(PauseIndicatorIface* pPause) {
  RetainPtr<CPDF_DIB> pSource = dibbase_.As<CPDF_DIB>();
  CPDF_DIB::LoadState ret = pSource->ContinueLoadDIBBase(pPause);
  if (ret == CPDF_DIB::LoadState::kContinue) {
    return true;
  }

  if (ret == CPDF_DIB::LoadState::kSuccess) {
    mask_ = pSource->DetachMask();
    matte_color_ = pSource->GetMatteColor();
  } else {
    dibbase_.Reset();
  }
  return false;
}

RetainPtr<CPDF_Dictionary> CPDF_Image::CreateXObjectImageDict(int width,
                                                              int height) {
  auto dict = document_->New<CPDF_Dictionary>();
  dict->SetNewFor<CPDF_Name>("Type", "XObject");
  dict->SetNewFor<CPDF_Name>("Subtype", "Image");
  dict->SetNewFor<CPDF_Number>("Width", width);
  dict->SetNewFor<CPDF_Number>("Height", height);
  return dict;
}
