7#include "core/fpdfapi/page/cpdf_colorspace.h"
19#include "core/fpdfapi/page/cpdf_devicecs.h"
20#include "core/fpdfapi/page/cpdf_docpagedata.h"
21#include "core/fpdfapi/page/cpdf_function.h"
22#include "core/fpdfapi/page/cpdf_iccprofile.h"
23#include "core/fpdfapi/page/cpdf_indexedcs.h"
24#include "core/fpdfapi/page/cpdf_pattern.h"
25#include "core/fpdfapi/page/cpdf_patterncs.h"
26#include "core/fpdfapi/parser/cpdf_array.h"
27#include "core/fpdfapi/parser/cpdf_dictionary.h"
28#include "core/fpdfapi/parser/cpdf_document.h"
29#include "core/fpdfapi/parser/cpdf_name.h"
30#include "core/fpdfapi/parser/cpdf_object.h"
31#include "core/fpdfapi/parser/cpdf_stream.h"
32#include "core/fpdfapi/parser/fpdf_parser_utility.h"
33#include "core/fxcodec/fx_codec.h"
34#include "core/fxcodec/icc/icc_transform.h"
35#include "core/fxcrt/data_vector.h"
36#include "core/fxcrt/fx_2d_size.h"
37#include "core/fxcrt/fx_memory_wrappers.h"
38#include "core/fxcrt/fx_safe_types.h"
39#include "core/fxcrt/maybe_owned.h"
40#include "core/fxcrt/scoped_set_insertion.h"
41#include "core/fxcrt/span_util.h"
42#include "core/fxcrt/stl_util.h"
43#include "third_party/base/check.h"
44#include "third_party/base/check_op.h"
45#include "third_party/base/containers/contains.h"
46#include "third_party/base/notreached.h"
50constexpr uint8_t kSRGBSamples1[] = {
51 0, 3, 6, 10, 13, 15, 18, 20, 22, 23, 25, 27, 28, 30, 31,
52 32, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
53 48, 49, 49, 50, 51, 52, 53, 53, 54, 55, 56, 56, 57, 58, 58,
54 59, 60, 61, 61, 62, 62, 63, 64, 64, 65, 66, 66, 67, 67, 68,
55 68, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74, 75, 76, 76,
56 77, 77, 78, 78, 79, 79, 79, 80, 80, 81, 81, 82, 82, 83, 83,
57 84, 84, 85, 85, 85, 86, 86, 87, 87, 88, 88, 88, 89, 89, 90,
58 90, 91, 91, 91, 92, 92, 93, 93, 93, 94, 94, 95, 95, 95, 96,
59 96, 97, 97, 97, 98, 98, 98, 99, 99, 99, 100, 100, 101, 101, 101,
60 102, 102, 102, 103, 103, 103, 104, 104, 104, 105, 105, 106, 106, 106, 107,
61 107, 107, 108, 108, 108, 109, 109, 109, 110, 110, 110, 110, 111, 111, 111,
62 112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 115, 116, 116,
63 116, 117, 117, 117, 118, 118, 118, 118, 119, 119, 119, 120,
66constexpr uint8_t kSRGBSamples2[] = {
67 120, 121, 122, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
68 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 149,
69 150, 151, 152, 153, 154, 155, 155, 156, 157, 158, 159, 159, 160, 161, 162,
70 163, 163, 164, 165, 166, 167, 167, 168, 169, 170, 170, 171, 172, 173, 173,
71 174, 175, 175, 176, 177, 178, 178, 179, 180, 180, 181, 182, 182, 183, 184,
72 185, 185, 186, 187, 187, 188, 189, 189, 190, 190, 191, 192, 192, 193, 194,
73 194, 195, 196, 196, 197, 197, 198, 199, 199, 200, 200, 201, 202, 202, 203,
74 203, 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, 210, 210, 211, 212,
75 212, 213, 213, 214, 214, 215, 215, 216, 216, 217, 218, 218, 219, 219, 220,
76 220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 226, 226, 227, 227, 228,
77 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235,
78 236, 236, 237, 237, 238, 238, 238, 239, 239, 240, 240, 241, 241, 242, 242,
79 243, 243, 244, 244, 245, 245, 246, 246, 246, 247, 247, 248, 248, 249, 249,
80 250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 255, 255,
83constexpr size_t kBlackWhitePointCount = 3;
85void GetDefaultBlackPoint(
float* pPoints) {
86 static constexpr float kDefaultValue = 0.0f;
87 for (size_t i = 0; i < kBlackWhitePointCount; ++i)
88 pPoints[i] = kDefaultValue;
91void GetBlackPoint(
const CPDF_Dictionary* pDict,
float* pPoints) {
92 RetainPtr<
const CPDF_Array> pParam = pDict->GetArrayFor(
"BlackPoint");
93 if (!pParam || pParam->size() != kBlackWhitePointCount) {
94 GetDefaultBlackPoint(pPoints);
99 for (size_t i = 0; i < kBlackWhitePointCount; ++i) {
100 pPoints[i] = pParam->GetFloatAt(i);
101 if (pPoints[i] < 0) {
102 GetDefaultBlackPoint(pPoints);
108bool GetWhitePoint(
const CPDF_Dictionary* pDict,
float* pPoints) {
109 RetainPtr<
const CPDF_Array> pParam = pDict->GetArrayFor(
"WhitePoint");
110 if (!pParam || pParam->size() != kBlackWhitePointCount)
113 for (size_t i = 0; i < kBlackWhitePointCount; ++i)
114 pPoints[i] = pParam->GetFloatAt(i);
115 return pPoints[0] > 0.0f && pPoints[1] == 1.0f && pPoints[2] > 0.0f;
121 ~CPDF_CalGray()
override;
124 bool GetRGB(pdfium::span<
const float> pBuf,
127 float* B)
const override;
129 const CPDF_Array* pArray,
130 std::set<
const CPDF_Object*>* pVisited)
override;
131 void TranslateImageLine(pdfium::span<uint8_t> dest_span,
132 pdfium::span<
const uint8_t> src_span,
136 bool bTransMask)
const override;
139 static constexpr float kDefaultGamma = 1.0f;
143 float m_Gamma = kDefaultGamma;
144 float m_WhitePoint[kBlackWhitePointCount] = {1.0f, 1.0f, 1.0f};
145 float m_BlackPoint[kBlackWhitePointCount] = {0.0f, 0.0f, 0.0f};
151 ~CPDF_CalRGB()
override;
154 bool GetRGB(pdfium::span<
const float> pBuf,
157 float* B)
const override;
158 void TranslateImageLine(pdfium::span<uint8_t> dest_span,
159 pdfium::span<
const uint8_t> src_span,
163 bool bTransMask)
const override;
165 const CPDF_Array* pArray,
166 std::set<
const CPDF_Object*>* pVisited)
override;
169 static constexpr size_t kGammaCount = 3;
170 static constexpr size_t kMatrixCount = 9;
174 float m_WhitePoint[kBlackWhitePointCount] = {1.0f, 1.0f, 1.0f};
175 float m_BlackPoint[kBlackWhitePointCount] = {0.0f, 0.0f, 0.0f};
176 float m_Gamma[kGammaCount] = {};
177 float m_Matrix[kMatrixCount] = {};
178 bool m_bHasGamma =
false;
179 bool m_bHasMatrix =
false;
185 ~CPDF_LabCS()
override;
188 bool GetRGB(pdfium::span<
const float> pBuf,
191 float* B)
const override;
192 void GetDefaultValue(
int iComponent,
195 float* max)
const override;
196 void TranslateImageLine(pdfium::span<uint8_t> dest_span,
197 pdfium::span<
const uint8_t> src_span,
201 bool bTransMask)
const override;
203 const CPDF_Array* pArray,
204 std::set<
const CPDF_Object*>* pVisited)
override;
207 static constexpr size_t kRangesCount = 4;
211 float m_WhitePoint[kBlackWhitePointCount] = {1.0f, 1.0f, 1.0f};
212 float m_BlackPoint[kBlackWhitePointCount] = {0.0f, 0.0f, 0.0f};
213 float m_Ranges[kRangesCount] = {};
219 ~CPDF_ICCBasedCS()
override;
222 bool GetRGB(pdfium::span<
const float> pBuf,
225 float* B)
const override;
226 void TranslateImageLine(pdfium::span<uint8_t> dest_span,
227 pdfium::span<
const uint8_t> src_span,
231 bool bTransMask)
const override;
232 bool IsNormal()
const override;
234 const CPDF_Array* pArray,
235 std::set<
const CPDF_Object*>* pVisited)
override;
242 const CPDF_Dictionary* pDict,
243 std::set<
const CPDF_Object*>* pVisited,
244 uint32_t nExpectedComponents);
246 uint32_t nComponents);
247 static std::vector<
float> GetRanges(
const CPDF_Dictionary* pDict,
248 uint32_t nComponents);
251 mutable DataVector<uint8_t> m_pCache;
252 std::vector<
float> m_pRanges;
258 ~CPDF_SeparationCS()
override;
261 bool GetRGB(pdfium::span<
const float> pBuf,
264 float* B)
const override;
265 void GetDefaultValue(
int iComponent,
268 float* max)
const override;
270 const CPDF_Array* pArray,
271 std::set<
const CPDF_Object*>* pVisited)
override;
276 bool m_IsNoneType =
false;
277 std::unique_ptr<
const CPDF_Function> m_pFunc;
283 ~CPDF_DeviceNCS()
override;
286 bool GetRGB(pdfium::span<
const float> pBuf,
289 float* B)
const override;
290 void GetDefaultValue(
int iComponent,
293 float* max)
const override;
295 const CPDF_Array* pArray,
296 std::set<
const CPDF_Object*>* pVisited)
override;
301 std::unique_ptr<
const CPDF_Function> m_pFunc;
306 Vector_3by1() : a(0.0f), b(0.0f), c(0.0f) {}
308 Vector_3by1(
float a1,
float b1,
float c1) : a(a1), b(b1), c(c1) {}
328 Matrix_3by3(
float a1,
337 : a(a1), b(b1), c(c1), d(d1), e(e1), f(f1), g(g1), h(h1), i(i1) {}
339 Matrix_3by3 Inverse() {
340 float det = a * (e * i - f * h) - b * (i * d - f * g) + c * (d * h - e * g);
341 if (fabs(det) <
std::numeric_limits<
float>::epsilon())
342 return Matrix_3by3();
345 (e * i - f * h) / det, -(b * i - c * h) / det, (b * f - c * e) / det,
346 -(d * i - f * g) / det, (a * i - c * g) / det, -(a * f - c * d) / det,
347 (d * h - e * g) / det, -(a * h - b * g) / det, (a * e - b * d) / det);
350 Matrix_3by3 Multiply(
const Matrix_3by3& m) {
351 return Matrix_3by3(a * m.a + b * m.d + c * m.g, a * m.b + b * m.e + c * m.h,
352 a * m.c + b * m.f + c * m.i, d * m.a + e * m.d + f * m.g,
353 d * m.b + e * m.e + f * m.h, d * m.c + e * m.f + f * m.i,
354 g * m.a + h * m.d + i * m.g, g * m.b + h * m.e + i * m.h,
355 g * m.c + h * m.f + i * m.i);
358 Vector_3by1 TransformVector(
const Vector_3by1& v) {
359 return Vector_3by1(a * v.a + b * v.b + c * v.c, d * v.a + e * v.b + f * v.c,
360 g * v.a + h * v.b + i * v.c);
374float RGB_Conversion(
float colorComponent) {
375 colorComponent =
std::clamp(colorComponent, 0.0f, 1.0f);
376 int scale =
std::max(
static_cast<
int>(colorComponent * 1023), 0);
378 return kSRGBSamples1[scale] / 255.0f;
379 return kSRGBSamples2[scale / 4 - 48] / 255.0f;
382void XYZ_to_sRGB(
float X,
float Y,
float Z,
float* R,
float* G,
float* B) {
383 float R1 = 3.2410f * X - 1.5374f * Y - 0.4986f * Z;
384 float G1 = -0.9692f * X + 1.8760f * Y + 0.0416f * Z;
385 float B1 = 0.0556f * X - 0.2040f * Y + 1.0570f * Z;
387 *R = RGB_Conversion(R1);
388 *G = RGB_Conversion(G1);
389 *B = RGB_Conversion(B1);
392void XYZ_to_sRGB_WhitePoint(
float X,
404 constexpr float Rx = 0.64f;
405 constexpr float Ry = 0.33f;
406 constexpr float Gx = 0.30f;
407 constexpr float Gy = 0.60f;
408 constexpr float Bx = 0.15f;
409 constexpr float By = 0.06f;
410 Matrix_3by3 RGB_xyz(Rx, Gx, Bx, Ry, Gy, By, 1 - Rx - Ry, 1 - Gx - Gy,
412 Vector_3by1 whitePoint(Xw, Yw, Zw);
413 Vector_3by1 XYZ(X, Y, Z);
415 Vector_3by1 RGB_Sum_XYZ = RGB_xyz.Inverse().TransformVector(whitePoint);
416 Matrix_3by3 RGB_SUM_XYZ_DIAG(RGB_Sum_XYZ.a, 0, 0, 0, RGB_Sum_XYZ.b, 0, 0, 0,
418 Matrix_3by3 M = RGB_xyz.Multiply(RGB_SUM_XYZ_DIAG);
419 Vector_3by1 RGB = M.Inverse().TransformVector(XYZ);
421 *R = RGB_Conversion(RGB.a);
422 *G = RGB_Conversion(RGB.b);
423 *B = RGB_Conversion(RGB.c);
426class StockColorSpaces {
429 : gray_(pdfium::MakeRetain<CPDF_DeviceCS>(
430 CPDF_ColorSpace::Family::kDeviceGray)),
431 rgb_(pdfium::MakeRetain<CPDF_DeviceCS>(
432 CPDF_ColorSpace::Family::kDeviceRGB)),
433 cmyk_(pdfium::MakeRetain<CPDF_DeviceCS>(
434 CPDF_ColorSpace::Family::kDeviceCMYK)),
435 pattern_(pdfium::MakeRetain<CPDF_PatternCS>()) {
436 pattern_->InitializeStockPattern();
438 StockColorSpaces(
const StockColorSpaces&) =
delete;
439 StockColorSpaces& operator=(
const StockColorSpaces&) =
delete;
440 ~StockColorSpaces() =
default;
455 NOTREACHED_NORETURN();
465StockColorSpaces* g_stock_colorspaces =
nullptr;
476 fxcrt::spancpy(pdfium::make_span(m_Comps), comps);
481 CHECK(!g_stock_colorspaces);
482 g_stock_colorspaces =
new StockColorSpaces();
487 delete g_stock_colorspaces;
488 g_stock_colorspaces =
nullptr;
493 return g_stock_colorspaces->GetStockCS(family);
498 const ByteString& name) {
499 if (name
== "DeviceRGB" || name
== "RGB")
501 if (name
== "DeviceGray" || name
== "G")
503 if (name
== "DeviceCMYK" || name
== "CMYK")
505 if (name
== "Pattern")
514 std::set<
const CPDF_Object*>* pVisited) {
518 if (pdfium::Contains(*pVisited, pObj))
527 RetainPtr<
const CPDF_Dictionary> pDict = pStream->GetDict();
532 for (
const auto& it : locker) {
533 RetainPtr<
const CPDF_Name> pValue = ToName(it.second);
535 RetainPtr<CPDF_ColorSpace> pRet =
536 GetStockCSForName(pValue->GetString());
552 ByteString familyname = pFamilyObj->GetString();
553 if (pArray->size() == 1)
554 return GetStockCSForName(familyname);
557 CPDF_ColorSpace::AllocateColorSpace(familyname.AsStringView());
561 pCS->m_pArray.Reset(pArray);
562 pCS->m_nComponents = pCS->v_Load(pDoc, pArray, pVisited);
563 if (pCS->m_nComponents == 0)
571 ByteStringView bsFamilyName) {
572 switch (bsFamilyName.GetID()) {
574 return pdfium::MakeRetain<CPDF_CalGray>();
576 return pdfium::MakeRetain<CPDF_CalRGB>();
578 return pdfium::MakeRetain<CPDF_LabCS>();
580 return pdfium::MakeRetain<CPDF_ICCBasedCS>();
583 return pdfium::MakeRetain<CPDF_IndexedCS>();
585 return pdfium::MakeRetain<CPDF_SeparationCS>();
587 return pdfium::MakeRetain<CPDF_DeviceNCS>();
589 return pdfium::MakeRetain<CPDF_PatternCS>();
605 NOTREACHED_NORETURN();
610 DCHECK(m_Family != Family::kPattern);
614 std::vector<
float> buf(m_nComponents);
615 for (uint32_t i = 0; i < m_nComponents; i++)
622 return m_nComponents;
635 pdfium::span<
const uint8_t> src_span,
639 bool bTransMask)
const {
640 uint8_t* dest_buf = dest_span.data();
641 const uint8_t* src_buf = src_span.data();
642 std::vector<
float> src(m_nComponents);
647 for (
int i = 0; i < pixels; i++) {
648 for (uint32_t j = 0; j < m_nComponents; j++)
649 src[j] =
static_cast<
float>(*src_buf++) / divisor;
651 *dest_buf++ =
static_cast<int32_t>(B * 255);
652 *dest_buf++ =
static_cast<int32_t>(G * 255);
653 *dest_buf++ =
static_cast<int32_t>(R * 255);
660 else if (m_dwStdConversion)
684 m_nComponents = nComponents;
689CPDF_CalGray::~CPDF_CalGray() =
default;
692 const CPDF_Array* pArray,
693 std::set<
const CPDF_Object*>* pVisited) {
694 RetainPtr<
const CPDF_Dictionary> pDict = pArray->GetDictAt(1);
698 if (!GetWhitePoint(pDict.Get(), m_WhitePoint))
701 GetBlackPoint(pDict.Get(), m_BlackPoint);
703 m_Gamma = pDict->GetFloatFor(
"Gamma");
705 m_Gamma = kDefaultGamma;
709bool CPDF_CalGray::GetRGB(pdfium::span<
const float> pBuf,
719void CPDF_CalGray::TranslateImageLine(pdfium::span<uint8_t> dest_span,
720 pdfium::span<
const uint8_t> src_span,
724 bool bTransMask)
const {
725 uint8_t* pDestBuf = dest_span.data();
726 const uint8_t* pSrcBuf = src_span.data();
727 for (
int i = 0; i < pixels; i++) {
729 const uint8_t pix = pSrcBuf[i];
738CPDF_CalRGB::~CPDF_CalRGB() =
default;
741 const CPDF_Array* pArray,
742 std::set<
const CPDF_Object*>* pVisited) {
743 RetainPtr<
const CPDF_Dictionary> pDict = pArray->GetDictAt(1);
747 if (!GetWhitePoint(pDict.Get(), m_WhitePoint))
750 GetBlackPoint(pDict.Get(), m_BlackPoint);
752 RetainPtr<
const CPDF_Array> pGamma = pDict->GetArrayFor(
"Gamma");
755 for (size_t i = 0; i < std::size(m_Gamma); ++i)
756 m_Gamma[i] = pGamma->GetFloatAt(i);
759 RetainPtr<
const CPDF_Array> pMatrix = pDict->GetArrayFor(
"Matrix");
762 for (size_t i = 0; i < std::size(m_Matrix); ++i)
763 m_Matrix[i] = pMatrix->GetFloatAt(i);
768bool CPDF_CalRGB::GetRGB(pdfium::span<
const float> pBuf,
776 A_ = powf(A_, m_Gamma[0]);
777 B_ = powf(B_, m_Gamma[1]);
778 C_ = powf(C_, m_Gamma[2]);
785 X = m_Matrix[0] * A_ + m_Matrix[3] * B_ + m_Matrix[6] * C_;
786 Y = m_Matrix[1] * A_ + m_Matrix[4] * B_ + m_Matrix[7] * C_;
787 Z = m_Matrix[2] * A_ + m_Matrix[5] * B_ + m_Matrix[8] * C_;
793 XYZ_to_sRGB_WhitePoint(X, Y, Z, m_WhitePoint[0], m_WhitePoint[1],
794 m_WhitePoint[2], R, G, B);
798void CPDF_CalRGB::TranslateImageLine(pdfium::span<uint8_t> dest_span,
799 pdfium::span<
const uint8_t> src_span,
803 bool bTransMask)
const {
804 uint8_t* pDestBuf = dest_span.data();
805 const uint8_t* pSrcBuf = src_span.data();
815 for (
int i = 0; i < pixels; i++) {
816 Cal[0] =
static_cast<
float>(pSrcBuf[2]) / 255;
817 Cal[1] =
static_cast<
float>(pSrcBuf[1]) / 255;
818 Cal[2] =
static_cast<
float>(pSrcBuf[0]) / 255;
819 GetRGB(Cal, &R, &G, &B);
830CPDF_LabCS::~CPDF_LabCS() =
default;
832void CPDF_LabCS::GetDefaultValue(
int iComponent,
836 DCHECK_LT(iComponent, 3);
838 if (iComponent > 0) {
839 float range_min = m_Ranges[iComponent * 2 - 2];
840 float range_max = m_Ranges[iComponent * 2 - 1];
841 if (range_min <= range_max) {
844 *value =
std::clamp(0.0f, *min, *max);
855 const CPDF_Array* pArray,
856 std::set<
const CPDF_Object*>* pVisited) {
857 RetainPtr<
const CPDF_Dictionary> pDict = pArray->GetDictAt(1);
861 if (!GetWhitePoint(pDict.Get(), m_WhitePoint))
864 GetBlackPoint(pDict.Get(), m_BlackPoint);
866 RetainPtr<
const CPDF_Array> pParam = pDict->GetArrayFor(
"Range");
867 static constexpr float kDefaultRanges[kRangesCount] = {-100.0f, 100.0f,
869 static_assert(std::size(kDefaultRanges) == std::extent<
decltype(m_Ranges)>(),
870 "Range size mismatch");
871 for (size_t i = 0; i < std::size(kDefaultRanges); ++i)
872 m_Ranges[i] = pParam ? pParam->GetFloatAt(i) : kDefaultRanges[i];
876bool CPDF_LabCS::GetRGB(pdfium::span<
const float> pBuf,
880 float Lstar = pBuf[0];
881 float astar = pBuf[1];
882 float bstar = pBuf[2];
883 float M = (Lstar + 16.0f) / 116.0f;
884 float L = M + astar / 500.0f;
885 float N = M - bstar / 200.0f;
890 X = 0.957f * 0.12842f * (L - 0.1379f);
892 X = 0.957f * L * L * L;
895 Y = 0.12842f * (M - 0.1379f);
900 Z = 1.0889f * 0.12842f * (N - 0.1379f);
902 Z = 1.0889f * N * N * N;
904 XYZ_to_sRGB(X, Y, Z, R, G, B);
908void CPDF_LabCS::TranslateImageLine(pdfium::span<uint8_t> dest_span,
909 pdfium::span<
const uint8_t> src_span,
913 bool bTransMask)
const {
914 uint8_t* pDestBuf = dest_span.data();
915 const uint8_t* pSrcBuf = src_span.data();
916 for (
int i = 0; i < pixels; i++) {
918 lab[0] = pSrcBuf[0] * 100 / 255.0f;
919 lab[1] = pSrcBuf[1] - 128;
920 lab[2] = pSrcBuf[2] - 128;
925 GetRGB(lab, &R, &G, &B);
926 pDestBuf[0] =
static_cast<int32_t>(B * 255);
927 pDestBuf[1] =
static_cast<int32_t>(G * 255);
928 pDestBuf[2] =
static_cast<int32_t>(R * 255);
936CPDF_ICCBasedCS::~CPDF_ICCBasedCS() =
default;
939 const CPDF_Array* pArray,
940 std::set<
const CPDF_Object*>* pVisited) {
941 RetainPtr<
const CPDF_Stream> pStream = pArray->GetStreamAt(1);
948 RetainPtr<
const CPDF_Dictionary> pDict = pStream->GetDict();
949 const int32_t nDictComponents = pDict ? pDict->GetIntegerFor(
"N") : 0;
955 const uint32_t nComponents =
static_cast<uint32_t>(nDictComponents);
956 m_pProfile = CPDF_DocPageData::FromDocument(pDoc)->GetIccProfile(pStream);
963 if (!m_pProfile->IsSupported() &&
964 !FindAlternateProfile(pDoc, pDict.Get(), pVisited, nComponents)) {
968 m_pBaseCS = GetStockAlternateProfile(nComponents);
971 m_pRanges = GetRanges(pDict.Get(), nComponents);
975bool CPDF_ICCBasedCS::GetRGB(pdfium::span<
const float> pBuf,
980 if (m_pProfile->IsSRGB()) {
986 if (m_pProfile->IsSupported()) {
988 m_pProfile->Translate(pBuf.first(CountComponents()), rgb);
995 return m_pBaseCS->GetRGB(pBuf, R, G, B);
1003void CPDF_ICCBasedCS::TranslateImageLine(pdfium::span<uint8_t> dest_span,
1004 pdfium::span<
const uint8_t> src_span,
1008 bool bTransMask)
const {
1009 if (m_pProfile->IsSRGB()) {
1013 if (!m_pProfile->IsSupported()) {
1015 m_pBaseCS->TranslateImageLine(dest_span, src_span, pixels, image_width,
1016 image_height,
false);
1023 DCHECK(fxcodec::IccTransform::IsValidIccComponents(nComponents));
1025 for (uint32_t i = 0; i < nComponents; i++)
1028 bool bTranslate = nComponents > 3;
1030 FX_SAFE_INT32 nPixelCount = image_width;
1031 nPixelCount *= image_height;
1032 if (nPixelCount.IsValid())
1033 bTranslate = nPixelCount.ValueOrDie() < nMaxColors * 3 / 2;
1035 if (bTranslate && m_pProfile->IsSupported()) {
1036 m_pProfile->TranslateScanline(dest_span, src_span, pixels);
1039 if (m_pCache.empty()) {
1040 m_pCache.resize(Fx2DSizeOrDie(nMaxColors, 3));
1041 DataVector<uint8_t> temp_src(Fx2DSizeOrDie(nMaxColors, nComponents));
1042 size_t src_index = 0;
1043 for (
int i = 0; i < nMaxColors; i++) {
1045 uint32_t order = nMaxColors / 52;
1046 for (uint32_t c = 0; c < nComponents; c++) {
1047 temp_src[src_index++] =
static_cast<uint8_t>(color / order * 5);
1052 if (m_pProfile->IsSupported()) {
1053 m_pProfile->TranslateScanline(m_pCache, temp_src, nMaxColors);
1056 uint8_t* pDestBuf = dest_span.data();
1057 const uint8_t* pSrcBuf = src_span.data();
1058 for (
int i = 0; i < pixels; i++) {
1060 for (uint32_t c = 0; c < nComponents; c++) {
1061 index = index * 52 + (*pSrcBuf) / 5;
1065 *pDestBuf++ = m_pCache[index];
1066 *pDestBuf++ = m_pCache[index + 1];
1067 *pDestBuf++ = m_pCache[index + 2];
1071bool CPDF_ICCBasedCS::IsNormal()
const {
1072 if (m_pProfile->IsSRGB())
1074 if (m_pProfile->IsSupported())
1075 return m_pProfile->IsNormal();
1077 return m_pBaseCS->IsNormal();
1081bool CPDF_ICCBasedCS::FindAlternateProfile(
1083 const CPDF_Dictionary* pDict,
1084 std::set<
const CPDF_Object*>* pVisited,
1085 uint32_t nExpectedComponents) {
1087 pDict->GetDirectObjectFor(
"Alternate");
1091 auto pAlterCS = CPDF_ColorSpace::Load(pDoc, pAlterCSObj.Get(), pVisited);
1098 if (pAlterCS->CountComponents() != nExpectedComponents)
1101 m_pBaseCS = std::move(pAlterCS);
1107 uint32_t nComponents) {
1108 if (nComponents == 1)
1110 if (nComponents == 3)
1112 if (nComponents == 4)
1114 NOTREACHED_NORETURN();
1118std::vector<
float> CPDF_ICCBasedCS::GetRanges(
const CPDF_Dictionary* pDict,
1119 uint32_t nComponents) {
1120 DCHECK(fxcodec::IccTransform::IsValidIccComponents(nComponents));
1121 RetainPtr<
const CPDF_Array> pRanges = pDict->GetArrayFor(
"Range");
1122 if (pRanges && pRanges->size() >= nComponents * 2)
1123 return ReadArrayElementsToVector(pRanges.Get(), nComponents * 2);
1125 std::vector<
float> ranges;
1126 ranges.reserve(nComponents * 2);
1127 for (uint32_t i = 0; i < nComponents; i++) {
1128 ranges.push_back(0.0f);
1129 ranges.push_back(1.0f);
1136CPDF_SeparationCS::~CPDF_SeparationCS() =
default;
1138void CPDF_SeparationCS::GetDefaultValue(
int iComponent,
1148 const CPDF_Array* pArray,
1149 std::set<
const CPDF_Object*>* pVisited) {
1150 m_IsNoneType = pArray->GetByteStringAt(1) ==
"None";
1158 m_pBaseCS = Load(pDoc, pAltArray.Get(), pVisited);
1162 if (m_pBaseCS->IsSpecial())
1166 if (pFuncObj && !pFuncObj->IsName()) {
1167 auto pFunc = CPDF_Function::Load(
std::move(pFuncObj));
1168 if (pFunc && pFunc->CountOutputs() >= m_pBaseCS->CountComponents())
1169 m_pFunc = std::move(pFunc);
1174bool CPDF_SeparationCS::GetRGB(pdfium::span<
const float> pBuf,
1185 int nComps = m_pBaseCS->CountComponents();
1186 std::vector<
float> results(nComps);
1187 for (
int i = 0; i < nComps; i++)
1188 results[i] = pBuf[0];
1189 return m_pBaseCS->GetRGB(results, R, G, B);
1193 std::vector<
float> results(std::max(m_pFunc->CountOutputs(), 16u));
1194 uint32_t nresults = m_pFunc->Call(pBuf.first(1), results).value_or(0);
1199 return m_pBaseCS->GetRGB(results, R, G, B);
1209CPDF_DeviceNCS::~CPDF_DeviceNCS() =
default;
1211void CPDF_DeviceNCS::GetDefaultValue(
int iComponent,
1221 const CPDF_Array* pArray,
1222 std::set<
const CPDF_Object*>* pVisited) {
1223 RetainPtr<
const CPDF_Array> pObj = ToArray(pArray->GetDirectObjectAt(1));
1231 m_pBaseCS = Load(pDoc, pAltCS.Get(), pVisited);
1232 m_pFunc = CPDF_Function::Load(pArray->GetDirectObjectAt(3));
1233 if (!m_pBaseCS || !m_pFunc)
1236 if (m_pBaseCS->IsSpecial())
1239 if (m_pFunc->CountOutputs() < m_pBaseCS->CountComponents())
1242 return fxcrt::CollectionSize<uint32_t>(*pObj);
1245bool CPDF_DeviceNCS::GetRGB(pdfium::span<
const float> pBuf,
1253 std::vector<
float> results(std::max(m_pFunc->CountOutputs(), 16u));
1255 m_pFunc->Call(pBuf.first(CountComponents()), pdfium::make_span(results))
1261 return m_pBaseCS->GetRGB(results, R, G, B);
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)
virtual bool GetRGB(pdfium::span< const float > pBuf, float *R, float *G, float *B) const =0
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)
bool HasSameArray(const CPDF_Object *pObj) const
void SetComponentsForStockCS(uint32_t nComponents)
static RetainPtr< CPDF_ColorSpace > GetStockCS(Family family)
uint32_t CountComponents() const
virtual void GetDefaultValue(int iComponent, float *value, float *min, float *max) const
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
constexpr uint32_t FXBSTR_ID(uint8_t c1, uint8_t c2, uint8_t c3, uint8_t c4)
int FXSYS_roundf(float f)
void ReverseRGB(uint8_t *pDestBuf, const uint8_t *pSrcBuf, int pixels)
#define CONSTRUCT_VIA_MAKE_RETAIN