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/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