Home | History | Annotate | Download | only in page
      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