// Copyright 2017 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_dib.h"

#include <stdint.h>

#include <algorithm>
#include <memory>
#include <optional>
#include <utility>
#include <vector>

#include "core/fpdfapi/page/cpdf_colorspace.h"
#include "core/fpdfapi/page/cpdf_docpagedata.h"
#include "core/fpdfapi/page/cpdf_image.h"
#include "core/fpdfapi/page/cpdf_imageobject.h"
#include "core/fpdfapi/page/cpdf_indexedcs.h"
#include "core/fpdfapi/page/jpx_decode_conversion.h"
#include "core/fpdfapi/parser/cpdf_array.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_stream.h"
#include "core/fpdfapi/parser/cpdf_stream_acc.h"
#include "core/fpdfapi/parser/fpdf_parser_decode.h"
#include "core/fpdfapi/parser/fpdf_parser_utility.h"
#include "core/fxcodec/basic/basicmodule.h"
#include "core/fxcodec/icc/icc_transform.h"
#include "core/fxcodec/jbig2/jbig2_decoder.h"
#include "core/fxcodec/jpeg/jpegmodule.h"
#include "core/fxcodec/jpx/cjpx_decoder.h"
#include "core/fxcodec/scanlinedecoder.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/check_op.h"
#include "core/fxcrt/compiler_specific.h"
#include "core/fxcrt/data_vector.h"
#include "core/fxcrt/fx_safe_types.h"
#include "core/fxcrt/span_util.h"
#include "core/fxcrt/stl_util.h"
#include "core/fxcrt/zip.h"
#include "core/fxge/calculate_pitch.h"
#include "core/fxge/dib/cfx_dibitmap.h"

namespace {

bool IsValidDimension(int value) {
  static constexpr int kMaxImageDimension = 0x01FFFF;
  return value > 0 && value <= kMaxImageDimension;
}

unsigned int GetBits8(pdfium::span<const uint8_t> pData,
                      uint64_t bitpos,
                      size_t nbits) {
  DCHECK(nbits == 1 || nbits == 2 || nbits == 4 || nbits == 8 || nbits == 16);
  DCHECK_EQ((bitpos & (nbits - 1)), 0u);
  unsigned int byte = pData[bitpos / 8];
  if (nbits == 8) {
    return byte;
  }
  if (nbits == 16) {
    return byte * 256 + pData[bitpos / 8 + 1];
  }
  return (byte >> (8 - nbits - (bitpos % 8))) & ((1 << nbits) - 1);
}

bool GetBitValue(pdfium::span<const uint8_t> pSrc, uint32_t pos) {
  return pSrc[pos / 8] & (1 << (7 - pos % 8));
}

// Just to sanity check and filter out obvious bad values.
bool IsMaybeValidBitsPerComponent(int bpc) {
  return bpc >= 0 && bpc <= 16;
}

bool IsAllowedBitsPerComponent(int bpc) {
  return bpc == 1 || bpc == 2 || bpc == 4 || bpc == 8 || bpc == 16;
}

bool IsColorIndexOutOfBounds(uint8_t index, const DIB_COMP_DATA& comp_datum) {
  return index < comp_datum.color_key_min_ || index > comp_datum.color_key_max_;
}

bool AreColorIndicesOutOfBounds(pdfium::span<const uint8_t> indices,
                                pdfium::span<const DIB_COMP_DATA> comp_data) {
  for (auto [idx, datum] : fxcrt::Zip(indices, comp_data)) {
    if (IsColorIndexOutOfBounds(idx, datum)) {
      return true;
    }
  }
  return false;
}

CJPX_Decoder::ColorSpaceOption ColorSpaceOptionFromColorSpace(
    CPDF_ColorSpace* pCS) {
  if (!pCS) {
    return CJPX_Decoder::ColorSpaceOption::kNone;
  }
  if (pCS->GetFamily() == CPDF_ColorSpace::Family::kIndexed) {
    return CJPX_Decoder::ColorSpaceOption::kIndexed;
  }
  return CJPX_Decoder::ColorSpaceOption::kNormal;
}

}  // namespace

CPDF_DIB::CPDF_DIB(CPDF_Document* doc, RetainPtr<const CPDF_Stream> pStream)
    : document_(doc), stream_(std::move(pStream)) {}

CPDF_DIB::~CPDF_DIB() = default;

CPDF_DIB::JpxSMaskInlineData::JpxSMaskInlineData() = default;

CPDF_DIB::JpxSMaskInlineData::~JpxSMaskInlineData() = default;

bool CPDF_DIB::Load() {
  if (!LoadInternal(nullptr, nullptr)) {
    return false;
  }

  if (CreateDecoder(0) == LoadState::kFail) {
    return false;
  }

  return ContinueInternal();
}

bool CPDF_DIB::ContinueToLoadMask() {
  if (color_space_ && std_cs_) {
    color_space_->EnableStdConversion(true);
  }

  return ContinueInternal();
}

bool CPDF_DIB::ContinueInternal() {
  if (image_mask_) {
    SetMaskProperties();
  } else {
    const uint32_t bpp = bpc_ * components_;
    if (bpp == 0) {
      return false;
    }

    if (bpp == 1) {
      SetFormat(FXDIB_Format::k1bppRgb);
    } else if (bpp <= 8) {
      SetFormat(FXDIB_Format::k8bppRgb);
    } else {
      SetFormat(FXDIB_Format::kBgr);
    }
  }

  std::optional<uint32_t> pitch = fxge::CalculatePitch32(GetBPP(), GetWidth());
  if (!pitch.has_value()) {
    return false;
  }

  line_buf_ = DataVector<uint8_t>(pitch.value());
  LoadPalette();
  if (color_key_) {
    // TODO(crbug.com/355676038): Consider adding support for
    // `FXDIB_Format::kBgraPremul`
    SetFormat(FXDIB_Format::kBgra);
    pitch = fxge::CalculatePitch32(GetBPP(), GetWidth());
    if (!pitch.has_value()) {
      return false;
    }
    mask_buf_ = DataVector<uint8_t>(pitch.value());
  }
  SetPitch(pitch.value());
  return true;
}

