• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "core/fpdfapi/page/cpdf_indexedcs.h"
6 
7 #include <set>
8 #include <vector>
9 
10 #include "core/fpdfapi/page/cpdf_colorspace.h"
11 #include "core/fpdfapi/page/cpdf_docpagedata.h"
12 #include "core/fpdfapi/parser/cpdf_array.h"
13 #include "core/fpdfapi/parser/cpdf_document.h"
14 #include "core/fpdfapi/parser/cpdf_object.h"
15 #include "core/fpdfapi/parser/cpdf_stream.h"
16 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
17 #include "core/fpdfapi/parser/cpdf_string.h"
18 #include "core/fxcrt/data_vector.h"
19 #include "core/fxcrt/fx_2d_size.h"
20 #include "core/fxcrt/fx_safe_types.h"
21 #include "core/fxcrt/retain_ptr.h"
22 #include "third_party/base/check_op.h"
23 #include "third_party/base/span.h"
24 
CPDF_IndexedCS()25 CPDF_IndexedCS::CPDF_IndexedCS() : CPDF_BasedCS(Family::kIndexed) {}
26 
27 CPDF_IndexedCS::~CPDF_IndexedCS() = default;
28 
AsIndexedCS() const29 const CPDF_IndexedCS* CPDF_IndexedCS::AsIndexedCS() const {
30   return this;
31 }
32 
v_Load(CPDF_Document * pDoc,const CPDF_Array * pArray,std::set<const CPDF_Object * > * pVisited)33 uint32_t CPDF_IndexedCS::v_Load(CPDF_Document* pDoc,
34                                 const CPDF_Array* pArray,
35                                 std::set<const CPDF_Object*>* pVisited) {
36   if (pArray->size() < 4)
37     return 0;
38 
39   RetainPtr<const CPDF_Object> pBaseObj = pArray->GetDirectObjectAt(1);
40   if (HasSameArray(pBaseObj.Get()))
41     return 0;
42 
43   auto* pDocPageData = CPDF_DocPageData::FromDocument(pDoc);
44   m_pBaseCS =
45       pDocPageData->GetColorSpaceGuarded(pBaseObj.Get(), nullptr, pVisited);
46   if (!m_pBaseCS)
47     return 0;
48 
49   // The base color space cannot be a Pattern or Indexed space, according to the
50   // PDF 1.7 spec, page 263.
51   Family family = m_pBaseCS->GetFamily();
52   if (family == Family::kIndexed || family == Family::kPattern)
53     return 0;
54 
55   m_nBaseComponents = m_pBaseCS->CountComponents();
56   DCHECK(m_nBaseComponents);
57   m_pCompMinMax = DataVector<float>(Fx2DSizeOrDie(m_nBaseComponents, 2));
58   float defvalue;
59   for (uint32_t i = 0; i < m_nBaseComponents; i++) {
60     m_pBaseCS->GetDefaultValue(i, &defvalue, &m_pCompMinMax[i * 2],
61                                &m_pCompMinMax[i * 2 + 1]);
62     m_pCompMinMax[i * 2 + 1] -= m_pCompMinMax[i * 2];
63   }
64   m_MaxIndex = pArray->GetIntegerAt(2);
65 
66   RetainPtr<const CPDF_Object> pTableObj = pArray->GetDirectObjectAt(3);
67   if (!pTableObj)
68     return 0;
69 
70   if (const CPDF_String* pString = pTableObj->AsString()) {
71     m_Table = pString->GetString();
72   } else if (const CPDF_Stream* pStream = pTableObj->AsStream()) {
73     auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pdfium::WrapRetain(pStream));
74     pAcc->LoadAllDataFiltered();
75     m_Table = ByteStringView(pAcc->GetSpan());
76   }
77   return 1;
78 }
79 
GetRGB(pdfium::span<const float> pBuf,float * R,float * G,float * B) const80 bool CPDF_IndexedCS::GetRGB(pdfium::span<const float> pBuf,
81                             float* R,
82                             float* G,
83                             float* B) const {
84   int32_t index = static_cast<int32_t>(pBuf[0]);
85   if (index < 0 || index > m_MaxIndex)
86     return false;
87 
88   DCHECK(m_nBaseComponents);
89   DCHECK_EQ(m_nBaseComponents, m_pBaseCS->CountComponents());
90 
91   FX_SAFE_SIZE_T length = index;
92   length += 1;
93   length *= m_nBaseComponents;
94   if (!length.IsValid() || length.ValueOrDie() > m_Table.GetLength()) {
95     *R = 0;
96     *G = 0;
97     *B = 0;
98     return false;
99   }
100 
101   std::vector<float> comps(m_nBaseComponents);
102   const uint8_t* pTable = m_Table.raw_str();
103   for (uint32_t i = 0; i < m_nBaseComponents; ++i) {
104     comps[i] =
105         m_pCompMinMax[i * 2] +
106         m_pCompMinMax[i * 2 + 1] * pTable[index * m_nBaseComponents + i] / 255;
107   }
108   return m_pBaseCS->GetRGB(comps, R, G, B);
109 }
110