// 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 <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/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_memcpy_wrappers.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;
}

enum class JpxDecodeAction {
  kFail,
  kDoNothing,
  kUseGray,
  kUseIndexed,
  kUseRgb,
  kUseCmyk,
  kConvertArgbToRgb,
};

// ISO 32000-1:2008 section 7.4.9 says the PDF and JPX colorspaces should have
// the same number of color channels. This helper function checks the
// colorspaces match, but also tolerates unknowns.
bool IsJPXColorSpaceOrUnspecifiedOrUnknown(COLOR_SPACE actual,
                                           COLOR_SPACE expected) {
  return actual == expected || actual == OPJ_CLRSPC_UNSPECIFIED ||
         actual == OPJ_CLRSPC_UNKNOWN;
}

// Decides which JpxDecodeAction to use based on the colorspace information from
// the PDF and the JPX image. Called only when the PDF's image object contains a
// "/ColorSpace" entry.
JpxDecodeAction GetJpxDecodeActionFromColorSpaces(
    const CJPX_Decoder::JpxImageInfo& jpx_info,
    const CPDF_ColorSpace* pdf_colorspace) {
  if (pdf_colorspace ==
      CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceGray)) {
    if (!IsJPXColorSpaceOrUnspecifiedOrUnknown(/*actual=*/jpx_info.colorspace,
                                               /*expected=*/OPJ_CLRSPC_GRAY)) {
      return JpxDecodeAction::kFail;
    }
    return JpxDecodeAction::kUseGray;
  }

  if (pdf_colorspace ==
      CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceRGB)) {
    if (!IsJPXColorSpaceOrUnspecifiedOrUnknown(/*actual=*/jpx_info.colorspace,
                                               /*expected=*/OPJ_CLRSPC_SRGB)) {
      return JpxDecodeAction::kFail;
    }

    // The channel count of a JPX image can be different from the PDF color
    // space's component count.
    if (jpx_info.channels > 3) {
      return JpxDecodeAction::kConvertArgbToRgb;
    }
    return JpxDecodeAction::kUseRgb;
  }

  if (pdf_colorspace ==
      CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceCMYK)) {
    if (!IsJPXColorSpaceOrUnspecifiedOrUnknown(/*actual=*/jpx_info.colorspace,
                                               /*expected=*/OPJ_CLRSPC_CMYK)) {
      return JpxDecodeAction::kFail;
    }
    return JpxDecodeAction::kUseCmyk;
  }

  // Many PDFs generated by iOS meets this condition. Handle the discrepancy.
  // See https://crbug.com/345431077 for example.
  if (pdf_colorspace->ComponentCount() == 3 && jpx_info.channels == 4 &&
      jpx_info.colorspace == OPJ_CLRSPC_SRGB) {
    return JpxDecodeAction::kConvertArgbToRgb;
  }

  if (pdf_colorspace->GetFamily() == CPDF_ColorSpace::Family::kIndexed &&
      pdf_colorspace->ComponentCount() == 1) {
    return JpxDecodeAction::kUseIndexed;
  }

  return JpxDecodeAction::kDoNothing;
}

JpxDecodeAction GetJpxDecodeActionFromImageColorSpace(
    const CJPX_Decoder::JpxImageInfo& jpx_info) {
  switch (jpx_info.colorspace) {
    case OPJ_CLRSPC_SYCC:
    case OPJ_CLRSPC_EYCC:
    case OPJ_CLRSPC_UNKNOWN:
    case OPJ_CLRSPC_UNSPECIFIED:
      return JpxDecodeAction::kDoNothing;

    case OPJ_CLRSPC_SRGB:
      if (jpx_info.channels > 3) {
        return JpxDecodeAction::kConvertArgbToRgb;
      }

      return JpxDecodeAction::kUseRgb;

    case OPJ_CLRSPC_GRAY:
      return JpxDecodeAction::kUseGray;

    case OPJ_CLRSPC_CMYK:
      return JpxDecodeAction::kUseCmyk;
  }
}

JpxDecodeAction GetJpxDecodeAction(const CJPX_Decoder::JpxImageInfo& jpx_info,
                                   const CPDF_ColorSpace* pdf_colorspace) {
  if (pdf_colorspace) {
    return GetJpxDecodeActionFromColorSpaces(jpx_info, pdf_colorspace);
  }

  // When PDF does not provide a color space, check the image color space.
  return GetJpxDecodeActionFromImageColorSpace(jpx_info);
}