CPDF_DIB::LoadState CPDF_DIB::StartLoadDIBBase(
    bool bHasMask,
    const CPDF_Dictionary* pFormResources,
    const CPDF_Dictionary* pPageResources,
    bool bStdCS,
    CPDF_ColorSpace::Family GroupFamily,
    bool bLoadMask,
    const CFX_Size& max_size_required) {
  std_cs_ = bStdCS;
  has_mask_ = bHasMask;
  group_family_ = GroupFamily;
  load_mask_ = bLoadMask;

  if (!stream_->IsInline()) {
    pFormResources = nullptr;
  }

  if (!LoadInternal(pFormResources, pPageResources)) {
    return LoadState::kFail;
  }

  uint8_t resolution_levels_to_skip = 0;
  if (max_size_required.width != 0 && max_size_required.height != 0) {
    resolution_levels_to_skip = static_cast<uint8_t>(std::log2(
        std::max(1, std::min(GetWidth() / max_size_required.width,
                             GetHeight() / max_size_required.height))));
  }

  LoadState iCreatedDecoder = CreateDecoder(resolution_levels_to_skip);
  if (iCreatedDecoder == LoadState::kFail) {
    return LoadState::kFail;
  }

  if (!ContinueToLoadMask()) {
    return LoadState::kFail;
  }

  LoadState iLoadedMask = has_mask_ ? StartLoadMask() : LoadState::kSuccess;
  if (iCreatedDecoder == LoadState::kContinue ||
      iLoadedMask == LoadState::kContinue) {
    return LoadState::kContinue;
  }

  DCHECK_EQ(iCreatedDecoder, LoadState::kSuccess);
  DCHECK_EQ(iLoadedMask, LoadState::kSuccess);
  if (color_space_ && std_cs_) {
    color_space_->EnableStdConversion(false);
  }
  return LoadState::kSuccess;
}

CPDF_DIB::LoadState CPDF_DIB::ContinueLoadDIBBase(PauseIndicatorIface* pPause) {
  if (status_ == LoadState::kContinue) {
    return ContinueLoadMaskDIB(pPause);
  }

  ByteString decoder = stream_acc_->GetImageDecoder();
  if (decoder == "JPXDecode") {
    return LoadState::kFail;
  }

  if (decoder != "JBIG2Decode") {
    return LoadState::kSuccess;
  }

  if (status_ == LoadState::kFail) {
    return LoadState::kFail;
  }

  FXCODEC_STATUS iDecodeStatus;
  if (!jbig_2context_) {
    jbig_2context_ = std::make_unique<Jbig2Context>();
    if (stream_acc_->GetImageParam()) {
      RetainPtr<const CPDF_Stream> pGlobals =
          stream_acc_->GetImageParam()->GetStreamFor("JBIG2Globals");
      if (pGlobals) {
        global_acc_ = pdfium::MakeRetain<CPDF_StreamAcc>(std::move(pGlobals));
        global_acc_->LoadAllDataFiltered();
      }
    }
    uint64_t nSrcKey = 0;
    pdfium::span<const uint8_t> pSrcSpan;
    if (stream_acc_) {
      pSrcSpan = stream_acc_->GetSpan();
      nSrcKey = stream_acc_->KeyForCache();
    }
    uint64_t nGlobalKey = 0;
    pdfium::span<const uint8_t> pGlobalSpan;
    if (global_acc_) {
      pGlobalSpan = global_acc_->GetSpan();
      nGlobalKey = global_acc_->KeyForCache();
    }
    const bool reject_large_regions_when_fuzzing = false;
    iDecodeStatus = Jbig2Decoder::StartDecode(
        jbig_2context_.get(), document_->GetOrCreateCodecContext(), GetWidth(),
        GetHeight(), pSrcSpan, nSrcKey, pGlobalSpan, nGlobalKey,
        cached_bitmap_->GetWritableBuffer(), cached_bitmap_->GetPitch(), pPause,
        reject_large_regions_when_fuzzing);
  } else {
    iDecodeStatus = Jbig2Decoder::ContinueDecode(jbig_2context_.get(), pPause);
  }

  if (iDecodeStatus == FXCODEC_STATUS::kError) {
    jbig_2context_.reset();
    cached_bitmap_.Reset();
    global_acc_.Reset();
    return LoadState::kFail;
  }
  if (iDecodeStatus == FXCODEC_STATUS::kDecodeToBeContinued) {
    return LoadState::kContinue;
  }

  LoadState iContinueStatus = LoadState::kSuccess;
  if (has_mask_) {
    if (ContinueLoadMaskDIB(pPause) == LoadState::kContinue) {
      iContinueStatus = LoadState::kContinue;
      status_ = LoadState::kContinue;
    }
  }
  if (iContinueStatus == LoadState::kContinue) {
    return LoadState::kContinue;
  }

  if (color_space_ && std_cs_) {
    color_space_->EnableStdConversion(false);
  }
  return iContinueStatus;
}

