Home | History | Annotate | Download | only in codec
      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 
     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 
     33 CLcmsCmm::CLcmsCmm(int srcComponents, cmsHTRANSFORM hTransform, bool isLab)
     34     : m_hTransform(hTransform),
     35       m_nSrcComponents(srcComponents),
     36       m_bLab(isLab) {}
     37 
     38 CLcmsCmm::~CLcmsCmm() {
     39   cmsDeleteTransform(m_hTransform);
     40 }
     41 
     42 CCodec_IccModule::CCodec_IccModule() : m_nComponents(0) {}
     43 
     44 CCodec_IccModule::~CCodec_IccModule() {}
     45 
     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 
    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 
    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