• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fpdfapi/page/pageint.h"
8 
9 #include <limits.h>
10 
11 #include <algorithm>
12 
13 #include "core/fpdfapi/cpdf_modulemgr.h"
14 #include "core/fpdfapi/parser/cpdf_array.h"
15 #include "core/fpdfapi/parser/cpdf_dictionary.h"
16 #include "core/fpdfapi/parser/cpdf_document.h"
17 #include "core/fpdfapi/parser/cpdf_stream.h"
18 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
19 #include "core/fpdfapi/parser/cpdf_string.h"
20 #include "core/fxcodec/fx_codec.h"
21 
22 namespace {
23 
NormalizeChannel(FX_FLOAT fVal)24 FX_FLOAT NormalizeChannel(FX_FLOAT fVal) {
25   return std::min(std::max(fVal, 0.0f), 1.0f);
26 }
27 
28 }  // namespace
29 
ComponentsForFamily(int family)30 uint32_t ComponentsForFamily(int family) {
31   if (family == PDFCS_DEVICERGB)
32     return 3;
33   if (family == PDFCS_DEVICEGRAY)
34     return 1;
35   ASSERT(family == PDFCS_DEVICECMYK);
36   return 4;
37 }
38 
sRGB_to_AdobeCMYK(FX_FLOAT R,FX_FLOAT G,FX_FLOAT B,FX_FLOAT & c,FX_FLOAT & m,FX_FLOAT & y,FX_FLOAT & k)39 void sRGB_to_AdobeCMYK(FX_FLOAT R,
40                        FX_FLOAT G,
41                        FX_FLOAT B,
42                        FX_FLOAT& c,
43                        FX_FLOAT& m,
44                        FX_FLOAT& y,
45                        FX_FLOAT& k) {
46   c = 1.0f - R;
47   m = 1.0f - G;
48   y = 1.0f - B;
49   k = c;
50   if (m < k) {
51     k = m;
52   }
53   if (y < k) {
54     k = y;
55   }
56 }
57 
ReverseRGB(uint8_t * pDestBuf,const uint8_t * pSrcBuf,int pixels)58 void ReverseRGB(uint8_t* pDestBuf, const uint8_t* pSrcBuf, int pixels) {
59   if (pDestBuf == pSrcBuf) {
60     for (int i = 0; i < pixels; i++) {
61       uint8_t temp = pDestBuf[2];
62       pDestBuf[2] = pDestBuf[0];
63       pDestBuf[0] = temp;
64       pDestBuf += 3;
65     }
66   } else {
67     for (int i = 0; i < pixels; i++) {
68       *pDestBuf++ = pSrcBuf[2];
69       *pDestBuf++ = pSrcBuf[1];
70       *pDestBuf++ = pSrcBuf[0];
71       pSrcBuf += 3;
72     }
73   }
74 }
75 
CPDF_DeviceCS(CPDF_Document * pDoc,int family)76 CPDF_DeviceCS::CPDF_DeviceCS(CPDF_Document* pDoc, int family)
77     : CPDF_ColorSpace(pDoc, family, ComponentsForFamily(family)) {
78   ASSERT(family == PDFCS_DEVICEGRAY || family == PDFCS_DEVICERGB ||
79          family == PDFCS_DEVICECMYK);
80 }
81 
GetRGB(FX_FLOAT * pBuf,FX_FLOAT & R,FX_FLOAT & G,FX_FLOAT & B) const82 bool CPDF_DeviceCS::GetRGB(FX_FLOAT* pBuf,
83                            FX_FLOAT& R,
84                            FX_FLOAT& G,
85                            FX_FLOAT& B) const {
86   switch (m_Family) {
87     case PDFCS_DEVICEGRAY:
88       R = NormalizeChannel(*pBuf);
89       G = R;
90       B = R;
91       break;
92     case PDFCS_DEVICERGB:
93       R = NormalizeChannel(pBuf[0]);
94       G = NormalizeChannel(pBuf[1]);
95       B = NormalizeChannel(pBuf[2]);
96       break;
97     case PDFCS_DEVICECMYK:
98       if (m_dwStdConversion) {
99         FX_FLOAT k = pBuf[3];
100         R = 1.0f - std::min(1.0f, pBuf[0] + k);
101         G = 1.0f - std::min(1.0f, pBuf[1] + k);
102         B = 1.0f - std::min(1.0f, pBuf[2] + k);
103       } else {
104         AdobeCMYK_to_sRGB(pBuf[0], pBuf[1], pBuf[2], pBuf[3], R, G, B);
105       }
106       break;
107     default:
108       ASSERT(false);
109       return false;
110   }
111   return true;
112 }
113 
v_GetCMYK(FX_FLOAT * pBuf,FX_FLOAT & c,FX_FLOAT & m,FX_FLOAT & y,FX_FLOAT & k) const114 bool CPDF_DeviceCS::v_GetCMYK(FX_FLOAT* pBuf,
115                               FX_FLOAT& c,
116                               FX_FLOAT& m,
117                               FX_FLOAT& y,
118                               FX_FLOAT& k) const {
119   if (m_Family != PDFCS_DEVICECMYK)
120     return false;
121 
122   c = pBuf[0];
123   m = pBuf[1];
124   y = pBuf[2];
125   k = pBuf[3];
126   return true;
127 }
128 
SetRGB(FX_FLOAT * pBuf,FX_FLOAT R,FX_FLOAT G,FX_FLOAT B) const129 bool CPDF_DeviceCS::SetRGB(FX_FLOAT* pBuf,
130                            FX_FLOAT R,
131                            FX_FLOAT G,
132                            FX_FLOAT B) const {
133   switch (m_Family) {
134     case PDFCS_DEVICEGRAY:
135       if (R != G || R != B)
136         return false;
137       *pBuf = R;
138       return true;
139     case PDFCS_DEVICERGB:
140       pBuf[0] = R;
141       pBuf[1] = G;
142       pBuf[2] = B;
143       return true;
144     case PDFCS_DEVICECMYK:
145       sRGB_to_AdobeCMYK(R, G, B, pBuf[0], pBuf[1], pBuf[2], pBuf[3]);
146       return true;
147     default:
148       ASSERT(false);
149       return false;
150   }
151 }
152 
v_SetCMYK(FX_FLOAT * pBuf,FX_FLOAT c,FX_FLOAT m,FX_FLOAT y,FX_FLOAT k) const153 bool CPDF_DeviceCS::v_SetCMYK(FX_FLOAT* pBuf,
154                               FX_FLOAT c,
155                               FX_FLOAT m,
156                               FX_FLOAT y,
157                               FX_FLOAT k) const {
158   switch (m_Family) {
159     case PDFCS_DEVICEGRAY:
160       return false;
161     case PDFCS_DEVICERGB:
162       AdobeCMYK_to_sRGB(c, m, y, k, pBuf[0], pBuf[1], pBuf[2]);
163       return true;
164     case PDFCS_DEVICECMYK:
165       pBuf[0] = c;
166       pBuf[1] = m;
167       pBuf[2] = y;
168       pBuf[3] = k;
169       return true;
170     default:
171       ASSERT(false);
172       return false;
173   }
174 }
175 
TranslateImageLine(uint8_t * pDestBuf,const uint8_t * pSrcBuf,int pixels,int image_width,int image_height,bool bTransMask) const176 void CPDF_DeviceCS::TranslateImageLine(uint8_t* pDestBuf,
177                                        const uint8_t* pSrcBuf,
178                                        int pixels,
179                                        int image_width,
180                                        int image_height,
181                                        bool bTransMask) const {
182   switch (m_Family) {
183     case PDFCS_DEVICEGRAY:
184       for (int i = 0; i < pixels; i++) {
185         *pDestBuf++ = pSrcBuf[i];
186         *pDestBuf++ = pSrcBuf[i];
187         *pDestBuf++ = pSrcBuf[i];
188       }
189       break;
190     case PDFCS_DEVICERGB:
191       ReverseRGB(pDestBuf, pSrcBuf, pixels);
192       break;
193     case PDFCS_DEVICECMYK:
194       if (bTransMask) {
195         for (int i = 0; i < pixels; i++) {
196           int k = 255 - pSrcBuf[3];
197           pDestBuf[0] = ((255 - pSrcBuf[0]) * k) / 255;
198           pDestBuf[1] = ((255 - pSrcBuf[1]) * k) / 255;
199           pDestBuf[2] = ((255 - pSrcBuf[2]) * k) / 255;
200           pDestBuf += 3;
201           pSrcBuf += 4;
202         }
203       } else {
204         for (int i = 0; i < pixels; i++) {
205           if (m_dwStdConversion) {
206             uint8_t k = pSrcBuf[3];
207             pDestBuf[2] = 255 - std::min(255, pSrcBuf[0] + k);
208             pDestBuf[1] = 255 - std::min(255, pSrcBuf[1] + k);
209             pDestBuf[0] = 255 - std::min(255, pSrcBuf[2] + k);
210           } else {
211             AdobeCMYK_to_sRGB1(pSrcBuf[0], pSrcBuf[1], pSrcBuf[2], pSrcBuf[3],
212                                pDestBuf[2], pDestBuf[1], pDestBuf[0]);
213           }
214           pSrcBuf += 4;
215           pDestBuf += 3;
216         }
217       }
218       break;
219     default:
220       ASSERT(false);
221       break;
222   }
223 }
224 
CPDF_IccProfile(const uint8_t * pData,uint32_t dwSize)225 CPDF_IccProfile::CPDF_IccProfile(const uint8_t* pData, uint32_t dwSize)
226     : m_bsRGB(false), m_pTransform(nullptr), m_nSrcComponents(0) {
227   if (dwSize == 3144 &&
228       FXSYS_memcmp(pData + 0x190, "sRGB IEC61966-2.1", 17) == 0) {
229     m_bsRGB = true;
230     m_nSrcComponents = 3;
231   } else if (CPDF_ModuleMgr::Get()->GetIccModule()) {
232     m_pTransform = CPDF_ModuleMgr::Get()->GetIccModule()->CreateTransform_sRGB(
233         pData, dwSize, m_nSrcComponents);
234   }
235 }
~CPDF_IccProfile()236 CPDF_IccProfile::~CPDF_IccProfile() {
237   if (m_pTransform) {
238     CPDF_ModuleMgr::Get()->GetIccModule()->DestroyTransform(m_pTransform);
239   }
240 }
241