bool CPDF_DIB::LoadColorInfo(const CPDF_Dictionary* pFormResources,
                             const CPDF_Dictionary* pPageResources) {
  std::optional<DecoderArray> decoder_array = GetDecoderArray(dict_);
  if (!decoder_array.has_value()) {
    return false;
  }

  bpc_orig_ = dict_->GetIntegerFor("BitsPerComponent");
  if (!IsMaybeValidBitsPerComponent(bpc_orig_)) {
    return false;
  }

  image_mask_ = dict_->GetBooleanFor("ImageMask", /*bDefault=*/false);

  if (image_mask_ || !dict_->KeyExist("ColorSpace")) {
    if (!image_mask_ && !decoder_array.value().empty()) {
      const ByteString& filter = decoder_array.value().back().first;
      if (filter == "JPXDecode") {
        do_bpc_check_ = false;
        return true;
      }
    }
    image_mask_ = true;
    bpc_ = components_ = 1;
    RetainPtr<const CPDF_Array> pDecode = dict_->GetArrayFor("Decode");
    default_decode_ = !pDecode || !pDecode->GetIntegerAt(0);
    return true;
  }

  RetainPtr<const CPDF_Object> pCSObj = dict_->GetDirectObjectFor("ColorSpace");
  if (!pCSObj) {
    return false;
  }

  auto* pDocPageData = CPDF_DocPageData::FromDocument(document_);
  if (pFormResources) {
    color_space_ = pDocPageData->GetColorSpace(pCSObj.Get(), pFormResources);
  }
  if (!color_space_) {
    color_space_ = pDocPageData->GetColorSpace(pCSObj.Get(), pPageResources);
  }
  if (!color_space_) {
    return false;
  }

  // If the checks above failed to find a colorspace, and the next line to set
  // |components_| does not get reached, then a decoder can try to set
  // |components_| based on the number of channels in the image being
  // decoded.
  components_ = color_space_->ComponentCount();
  family_ = color_space_->GetFamily();
  if (family_ == CPDF_ColorSpace::Family::kICCBased && pCSObj->IsName()) {
    ByteString cs = pCSObj->GetString();
    if (cs == "DeviceGray") {
      components_ = 1;
    } else if (cs == "DeviceRGB") {
      components_ = 3;
    } else if (cs == "DeviceCMYK") {
      components_ = 4;
    }
  }

  ByteString filter;
  if (!decoder_array.value().empty()) {
    filter = decoder_array.value().back().first;
  }

  if (!ValidateDictParam(filter)) {
    return false;
  }

  return GetDecodeAndMaskArray();
}

bool CPDF_DIB::GetDecodeAndMaskArray() {
  if (!color_space_) {
    return false;
  }

  comp_data_.resize(components_);
  int max_data = (1 << bpc_) - 1;
  RetainPtr<const CPDF_Array> pDecode = dict_->GetArrayFor("Decode");
  if (pDecode) {
    for (uint32_t i = 0; i < components_; i++) {
      comp_data_[i].decode_min_ = pDecode->GetFloatAt(i * 2);
      float max = pDecode->GetFloatAt(i * 2 + 1);
      comp_data_[i].decode_step_ = (max - comp_data_[i].decode_min_) / max_data;
      float def_value;
      float def_min;
      float def_max;
      color_space_->GetDefaultValue(i, &def_value, &def_min, &def_max);
      if (family_ == CPDF_ColorSpace::Family::kIndexed) {
        def_max = max_data;
      }
      if (def_min != comp_data_[i].decode_min_ || def_max != max) {
        default_decode_ = false;
      }
    }
  } else {
    for (uint32_t i = 0; i < components_; i++) {
      float def_value;
      color_space_->GetDefaultValue(i, &def_value, &comp_data_[i].decode_min_,
                                    &comp_data_[i].decode_step_);
      if (family_ == CPDF_ColorSpace::Family::kIndexed) {
        comp_data_[i].decode_step_ = max_data;
      }
      comp_data_[i].decode_step_ =
          (comp_data_[i].decode_step_ - comp_data_[i].decode_min_) / max_data;
    }
  }
  if (dict_->KeyExist("SMask")) {
    return true;
  }

  RetainPtr<const CPDF_Object> pMask = dict_->GetDirectObjectFor("Mask");
  if (!pMask) {
    return true;
  }

  if (const CPDF_Array* pArray = pMask->AsArray()) {
    if (pArray->size() >= components_ * 2) {
      for (uint32_t i = 0; i < components_; i++) {
        int min_num = pArray->GetIntegerAt(i * 2);
        int max_num = pArray->GetIntegerAt(i * 2 + 1);
        comp_data_[i].color_key_min_ = std::max(min_num, 0);
        comp_data_[i].color_key_max_ = std::min(max_num, max_data);
      }
    }
    color_key_ = true;
  }
  return true;
}

CPDF_DIB::LoadState CPDF_DIB::CreateDecoder(uint8_t resolution_levels_to_skip) {
  ByteString decoder = stream_acc_->GetImageDecoder();
  if (decoder.IsEmpty()) {
    return LoadState::kSuccess;
  }

  if (do_bpc_check_ && bpc_ == 0) {
    return LoadState::kFail;
  }

  if (decoder == "JPXDecode") {
    cached_bitmap_ = LoadJpxBitmap(resolution_levels_to_skip);
    return cached_bitmap_ ? LoadState::kSuccess : LoadState::kFail;
  }

  if (decoder == "JBIG2Decode") {
    cached_bitmap_ = pdfium::MakeRetain<CFX_DIBitmap>();
    if (!cached_bitmap_->Create(
            GetWidth(), GetHeight(),
            image_mask_ ? FXDIB_Format::k1bppMask : FXDIB_Format::k1bppRgb)) {
      cached_bitmap_.Reset();
      return LoadState::kFail;
    }
    status_ = LoadState::kSuccess;
    return LoadState::kContinue;
  }

  pdfium::span<const uint8_t> src_span = stream_acc_->GetSpan();
  RetainPtr<const CPDF_Dictionary> pParams = stream_acc_->GetImageParam();
  if (decoder == "CCITTFaxDecode") {
    decoder_ = CreateFaxDecoder(src_span, GetWidth(), GetHeight(), pParams);
  } else if (decoder == "FlateDecode") {
    decoder_ = CreateFlateDecoder(src_span, GetWidth(), GetHeight(),
                                  components_, bpc_, pParams);
  } else if (decoder == "RunLengthDecode") {
    decoder_ = BasicModule::CreateRunLengthDecoder(
        src_span, GetWidth(), GetHeight(), components_, bpc_);
  } else if (decoder == "DCTDecode") {
    if (!CreateDCTDecoder(src_span, pParams)) {
      return LoadState::kFail;
    }
  }
  if (!decoder_) {
    return LoadState::kFail;
  }

  const std::optional<uint32_t> requested_pitch =
      fxge::CalculatePitch8(bpc_, components_, GetWidth());
  if (!requested_pitch.has_value()) {
    return LoadState::kFail;
  }
  const std::optional<uint32_t> provided_pitch = fxge::CalculatePitch8(
      decoder_->GetBPC(), decoder_->CountComps(), decoder_->GetWidth());
  if (!provided_pitch.has_value()) {
    return LoadState::kFail;
  }
  if (provided_pitch.value() < requested_pitch.value()) {
    return LoadState::kFail;
  }
  return LoadState::kSuccess;
}

