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/cpdf_devicecs.h"
8
9 #include <limits.h>
10
11 #include <algorithm>
12
13 #include "core/fpdfapi/parser/cpdf_array.h"
14 #include "core/fpdfapi/parser/cpdf_dictionary.h"
15 #include "core/fpdfapi/parser/cpdf_document.h"
16 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
17 #include "core/fpdfapi/parser/cpdf_string.h"
18 #include "core/fxcodec/fx_codec.h"
19 #include "core/fxge/dib/cfx_cmyk_to_srgb.h"
20 #include "third_party/base/logging.h"
21 #include "third_party/base/stl_util.h"
22
23 namespace {
24
NormalizeChannel(float fVal)25 float NormalizeChannel(float fVal) {
26 return pdfium::clamp(fVal, 0.0f, 1.0f);
27 }
28
29 } // namespace
30
CPDF_DeviceCS(int family)31 CPDF_DeviceCS::CPDF_DeviceCS(int family) : CPDF_ColorSpace(nullptr, family) {
32 ASSERT(family == PDFCS_DEVICEGRAY || family == PDFCS_DEVICERGB ||
33 family == PDFCS_DEVICECMYK);
34 SetComponentsForStockCS(ComponentsForFamily(GetFamily()));
35 }
36
37 CPDF_DeviceCS::~CPDF_DeviceCS() = default;
38
v_Load(CPDF_Document * pDoc,const CPDF_Array * pArray,std::set<const CPDF_Object * > * pVisited)39 uint32_t CPDF_DeviceCS::v_Load(CPDF_Document* pDoc,
40 const CPDF_Array* pArray,
41 std::set<const CPDF_Object*>* pVisited) {
42 // Unlike other classes that inherit from CPDF_ColorSpace, CPDF_DeviceCS is
43 // never loaded by CPDF_ColorSpace.
44 NOTREACHED();
45 return 0;
46 }
47
GetRGB(const float * pBuf,float * R,float * G,float * B) const48 bool CPDF_DeviceCS::GetRGB(const float* pBuf,
49 float* R,
50 float* G,
51 float* B) const {
52 switch (m_Family) {
53 case PDFCS_DEVICEGRAY:
54 *R = NormalizeChannel(*pBuf);
55 *G = *R;
56 *B = *R;
57 return true;
58 case PDFCS_DEVICERGB:
59 *R = NormalizeChannel(pBuf[0]);
60 *G = NormalizeChannel(pBuf[1]);
61 *B = NormalizeChannel(pBuf[2]);
62 return true;
63 case PDFCS_DEVICECMYK:
64 if (m_dwStdConversion) {
65 float k = pBuf[3];
66 *R = 1.0f - std::min(1.0f, pBuf[0] + k);
67 *G = 1.0f - std::min(1.0f, pBuf[1] + k);
68 *B = 1.0f - std::min(1.0f, pBuf[2] + k);
69 } else {
70 std::tie(*R, *G, *B) = AdobeCMYK_to_sRGB(
71 NormalizeChannel(pBuf[0]), NormalizeChannel(pBuf[1]),
72 NormalizeChannel(pBuf[2]), NormalizeChannel(pBuf[3]));
73 }
74 return true;
75 default:
76 NOTREACHED();
77 return false;
78 }
79 }
80
TranslateImageLine(uint8_t * pDestBuf,const uint8_t * pSrcBuf,int pixels,int image_width,int image_height,bool bTransMask) const81 void CPDF_DeviceCS::TranslateImageLine(uint8_t* pDestBuf,
82 const uint8_t* pSrcBuf,
83 int pixels,
84 int image_width,
85 int image_height,
86 bool bTransMask) const {
87 switch (m_Family) {
88 case PDFCS_DEVICEGRAY:
89 for (int i = 0; i < pixels; i++) {
90 *pDestBuf++ = pSrcBuf[i];
91 *pDestBuf++ = pSrcBuf[i];
92 *pDestBuf++ = pSrcBuf[i];
93 }
94 break;
95 case PDFCS_DEVICERGB:
96 fxcodec::ReverseRGB(pDestBuf, pSrcBuf, pixels);
97 break;
98 case PDFCS_DEVICECMYK:
99 if (bTransMask) {
100 for (int i = 0; i < pixels; i++) {
101 int k = 255 - pSrcBuf[3];
102 pDestBuf[0] = ((255 - pSrcBuf[0]) * k) / 255;
103 pDestBuf[1] = ((255 - pSrcBuf[1]) * k) / 255;
104 pDestBuf[2] = ((255 - pSrcBuf[2]) * k) / 255;
105 pDestBuf += 3;
106 pSrcBuf += 4;
107 }
108 } else {
109 for (int i = 0; i < pixels; i++) {
110 if (m_dwStdConversion) {
111 uint8_t k = pSrcBuf[3];
112 pDestBuf[2] = 255 - std::min(255, pSrcBuf[0] + k);
113 pDestBuf[1] = 255 - std::min(255, pSrcBuf[1] + k);
114 pDestBuf[0] = 255 - std::min(255, pSrcBuf[2] + k);
115 } else {
116 std::tie(pDestBuf[2], pDestBuf[1], pDestBuf[0]) =
117 AdobeCMYK_to_sRGB1(pSrcBuf[0], pSrcBuf[1], pSrcBuf[2],
118 pSrcBuf[3]);
119 }
120 pSrcBuf += 4;
121 pDestBuf += 3;
122 }
123 }
124 break;
125 default:
126 NOTREACHED();
127 break;
128 }
129 }
130