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 "third_party/base/logging.h" 20 #include "third_party/base/stl_util.h" 21 22 namespace { 23 24 float NormalizeChannel(float fVal) { 25 return pdfium::clamp(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 ReverseRGB(uint8_t* pDestBuf, const uint8_t* pSrcBuf, int pixels) { 40 if (pDestBuf == pSrcBuf) { 41 for (int i = 0; i < pixels; i++) { 42 uint8_t temp = pDestBuf[2]; 43 pDestBuf[2] = pDestBuf[0]; 44 pDestBuf[0] = temp; 45 pDestBuf += 3; 46 } 47 } else { 48 for (int i = 0; i < pixels; i++) { 49 *pDestBuf++ = pSrcBuf[2]; 50 *pDestBuf++ = pSrcBuf[1]; 51 *pDestBuf++ = pSrcBuf[0]; 52 pSrcBuf += 3; 53 } 54 } 55 } 56 57 CPDF_DeviceCS::CPDF_DeviceCS(int family) : CPDF_ColorSpace(nullptr, family) { 58 ASSERT(family == PDFCS_DEVICEGRAY || family == PDFCS_DEVICERGB || 59 family == PDFCS_DEVICECMYK); 60 SetComponentsForStockCS(ComponentsForFamily(GetFamily())); 61 } 62 63 CPDF_DeviceCS::~CPDF_DeviceCS() {} 64 65 uint32_t CPDF_DeviceCS::v_Load(CPDF_Document* pDoc, 66 CPDF_Array* pArray, 67 std::set<CPDF_Object*>* pVisited) { 68 // Unlike other classes that inherit from CPDF_ColorSpace, CPDF_DeviceCS is 69 // never loaded by CPDF_ColorSpace. 70 NOTREACHED(); 71 return 0; 72 } 73 74 bool CPDF_DeviceCS::GetRGB(float* pBuf, float* R, float* G, float* B) const { 75 switch (m_Family) { 76 case PDFCS_DEVICEGRAY: 77 *R = NormalizeChannel(*pBuf); 78 *G = *R; 79 *B = *R; 80 return true; 81 case PDFCS_DEVICERGB: 82 *R = NormalizeChannel(pBuf[0]); 83 *G = NormalizeChannel(pBuf[1]); 84 *B = NormalizeChannel(pBuf[2]); 85 return true; 86 case PDFCS_DEVICECMYK: 87 if (m_dwStdConversion) { 88 float k = pBuf[3]; 89 *R = 1.0f - std::min(1.0f, pBuf[0] + k); 90 *G = 1.0f - std::min(1.0f, pBuf[1] + k); 91 *B = 1.0f - std::min(1.0f, pBuf[2] + k); 92 } else { 93 std::tie(*R, *G, *B) = AdobeCMYK_to_sRGB( 94 NormalizeChannel(pBuf[0]), NormalizeChannel(pBuf[1]), 95 NormalizeChannel(pBuf[2]), NormalizeChannel(pBuf[3])); 96 } 97 return true; 98 default: 99 NOTREACHED(); 100 return false; 101 } 102 } 103 104 void CPDF_DeviceCS::TranslateImageLine(uint8_t* pDestBuf, 105 const uint8_t* pSrcBuf, 106 int pixels, 107 int image_width, 108 int image_height, 109 bool bTransMask) const { 110 switch (m_Family) { 111 case PDFCS_DEVICEGRAY: 112 for (int i = 0; i < pixels; i++) { 113 *pDestBuf++ = pSrcBuf[i]; 114 *pDestBuf++ = pSrcBuf[i]; 115 *pDestBuf++ = pSrcBuf[i]; 116 } 117 break; 118 case PDFCS_DEVICERGB: 119 ReverseRGB(pDestBuf, pSrcBuf, pixels); 120 break; 121 case PDFCS_DEVICECMYK: 122 if (bTransMask) { 123 for (int i = 0; i < pixels; i++) { 124 int k = 255 - pSrcBuf[3]; 125 pDestBuf[0] = ((255 - pSrcBuf[0]) * k) / 255; 126 pDestBuf[1] = ((255 - pSrcBuf[1]) * k) / 255; 127 pDestBuf[2] = ((255 - pSrcBuf[2]) * k) / 255; 128 pDestBuf += 3; 129 pSrcBuf += 4; 130 } 131 } else { 132 for (int i = 0; i < pixels; i++) { 133 if (m_dwStdConversion) { 134 uint8_t k = pSrcBuf[3]; 135 pDestBuf[2] = 255 - std::min(255, pSrcBuf[0] + k); 136 pDestBuf[1] = 255 - std::min(255, pSrcBuf[1] + k); 137 pDestBuf[0] = 255 - std::min(255, pSrcBuf[2] + k); 138 } else { 139 std::tie(pDestBuf[2], pDestBuf[1], pDestBuf[0]) = 140 AdobeCMYK_to_sRGB1(pSrcBuf[0], pSrcBuf[1], pSrcBuf[2], 141 pSrcBuf[3]); 142 } 143 pSrcBuf += 4; 144 pDestBuf += 3; 145 } 146 } 147 break; 148 default: 149 NOTREACHED(); 150 break; 151 } 152 } 153