bool CPDF_DIB::CreateDCTDecoder(pdfium::span<const uint8_t> src_span,
                                const CPDF_Dictionary* pParams) {
  decoder_ = JpegModule::CreateDecoder(
      src_span, GetWidth(), GetHeight(), components_,
      !pParams || pParams->GetIntegerFor("ColorTransform", 1));
  if (decoder_) {
    return true;
  }

  std::optional<JpegModule::ImageInfo> info_opt =
      JpegModule::LoadInfo(src_span);
  if (!info_opt.has_value()) {
    return false;
  }

  const JpegModule::ImageInfo& info = info_opt.value();
  SetWidth(info.width);
  SetHeight(info.height);

  if (!CPDF_Image::IsValidJpegComponent(info.num_components) ||
      !CPDF_Image::IsValidJpegBitsPerComponent(info.bits_per_components)) {
    return false;
  }

  if (components_ == static_cast<uint32_t>(info.num_components)) {
    bpc_ = info.bits_per_components;
    decoder_ = JpegModule::CreateDecoder(src_span, GetWidth(), GetHeight(),
                                         components_, info.color_transform);
    return true;
  }

  components_ = static_cast<uint32_t>(info.num_components);
  comp_data_.clear();
  if (color_space_) {
    uint32_t colorspace_comps = color_space_->ComponentCount();
    switch (family_) {
      case CPDF_ColorSpace::Family::kDeviceGray:
      case CPDF_ColorSpace::Family::kDeviceRGB:
      case CPDF_ColorSpace::Family::kDeviceCMYK: {
        uint32_t dwMinComps = CPDF_ColorSpace::ComponentsForFamily(family_);
        if (colorspace_comps < dwMinComps || components_ < dwMinComps) {
          return false;
        }
        break;
      }
      case CPDF_ColorSpace::Family::kLab: {
        if (components_ != 3 || colorspace_comps < 3) {
          return false;
        }
        break;
      }
      case CPDF_ColorSpace::Family::kICCBased: {
        if (!fxcodec::IccTransform::IsValidIccComponents(colorspace_comps) ||
            !fxcodec::IccTransform::IsValidIccComponents(components_) ||
            colorspace_comps < components_) {
          return false;
        }
        break;
      }
      default: {
        if (colorspace_comps != components_) {
          return false;
        }
        break;
      }
    }
  } else {
    if (family_ == CPDF_ColorSpace::Family::kLab && components_ != 3) {
      return false;
    }
  }
  if (!GetDecodeAndMaskArray()) {
    return false;
  }

  bpc_ = info.bits_per_components;
  decoder_ = JpegModule::CreateDecoder(src_span, GetWidth(), GetHeight(),
                                       components_, info.color_transform);
  return true;
}

RetainPtr<CFX_DIBitmap> CPDF_DIB::LoadJpxBitmap(
    uint8_t resolution_levels_to_skip) {
  std::unique_ptr<CJPX_Decoder> decoder =
      CJPX_Decoder::Create(stream_acc_->GetSpan(),
                           ColorSpaceOptionFromColorSpace(color_space_.Get()),
                           resolution_levels_to_skip, /*strict_mode=*/true);
  if (!decoder) {
    return nullptr;
  }

  SetWidth(GetWidth() >> resolution_levels_to_skip);
  SetHeight(GetHeight() >> resolution_levels_to_skip);

  if (!decoder->StartDecode()) {
    return nullptr;
  }

  CJPX_Decoder::JpxImageInfo image_info = decoder->GetInfo();
  if (static_cast<int>(image_info.width) < GetWidth() ||
      static_cast<int>(image_info.height) < GetHeight()) {
    return nullptr;
  }

  auto maybe_conversion =
      JpxDecodeConversion::Create(image_info, color_space_.Get());
  if (!maybe_conversion.has_value()) {
    return nullptr;
  }

  const auto& conversion = maybe_conversion.value();
  if (conversion.override_colorspace().has_value()) {
    color_space_ = conversion.override_colorspace().value();
  }

  if (conversion.jpx_components_count().has_value()) {
    DCHECK_EQ(0u, components_);
    components_ = conversion.jpx_components_count().value();
    if (components_ <= 0) {
      return nullptr;
    }
  } else {
    // LoadColorInfo() already set `components_`.
    DCHECK_NE(0u, components_);
  }

  image_info.width = conversion.width();

  auto result_bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
  if (!result_bitmap->Create(image_info.width, image_info.height,
                             conversion.format())) {
    return nullptr;
  }

  result_bitmap->Clear(0xFFFFFFFF);
  if (!decoder->Decode(result_bitmap->GetWritableBuffer(),
                       result_bitmap->GetPitch(), conversion.swap_rgb(),
                       components_)) {
    return nullptr;
  }

  if (conversion.convert_argb_to_rgb()) {
    result_bitmap = ConvertArgbJpxBitmapToRgb(result_bitmap, image_info.width,
                                              image_info.height);
    if (!result_bitmap) {
      return nullptr;
    }
  } else if (color_space_ &&
             color_space_->GetFamily() == CPDF_ColorSpace::Family::kIndexed &&
             bpc_ < 8) {
    int scale = 8 - bpc_;
    for (uint32_t row = 0; row < image_info.height; ++row) {
      pdfium::span<uint8_t> scanline =
          result_bitmap->GetWritableScanline(row).first(image_info.width);
      for (auto& pixel : scanline) {
        pixel >>= scale;
      }
    }
  }

  // TODO(crbug.com/42270756): Handle SMaskInData entries for different
  // color space types.

  bpc_ = 8;
  return result_bitmap;
}

