7#include "core/fpdfapi/page/cpdf_colorspace.h"
21#include "core/fpdfapi/page/cpdf_devicecs.h"
22#include "core/fpdfapi/page/cpdf_docpagedata.h"
23#include "core/fpdfapi/page/cpdf_function.h"
24#include "core/fpdfapi/page/cpdf_iccprofile.h"
25#include "core/fpdfapi/page/cpdf_indexedcs.h"
26#include "core/fpdfapi/page/cpdf_pattern.h"
27#include "core/fpdfapi/page/cpdf_patterncs.h"
28#include "core/fpdfapi/parser/cpdf_array.h"
29#include "core/fpdfapi/parser/cpdf_dictionary.h"
30#include "core/fpdfapi/parser/cpdf_document.h"
31#include "core/fpdfapi/parser/cpdf_name.h"
32#include "core/fpdfapi/parser/cpdf_object.h"
33#include "core/fpdfapi/parser/cpdf_stream.h"
34#include "core/fpdfapi/parser/fpdf_parser_utility.h"
35#include "core/fxcodec/fx_codec.h"
36#include "core/fxcodec/icc/icc_transform.h"
37#include "core/fxcrt/check.h"
38#include "core/fxcrt/check_op.h"
39#include "core/fxcrt/compiler_specific.h"
40#include "core/fxcrt/containers/contains.h"
41#include "core/fxcrt/data_vector.h"
42#include "core/fxcrt/fx_2d_size.h"
43#include "core/fxcrt/fx_safe_types.h"
44#include "core/fxcrt/fx_system.h"
45#include "core/fxcrt/maybe_owned.h"
46#include "core/fxcrt/notreached.h"
47#include "core/fxcrt/scoped_set_insertion.h"
48#include "core/fxcrt/stl_util.h"
49#include "core/fxcrt/zip.h"
50#include "core/fxge/dib/fx_dib.h"
54constexpr auto kSRGBSamples1 =
fxcrt::ToArray<
const uint8_t>({
55 0, 3, 6, 10, 13, 15, 18, 20, 22, 23, 25, 27, 28, 30, 31,
56 32, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
57 48, 49, 49, 50, 51, 52, 53, 53, 54, 55, 56, 56, 57, 58, 58,
58 59, 60, 61, 61, 62, 62, 63, 64, 64, 65, 66, 66, 67, 67, 68,
59 68, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74, 75, 76, 76,
60 77, 77, 78, 78, 79, 79, 79, 80, 80, 81, 81, 82, 82, 83, 83,
61 84, 84, 85, 85, 85, 86, 86, 87, 87, 88, 88, 88, 89, 89, 90,
62 90, 91, 91, 91, 92, 92, 93, 93, 93, 94, 94, 95, 95, 95, 96,
63 96, 97, 97, 97, 98, 98, 98, 99, 99, 99, 100, 100, 101, 101, 101,
64 102, 102, 102, 103, 103, 103, 104, 104, 104, 105, 105, 106, 106, 106, 107,
65 107, 107, 108, 108, 108, 109, 109, 109, 110, 110, 110, 110, 111, 111, 111,
66 112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 115, 116, 116,
67 116, 117, 117, 117, 118, 118, 118, 118, 119, 119, 119, 120,
70constexpr auto kSRGBSamples2 =
fxcrt::ToArray<
const uint8_t>({
71 120, 121, 122, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
72 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 149,
73 150, 151, 152, 153, 154, 155, 155, 156, 157, 158, 159, 159, 160, 161, 162,
74 163, 163, 164, 165, 166, 167, 167, 168, 169, 170, 170, 171, 172, 173, 173,
75 174, 175, 175, 176, 177, 178, 178, 179, 180, 180, 181, 182, 182, 183, 184,
76 185, 185, 186, 187, 187, 188, 189, 189, 190, 190, 191, 192, 192, 193, 194,
77 194, 195, 196, 196, 197, 197, 198, 199, 199, 200, 200, 201, 202, 202, 203,
78 203, 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, 210, 210, 211, 212,
79 212, 213, 213, 214, 214, 215, 215, 216, 216, 217, 218, 218, 219, 219, 220,
80 220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 226, 226, 227, 227, 228,
81 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235,
82 236, 236, 237, 237, 238, 238, 238, 239, 239, 240, 240, 241, 241, 242, 242,
83 243, 243, 244, 244, 245, 245, 246, 246, 246, 247, 247, 248, 248, 249, 249,
84 250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 255, 255,
87constexpr size_t kBlackWhitePointCount = 3;
89void GetDefaultBlackPoint(pdfium::span<
float> pPoints) {
90 static constexpr float kDefaultValue = 0.0f;
91 for (size_t i = 0; i < kBlackWhitePointCount; ++i)
92 pPoints[i] = kDefaultValue;
95void GetBlackPoint(
const CPDF_Dictionary* pDict, pdfium::span<
float> pPoints) {
97 if (!pParam || pParam->size() != kBlackWhitePointCount) {
98 GetDefaultBlackPoint(pPoints);
103 for (size_t i = 0; i < kBlackWhitePointCount; ++i) {
104 pPoints[i] = pParam->GetFloatAt(i);
105 if (pPoints[i] < 0) {
106 GetDefaultBlackPoint(pPoints);
112bool GetWhitePoint(
const CPDF_Dictionary* pDict, pdfium::span<
float> pPoints) {
114 if (!pParam || pParam->size() != kBlackWhitePointCount)
117 for (size_t i = 0; i < kBlackWhitePointCount; ++i)
118 pPoints[i] = pParam->GetFloatAt(i);
119 return pPoints[0] > 0.0f && pPoints[1] == 1.0f && pPoints[2] > 0.0f;
125 ~CPDF_CalGray()
override;
129 pdfium::span<
const float> pBuf)
const override;
132 std::set<
const CPDF_Object*>* pVisited)
override;
133 void TranslateImageLine(pdfium::span<uint8_t> dest_span,
134 pdfium::span<
const uint8_t> src_span,
138 bool bTransMask)
const override;
141 static constexpr float kDefaultGamma = 1.0f;
145 float gamma_ = kDefaultGamma;
146 std::array<
float, kBlackWhitePointCount> white_point_ = {{1.0f, 1.0f, 1.0f}};
147 std::array<
float, kBlackWhitePointCount> black_point_ = {{0.0f, 0.0f, 0.0f}};
153 ~CPDF_CalRGB()
override;
157 pdfium::span<
const float> pBuf)
const override;
158 void TranslateImageLine(pdfium::span<uint8_t> dest_span,
159 pdfium::span<
const uint8_t> src_span,
163 bool bTransMask)
const override;
166 std::set<
const CPDF_Object*>* pVisited)
override;
169 static constexpr size_t kGammaCount = 3;
170 static constexpr size_t kMatrixCount = 9;
174 std::array<
float, kBlackWhitePointCount> white_point_ = {{1.0f, 1.0f, 1.0f}};
175 std::array<
float, kBlackWhitePointCount> black_point_ = {{0.0f, 0.0f, 0.0f}};
176 std::optional<std::array<
float, kGammaCount>> gamma_;
177 std::optional<std::array<
float, kMatrixCount>> matrix_;
183 ~CPDF_LabCS()
override;
187 pdfium::span<
const float> pBuf)
const override;
188 void GetDefaultValue(
int iComponent,
191 float* max)
const override;
192 void TranslateImageLine(pdfium::span<uint8_t> dest_span,
193 pdfium::span<
const uint8_t> src_span,
197 bool bTransMask)
const override;
200 std::set<
const CPDF_Object*>* pVisited)
override;
203 static constexpr size_t kRangesCount = 4;
207 std::array<
float, kBlackWhitePointCount> white_point_ = {{1.0f, 1.0f, 1.0f}};
208 std::array<
float, kBlackWhitePointCount> black_point_ = {{0.0f, 0.0f, 0.0f}};
209 std::array<
float, kRangesCount> m_Ranges = {};
215 ~CPDF_ICCBasedCS()
override;
219 pdfium::span<
const float> pBuf)
const override;
220 void TranslateImageLine(pdfium::span<uint8_t> dest_span,
221 pdfium::span<
const uint8_t> src_span,
225 bool bTransMask)
const override;
226 bool IsNormal()
const override;
229 std::set<
const CPDF_Object*>* pVisited)
override;
237 std::set<
const CPDF_Object*>* pVisited,
238 uint32_t nExpectedComponents);
240 uint32_t nComponents);
242 uint32_t nComponents);
245 mutable DataVector<uint8_t> cache_;
246 std::vector<
float> ranges_;
252 ~CPDF_SeparationCS()
override;
256 pdfium::span<
const float> pBuf)
const override;
257 void GetDefaultValue(
int iComponent,
260 float* max)
const override;
263 std::set<
const CPDF_Object*>* pVisited)
override;
268 bool m_IsNoneType =
false;
269 std::unique_ptr<
const CPDF_Function> m_pFunc;
275 ~CPDF_DeviceNCS()
override;
279 pdfium::span<
const float> pBuf)
const override;
280 void GetDefaultValue(
int iComponent,
283 float* max)
const override;
286 std::set<
const CPDF_Object*>* pVisited)
override;
291 std::unique_ptr<
const CPDF_Function> m_pFunc;
296 Vector_3by1() : a(0.0f), b(0.0f), c(0.0f) {}
298 Vector_3by1(
float a1,
float b1,
float c1) : a(a1), b(b1), c(c1) {}
318 Matrix_3by3(
float a1,
327 : a(a1), b(b1), c(c1), d(d1), e(e1), f(f1), g(g1), h(h1), i(i1) {}
329 Matrix_3by3 Inverse() {
330 float det = a * (e * i - f * h) - b * (i * d - f * g) + c * (d * h - e * g);
331 if (fabs(det) <
std::numeric_limits<
float>::epsilon())
332 return Matrix_3by3();
335 (e * i - f * h) / det, -(b * i - c * h) / det, (b * f - c * e) / det,
336 -(d * i - f * g) / det, (a * i - c * g) / det, -(a * f - c * d) / det,
337 (d * h - e * g) / det, -(a * h - b * g) / det, (a * e - b * d) / det);
340 Matrix_3by3 Multiply(
const Matrix_3by3& m) {
341 return Matrix_3by3(a * m.a + b * m.d + c * m.g, a * m.b + b * m.e + c * m.h,
342 a * m.c + b * m.f + c * m.i, d * m.a + e * m.d + f * m.g,
343 d * m.b + e * m.e + f * m.h, d * m.c + e * m.f + f * m.i,
344 g * m.a + h * m.d + i * m.g, g * m.b + h * m.e + i * m.h,
345 g * m.c + h * m.f + i * m.i);
348 Vector_3by1 TransformVector(
const Vector_3by1& v) {
349 return Vector_3by1(a * v.a + b * v.b + c * v.c, d * v.a + e * v.b + f * v.c,
350 g * v.a + h * v.b + i * v.c);
364float RGB_Conversion(
float colorComponent) {
365 colorComponent =
std::clamp(colorComponent, 0.0f, 1.0f);
366 int scale =
std::max(
static_cast<
int>(colorComponent * 1023), 0);
368 return kSRGBSamples1[scale] / 255.0f;
370 return kSRGBSamples2[scale / 4 - 48] / 255.0f;
374 const float R1 = 3.2410f * X - 1.5374f * Y - 0.4986f * Z;
375 const float G1 = -0.9692f * X + 1.8760f * Y + 0.0416f * Z;
376 const float B1 = 0.0556f * X - 0.2040f * Y + 1.0570f * Z;
377 return {RGB_Conversion(R1), RGB_Conversion(G1), RGB_Conversion(B1)};
389 constexpr float Rx = 0.64f;
390 constexpr float Ry = 0.33f;
391 constexpr float Gx = 0.30f;
392 constexpr float Gy = 0.60f;
393 constexpr float Bx = 0.15f;
394 constexpr float By = 0.06f;
395 Matrix_3by3 RGB_xyz(Rx, Gx, Bx, Ry, Gy, By, 1 - Rx - Ry, 1 - Gx - Gy,
397 Vector_3by1 whitePoint(Xw, Yw, Zw);
398 Vector_3by1 XYZ(X, Y, Z);
400 Vector_3by1 RGB_Sum_XYZ = RGB_xyz.Inverse().TransformVector(whitePoint);
401 Matrix_3by3 RGB_SUM_XYZ_DIAG(RGB_Sum_XYZ.a, 0, 0, 0, RGB_Sum_XYZ.b, 0, 0, 0,
403 Matrix_3by3 M = RGB_xyz.Multiply(RGB_SUM_XYZ_DIAG);
404 Vector_3by1 RGB = M.Inverse().TransformVector(XYZ);
406 return {RGB_Conversion(RGB.a), RGB_Conversion(RGB.b), RGB_Conversion(RGB.c)};
409class StockColorSpaces {
412 : gray_(pdfium::MakeRetain<CPDF_DeviceCS>(
413 CPDF_ColorSpace::Family::kDeviceGray)),
414 rgb_(pdfium::MakeRetain<CPDF_DeviceCS>(
415 CPDF_ColorSpace::Family::kDeviceRGB)),
416 cmyk_(pdfium::MakeRetain<CPDF_DeviceCS>(
417 CPDF_ColorSpace::Family::kDeviceCMYK)),
418 pattern_(pdfium::MakeRetain<CPDF_PatternCS>()) {
419 pattern_->InitializeStockPattern();
421 StockColorSpaces(
const StockColorSpaces&) =
delete;
422 StockColorSpaces& operator=(
const StockColorSpaces&) =
delete;
423 ~StockColorSpaces() =
default;
448StockColorSpaces* g_stock_colorspaces =
nullptr;
459 fxcrt::Copy(comps, m_Comps);
464 CHECK(!g_stock_colorspaces);
465 g_stock_colorspaces =
new StockColorSpaces();
470 delete g_stock_colorspaces;
471 g_stock_colorspaces =
nullptr;
476 return g_stock_colorspaces->GetStockCS(family);
482 if (name
== "DeviceRGB" || name
== "RGB")
484 if (name
== "DeviceGray" || name
== "G")
486 if (name
== "DeviceCMYK" || name
== "CMYK")
488 if (name
== "Pattern")
497 std::set<
const CPDF_Object*>* pVisited) {
501 if (
pdfium::Contains(*pVisited, pObj))
512 for (
const auto& it : locker) {
513 RetainPtr<
const CPDF_Name> pValue = ToName(it.second);
515 RetainPtr<CPDF_ColorSpace> pRet =
516 GetStockCSForName(pValue->GetString());
532 ByteString familyname = pFamilyObj->GetString();
533 if (pArray->size() == 1)
534 return GetStockCSForName(familyname);
537 CPDF_ColorSpace::AllocateColorSpace(familyname.AsStringView());
541 pCS->m_pArray.Reset(pArray);
542 pCS->m_nComponents = pCS->v_Load(pDoc, pArray, pVisited);
543 if (pCS->m_nComponents == 0)
552 switch (bsFamilyName.GetID()) {
554 return pdfium::MakeRetain<CPDF_CalGray>();
556 return pdfium::MakeRetain<CPDF_CalRGB>();
558 return pdfium::MakeRetain<CPDF_LabCS>();
560 return pdfium::MakeRetain<CPDF_ICCBasedCS>();
563 return pdfium::MakeRetain<CPDF_IndexedCS>();
565 return pdfium::MakeRetain<CPDF_SeparationCS>();
567 return pdfium::MakeRetain<CPDF_DeviceNCS>();
569 return pdfium::MakeRetain<CPDF_PatternCS>();
590 DCHECK(m_Family != Family::kPattern);
594 std::vector<
float> buf(m_nComponents);
595 for (uint32_t i = 0; i < m_nComponents; i++)
602 return m_nComponents;
615 pdfium::span<
const uint8_t> src_span,
619 bool bTransMask)
const {
624 uint8_t* dest_buf = dest_span.data();
625 const uint8_t* src_buf = src_span.data();
626 std::vector<
float> src(m_nComponents);
629 for (
int i = 0; i < pixels; i++) {
630 for (uint32_t j = 0; j < m_nComponents; j++) {
631 src[j] =
static_cast<
float>(*src_buf++) / divisor;
633 auto rgb = GetRGBOrZerosOnError(src);
634 *dest_buf++ =
static_cast<int32_t>(rgb.blue * 255);
635 *dest_buf++ =
static_cast<int32_t>(rgb.green * 255);
636 *dest_buf++ =
static_cast<int32_t>(rgb.red * 255);
644 else if (m_dwStdConversion)
668 m_nComponents = nComponents;
673CPDF_CalGray::~CPDF_CalGray() =
default;
677 std::set<
const CPDF_Object*>* pVisited) {
682 if (!GetWhitePoint(pDict.Get(), white_point_)) {
686 GetBlackPoint(pDict.Get(), black_point_);
688 gamma_ = pDict->GetFloatFor(
"Gamma");
690 gamma_ = kDefaultGamma;
696 pdfium::span<
const float> pBuf)
const {
697 const float gray = pBuf[0];
698 return FX_RGB_STRUCT<
float>{gray, gray, gray};
701void CPDF_CalGray::TranslateImageLine(pdfium::span<uint8_t> dest_span,
702 pdfium::span<
const uint8_t> src_span,
706 bool bTransMask)
const {
709 auto gray_span = src_span.first(pixels);
711 for (
auto [gray_ref, rgb_ref] : fxcrt::Zip(gray_span, rgb_span)) {
713 const uint8_t pix = gray_ref;
722CPDF_CalRGB::~CPDF_CalRGB() =
default;
726 std::set<
const CPDF_Object*>* pVisited) {
731 if (!GetWhitePoint(pDict.Get(), white_point_)) {
735 GetBlackPoint(pDict.Get(), black_point_);
739 auto& gamma = gamma_.emplace();
740 for (size_t i = 0; i <
std::size(gamma); ++i) {
741 gamma[i] = pGamma->GetFloatAt(i);
747 auto& matrix = matrix_.emplace();
748 for (size_t i = 0; i <
std::size(matrix); ++i) {
749 matrix[i] = pMatrix->GetFloatAt(i);
756 pdfium::span<
const float> pBuf)
const {
760 if (gamma_.has_value()) {
761 const auto& gamma = gamma_.value();
762 a = powf(a, gamma[0]);
763 b = powf(b, gamma[1]);
764 c = powf(c, gamma[2]);
769 if (matrix_.has_value()) {
770 const auto& matrix = matrix_.value();
771 x = matrix[0] * a + matrix[3] * b + matrix[6] * c;
772 y = matrix[1] * a + matrix[4] * b + matrix[7] * c;
773 z = matrix[2] * a + matrix[5] * b + matrix[8] * c;
779 return XYZ_to_sRGB_WhitePoint(x, y, z, white_point_[0], white_point_[1],
783void CPDF_CalRGB::TranslateImageLine(pdfium::span<uint8_t> dest_span,
784 pdfium::span<
const uint8_t> src_span,
788 bool bTransMask)
const {
795CPDF_LabCS::~CPDF_LabCS() =
default;
797void CPDF_LabCS::GetDefaultValue(
int iComponent,
803 if (iComponent > 0) {
804 float range_min = m_Ranges[iComponent * 2 - 2];
805 float range_max = m_Ranges[iComponent * 2 - 1];
806 if (range_min <= range_max) {
809 *value =
std::clamp(0.0f, *min, *max);
821 std::set<
const CPDF_Object*>* pVisited) {
826 if (!GetWhitePoint(pDict.Get(), white_point_)) {
830 GetBlackPoint(pDict.Get(), black_point_);
833 static constexpr std::array<
float, kRangesCount> kDefaultRanges = {
834 {-100.0f, 100.0f, -100.0f, 100.0f}};
835 for (size_t i = 0; i <
std::size(kDefaultRanges); ++i) {
836 m_Ranges[i] = pParam ? pParam->GetFloatAt(i) : kDefaultRanges[i];
842 pdfium::span<
const float> pBuf)
const {
843 float Lstar = pBuf[0];
844 float astar = pBuf[1];
845 float bstar = pBuf[2];
846 float M = (Lstar + 16.0f) / 116.0f;
847 float L = M + astar / 500.0f;
848 float N = M - bstar / 200.0f;
853 X = 0.957f * 0.12842f * (L - 0.1379f);
855 X = 0.957f * L * L * L;
858 Y = 0.12842f * (M - 0.1379f);
863 Z = 1.0889f * 0.12842f * (N - 0.1379f);
865 Z = 1.0889f * N * N * N;
867 return XYZ_to_sRGB(X, Y, Z);
870void CPDF_LabCS::TranslateImageLine(pdfium::span<uint8_t> dest_span,
871 pdfium::span<
const uint8_t> src_span,
875 bool bTransMask)
const {
882 for (
auto [lab_ref, bgr_ref] : fxcrt::Zip(lab_span, bgr_span)) {
883 const float lab[3] = {
884 static_cast<
float>(lab_ref.lightness_star * 100) / 255.0f,
885 static_cast<
float>(lab_ref.a_star - 128),
886 static_cast<
float>(lab_ref.b_star - 128),
891 auto rgb = GetRGB(lab).value_or(FX_RGB_STRUCT<
float>{});
892 bgr_ref.blue =
static_cast<int32_t>(rgb.blue * 255);
893 bgr_ref.green =
static_cast<int32_t>(rgb.green * 255);
894 bgr_ref.red =
static_cast<int32_t>(rgb.red * 255);
900CPDF_ICCBasedCS::~CPDF_ICCBasedCS() =
default;
904 std::set<
const CPDF_Object*>* pVisited) {
905 RetainPtr<
const CPDF_Stream> pStream = pArray->GetStreamAt(1);
913 const int32_t nDictComponents = pDict->GetIntegerFor(
"N");
919 const uint32_t nComponents =
static_cast<uint32_t>(nDictComponents);
920 profile_ = CPDF_DocPageData::FromDocument(pDoc)->GetIccProfile(pStream);
928 if (!profile_->IsSupported() &&
929 !FindAlternateProfile(pDoc, pDict.Get(), pVisited, nComponents)) {
933 m_pBaseCS = GetStockAlternateProfile(nComponents);
937 ranges_ = GetRanges(pDict.Get(), nComponents);
942 pdfium::span<
const float> pBuf)
const {
943 if (profile_->IsSRGB()) {
946 if (profile_->IsSupported()) {
948 profile_->Translate(pBuf.first(ComponentCount()), rgb);
949 return FX_RGB_STRUCT<
float>{rgb[0], rgb[1], rgb[2]};
952 return m_pBaseCS->GetRGB(pBuf);
954 return FX_RGB_STRUCT<
float>{};
957void CPDF_ICCBasedCS::TranslateImageLine(pdfium::span<uint8_t> dest_span,
958 pdfium::span<
const uint8_t> src_span,
962 bool bTransMask)
const {
965 if (profile_->IsSRGB()) {
969 if (!profile_->IsSupported()) {
971 m_pBaseCS->TranslateImageLine(dest_span, src_span, pixels, image_width,
972 image_height,
false);
979 DCHECK(fxcodec::IccTransform::IsValidIccComponents(nComponents));
981 for (uint32_t i = 0; i < nComponents; i++)
984 bool bTranslate = nComponents > 3;
987 nPixelCount *= image_height;
988 if (nPixelCount.IsValid())
989 bTranslate = nPixelCount.ValueOrDie() < nMaxColors * 3 / 2;
991 if (bTranslate && profile_->IsSupported()) {
992 profile_->TranslateScanline(dest_span, src_span, pixels);
995 if (cache_.empty()) {
996 cache_.resize(Fx2DSizeOrDie(nMaxColors, 3));
997 DataVector<uint8_t> temp_src(Fx2DSizeOrDie(nMaxColors, nComponents));
998 size_t src_index = 0;
999 for (
int i = 0; i < nMaxColors; i++) {
1001 uint32_t order = nMaxColors / 52;
1002 for (uint32_t c = 0; c < nComponents; c++) {
1003 temp_src[src_index++] =
static_cast<uint8_t>(color / order * 5);
1008 if (profile_->IsSupported()) {
1009 profile_->TranslateScanline(cache_, temp_src, nMaxColors);
1012 uint8_t* pDestBuf = dest_span.data();
1013 const uint8_t* pSrcBuf = src_span.data();
1015 for (
int i = 0; i < pixels; i++) {
1017 for (uint32_t c = 0; c < nComponents; c++) {
1018 index = index * 52 + (*pSrcBuf) / 5;
1022 *pDestBuf++ = cache_[index];
1023 *pDestBuf++ = cache_[index + 1];
1024 *pDestBuf++ = cache_[index + 2];
1029bool CPDF_ICCBasedCS::IsNormal()
const {
1030 if (profile_->IsSRGB()) {
1033 if (profile_->IsSupported()) {
1034 return profile_->IsNormal();
1037 return m_pBaseCS->IsNormal();
1041bool CPDF_ICCBasedCS::FindAlternateProfile(
1044 std::set<
const CPDF_Object*>* pVisited,
1045 uint32_t nExpectedComponents) {
1047 pDict->GetDirectObjectFor(
"Alternate");
1051 auto pAlterCS = CPDF_ColorSpace::Load(pDoc, pAlterCSObj.Get(), pVisited);
1058 if (pAlterCS->ComponentCount() != nExpectedComponents) {
1062 m_pBaseCS = std::move(pAlterCS);
1068 uint32_t nComponents) {
1069 if (nComponents == 1)
1071 if (nComponents == 3)
1073 if (nComponents == 4)
1079std::vector<
float> CPDF_ICCBasedCS::GetRanges(
const CPDF_Dictionary* pDict,
1080 uint32_t nComponents) {
1081 DCHECK(fxcodec::IccTransform::IsValidIccComponents(nComponents));
1083 if (pRanges && pRanges->size() >= nComponents * 2)
1084 return ReadArrayElementsToVector(pRanges.Get(), nComponents * 2);
1086 std::vector<
float> ranges;
1087 ranges.reserve(nComponents * 2);
1088 for (uint32_t i = 0; i < nComponents; i++) {
1089 ranges.push_back(0.0f);
1090 ranges.push_back(1.0f);
1097CPDF_SeparationCS::~CPDF_SeparationCS() =
default;
1099void CPDF_SeparationCS::GetDefaultValue(
int iComponent,
1110 std::set<
const CPDF_Object*>* pVisited) {
1111 m_IsNoneType = pArray->GetByteStringAt(1) ==
"None";
1119 m_pBaseCS = Load(pDoc, pAltArray.Get(), pVisited);
1123 if (m_pBaseCS->IsSpecial())
1127 if (pFuncObj && !pFuncObj->IsName()) {
1128 auto pFunc = CPDF_Function::Load(
std::move(pFuncObj));
1129 if (pFunc && pFunc->OutputCount() >= m_pBaseCS->ComponentCount()) {
1130 m_pFunc = std::move(pFunc);
1137 pdfium::span<
const float> pBuf)
const {
1139 return std::nullopt;
1143 return std::nullopt;
1145 std::vector<
float> results(m_pBaseCS->ComponentCount(), pBuf[0]);
1146 return m_pBaseCS->GetRGB(results);
1150 std::vector<
float> results(std::max(m_pFunc->OutputCount(), 16u));
1151 uint32_t nresults = m_pFunc->Call(pBuf.first(1), results).value_or(0);
1152 if (nresults == 0) {
1153 return std::nullopt;
1156 return m_pBaseCS->GetRGB(results);
1158 return std::nullopt;
1163CPDF_DeviceNCS::~CPDF_DeviceNCS() =
default;
1165void CPDF_DeviceNCS::GetDefaultValue(
int iComponent,
1176 std::set<
const CPDF_Object*>* pVisited) {
1185 m_pBaseCS = Load(pDoc, pAltCS.Get(), pVisited);
1186 m_pFunc = CPDF_Function::Load(pArray->GetDirectObjectAt(3));
1187 if (!m_pBaseCS || !m_pFunc)
1190 if (m_pBaseCS->IsSpecial())
1193 if (m_pFunc->OutputCount() < m_pBaseCS->ComponentCount()) {
1197 return fxcrt::CollectionSize<uint32_t>(*pObj);
1201 pdfium::span<
const float> pBuf)
const {
1203 return std::nullopt;
1206 std::vector<
float> results(std::max(m_pFunc->OutputCount(), 16u));
1208 m_pFunc->Call(pBuf.first(ComponentCount()), results).value_or(0);
1210 if (nresults == 0) {
1211 return std::nullopt;
1213 return m_pBaseCS->GetRGB(results);
fxcrt::ByteString ByteString
std::vector< RetainPtr< CPDF_Object > >::const_iterator const_iterator
CPDF_BasedCS(Family family)
virtual const CPDF_IndexedCS * AsIndexedCS() const
static void InitializeGlobals()
~CPDF_ColorSpace() override
static void DestroyGlobals()
virtual const CPDF_PatternCS * AsPatternCS() const
virtual bool IsNormal() const
virtual void EnableStdConversion(bool bEnabled)
std::vector< float > CreateBufAndSetDefaultColor() const
CPDF_ColorSpace(Family family)
static uint32_t ComponentsForFamily(Family family)
virtual void TranslateImageLine(pdfium::span< uint8_t > dest_span, pdfium::span< const uint8_t > src_span, int pixels, int image_width, int image_height, bool bTransMask) const
static RetainPtr< CPDF_ColorSpace > GetStockCSForName(const ByteString &name)
uint32_t ComponentCount() const
bool HasSameArray(const CPDF_Object *pObj) const
void SetComponentsForStockCS(uint32_t nComponents)
static RetainPtr< CPDF_ColorSpace > GetStockCS(Family family)
virtual void GetDefaultValue(int iComponent, float *value, float *min, float *max) const
std::map< ByteString, RetainPtr< CPDF_Object >, std::less<> > DictMap
virtual ByteString GetString() const
const CPDF_Array * AsArray() const
const CPDF_Stream * AsStream() const
void SetComps(pdfium::span< const float > comps)
PatternValue(const PatternValue &that)
bool operator==(const char *ptr) const
pdfium::CheckedNumeric< int32_t > FX_SAFE_INT32
constexpr uint32_t FXBSTR_ID(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4)
void ReverseRGB(pdfium::span< uint8_t > pDestBuf, pdfium::span< const uint8_t > pSrcBuf, int pixels)
#define NOTREACHED_NORETURN()
#define CONSTRUCT_VIA_MAKE_RETAIN
fxcrt::ByteStringView ByteStringView