int GetComponentCountFromOpjColorSpace(OPJ_COLOR_SPACE colorspace) {
  switch (colorspace) {
    case OPJ_CLRSPC_GRAY:
      return 1;

    case OPJ_CLRSPC_SRGB:
    case OPJ_CLRSPC_SYCC:
    case OPJ_CLRSPC_EYCC:
      return 3;

    case OPJ_CLRSPC_CMYK:
      return 4;

    default:
      return 0;
  }
}

}  // namespace

CPDF_DIB::CPDF_DIB(CPDF_Document* pDoc, RetainPtr<const CPDF_Stream> pStream)
    : document_(pDoc), 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();
    }
    iDecodeStatus = Jbig2Decoder::StartDecode(
        jbig_2context_.get(), document_->GetOrCreateCodecContext(), GetWidth(),
        GetHeight(), pSrcSpan, nSrcKey, pGlobalSpan, nGlobalKey,
        cached_bitmap_->GetWritableBuffer(), cached_bitmap_->GetPitch(),
        pPause);
  } 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;
  }

  RetainPtr<CPDF_ColorSpace> original_colorspace = color_space_;
  bool swap_rgb = false;
  bool convert_argb_to_rgb = false;
  auto action = GetJpxDecodeAction(image_info, color_space_.Get());
  switch (action) {
    case JpxDecodeAction::kFail:
      return nullptr;

    case JpxDecodeAction::kDoNothing:
      break;

    case JpxDecodeAction::kUseGray:
      color_space_ =
          CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceGray);
      break;

    case JpxDecodeAction::kUseIndexed:
      break;

    case JpxDecodeAction::kUseRgb:
      DCHECK(image_info.channels >= 3);
      swap_rgb = true;
      color_space_ = nullptr;
      break;

    case JpxDecodeAction::kUseCmyk:
      color_space_ =
          CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceCMYK);
      break;

    case JpxDecodeAction::kConvertArgbToRgb:
      swap_rgb = true;
      convert_argb_to_rgb = true;
      color_space_.Reset();
      break;
  }

  // If |original_colorspace| exists, then LoadColorInfo() already set
  // |components_|.
  if (original_colorspace) {
    DCHECK_NE(0u, components_);
  } else {
    DCHECK_EQ(0u, components_);
    components_ = GetComponentCountFromOpjColorSpace(image_info.colorspace);
    if (components_ == 0) {
      return nullptr;
    }
  }

  FXDIB_Format format;
  if (action == JpxDecodeAction::kUseGray ||
      action == JpxDecodeAction::kUseIndexed) {
    format = FXDIB_Format::k8bppRgb;
  } else if (action == JpxDecodeAction::kUseRgb && image_info.channels == 3) {
    format = FXDIB_Format::kBgr;
  } else if (action == JpxDecodeAction::kUseRgb && image_info.channels == 4) {
    format = FXDIB_Format::kBgrx;
  } else if (action == JpxDecodeAction::kConvertArgbToRgb) {
    CHECK_GE(image_info.channels, 4);
    format = FXDIB_Format::kBgrx;
  } else {
    image_info.width = (image_info.width * image_info.channels + 2) / 3;
    format = FXDIB_Format::kBgr;
  }

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

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

  if (convert_argb_to_rgb) {
    DCHECK_EQ(3u, components_);
    auto rgb_bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
    if (!rgb_bitmap->Create(image_info.width, image_info.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 = image_info.width;
      jpx_inline_data_.height = image_info.height;
      jpx_inline_data_.data.reserve(image_info.width * image_info.height);
      for (uint32_t row = 0; row < image_info.height; ++row) {
        auto src =
            result_bitmap->GetScanlineAs<FX_BGRA_STRUCT<uint8_t>>(row).first(
                image_info.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;
        }
      }
    } else {
      // TODO(thestig): Is there existing code that does this already?
      for (uint32_t row = 0; row < image_info.height; ++row) {
        auto src =
            result_bitmap->GetScanlineAs<FX_BGRA_STRUCT<uint8_t>>(row).first(
                image_info.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;
        }
      }
    }
    result_bitmap = std::move(rgb_bitmap);
  } 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/pdfium/1747): Handle SMaskInData entries for different
  // color space types.

  bpc_ = 8;
  return result_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::fill(std::begin(color_values), std::end(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;
}