RetainPtr<CFX_DIBitmap> CPDF_DIB::ConvertArgbJpxBitmapToRgb(
    RetainPtr<CFX_DIBitmap> argb_bitmap,
    uint32_t width,
    uint32_t height) {
  DCHECK_EQ(3u, components_);
  auto rgb_bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
  if (!rgb_bitmap->Create(width, height, FXDIB_Format::kBgr)) {
    return nullptr;
  }
  if (dict_->GetIntegerFor("SMaskInData") == 1) {
    // TODO(thestig): Acrobat does not support "/SMaskInData 1" combined with
    // filters. Check for that and fail early.
    DCHECK(jpx_inline_data_.data.empty());
    jpx_inline_data_.width = width;
    jpx_inline_data_.height = height;
    jpx_inline_data_.data.reserve(width * height);
    for (uint32_t row = 0; row < height; ++row) {
      auto src =
          argb_bitmap->GetScanlineAs<FX_BGRA_STRUCT<uint8_t>>(row).first(width);
      auto dest =
          rgb_bitmap->GetWritableScanlineAs<FX_BGR_STRUCT<uint8_t>>(row);
      for (auto [input, output] : fxcrt::Zip(src, dest)) {
        jpx_inline_data_.data.push_back(input.alpha);
        const uint8_t na = 255 - input.alpha;
        output.blue = (input.blue * input.alpha + 255 * na) / 255;
        output.green = (input.green * input.alpha + 255 * na) / 255;
        output.red = (input.red * input.alpha + 255 * na) / 255;
      }
    }
    return rgb_bitmap;
  }

  // TODO(thestig): Is there existing code that does this already?
  for (uint32_t row = 0; row < height; ++row) {
    auto src =
        argb_bitmap->GetScanlineAs<FX_BGRA_STRUCT<uint8_t>>(row).first(width);
    auto dest = rgb_bitmap->GetWritableScanlineAs<FX_BGR_STRUCT<uint8_t>>(row);
    for (auto [input, output] : fxcrt::Zip(src, dest)) {
      output.green = input.green;
      output.red = input.red;
      output.blue = input.blue;
    }
  }
  return rgb_bitmap;
}

bool CPDF_DIB::LoadInternal(const CPDF_Dictionary* pFormResources,
                            const CPDF_Dictionary* pPageResources) {
  if (!stream_) {
    return false;
  }

  dict_ = stream_->GetDict();
  SetWidth(dict_->GetIntegerFor("Width"));
  SetHeight(dict_->GetIntegerFor("Height"));
  if (!IsValidDimension(GetWidth()) || !IsValidDimension(GetHeight())) {
    return false;
  }

  if (!LoadColorInfo(pFormResources, pPageResources)) {
    return false;
  }

  if (do_bpc_check_ && (bpc_ == 0 || components_ == 0)) {
    return false;
  }

  const std::optional<uint32_t> maybe_size =
      fxge::CalculatePitch8(bpc_, components_, GetWidth());
  if (!maybe_size.has_value()) {
    return false;
  }

  FX_SAFE_UINT32 src_size = maybe_size.value();
  src_size *= GetHeight();
  if (!src_size.IsValid()) {
    return false;
  }

  stream_acc_ = pdfium::MakeRetain<CPDF_StreamAcc>(stream_);
  stream_acc_->LoadAllDataImageAcc(src_size.ValueOrDie());
  return !stream_acc_->GetSpan().empty();
}

CPDF_DIB::LoadState CPDF_DIB::StartLoadMask() {
  matte_color_ = 0XFFFFFFFF;

  if (!jpx_inline_data_.data.empty()) {
    auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
    dict->SetNewFor<CPDF_Name>("Type", "XObject");
    dict->SetNewFor<CPDF_Name>("Subtype", "Image");
    dict->SetNewFor<CPDF_Name>("ColorSpace", "DeviceGray");
    dict->SetNewFor<CPDF_Number>("Width", jpx_inline_data_.width);
    dict->SetNewFor<CPDF_Number>("Height", jpx_inline_data_.height);
    dict->SetNewFor<CPDF_Number>("BitsPerComponent", 8);

    return StartLoadMaskDIB(pdfium::MakeRetain<CPDF_Stream>(
        jpx_inline_data_.data, std::move(dict)));
  }

  RetainPtr<const CPDF_Stream> mask(dict_->GetStreamFor("SMask"));
  if (!mask) {
    mask = ToStream(dict_->GetDirectObjectFor("Mask"));
    return mask ? StartLoadMaskDIB(std::move(mask)) : LoadState::kSuccess;
  }

  RetainPtr<const CPDF_Array> pMatte = mask->GetDict()->GetArrayFor("Matte");
  if (pMatte && color_space_ && family_ != CPDF_ColorSpace::Family::kPattern &&
      pMatte->size() == components_ &&
      color_space_->ComponentCount() <= components_) {
    std::vector<float> colors =
        ReadArrayElementsToVector(pMatte.Get(), components_);

    auto rgb = color_space_->GetRGBOrZerosOnError(colors);
    matte_color_ =
        ArgbEncode(0, FXSYS_roundf(rgb.red * 255),
                   FXSYS_roundf(rgb.green * 255), FXSYS_roundf(rgb.blue * 255));
  }
  return StartLoadMaskDIB(std::move(mask));
}

CPDF_DIB::LoadState CPDF_DIB::ContinueLoadMaskDIB(PauseIndicatorIface* pPause) {
  if (!mask_) {
    return LoadState::kSuccess;
  }

  LoadState ret = mask_->ContinueLoadDIBBase(pPause);
  if (ret == LoadState::kContinue) {
    return LoadState::kContinue;
  }

  if (color_space_ && std_cs_) {
    color_space_->EnableStdConversion(false);
  }

  if (ret == LoadState::kFail) {
    mask_.Reset();
    return LoadState::kFail;
  }
  return LoadState::kSuccess;
}

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

