1 // Copyright 2016 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_colorspace.h" 8 9 #include <memory> 10 #include <utility> 11 12 #include "core/fpdfapi/cpdf_modulemgr.h" 13 #include "core/fpdfapi/page/cpdf_docpagedata.h" 14 #include "core/fpdfapi/page/cpdf_pagemodule.h" 15 #include "core/fpdfapi/parser/cpdf_array.h" 16 #include "core/fpdfapi/parser/cpdf_dictionary.h" 17 #include "core/fpdfapi/parser/cpdf_document.h" 18 #include "core/fpdfapi/parser/cpdf_name.h" 19 #include "core/fpdfapi/parser/cpdf_object.h" 20 #include "core/fpdfapi/parser/cpdf_stream.h" 21 #include "core/fpdfapi/parser/cpdf_stream_acc.h" 22 #include "core/fpdfapi/parser/cpdf_string.h" 23 #include "core/fxcodec/fx_codec.h" 24 #include "core/fxcrt/cfx_maybe_owned.h" 25 #include "core/fxcrt/fx_memory.h" 26 27 namespace { 28 29 const uint8_t g_sRGBSamples1[] = { 30 0, 3, 6, 10, 13, 15, 18, 20, 22, 23, 25, 27, 28, 30, 31, 31 32, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 32 48, 49, 49, 50, 51, 52, 53, 53, 54, 55, 56, 56, 57, 58, 58, 33 59, 60, 61, 61, 62, 62, 63, 64, 64, 65, 66, 66, 67, 67, 68, 34 68, 69, 70, 70, 71, 71, 72, 72, 73, 73, 74, 74, 75, 76, 76, 35 77, 77, 78, 78, 79, 79, 79, 80, 80, 81, 81, 82, 82, 83, 83, 36 84, 84, 85, 85, 85, 86, 86, 87, 87, 88, 88, 88, 89, 89, 90, 37 90, 91, 91, 91, 92, 92, 93, 93, 93, 94, 94, 95, 95, 95, 96, 38 96, 97, 97, 97, 98, 98, 98, 99, 99, 99, 100, 100, 101, 101, 101, 39 102, 102, 102, 103, 103, 103, 104, 104, 104, 105, 105, 106, 106, 106, 107, 40 107, 107, 108, 108, 108, 109, 109, 109, 110, 110, 110, 110, 111, 111, 111, 41 112, 112, 112, 113, 113, 113, 114, 114, 114, 115, 115, 115, 115, 116, 116, 42 116, 117, 117, 117, 118, 118, 118, 118, 119, 119, 119, 120, 43 }; 44 45 const uint8_t g_sRGBSamples2[] = { 46 120, 121, 122, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 47 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 149, 48 150, 151, 152, 153, 154, 155, 155, 156, 157, 158, 159, 159, 160, 161, 162, 49 163, 163, 164, 165, 166, 167, 167, 168, 169, 170, 170, 171, 172, 173, 173, 50 174, 175, 175, 176, 177, 178, 178, 179, 180, 180, 181, 182, 182, 183, 184, 51 185, 185, 186, 187, 187, 188, 189, 189, 190, 190, 191, 192, 192, 193, 194, 52 194, 195, 196, 196, 197, 197, 198, 199, 199, 200, 200, 201, 202, 202, 203, 53 203, 204, 205, 205, 206, 206, 207, 208, 208, 209, 209, 210, 210, 211, 212, 54 212, 213, 213, 214, 214, 215, 215, 216, 216, 217, 218, 218, 219, 219, 220, 55 220, 221, 221, 222, 222, 223, 223, 224, 224, 225, 226, 226, 227, 227, 228, 56 228, 229, 229, 230, 230, 231, 231, 232, 232, 233, 233, 234, 234, 235, 235, 57 236, 236, 237, 237, 238, 238, 238, 239, 239, 240, 240, 241, 241, 242, 242, 58 243, 243, 244, 244, 245, 245, 246, 246, 246, 247, 247, 248, 248, 249, 249, 59 250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 255, 255, 60 }; 61 62 class CPDF_CalGray : public CPDF_ColorSpace { 63 public: 64 explicit CPDF_CalGray(CPDF_Document* pDoc); 65 66 bool v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override; 67 68 bool GetRGB(FX_FLOAT* pBuf, 69 FX_FLOAT& R, 70 FX_FLOAT& G, 71 FX_FLOAT& B) const override; 72 bool SetRGB(FX_FLOAT* pBuf, 73 FX_FLOAT R, 74 FX_FLOAT G, 75 FX_FLOAT B) const override; 76 77 void TranslateImageLine(uint8_t* pDestBuf, 78 const uint8_t* pSrcBuf, 79 int pixels, 80 int image_width, 81 int image_height, 82 bool bTransMask = false) const override; 83 84 private: 85 FX_FLOAT m_WhitePoint[3]; 86 FX_FLOAT m_BlackPoint[3]; 87 FX_FLOAT m_Gamma; 88 }; 89 90 class CPDF_CalRGB : public CPDF_ColorSpace { 91 public: 92 explicit CPDF_CalRGB(CPDF_Document* pDoc); 93 94 bool v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override; 95 96 bool GetRGB(FX_FLOAT* pBuf, 97 FX_FLOAT& R, 98 FX_FLOAT& G, 99 FX_FLOAT& B) const override; 100 bool SetRGB(FX_FLOAT* pBuf, 101 FX_FLOAT R, 102 FX_FLOAT G, 103 FX_FLOAT B) const override; 104 105 void TranslateImageLine(uint8_t* pDestBuf, 106 const uint8_t* pSrcBuf, 107 int pixels, 108 int image_width, 109 int image_height, 110 bool bTransMask = false) const override; 111 112 FX_FLOAT m_WhitePoint[3]; 113 FX_FLOAT m_BlackPoint[3]; 114 FX_FLOAT m_Gamma[3]; 115 FX_FLOAT m_Matrix[9]; 116 bool m_bGamma; 117 bool m_bMatrix; 118 }; 119 120 class CPDF_LabCS : public CPDF_ColorSpace { 121 public: 122 explicit CPDF_LabCS(CPDF_Document* pDoc); 123 124 bool v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override; 125 126 void GetDefaultValue(int iComponent, 127 FX_FLOAT& value, 128 FX_FLOAT& min, 129 FX_FLOAT& max) const override; 130 bool GetRGB(FX_FLOAT* pBuf, 131 FX_FLOAT& R, 132 FX_FLOAT& G, 133 FX_FLOAT& B) const override; 134 bool SetRGB(FX_FLOAT* pBuf, 135 FX_FLOAT R, 136 FX_FLOAT G, 137 FX_FLOAT B) const override; 138 139 void TranslateImageLine(uint8_t* pDestBuf, 140 const uint8_t* pSrcBuf, 141 int pixels, 142 int image_width, 143 int image_height, 144 bool bTransMask = false) const override; 145 146 FX_FLOAT m_WhitePoint[3]; 147 FX_FLOAT m_BlackPoint[3]; 148 FX_FLOAT m_Ranges[4]; 149 }; 150 151 class CPDF_ICCBasedCS : public CPDF_ColorSpace { 152 public: 153 explicit CPDF_ICCBasedCS(CPDF_Document* pDoc); 154 ~CPDF_ICCBasedCS() override; 155 156 bool v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override; 157 158 bool GetRGB(FX_FLOAT* pBuf, 159 FX_FLOAT& R, 160 FX_FLOAT& G, 161 FX_FLOAT& B) const override; 162 bool SetRGB(FX_FLOAT* pBuf, 163 FX_FLOAT R, 164 FX_FLOAT G, 165 FX_FLOAT B) const override; 166 167 bool v_GetCMYK(FX_FLOAT* pBuf, 168 FX_FLOAT& c, 169 FX_FLOAT& m, 170 FX_FLOAT& y, 171 FX_FLOAT& k) const override; 172 173 void EnableStdConversion(bool bEnabled) override; 174 void TranslateImageLine(uint8_t* pDestBuf, 175 const uint8_t* pSrcBuf, 176 int pixels, 177 int image_width, 178 int image_height, 179 bool bTransMask = false) const override; 180 181 CFX_MaybeOwned<CPDF_ColorSpace> m_pAlterCS; 182 CPDF_IccProfile* m_pProfile; 183 uint8_t* m_pCache; 184 FX_FLOAT* m_pRanges; 185 }; 186 187 class CPDF_IndexedCS : public CPDF_ColorSpace { 188 public: 189 explicit CPDF_IndexedCS(CPDF_Document* pDoc); 190 ~CPDF_IndexedCS() override; 191 192 bool v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override; 193 194 bool GetRGB(FX_FLOAT* pBuf, 195 FX_FLOAT& R, 196 FX_FLOAT& G, 197 FX_FLOAT& B) const override; 198 CPDF_ColorSpace* GetBaseCS() const override; 199 200 void EnableStdConversion(bool bEnabled) override; 201 202 CPDF_ColorSpace* m_pBaseCS; 203 CPDF_CountedColorSpace* m_pCountedBaseCS; 204 int m_nBaseComponents; 205 int m_MaxIndex; 206 CFX_ByteString m_Table; 207 FX_FLOAT* m_pCompMinMax; 208 }; 209 210 class CPDF_SeparationCS : public CPDF_ColorSpace { 211 public: 212 explicit CPDF_SeparationCS(CPDF_Document* pDoc); 213 ~CPDF_SeparationCS() override; 214 215 // CPDF_ColorSpace: 216 void GetDefaultValue(int iComponent, 217 FX_FLOAT& value, 218 FX_FLOAT& min, 219 FX_FLOAT& max) const override; 220 bool v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override; 221 bool GetRGB(FX_FLOAT* pBuf, 222 FX_FLOAT& R, 223 FX_FLOAT& G, 224 FX_FLOAT& B) const override; 225 void EnableStdConversion(bool bEnabled) override; 226 227 std::unique_ptr<CPDF_ColorSpace> m_pAltCS; 228 std::unique_ptr<CPDF_Function> m_pFunc; 229 enum { None, All, Colorant } m_Type; 230 }; 231 232 class CPDF_DeviceNCS : public CPDF_ColorSpace { 233 public: 234 explicit CPDF_DeviceNCS(CPDF_Document* pDoc); 235 ~CPDF_DeviceNCS() override; 236 237 // CPDF_ColorSpace: 238 void GetDefaultValue(int iComponent, 239 FX_FLOAT& value, 240 FX_FLOAT& min, 241 FX_FLOAT& max) const override; 242 bool v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) override; 243 bool GetRGB(FX_FLOAT* pBuf, 244 FX_FLOAT& R, 245 FX_FLOAT& G, 246 FX_FLOAT& B) const override; 247 void EnableStdConversion(bool bEnabled) override; 248 249 std::unique_ptr<CPDF_ColorSpace> m_pAltCS; 250 std::unique_ptr<CPDF_Function> m_pFunc; 251 }; 252 253 FX_FLOAT RGB_Conversion(FX_FLOAT colorComponent) { 254 if (colorComponent > 1) 255 colorComponent = 1; 256 if (colorComponent < 0) 257 colorComponent = 0; 258 259 int scale = (int)(colorComponent * 1023); 260 if (scale < 0) 261 scale = 0; 262 if (scale < 192) 263 colorComponent = (g_sRGBSamples1[scale] / 255.0f); 264 else 265 colorComponent = (g_sRGBSamples2[scale / 4 - 48] / 255.0f); 266 return colorComponent; 267 } 268 269 void XYZ_to_sRGB(FX_FLOAT X, 270 FX_FLOAT Y, 271 FX_FLOAT Z, 272 FX_FLOAT& R, 273 FX_FLOAT& G, 274 FX_FLOAT& B) { 275 FX_FLOAT R1 = 3.2410f * X - 1.5374f * Y - 0.4986f * Z; 276 FX_FLOAT G1 = -0.9692f * X + 1.8760f * Y + 0.0416f * Z; 277 FX_FLOAT B1 = 0.0556f * X - 0.2040f * Y + 1.0570f * Z; 278 279 R = RGB_Conversion(R1); 280 G = RGB_Conversion(G1); 281 B = RGB_Conversion(B1); 282 } 283 284 void XYZ_to_sRGB_WhitePoint(FX_FLOAT X, 285 FX_FLOAT Y, 286 FX_FLOAT Z, 287 FX_FLOAT& R, 288 FX_FLOAT& G, 289 FX_FLOAT& B, 290 FX_FLOAT Xw, 291 FX_FLOAT Yw, 292 FX_FLOAT Zw) { 293 // The following RGB_xyz is based on 294 // sRGB value {Rx,Ry}={0.64, 0.33}, {Gx,Gy}={0.30, 0.60}, {Bx,By}={0.15, 0.06} 295 296 FX_FLOAT Rx = 0.64f, Ry = 0.33f; 297 FX_FLOAT Gx = 0.30f, Gy = 0.60f; 298 FX_FLOAT Bx = 0.15f, By = 0.06f; 299 CFX_Matrix_3by3 RGB_xyz(Rx, Gx, Bx, Ry, Gy, By, 1 - Rx - Ry, 1 - Gx - Gy, 300 1 - Bx - By); 301 CFX_Vector_3by1 whitePoint(Xw, Yw, Zw); 302 CFX_Vector_3by1 XYZ(X, Y, Z); 303 304 CFX_Vector_3by1 RGB_Sum_XYZ = RGB_xyz.Inverse().TransformVector(whitePoint); 305 CFX_Matrix_3by3 RGB_SUM_XYZ_DIAG(RGB_Sum_XYZ.a, 0, 0, 0, RGB_Sum_XYZ.b, 0, 0, 306 0, RGB_Sum_XYZ.c); 307 CFX_Matrix_3by3 M = RGB_xyz.Multiply(RGB_SUM_XYZ_DIAG); 308 CFX_Vector_3by1 RGB = M.Inverse().TransformVector(XYZ); 309 310 R = RGB_Conversion(RGB.a); 311 G = RGB_Conversion(RGB.b); 312 B = RGB_Conversion(RGB.c); 313 } 314 315 } // namespace 316 317 CPDF_ColorSpace* CPDF_ColorSpace::ColorspaceFromName( 318 const CFX_ByteString& name) { 319 if (name == "DeviceRGB" || name == "RGB") 320 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB); 321 if (name == "DeviceGray" || name == "G") 322 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY); 323 if (name == "DeviceCMYK" || name == "CMYK") 324 return CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK); 325 if (name == "Pattern") 326 return CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN); 327 return nullptr; 328 } 329 330 CPDF_ColorSpace* CPDF_ColorSpace::GetStockCS(int family) { 331 return CPDF_ModuleMgr::Get()->GetPageModule()->GetStockCS(family); 332 } 333 334 std::unique_ptr<CPDF_ColorSpace> CPDF_ColorSpace::Load(CPDF_Document* pDoc, 335 CPDF_Object* pObj) { 336 if (!pObj) 337 return nullptr; 338 339 if (pObj->IsName()) { 340 return std::unique_ptr<CPDF_ColorSpace>( 341 ColorspaceFromName(pObj->GetString())); 342 } 343 if (CPDF_Stream* pStream = pObj->AsStream()) { 344 CPDF_Dictionary* pDict = pStream->GetDict(); 345 if (!pDict) 346 return nullptr; 347 348 for (const auto& it : *pDict) { 349 std::unique_ptr<CPDF_ColorSpace> pRet; 350 CPDF_Object* pValue = it.second.get(); 351 if (ToName(pValue)) 352 pRet.reset(ColorspaceFromName(pValue->GetString())); 353 if (pRet) 354 return pRet; 355 } 356 return nullptr; 357 } 358 359 CPDF_Array* pArray = pObj->AsArray(); 360 if (!pArray || pArray->IsEmpty()) 361 return nullptr; 362 363 CPDF_Object* pFamilyObj = pArray->GetDirectObjectAt(0); 364 if (!pFamilyObj) 365 return nullptr; 366 367 CFX_ByteString familyname = pFamilyObj->GetString(); 368 if (pArray->GetCount() == 1) 369 return std::unique_ptr<CPDF_ColorSpace>(ColorspaceFromName(familyname)); 370 371 std::unique_ptr<CPDF_ColorSpace> pCS; 372 uint32_t id = familyname.GetID(); 373 if (id == FXBSTR_ID('C', 'a', 'l', 'G')) { 374 pCS.reset(new CPDF_CalGray(pDoc)); 375 } else if (id == FXBSTR_ID('C', 'a', 'l', 'R')) { 376 pCS.reset(new CPDF_CalRGB(pDoc)); 377 } else if (id == FXBSTR_ID('L', 'a', 'b', 0)) { 378 pCS.reset(new CPDF_LabCS(pDoc)); 379 } else if (id == FXBSTR_ID('I', 'C', 'C', 'B')) { 380 pCS.reset(new CPDF_ICCBasedCS(pDoc)); 381 } else if (id == FXBSTR_ID('I', 'n', 'd', 'e') || 382 id == FXBSTR_ID('I', 0, 0, 0)) { 383 pCS.reset(new CPDF_IndexedCS(pDoc)); 384 } else if (id == FXBSTR_ID('S', 'e', 'p', 'a')) { 385 pCS.reset(new CPDF_SeparationCS(pDoc)); 386 } else if (id == FXBSTR_ID('D', 'e', 'v', 'i')) { 387 pCS.reset(new CPDF_DeviceNCS(pDoc)); 388 } else if (id == FXBSTR_ID('P', 'a', 't', 't')) { 389 pCS.reset(new CPDF_PatternCS(pDoc)); 390 } else { 391 return nullptr; 392 } 393 pCS->m_pArray = pArray; 394 if (!pCS->v_Load(pDoc, pArray)) 395 return nullptr; 396 397 return pCS; 398 } 399 400 void CPDF_ColorSpace::Release() { 401 if (this == GetStockCS(PDFCS_DEVICERGB) || 402 this == GetStockCS(PDFCS_DEVICEGRAY) || 403 this == GetStockCS(PDFCS_DEVICECMYK) || 404 this == GetStockCS(PDFCS_PATTERN)) { 405 return; 406 } 407 delete this; 408 } 409 410 int CPDF_ColorSpace::GetBufSize() const { 411 if (m_Family == PDFCS_PATTERN) { 412 return sizeof(PatternValue); 413 } 414 return m_nComponents * sizeof(FX_FLOAT); 415 } 416 417 FX_FLOAT* CPDF_ColorSpace::CreateBuf() { 418 int size = GetBufSize(); 419 uint8_t* pBuf = FX_Alloc(uint8_t, size); 420 return (FX_FLOAT*)pBuf; 421 } 422 423 bool CPDF_ColorSpace::sRGB() const { 424 if (m_Family == PDFCS_DEVICERGB) { 425 return true; 426 } 427 if (m_Family != PDFCS_ICCBASED) { 428 return false; 429 } 430 CPDF_ICCBasedCS* pCS = (CPDF_ICCBasedCS*)this; 431 return pCS->m_pProfile->m_bsRGB; 432 } 433 434 bool CPDF_ColorSpace::SetRGB(FX_FLOAT* pBuf, 435 FX_FLOAT R, 436 FX_FLOAT G, 437 FX_FLOAT B) const { 438 return false; 439 } 440 441 bool CPDF_ColorSpace::GetCMYK(FX_FLOAT* pBuf, 442 FX_FLOAT& c, 443 FX_FLOAT& m, 444 FX_FLOAT& y, 445 FX_FLOAT& k) const { 446 if (v_GetCMYK(pBuf, c, m, y, k)) { 447 return true; 448 } 449 FX_FLOAT R, G, B; 450 if (!GetRGB(pBuf, R, G, B)) { 451 return false; 452 } 453 sRGB_to_AdobeCMYK(R, G, B, c, m, y, k); 454 return true; 455 } 456 457 bool CPDF_ColorSpace::SetCMYK(FX_FLOAT* pBuf, 458 FX_FLOAT c, 459 FX_FLOAT m, 460 FX_FLOAT y, 461 FX_FLOAT k) const { 462 if (v_SetCMYK(pBuf, c, m, y, k)) { 463 return true; 464 } 465 FX_FLOAT R, G, B; 466 AdobeCMYK_to_sRGB(c, m, y, k, R, G, B); 467 return SetRGB(pBuf, R, G, B); 468 } 469 470 void CPDF_ColorSpace::GetDefaultColor(FX_FLOAT* buf) const { 471 if (!buf || m_Family == PDFCS_PATTERN) { 472 return; 473 } 474 FX_FLOAT min, max; 475 for (uint32_t i = 0; i < m_nComponents; i++) { 476 GetDefaultValue(i, buf[i], min, max); 477 } 478 } 479 480 uint32_t CPDF_ColorSpace::CountComponents() const { 481 return m_nComponents; 482 } 483 484 void CPDF_ColorSpace::GetDefaultValue(int iComponent, 485 FX_FLOAT& value, 486 FX_FLOAT& min, 487 FX_FLOAT& max) const { 488 value = 0; 489 min = 0; 490 max = 1.0f; 491 } 492 493 void CPDF_ColorSpace::TranslateImageLine(uint8_t* dest_buf, 494 const uint8_t* src_buf, 495 int pixels, 496 int image_width, 497 int image_height, 498 bool bTransMask) const { 499 CFX_FixedBufGrow<FX_FLOAT, 16> srcbuf(m_nComponents); 500 FX_FLOAT* src = srcbuf; 501 FX_FLOAT R, G, B; 502 for (int i = 0; i < pixels; i++) { 503 for (uint32_t j = 0; j < m_nComponents; j++) 504 if (m_Family == PDFCS_INDEXED) { 505 src[j] = (FX_FLOAT)(*src_buf++); 506 } else { 507 src[j] = (FX_FLOAT)(*src_buf++) / 255; 508 } 509 GetRGB(src, R, G, B); 510 *dest_buf++ = (int32_t)(B * 255); 511 *dest_buf++ = (int32_t)(G * 255); 512 *dest_buf++ = (int32_t)(R * 255); 513 } 514 } 515 516 CPDF_ColorSpace* CPDF_ColorSpace::GetBaseCS() const { 517 return nullptr; 518 } 519 520 void CPDF_ColorSpace::EnableStdConversion(bool bEnabled) { 521 if (bEnabled) 522 m_dwStdConversion++; 523 else if (m_dwStdConversion) 524 m_dwStdConversion--; 525 } 526 527 CPDF_ColorSpace::CPDF_ColorSpace(CPDF_Document* pDoc, 528 int family, 529 uint32_t nComponents) 530 : m_pDocument(pDoc), 531 m_Family(family), 532 m_nComponents(nComponents), 533 m_pArray(nullptr), 534 m_dwStdConversion(0) {} 535 536 CPDF_ColorSpace::~CPDF_ColorSpace() {} 537 538 bool CPDF_ColorSpace::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { 539 return true; 540 } 541 542 bool CPDF_ColorSpace::v_GetCMYK(FX_FLOAT* pBuf, 543 FX_FLOAT& c, 544 FX_FLOAT& m, 545 FX_FLOAT& y, 546 FX_FLOAT& k) const { 547 return false; 548 } 549 550 bool CPDF_ColorSpace::v_SetCMYK(FX_FLOAT* pBuf, 551 FX_FLOAT c, 552 FX_FLOAT m, 553 FX_FLOAT y, 554 FX_FLOAT k) const { 555 return false; 556 } 557 558 CPDF_CalGray::CPDF_CalGray(CPDF_Document* pDoc) 559 : CPDF_ColorSpace(pDoc, PDFCS_CALGRAY, 1) {} 560 561 bool CPDF_CalGray::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { 562 CPDF_Dictionary* pDict = pArray->GetDictAt(1); 563 if (!pDict) 564 return false; 565 566 CPDF_Array* pParam = pDict->GetArrayFor("WhitePoint"); 567 int i; 568 for (i = 0; i < 3; i++) 569 m_WhitePoint[i] = pParam ? pParam->GetNumberAt(i) : 0; 570 571 pParam = pDict->GetArrayFor("BlackPoint"); 572 for (i = 0; i < 3; i++) 573 m_BlackPoint[i] = pParam ? pParam->GetNumberAt(i) : 0; 574 575 m_Gamma = pDict->GetNumberFor("Gamma"); 576 if (m_Gamma == 0) 577 m_Gamma = 1.0f; 578 return true; 579 } 580 581 bool CPDF_CalGray::GetRGB(FX_FLOAT* pBuf, 582 FX_FLOAT& R, 583 FX_FLOAT& G, 584 FX_FLOAT& B) const { 585 R = G = B = *pBuf; 586 return true; 587 } 588 589 bool CPDF_CalGray::SetRGB(FX_FLOAT* pBuf, 590 FX_FLOAT R, 591 FX_FLOAT G, 592 FX_FLOAT B) const { 593 if (R == G && R == B) { 594 *pBuf = R; 595 return true; 596 } 597 return false; 598 } 599 600 void CPDF_CalGray::TranslateImageLine(uint8_t* pDestBuf, 601 const uint8_t* pSrcBuf, 602 int pixels, 603 int image_width, 604 int image_height, 605 bool bTransMask) const { 606 for (int i = 0; i < pixels; i++) { 607 *pDestBuf++ = pSrcBuf[i]; 608 *pDestBuf++ = pSrcBuf[i]; 609 *pDestBuf++ = pSrcBuf[i]; 610 } 611 } 612 613 CPDF_CalRGB::CPDF_CalRGB(CPDF_Document* pDoc) 614 : CPDF_ColorSpace(pDoc, PDFCS_CALRGB, 3) {} 615 616 bool CPDF_CalRGB::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { 617 CPDF_Dictionary* pDict = pArray->GetDictAt(1); 618 if (!pDict) 619 return false; 620 621 CPDF_Array* pParam = pDict->GetArrayFor("WhitePoint"); 622 int i; 623 for (i = 0; i < 3; i++) 624 m_WhitePoint[i] = pParam ? pParam->GetNumberAt(i) : 0; 625 626 pParam = pDict->GetArrayFor("BlackPoint"); 627 for (i = 0; i < 3; i++) 628 m_BlackPoint[i] = pParam ? pParam->GetNumberAt(i) : 0; 629 630 pParam = pDict->GetArrayFor("Gamma"); 631 if (pParam) { 632 m_bGamma = true; 633 for (i = 0; i < 3; i++) 634 m_Gamma[i] = pParam->GetNumberAt(i); 635 } else { 636 m_bGamma = false; 637 } 638 639 pParam = pDict->GetArrayFor("Matrix"); 640 if (pParam) { 641 m_bMatrix = true; 642 for (i = 0; i < 9; i++) 643 m_Matrix[i] = pParam->GetNumberAt(i); 644 } else { 645 m_bMatrix = false; 646 } 647 return true; 648 } 649 650 bool CPDF_CalRGB::GetRGB(FX_FLOAT* pBuf, 651 FX_FLOAT& R, 652 FX_FLOAT& G, 653 FX_FLOAT& B) const { 654 FX_FLOAT A_ = pBuf[0]; 655 FX_FLOAT B_ = pBuf[1]; 656 FX_FLOAT C_ = pBuf[2]; 657 if (m_bGamma) { 658 A_ = (FX_FLOAT)FXSYS_pow(A_, m_Gamma[0]); 659 B_ = (FX_FLOAT)FXSYS_pow(B_, m_Gamma[1]); 660 C_ = (FX_FLOAT)FXSYS_pow(C_, m_Gamma[2]); 661 } 662 663 FX_FLOAT X; 664 FX_FLOAT Y; 665 FX_FLOAT Z; 666 if (m_bMatrix) { 667 X = m_Matrix[0] * A_ + m_Matrix[3] * B_ + m_Matrix[6] * C_; 668 Y = m_Matrix[1] * A_ + m_Matrix[4] * B_ + m_Matrix[7] * C_; 669 Z = m_Matrix[2] * A_ + m_Matrix[5] * B_ + m_Matrix[8] * C_; 670 } else { 671 X = A_; 672 Y = B_; 673 Z = C_; 674 } 675 XYZ_to_sRGB_WhitePoint(X, Y, Z, R, G, B, m_WhitePoint[0], m_WhitePoint[1], 676 m_WhitePoint[2]); 677 return true; 678 } 679 680 bool CPDF_CalRGB::SetRGB(FX_FLOAT* pBuf, 681 FX_FLOAT R, 682 FX_FLOAT G, 683 FX_FLOAT B) const { 684 pBuf[0] = R; 685 pBuf[1] = G; 686 pBuf[2] = B; 687 return true; 688 } 689 690 void CPDF_CalRGB::TranslateImageLine(uint8_t* pDestBuf, 691 const uint8_t* pSrcBuf, 692 int pixels, 693 int image_width, 694 int image_height, 695 bool bTransMask) const { 696 if (bTransMask) { 697 FX_FLOAT Cal[3]; 698 FX_FLOAT R; 699 FX_FLOAT G; 700 FX_FLOAT B; 701 for (int i = 0; i < pixels; i++) { 702 Cal[0] = ((FX_FLOAT)pSrcBuf[2]) / 255; 703 Cal[1] = ((FX_FLOAT)pSrcBuf[1]) / 255; 704 Cal[2] = ((FX_FLOAT)pSrcBuf[0]) / 255; 705 GetRGB(Cal, R, G, B); 706 pDestBuf[0] = FXSYS_round(B * 255); 707 pDestBuf[1] = FXSYS_round(G * 255); 708 pDestBuf[2] = FXSYS_round(R * 255); 709 pSrcBuf += 3; 710 pDestBuf += 3; 711 } 712 } 713 ReverseRGB(pDestBuf, pSrcBuf, pixels); 714 } 715 716 CPDF_LabCS::CPDF_LabCS(CPDF_Document* pDoc) 717 : CPDF_ColorSpace(pDoc, PDFCS_LAB, 3) {} 718 719 void CPDF_LabCS::GetDefaultValue(int iComponent, 720 FX_FLOAT& value, 721 FX_FLOAT& min, 722 FX_FLOAT& max) const { 723 ASSERT(iComponent < 3); 724 value = 0; 725 if (iComponent == 0) { 726 min = 0; 727 max = 100 * 1.0f; 728 } else { 729 min = m_Ranges[iComponent * 2 - 2]; 730 max = m_Ranges[iComponent * 2 - 1]; 731 if (value < min) 732 value = min; 733 else if (value > max) 734 value = max; 735 } 736 } 737 738 bool CPDF_LabCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { 739 CPDF_Dictionary* pDict = pArray->GetDictAt(1); 740 if (!pDict) 741 return false; 742 743 CPDF_Array* pParam = pDict->GetArrayFor("WhitePoint"); 744 int i; 745 for (i = 0; i < 3; i++) 746 m_WhitePoint[i] = pParam ? pParam->GetNumberAt(i) : 0; 747 748 pParam = pDict->GetArrayFor("BlackPoint"); 749 for (i = 0; i < 3; i++) 750 m_BlackPoint[i] = pParam ? pParam->GetNumberAt(i) : 0; 751 752 pParam = pDict->GetArrayFor("Range"); 753 const FX_FLOAT def_ranges[4] = {-100 * 1.0f, 100 * 1.0f, -100 * 1.0f, 754 100 * 1.0f}; 755 for (i = 0; i < 4; i++) 756 m_Ranges[i] = pParam ? pParam->GetNumberAt(i) : def_ranges[i]; 757 return true; 758 } 759 760 bool CPDF_LabCS::GetRGB(FX_FLOAT* pBuf, 761 FX_FLOAT& R, 762 FX_FLOAT& G, 763 FX_FLOAT& B) const { 764 FX_FLOAT Lstar = pBuf[0]; 765 FX_FLOAT astar = pBuf[1]; 766 FX_FLOAT bstar = pBuf[2]; 767 FX_FLOAT M = (Lstar + 16.0f) / 116.0f; 768 FX_FLOAT L = M + astar / 500.0f; 769 FX_FLOAT N = M - bstar / 200.0f; 770 FX_FLOAT X, Y, Z; 771 if (L < 0.2069f) 772 X = 0.957f * 0.12842f * (L - 0.1379f); 773 else 774 X = 0.957f * L * L * L; 775 776 if (M < 0.2069f) 777 Y = 0.12842f * (M - 0.1379f); 778 else 779 Y = M * M * M; 780 781 if (N < 0.2069f) 782 Z = 1.0889f * 0.12842f * (N - 0.1379f); 783 else 784 Z = 1.0889f * N * N * N; 785 786 XYZ_to_sRGB(X, Y, Z, R, G, B); 787 return true; 788 } 789 790 bool CPDF_LabCS::SetRGB(FX_FLOAT* pBuf, 791 FX_FLOAT R, 792 FX_FLOAT G, 793 FX_FLOAT B) const { 794 return false; 795 } 796 797 void CPDF_LabCS::TranslateImageLine(uint8_t* pDestBuf, 798 const uint8_t* pSrcBuf, 799 int pixels, 800 int image_width, 801 int image_height, 802 bool bTransMask) const { 803 for (int i = 0; i < pixels; i++) { 804 FX_FLOAT lab[3]; 805 FX_FLOAT R, G, B; 806 lab[0] = (pSrcBuf[0] * 100 / 255.0f); 807 lab[1] = (FX_FLOAT)(pSrcBuf[1] - 128); 808 lab[2] = (FX_FLOAT)(pSrcBuf[2] - 128); 809 GetRGB(lab, R, G, B); 810 pDestBuf[0] = (int32_t)(B * 255); 811 pDestBuf[1] = (int32_t)(G * 255); 812 pDestBuf[2] = (int32_t)(R * 255); 813 pDestBuf += 3; 814 pSrcBuf += 3; 815 } 816 } 817 818 CPDF_ICCBasedCS::CPDF_ICCBasedCS(CPDF_Document* pDoc) 819 : CPDF_ColorSpace(pDoc, PDFCS_ICCBASED, 0), 820 m_pProfile(nullptr), 821 m_pCache(nullptr), 822 m_pRanges(nullptr) {} 823 824 CPDF_ICCBasedCS::~CPDF_ICCBasedCS() { 825 FX_Free(m_pCache); 826 FX_Free(m_pRanges); 827 if (m_pProfile && m_pDocument) 828 m_pDocument->GetPageData()->ReleaseIccProfile(m_pProfile); 829 } 830 831 bool CPDF_ICCBasedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { 832 CPDF_Stream* pStream = pArray->GetStreamAt(1); 833 if (!pStream) 834 return false; 835 836 m_pProfile = pDoc->LoadIccProfile(pStream); 837 if (!m_pProfile) 838 return false; 839 840 // Try using the |nComponents| from ICC profile 841 m_nComponents = m_pProfile->GetComponents(); 842 CPDF_Dictionary* pDict = pStream->GetDict(); 843 if (!m_pProfile->m_pTransform) { // No valid ICC profile or using sRGB 844 CPDF_Object* pAlterCSObj = 845 pDict ? pDict->GetDirectObjectFor("Alternate") : nullptr; 846 if (pAlterCSObj) { 847 std::unique_ptr<CPDF_ColorSpace> pAlterCS = 848 CPDF_ColorSpace::Load(pDoc, pAlterCSObj); 849 if (pAlterCS) { 850 if (m_nComponents == 0) { // NO valid ICC profile 851 if (pAlterCS->CountComponents() > 0) { // Use Alternative colorspace 852 m_nComponents = pAlterCS->CountComponents(); 853 m_pAlterCS = std::move(pAlterCS); 854 } else { // No valid alternative colorspace 855 int32_t nDictComponents = pDict ? pDict->GetIntegerFor("N") : 0; 856 if (nDictComponents != 1 && nDictComponents != 3 && 857 nDictComponents != 4) { 858 return false; 859 } 860 m_nComponents = nDictComponents; 861 } 862 } else { // Using sRGB 863 if (pAlterCS->CountComponents() == m_nComponents) 864 m_pAlterCS = std::move(pAlterCS); 865 } 866 } 867 } 868 if (!m_pAlterCS) { 869 if (m_nComponents == 1) 870 m_pAlterCS = GetStockCS(PDFCS_DEVICEGRAY); 871 else if (m_nComponents == 3) 872 m_pAlterCS = GetStockCS(PDFCS_DEVICERGB); 873 else if (m_nComponents == 4) 874 m_pAlterCS = GetStockCS(PDFCS_DEVICECMYK); 875 } 876 } 877 CPDF_Array* pRanges = pDict->GetArrayFor("Range"); 878 m_pRanges = FX_Alloc2D(FX_FLOAT, m_nComponents, 2); 879 for (uint32_t i = 0; i < m_nComponents * 2; i++) { 880 if (pRanges) 881 m_pRanges[i] = pRanges->GetNumberAt(i); 882 else if (i % 2) 883 m_pRanges[i] = 1.0f; 884 else 885 m_pRanges[i] = 0; 886 } 887 return true; 888 } 889 890 bool CPDF_ICCBasedCS::GetRGB(FX_FLOAT* pBuf, 891 FX_FLOAT& R, 892 FX_FLOAT& G, 893 FX_FLOAT& B) const { 894 if (m_pProfile && m_pProfile->m_bsRGB) { 895 R = pBuf[0]; 896 G = pBuf[1]; 897 B = pBuf[2]; 898 return true; 899 } 900 CCodec_IccModule* pIccModule = CPDF_ModuleMgr::Get()->GetIccModule(); 901 if (!m_pProfile->m_pTransform || !pIccModule) { 902 if (m_pAlterCS) 903 return m_pAlterCS->GetRGB(pBuf, R, G, B); 904 905 R = 0.0f; 906 G = 0.0f; 907 B = 0.0f; 908 return true; 909 } 910 FX_FLOAT rgb[3]; 911 pIccModule->SetComponents(m_nComponents); 912 pIccModule->Translate(m_pProfile->m_pTransform, pBuf, rgb); 913 R = rgb[0]; 914 G = rgb[1]; 915 B = rgb[2]; 916 return true; 917 } 918 919 bool CPDF_ICCBasedCS::SetRGB(FX_FLOAT* pBuf, 920 FX_FLOAT R, 921 FX_FLOAT G, 922 FX_FLOAT B) const { 923 return false; 924 } 925 926 bool CPDF_ICCBasedCS::v_GetCMYK(FX_FLOAT* pBuf, 927 FX_FLOAT& c, 928 FX_FLOAT& m, 929 FX_FLOAT& y, 930 FX_FLOAT& k) const { 931 if (m_nComponents != 4) 932 return false; 933 934 c = pBuf[0]; 935 m = pBuf[1]; 936 y = pBuf[2]; 937 k = pBuf[3]; 938 return true; 939 } 940 941 void CPDF_ICCBasedCS::EnableStdConversion(bool bEnabled) { 942 CPDF_ColorSpace::EnableStdConversion(bEnabled); 943 if (m_pAlterCS) 944 m_pAlterCS->EnableStdConversion(bEnabled); 945 } 946 947 void CPDF_ICCBasedCS::TranslateImageLine(uint8_t* pDestBuf, 948 const uint8_t* pSrcBuf, 949 int pixels, 950 int image_width, 951 int image_height, 952 bool bTransMask) const { 953 if (m_pProfile->m_bsRGB) { 954 ReverseRGB(pDestBuf, pSrcBuf, pixels); 955 } else if (m_pProfile->m_pTransform) { 956 int nMaxColors = 1; 957 for (uint32_t i = 0; i < m_nComponents; i++) { 958 nMaxColors *= 52; 959 } 960 if (m_nComponents > 3 || image_width * image_height < nMaxColors * 3 / 2) { 961 CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline( 962 m_pProfile->m_pTransform, pDestBuf, pSrcBuf, pixels); 963 } else { 964 if (!m_pCache) { 965 ((CPDF_ICCBasedCS*)this)->m_pCache = FX_Alloc2D(uint8_t, nMaxColors, 3); 966 uint8_t* temp_src = FX_Alloc2D(uint8_t, nMaxColors, m_nComponents); 967 uint8_t* pSrc = temp_src; 968 for (int i = 0; i < nMaxColors; i++) { 969 uint32_t color = i; 970 uint32_t order = nMaxColors / 52; 971 for (uint32_t c = 0; c < m_nComponents; c++) { 972 *pSrc++ = (uint8_t)(color / order * 5); 973 color %= order; 974 order /= 52; 975 } 976 } 977 CPDF_ModuleMgr::Get()->GetIccModule()->TranslateScanline( 978 m_pProfile->m_pTransform, m_pCache, temp_src, nMaxColors); 979 FX_Free(temp_src); 980 } 981 for (int i = 0; i < pixels; i++) { 982 int index = 0; 983 for (uint32_t c = 0; c < m_nComponents; c++) { 984 index = index * 52 + (*pSrcBuf) / 5; 985 pSrcBuf++; 986 } 987 index *= 3; 988 *pDestBuf++ = m_pCache[index]; 989 *pDestBuf++ = m_pCache[index + 1]; 990 *pDestBuf++ = m_pCache[index + 2]; 991 } 992 } 993 } else if (m_pAlterCS) { 994 m_pAlterCS->TranslateImageLine(pDestBuf, pSrcBuf, pixels, image_width, 995 image_height); 996 } 997 } 998 999 CPDF_IndexedCS::CPDF_IndexedCS(CPDF_Document* pDoc) 1000 : CPDF_ColorSpace(pDoc, PDFCS_INDEXED, 1), 1001 m_pBaseCS(nullptr), 1002 m_pCountedBaseCS(nullptr), 1003 m_pCompMinMax(nullptr) {} 1004 1005 CPDF_IndexedCS::~CPDF_IndexedCS() { 1006 FX_Free(m_pCompMinMax); 1007 CPDF_ColorSpace* pCS = m_pCountedBaseCS ? m_pCountedBaseCS->get() : nullptr; 1008 if (pCS && m_pDocument) { 1009 m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray()); 1010 } 1011 } 1012 1013 bool CPDF_IndexedCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { 1014 if (pArray->GetCount() < 4) { 1015 return false; 1016 } 1017 CPDF_Object* pBaseObj = pArray->GetDirectObjectAt(1); 1018 if (pBaseObj == m_pArray) { 1019 return false; 1020 } 1021 CPDF_DocPageData* pDocPageData = pDoc->GetPageData(); 1022 m_pBaseCS = pDocPageData->GetColorSpace(pBaseObj, nullptr); 1023 if (!m_pBaseCS) { 1024 return false; 1025 } 1026 m_pCountedBaseCS = pDocPageData->FindColorSpacePtr(m_pBaseCS->GetArray()); 1027 m_nBaseComponents = m_pBaseCS->CountComponents(); 1028 m_pCompMinMax = FX_Alloc2D(FX_FLOAT, m_nBaseComponents, 2); 1029 FX_FLOAT defvalue; 1030 for (int i = 0; i < m_nBaseComponents; i++) { 1031 m_pBaseCS->GetDefaultValue(i, defvalue, m_pCompMinMax[i * 2], 1032 m_pCompMinMax[i * 2 + 1]); 1033 m_pCompMinMax[i * 2 + 1] -= m_pCompMinMax[i * 2]; 1034 } 1035 m_MaxIndex = pArray->GetIntegerAt(2); 1036 1037 CPDF_Object* pTableObj = pArray->GetDirectObjectAt(3); 1038 if (!pTableObj) 1039 return false; 1040 1041 if (CPDF_String* pString = pTableObj->AsString()) { 1042 m_Table = pString->GetString(); 1043 } else if (CPDF_Stream* pStream = pTableObj->AsStream()) { 1044 CPDF_StreamAcc acc; 1045 acc.LoadAllData(pStream, false); 1046 m_Table = CFX_ByteStringC(acc.GetData(), acc.GetSize()); 1047 } 1048 return true; 1049 } 1050 1051 bool CPDF_IndexedCS::GetRGB(FX_FLOAT* pBuf, 1052 FX_FLOAT& R, 1053 FX_FLOAT& G, 1054 FX_FLOAT& B) const { 1055 int index = (int32_t)(*pBuf); 1056 if (index < 0 || index > m_MaxIndex) { 1057 return false; 1058 } 1059 if (m_nBaseComponents) { 1060 if (index == INT_MAX || (index + 1) > INT_MAX / m_nBaseComponents || 1061 (index + 1) * m_nBaseComponents > (int)m_Table.GetLength()) { 1062 R = G = B = 0; 1063 return false; 1064 } 1065 } 1066 CFX_FixedBufGrow<FX_FLOAT, 16> Comps(m_nBaseComponents); 1067 FX_FLOAT* comps = Comps; 1068 const uint8_t* pTable = m_Table.raw_str(); 1069 for (int i = 0; i < m_nBaseComponents; i++) { 1070 comps[i] = 1071 m_pCompMinMax[i * 2] + 1072 m_pCompMinMax[i * 2 + 1] * pTable[index * m_nBaseComponents + i] / 255; 1073 } 1074 return m_pBaseCS->GetRGB(comps, R, G, B); 1075 } 1076 1077 CPDF_ColorSpace* CPDF_IndexedCS::GetBaseCS() const { 1078 return m_pBaseCS; 1079 } 1080 1081 void CPDF_IndexedCS::EnableStdConversion(bool bEnabled) { 1082 CPDF_ColorSpace::EnableStdConversion(bEnabled); 1083 if (m_pBaseCS) { 1084 m_pBaseCS->EnableStdConversion(bEnabled); 1085 } 1086 } 1087 1088 CPDF_PatternCS::CPDF_PatternCS(CPDF_Document* pDoc) 1089 : CPDF_ColorSpace(pDoc, PDFCS_PATTERN, 1), 1090 m_pBaseCS(nullptr), 1091 m_pCountedBaseCS(nullptr) {} 1092 1093 CPDF_PatternCS::~CPDF_PatternCS() { 1094 CPDF_ColorSpace* pCS = m_pCountedBaseCS ? m_pCountedBaseCS->get() : nullptr; 1095 if (pCS && m_pDocument) { 1096 m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray()); 1097 } 1098 } 1099 1100 bool CPDF_PatternCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { 1101 CPDF_Object* pBaseCS = pArray->GetDirectObjectAt(1); 1102 if (pBaseCS == m_pArray) { 1103 return false; 1104 } 1105 CPDF_DocPageData* pDocPageData = pDoc->GetPageData(); 1106 m_pBaseCS = pDocPageData->GetColorSpace(pBaseCS, nullptr); 1107 if (m_pBaseCS) { 1108 if (m_pBaseCS->GetFamily() == PDFCS_PATTERN) { 1109 return false; 1110 } 1111 m_pCountedBaseCS = pDocPageData->FindColorSpacePtr(m_pBaseCS->GetArray()); 1112 m_nComponents = m_pBaseCS->CountComponents() + 1; 1113 if (m_pBaseCS->CountComponents() > MAX_PATTERN_COLORCOMPS) { 1114 return false; 1115 } 1116 } else { 1117 m_nComponents = 1; 1118 } 1119 return true; 1120 } 1121 1122 bool CPDF_PatternCS::GetRGB(FX_FLOAT* pBuf, 1123 FX_FLOAT& R, 1124 FX_FLOAT& G, 1125 FX_FLOAT& B) const { 1126 if (m_pBaseCS) { 1127 ASSERT(m_pBaseCS->GetFamily() != PDFCS_PATTERN); 1128 PatternValue* pvalue = (PatternValue*)pBuf; 1129 if (m_pBaseCS->GetRGB(pvalue->m_Comps, R, G, B)) { 1130 return true; 1131 } 1132 } 1133 R = G = B = 0.75f; 1134 return false; 1135 } 1136 1137 CPDF_ColorSpace* CPDF_PatternCS::GetBaseCS() const { 1138 return m_pBaseCS; 1139 } 1140 1141 CPDF_SeparationCS::CPDF_SeparationCS(CPDF_Document* pDoc) 1142 : CPDF_ColorSpace(pDoc, PDFCS_SEPARATION, 1) {} 1143 1144 CPDF_SeparationCS::~CPDF_SeparationCS() {} 1145 1146 void CPDF_SeparationCS::GetDefaultValue(int iComponent, 1147 FX_FLOAT& value, 1148 FX_FLOAT& min, 1149 FX_FLOAT& max) const { 1150 value = 1.0f; 1151 min = 0; 1152 max = 1.0f; 1153 } 1154 1155 bool CPDF_SeparationCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { 1156 CFX_ByteString name = pArray->GetStringAt(1); 1157 if (name == "None") { 1158 m_Type = None; 1159 return true; 1160 } 1161 1162 m_Type = Colorant; 1163 CPDF_Object* pAltCS = pArray->GetDirectObjectAt(2); 1164 if (pAltCS == m_pArray) 1165 return false; 1166 1167 m_pAltCS = Load(pDoc, pAltCS); 1168 if (!m_pAltCS) 1169 return false; 1170 1171 CPDF_Object* pFuncObj = pArray->GetDirectObjectAt(3); 1172 if (pFuncObj && !pFuncObj->IsName()) 1173 m_pFunc = CPDF_Function::Load(pFuncObj); 1174 1175 if (m_pFunc && m_pFunc->CountOutputs() < m_pAltCS->CountComponents()) 1176 m_pFunc.reset(); 1177 return true; 1178 } 1179 1180 bool CPDF_SeparationCS::GetRGB(FX_FLOAT* pBuf, 1181 FX_FLOAT& R, 1182 FX_FLOAT& G, 1183 FX_FLOAT& B) const { 1184 if (m_Type == None) 1185 return false; 1186 1187 if (!m_pFunc) { 1188 if (!m_pAltCS) 1189 return false; 1190 1191 int nComps = m_pAltCS->CountComponents(); 1192 CFX_FixedBufGrow<FX_FLOAT, 16> results(nComps); 1193 for (int i = 0; i < nComps; i++) 1194 results[i] = *pBuf; 1195 return m_pAltCS->GetRGB(results, R, G, B); 1196 } 1197 1198 CFX_FixedBufGrow<FX_FLOAT, 16> results(m_pFunc->CountOutputs()); 1199 int nresults = 0; 1200 m_pFunc->Call(pBuf, 1, results, nresults); 1201 if (nresults == 0) 1202 return false; 1203 1204 if (m_pAltCS) 1205 return m_pAltCS->GetRGB(results, R, G, B); 1206 1207 R = 0; 1208 G = 0; 1209 B = 0; 1210 return false; 1211 } 1212 1213 void CPDF_SeparationCS::EnableStdConversion(bool bEnabled) { 1214 CPDF_ColorSpace::EnableStdConversion(bEnabled); 1215 if (m_pAltCS) 1216 m_pAltCS->EnableStdConversion(bEnabled); 1217 } 1218 1219 CPDF_DeviceNCS::CPDF_DeviceNCS(CPDF_Document* pDoc) 1220 : CPDF_ColorSpace(pDoc, PDFCS_DEVICEN, 0) {} 1221 1222 CPDF_DeviceNCS::~CPDF_DeviceNCS() {} 1223 1224 void CPDF_DeviceNCS::GetDefaultValue(int iComponent, 1225 FX_FLOAT& value, 1226 FX_FLOAT& min, 1227 FX_FLOAT& max) const { 1228 value = 1.0f; 1229 min = 0; 1230 max = 1.0f; 1231 } 1232 1233 bool CPDF_DeviceNCS::v_Load(CPDF_Document* pDoc, CPDF_Array* pArray) { 1234 CPDF_Array* pObj = ToArray(pArray->GetDirectObjectAt(1)); 1235 if (!pObj) 1236 return false; 1237 1238 m_nComponents = pObj->GetCount(); 1239 CPDF_Object* pAltCS = pArray->GetDirectObjectAt(2); 1240 if (!pAltCS || pAltCS == m_pArray) 1241 return false; 1242 1243 m_pAltCS = Load(pDoc, pAltCS); 1244 m_pFunc = CPDF_Function::Load(pArray->GetDirectObjectAt(3)); 1245 if (!m_pAltCS || !m_pFunc) 1246 return false; 1247 1248 return m_pFunc->CountOutputs() >= m_pAltCS->CountComponents(); 1249 } 1250 1251 bool CPDF_DeviceNCS::GetRGB(FX_FLOAT* pBuf, 1252 FX_FLOAT& R, 1253 FX_FLOAT& G, 1254 FX_FLOAT& B) const { 1255 if (!m_pFunc) 1256 return false; 1257 1258 CFX_FixedBufGrow<FX_FLOAT, 16> results(m_pFunc->CountOutputs()); 1259 int nresults = 0; 1260 m_pFunc->Call(pBuf, m_nComponents, results, nresults); 1261 if (nresults == 0) 1262 return false; 1263 1264 return m_pAltCS->GetRGB(results, R, G, B); 1265 } 1266 1267 void CPDF_DeviceNCS::EnableStdConversion(bool bEnabled) { 1268 CPDF_ColorSpace::EnableStdConversion(bEnabled); 1269 if (m_pAltCS) { 1270 m_pAltCS->EnableStdConversion(bEnabled); 1271 } 1272 } 1273