• 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 <memory>
8 
9 #include "core/fxcodec/codec/ccodec_iccmodule.h"
10 #include "core/fxcodec/codec/codec_int.h"
11 #include "core/fxcrt/cfx_fixedbufgrow.h"
12 
13 namespace {
14 
Check3Components(cmsColorSpaceSignature cs,bool bDst)15 bool Check3Components(cmsColorSpaceSignature cs, bool bDst) {
16   switch (cs) {
17     case cmsSigGrayData:
18       return false;
19     case cmsSigCmykData:
20       if (bDst)
21         return false;
22       break;
23     case cmsSigLabData:
24     case cmsSigRgbData:
25     default:
26       break;
27   }
28   return true;
29 }
30 
31 }  // namespace
32 
CLcmsCmm(int srcComponents,cmsHTRANSFORM hTransform,bool isLab)33 CLcmsCmm::CLcmsCmm(int srcComponents, cmsHTRANSFORM hTransform, bool isLab)
34     : m_hTransform(hTransform),
35       m_nSrcComponents(srcComponents),
36       m_bLab(isLab) {}
37 
~CLcmsCmm()38 CLcmsCmm::~CLcmsCmm() {
39   cmsDeleteTransform(m_hTransform);
40 }
41 
CCodec_IccModule()42 CCodec_IccModule::CCodec_IccModule() : m_nComponents(0) {}
43 
~CCodec_IccModule()44 CCodec_IccModule::~CCodec_IccModule() {}
45 
CreateTransform_sRGB(const unsigned char * pSrcProfileData,uint32_t dwSrcProfileSize,uint32_t * nSrcComponents)46 std::unique_ptr<CLcmsCmm> CCodec_IccModule::CreateTransform_sRGB(
47     const unsigned char* pSrcProfileData,
48     uint32_t dwSrcProfileSize,
49     uint32_t* nSrcComponents) {
50   *nSrcComponents = 0;
51   cmsHPROFILE srcProfile =
52       cmsOpenProfileFromMem(pSrcProfileData, dwSrcProfileSize);
53   if (!srcProfile)
54     return nullptr;
55 
56   cmsHPROFILE dstProfile;
57   dstProfile = cmsCreate_sRGBProfile();
58   if (!dstProfile) {
59     cmsCloseProfile(srcProfile);
60     return nullptr;
61   }
62   int srcFormat;
63   bool bLab = false;
64   cmsColorSpaceSignature srcCS = cmsGetColorSpace(srcProfile);
65 
66   *nSrcComponents = cmsChannelsOf(srcCS);
67   // According to PDF spec, number of components must be 1, 3, or 4.
68   if (*nSrcComponents != 1 && *nSrcComponents != 3 && *nSrcComponents != 4) {
69     cmsCloseProfile(srcProfile);
70     cmsCloseProfile(dstProfile);
71     return nullptr;
72   }
73 
74   if (srcCS == cmsSigLabData) {
75     srcFormat =
76         COLORSPACE_SH(PT_Lab) | CHANNELS_SH(*nSrcComponents) | BYTES_SH(0);
77     bLab = true;
78   } else {
79     srcFormat =
80         COLORSPACE_SH(PT_ANY) | CHANNELS_SH(*nSrcComponents) | BYTES_SH(1);
81   }
82   cmsColorSpaceSignature dstCS = cmsGetColorSpace(dstProfile);
83   if (!Check3Components(dstCS, true)) {
84     cmsCloseProfile(srcProfile);
85     cmsCloseProfile(dstProfile);
86     return nullptr;
87   }
88 
89   cmsHTRANSFORM hTransform = nullptr;
90   int intent = 0;
91   switch (dstCS) {
92     case cmsSigGrayData:
93       hTransform = cmsCreateTransform(srcProfile, srcFormat, dstProfile,
94                                       TYPE_GRAY_8, intent, 0);
95       break;
96     case cmsSigRgbData:
97       hTransform = cmsCreateTransform(srcProfile, srcFormat, dstProfile,
98                                       TYPE_BGR_8, intent, 0);
99       break;
100     case cmsSigCmykData:
101       hTransform = cmsCreateTransform(srcProfile, srcFormat, dstProfile,
102                                       TYPE_CMYK_8, intent, 0);
103       break;
104     default:
105       break;
106   }
107   if (!hTransform) {
108     cmsCloseProfile(srcProfile);
109     cmsCloseProfile(dstProfile);
110     return nullptr;
111   }
112   auto pCmm = pdfium::MakeUnique<CLcmsCmm>(*nSrcComponents, hTransform, bLab);
113   cmsCloseProfile(srcProfile);
114   cmsCloseProfile(dstProfile);
115   return pCmm;
116 }
117 
Translate(CLcmsCmm * pTransform,const float * pSrcValues,float * pDestValues)118 void CCodec_IccModule::Translate(CLcmsCmm* pTransform,
119                                  const float* pSrcValues,
120                                  float* pDestValues) {
121   if (!pTransform)
122     return;
123 
124   uint32_t nSrcComponents = m_nComponents;
125   uint8_t output[4];
126   if (pTransform->m_bLab) {
127     CFX_FixedBufGrow<double, 16> inputs(nSrcComponents);
128     double* input = inputs;
129     for (uint32_t i = 0; i < nSrcComponents; ++i)
130       input[i] = pSrcValues[i];
131     cmsDoTransform(pTransform->m_hTransform, input, output, 1);
132   } else {
133     CFX_FixedBufGrow<uint8_t, 16> inputs(nSrcComponents);
134     uint8_t* input = inputs;
135     for (uint32_t i = 0; i < nSrcComponents; ++i) {
136       input[i] =
137           pdfium::clamp(static_cast<int>(pSrcValues[i] * 255.0f), 0, 255);
138     }
139     cmsDoTransform(pTransform->m_hTransform, input, output, 1);
140   }
141   pDestValues[0] = output[2] / 255.0f;
142   pDestValues[1] = output[1] / 255.0f;
143   pDestValues[2] = output[0] / 255.0f;
144 }
145 
TranslateScanline(CLcmsCmm * pTransform,unsigned char * pDest,const unsigned char * pSrc,int32_t pixels)146 void CCodec_IccModule::TranslateScanline(CLcmsCmm* pTransform,
147                                          unsigned char* pDest,
148                                          const unsigned char* pSrc,
149                                          int32_t pixels) {
150   if (pTransform)
151     cmsDoTransform(pTransform->m_hTransform, pSrc, pDest, pixels);
152 }
153