bool CPDF_DIB::IsJBigImage() const {
  return stream_acc_->GetImageDecoder() == "JBIG2Decode";
}

CPDF_DIB::LoadState CPDF_DIB::StartLoadMaskDIB(
    RetainPtr<const CPDF_Stream> mask_stream) {
  mask_ = pdfium::MakeRetain<CPDF_DIB>(document_, std::move(mask_stream));
  LoadState ret =
      mask_->StartLoadDIBBase(false, nullptr, nullptr, true,
                              CPDF_ColorSpace::Family::kUnknown, false, {0, 0});
  if (ret == LoadState::kContinue) {
    if (status_ == LoadState::kFail) {
      status_ = LoadState::kContinue;
    }
    return LoadState::kContinue;
  }
  if (ret == LoadState::kFail) {
    mask_.Reset();
  }
  return LoadState::kSuccess;
}

void CPDF_DIB::LoadPalette() {
  if (!color_space_ || family_ == CPDF_ColorSpace::Family::kPattern) {
    return;
  }

  if (bpc_ == 0) {
    return;
  }

  // Use FX_SAFE_UINT32 just to be on the safe side, in case |bpc_| or
  // |components_| somehow gets a bad value.
  FX_SAFE_UINT32 safe_bits = bpc_;
  safe_bits *= components_;
  uint32_t bits = safe_bits.ValueOrDefault(255);
  if (bits > 8) {
    return;
  }

  if (bits == 1) {
    if (default_decode_ && (family_ == CPDF_ColorSpace::Family::kDeviceGray ||
                            family_ == CPDF_ColorSpace::Family::kDeviceRGB)) {
      return;
    }
    if (color_space_->ComponentCount() > 3) {
      return;
    }
    float color_values[3];
    std::ranges::fill(color_values, comp_data_[0].decode_min_);

    auto rgb = color_space_->GetRGBOrZerosOnError(color_values);
    FX_ARGB argb0 =
        ArgbEncode(255, FXSYS_roundf(rgb.red * 255),
                   FXSYS_roundf(rgb.green * 255), FXSYS_roundf(rgb.blue * 255));
    FX_ARGB argb1;
    const CPDF_IndexedCS* indexed_cs = color_space_->AsIndexedCS();
    if (indexed_cs && indexed_cs->GetMaxIndex() == 0) {
      // If an indexed color space's hival value is 0, only 1 color is specified
      // in the lookup table. Another color should be set to 0xFF000000 by
      // default to set the range of the color space.
      argb1 = 0xFF000000;
    } else {
      color_values[0] += comp_data_[0].decode_step_;
      color_values[1] += comp_data_[0].decode_step_;
      color_values[2] += comp_data_[0].decode_step_;
      auto result = color_space_->GetRGBOrZerosOnError(color_values);
      argb1 = ArgbEncode(255, FXSYS_roundf(result.red * 255),
                         FXSYS_roundf(result.green * 255),
                         FXSYS_roundf(result.blue * 255));
    }

    if (argb0 != 0xFF000000 || argb1 != 0xFFFFFFFF) {
      SetPaletteArgb(0, argb0);
      SetPaletteArgb(1, argb1);
    }
    return;
  }
  if (bpc_ == 8 && default_decode_ &&
      color_space_ ==
          CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceGray)) {
    return;
  }

  int palette_count = 1 << bits;
  // Using at least 16 elements due to the call color_space_->GetRGB().
  std::vector<float> color_values(std::max(components_, 16u));
  for (int i = 0; i < palette_count; i++) {
    int color_data = i;
    for (uint32_t j = 0; j < components_; j++) {
      int encoded_component = color_data % (1 << bpc_);
      color_data /= 1 << bpc_;
      color_values[j] = comp_data_[j].decode_min_ +
                        comp_data_[j].decode_step_ * encoded_component;
    }
    FX_RGB_STRUCT<float> rgb;
    if (components_ == 1 && family_ == CPDF_ColorSpace::Family::kICCBased &&
        color_space_->ComponentCount() > 1) {
      const size_t nComponents = color_space_->ComponentCount();
      std::vector<float> temp_buf(nComponents, color_values[0]);
      rgb = color_space_->GetRGBOrZerosOnError(temp_buf);
    } else {
      rgb = color_space_->GetRGBOrZerosOnError(color_values);
    }
    SetPaletteArgb(i, ArgbEncode(255, FXSYS_roundf(rgb.red * 255),
                                 FXSYS_roundf(rgb.green * 255),
                                 FXSYS_roundf(rgb.blue * 255)));
  }
}

bool CPDF_DIB::ValidateDictParam(const ByteString& filter) {
  bpc_ = bpc_orig_;

  // Per spec, |bpc_| should always be 8 for RunLengthDecode, but too many
  // documents do not conform to it. So skip this check.

  if (filter == "JPXDecode") {
    do_bpc_check_ = false;
    return true;
  }

  if (filter == "CCITTFaxDecode" || filter == "JBIG2Decode") {
    bpc_ = 1;
    components_ = 1;
  } else if (filter == "DCTDecode") {
    bpc_ = 8;
  }

  if (!IsAllowedBitsPerComponent(bpc_)) {
    bpc_ = 0;
    return false;
  }
  return true;
}

