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 24 FX_FLOAT NormalizeChannel(FX_FLOAT fVal) { 25 return std::min(std::max(fVal, 0.0f), 1.0f); 26 } 27 28 } // namespace 29 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 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 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 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 82 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 114 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 129 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 153 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 176 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 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 } 236 CPDF_IccProfile::~CPDF_IccProfile() { 237 if (m_pTransform) { 238 CPDF_ModuleMgr::Get()->GetIccModule()->DestroyTransform(m_pTransform); 239 } 240 } 241