void CPDF_DIB::TranslateScanline24bpp(
    pdfium::span<uint8_t> dest_scan,
    pdfium::span<const uint8_t> src_scan) const {
  if (bpc_ == 0) {
    return;
  }

  if (TranslateScanline24bppDefaultDecode(dest_scan, src_scan)) {
    return;
  }

  // Using at least 16 elements due to the call color_space_->GetRGB().
  std::vector<float> color_values(std::max(components_, 16u));
  FX_RGB_STRUCT<float> rgb = {};
  uint64_t src_bit_pos = 0;
  uint64_t src_byte_pos = 0;
  size_t dest_byte_pos = 0;
  const bool bpp8 = bpc_ == 8;
  for (int column = 0; column < GetWidth(); column++) {
    for (uint32_t color = 0; color < components_; color++) {
      if (bpp8) {
        uint8_t data = src_scan[src_byte_pos++];
        color_values[color] = comp_data_[color].decode_min_ +
                              comp_data_[color].decode_step_ * data;
      } else {
        unsigned int data = GetBits8(src_scan, src_bit_pos, bpc_);
        color_values[color] = comp_data_[color].decode_min_ +
                              comp_data_[color].decode_step_ * data;
        src_bit_pos += bpc_;
      }
    }
    if (TransMask()) {
      float k = 1.0f - color_values[3];
      rgb.red = (1.0f - color_values[0]) * k;
      rgb.green = (1.0f - color_values[1]) * k;
      rgb.blue = (1.0f - color_values[2]) * k;
    } else if (family_ != CPDF_ColorSpace::Family::kPattern) {
      rgb = color_space_->GetRGBOrZerosOnError(color_values);
    }
    const float R = std::clamp(rgb.red, 0.0f, 1.0f);
    const float G = std::clamp(rgb.green, 0.0f, 1.0f);
    const float B = std::clamp(rgb.blue, 0.0f, 1.0f);
    dest_scan[dest_byte_pos] = static_cast<uint8_t>(B * 255);
    dest_scan[dest_byte_pos + 1] = static_cast<uint8_t>(G * 255);
    dest_scan[dest_byte_pos + 2] = static_cast<uint8_t>(R * 255);
    dest_byte_pos += 3;
  }
}

bool CPDF_DIB::TranslateScanline24bppDefaultDecode(
    pdfium::span<uint8_t> dest_scan,
    pdfium::span<const uint8_t> src_scan) const {
  if (!default_decode_) {
    return false;
  }

  if (family_ != CPDF_ColorSpace::Family::kDeviceRGB &&
      family_ != CPDF_ColorSpace::Family::kCalRGB) {
    if (bpc_ != 8) {
      return false;
    }

    if (components_ == color_space_->ComponentCount()) {
      color_space_->TranslateImageLine(dest_scan, src_scan, GetWidth(),
                                       GetWidth(), GetHeight(), TransMask());
    }
    return true;
  }

  if (components_ != 3) {
    return true;
  }

  uint8_t* dest_pos = dest_scan.data();
  const uint8_t* src_pos = src_scan.data();
  switch (bpc_) {
    case 8:
      UNSAFE_TODO({
        for (int column = 0; column < GetWidth(); column++) {
          *dest_pos++ = src_pos[2];
          *dest_pos++ = src_pos[1];
          *dest_pos++ = *src_pos;
          src_pos += 3;
        }
      });
      break;
    case 16:
      UNSAFE_TODO({
        for (int col = 0; col < GetWidth(); col++) {
          *dest_pos++ = src_pos[4];
          *dest_pos++ = src_pos[2];
          *dest_pos++ = *src_pos;
          src_pos += 6;
        }
      });
      break;
    default:
      const unsigned int max_data = (1 << bpc_) - 1;
      uint64_t src_bit_pos = 0;
      size_t dest_byte_pos = 0;
      for (int column = 0; column < GetWidth(); column++) {
        unsigned int R = GetBits8(src_scan, src_bit_pos, bpc_);
        src_bit_pos += bpc_;
        unsigned int G = GetBits8(src_scan, src_bit_pos, bpc_);
        src_bit_pos += bpc_;
        unsigned int B = GetBits8(src_scan, src_bit_pos, bpc_);
        src_bit_pos += bpc_;
        R = std::min(R, max_data);
        G = std::min(G, max_data);
        B = std::min(B, max_data);
        UNSAFE_TODO({
          dest_pos[dest_byte_pos] = B * 255 / max_data;
          dest_pos[dest_byte_pos + 1] = G * 255 / max_data;
          dest_pos[dest_byte_pos + 2] = R * 255 / max_data;
          dest_byte_pos += 3;
        });
      }
      break;
  }
  return true;
}

pdfium::span<const uint8_t> CPDF_DIB::GetScanline(int line) const {
  if (bpc_ == 0) {
    return pdfium::span<const uint8_t>();
  }

  const std::optional<uint32_t> src_pitch =
      fxge::CalculatePitch8(bpc_, components_, GetWidth());
  if (!src_pitch.has_value()) {
    return pdfium::span<const uint8_t>();
  }

  uint32_t src_pitch_value = src_pitch.value();
  // This is used as the buffer of `pSrcLine` when the stream is truncated,
  // and the remaining bytes count is less than `src_pitch_value`
  DataVector<uint8_t> temp_buffer;
  pdfium::span<const uint8_t> pSrcLine;

  if (cached_bitmap_ && src_pitch_value <= cached_bitmap_->GetPitch()) {
    if (line >= cached_bitmap_->GetHeight()) {
      line = cached_bitmap_->GetHeight() - 1;
    }
    pSrcLine = cached_bitmap_->GetScanline(line);
  } else if (decoder_) {
    pSrcLine = decoder_->GetScanline(line);
  } else if (stream_acc_->GetSize() > line * src_pitch_value) {
    pdfium::span<const uint8_t> remaining_bytes =
        stream_acc_->GetSpan().subspan(line * src_pitch_value);
    if (remaining_bytes.size() >= src_pitch_value) {
      pSrcLine = remaining_bytes.first(src_pitch_value);
    } else {
      temp_buffer = DataVector<uint8_t>(src_pitch_value);
      fxcrt::Copy(remaining_bytes, temp_buffer);
      pSrcLine = temp_buffer;
    }
  }

  if (pSrcLine.empty()) {
    pdfium::span<uint8_t> result = !mask_buf_.empty() ? mask_buf_ : line_buf_;
    std::ranges::fill(result, 0);
    return result;
  }
  if (bpc_ * components_ == 1) {
    if (image_mask_ && default_decode_) {
      for (uint32_t i = 0; i < src_pitch_value; i++) {
        // TODO(tsepez): Bounds check if cost is acceptable.
        UNSAFE_TODO(line_buf_[i] = ~pSrcLine.data()[i]);
      }
      return pdfium::span(line_buf_).first(src_pitch_value);
    }
    if (!color_key_) {
      fxcrt::Copy(pSrcLine.first(src_pitch_value), line_buf_);
      return pdfium::span(line_buf_).first(src_pitch_value);
    }
    uint32_t reset_argb = Get1BitResetValue();
    uint32_t set_argb = Get1BitSetValue();
    auto mask32_span =
        fxcrt::reinterpret_span<uint32_t>(pdfium::span(mask_buf_));
    for (int col = 0; col < GetWidth(); col++) {
      mask32_span[col] = GetBitValue(pSrcLine, col) ? set_argb : reset_argb;
    }
    return fxcrt::reinterpret_span<uint8_t>(
        mask32_span.first(static_cast<size_t>(GetWidth())));
  }
  if (bpc_ * components_ <= 8) {
    pdfium::span<uint8_t> result = line_buf_;
    if (bpc_ == 8) {
      fxcrt::Copy(pSrcLine.first(src_pitch_value), result);
      result = result.first(src_pitch_value);
    } else {
      uint64_t src_bit_pos = 0;
      for (int col = 0; col < GetWidth(); col++) {
        unsigned int color_index = 0;
        for (uint32_t color = 0; color < components_; color++) {
          unsigned int data = GetBits8(pSrcLine, src_bit_pos, bpc_);
          color_index |= data << (color * bpc_);
          src_bit_pos += bpc_;
        }
        line_buf_[col] = color_index;
      }
      result = result.first(static_cast<size_t>(GetWidth()));
    }
    if (!color_key_) {
      return result;
    }

    uint8_t* pDestPixel = mask_buf_.data();
    const uint8_t* pSrcPixel = line_buf_.data();
    pdfium::span<const uint32_t> palette = GetPaletteSpan();
    UNSAFE_TODO({
      if (HasPalette()) {
        for (int col = 0; col < GetWidth(); col++) {
          uint8_t index = *pSrcPixel++;
          *pDestPixel++ = FXARGB_B(palette[index]);
          *pDestPixel++ = FXARGB_G(palette[index]);
          *pDestPixel++ = FXARGB_R(palette[index]);
          *pDestPixel++ =
              IsColorIndexOutOfBounds(index, comp_data_[0]) ? 0xFF : 0;
        }
      } else {
        for (int col = 0; col < GetWidth(); col++) {
          uint8_t index = *pSrcPixel++;
          *pDestPixel++ = index;
          *pDestPixel++ = index;
          *pDestPixel++ = index;
          *pDestPixel++ =
              IsColorIndexOutOfBounds(index, comp_data_[0]) ? 0xFF : 0;
        }
      }
    });
    return pdfium::span(mask_buf_).first(static_cast<size_t>(4 * GetWidth()));
  }
  if (color_key_) {
    if (components_ == 3 && bpc_ == 8) {
      UNSAFE_TODO({
        uint8_t* alpha_channel = mask_buf_.data() + 3;
        for (int col = 0; col < GetWidth(); col++) {
          const auto pPixel =
              pSrcLine.subspan(static_cast<size_t>(col * 3), 3u);
          alpha_channel[col * 4] =
              AreColorIndicesOutOfBounds(pPixel, comp_data_) ? 0xFF : 0;
        }
      });
    } else {
      std::ranges::fill(mask_buf_, 0xFF);
    }
  }
  if (color_space_) {
    TranslateScanline24bpp(line_buf_, pSrcLine);
    src_pitch_value = 3 * GetWidth();
    pSrcLine = pdfium::span(line_buf_).first(src_pitch_value);
  }
  if (!color_key_) {
    return pSrcLine;
  }

  // TODO(tsepez): Bounds check if cost is acceptable.
  const uint8_t* pSrcPixel = pSrcLine.data();
  uint8_t* pDestPixel = mask_buf_.data();
  UNSAFE_TODO({
    for (int col = 0; col < GetWidth(); col++) {
      *pDestPixel++ = *pSrcPixel++;
      *pDestPixel++ = *pSrcPixel++;
      *pDestPixel++ = *pSrcPixel++;
      pDestPixel++;
    }
  });
  return pdfium::span(mask_buf_).first(static_cast<size_t>(4 * GetWidth()));
}

bool CPDF_DIB::SkipToScanline(int line, PauseIndicatorIface* pPause) const {
  return decoder_ && decoder_->SkipToScanline(line, pPause);
}

size_t CPDF_DIB::GetEstimatedImageMemoryBurden() const {
  return cached_bitmap_ ? cached_bitmap_->GetEstimatedImageMemoryBurden() : 0;
}

bool CPDF_DIB::TransMask() const {
  return load_mask_ && group_family_ == CPDF_ColorSpace::Family::kDeviceCMYK &&
         family_ == CPDF_ColorSpace::Family::kDeviceCMYK;
}

void CPDF_DIB::SetMaskProperties() {
  bpc_ = 1;
  components_ = 1;
  SetFormat(FXDIB_Format::k1bppMask);
}

uint32_t CPDF_DIB::Get1BitSetValue() const {
  if (comp_data_[0].color_key_max_ == 1) {
    return 0x00000000;
  }
  return HasPalette() ? GetPaletteSpan()[1] : 0xFFFFFFFF;
}

uint32_t CPDF_DIB::Get1BitResetValue() const {
  if (comp_data_[0].color_key_min_ == 0) {
    return 0x00000000;
  }
  return HasPalette() ? GetPaletteSpan()[0] : 0xFF000000;
}
