1 // Copyright 2016 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_transferfuncdib.h"
8 
9 #include <vector>
10 
11 #include "build/build_config.h"
12 #include "core/fpdfapi/page/cpdf_transferfunc.h"
13 #include "core/fpdfapi/parser/cpdf_dictionary.h"
14 #include "third_party/base/compiler_specific.h"
15 
CPDF_TransferFuncDIB(const RetainPtr<CFX_DIBBase> & pSrc,const RetainPtr<CPDF_TransferFunc> & pTransferFunc)16 CPDF_TransferFuncDIB::CPDF_TransferFuncDIB(
17     const RetainPtr<CFX_DIBBase>& pSrc,
18     const RetainPtr<CPDF_TransferFunc>& pTransferFunc)
19     : m_pSrc(pSrc),
20       m_pTransferFunc(pTransferFunc),
21       m_RampR(pTransferFunc->GetSamplesR()),
22       m_RampG(pTransferFunc->GetSamplesG()),
23       m_RampB(pTransferFunc->GetSamplesB()) {
24   m_Width = pSrc->GetWidth();
25   m_Height = pSrc->GetHeight();
26   FXDIB_Format format = GetDestFormat();
27   m_bpp = GetBppFromFormat(format);
28   m_AlphaFlag = GetAlphaFlagFromFormat(format);
29   m_Pitch = (m_Width * m_bpp + 31) / 32 * 4;
30   m_pPalette.reset();
31   m_Scanline.resize(m_Pitch);
32 }
33 
34 CPDF_TransferFuncDIB::~CPDF_TransferFuncDIB() = default;
35 
GetDestFormat() const36 FXDIB_Format CPDF_TransferFuncDIB::GetDestFormat() const {
37   if (m_pSrc->IsAlphaMask())
38     return FXDIB_8bppMask;
39 
40 #if defined(OS_MACOSX)
41   return m_pSrc->HasAlpha() ? FXDIB_Argb : FXDIB_Rgb32;
42 #else
43   return m_pSrc->HasAlpha() ? FXDIB_Argb : FXDIB_Rgb;
44 #endif
45 }
46 
TranslateScanline(const uint8_t * src_buf,std::vector<uint8_t> * dest_buf) const47 void CPDF_TransferFuncDIB::TranslateScanline(
48     const uint8_t* src_buf,
49     std::vector<uint8_t>* dest_buf) const {
50   bool bSkip = false;
51   switch (m_pSrc->GetFormat()) {
52     case FXDIB_1bppRgb: {
53       int r0 = m_RampR[0];
54       int g0 = m_RampG[0];
55       int b0 = m_RampB[0];
56       int r1 = m_RampR[255];
57       int g1 = m_RampG[255];
58       int b1 = m_RampB[255];
59       int index = 0;
60       for (int i = 0; i < m_Width; i++) {
61         if (src_buf[i / 8] & (1 << (7 - i % 8))) {
62           (*dest_buf)[index++] = b1;
63           (*dest_buf)[index++] = g1;
64           (*dest_buf)[index++] = r1;
65         } else {
66           (*dest_buf)[index++] = b0;
67           (*dest_buf)[index++] = g0;
68           (*dest_buf)[index++] = r0;
69         }
70 #if defined(OS_MACOSX)
71         index++;
72 #endif
73       }
74       break;
75     }
76     case FXDIB_1bppMask: {
77       int m0 = m_RampR[0];
78       int m1 = m_RampR[255];
79       int index = 0;
80       for (int i = 0; i < m_Width; i++) {
81         if (src_buf[i / 8] & (1 << (7 - i % 8)))
82           (*dest_buf)[index++] = m1;
83         else
84           (*dest_buf)[index++] = m0;
85       }
86       break;
87     }
88     case FXDIB_8bppRgb: {
89       FX_ARGB* pPal = m_pSrc->GetPalette();
90       int index = 0;
91       for (int i = 0; i < m_Width; i++) {
92         if (pPal) {
93           FX_ARGB src_argb = pPal[*src_buf];
94           (*dest_buf)[index++] = m_RampB[FXARGB_R(src_argb)];
95           (*dest_buf)[index++] = m_RampG[FXARGB_G(src_argb)];
96           (*dest_buf)[index++] = m_RampR[FXARGB_B(src_argb)];
97         } else {
98           uint32_t src_byte = *src_buf;
99           (*dest_buf)[index++] = m_RampB[src_byte];
100           (*dest_buf)[index++] = m_RampG[src_byte];
101           (*dest_buf)[index++] = m_RampR[src_byte];
102         }
103         src_buf++;
104 #if defined(OS_MACOSX)
105         index++;
106 #endif
107       }
108       break;
109     }
110     case FXDIB_8bppMask: {
111       int index = 0;
112       for (int i = 0; i < m_Width; i++)
113         (*dest_buf)[index++] = m_RampR[*(src_buf++)];
114       break;
115     }
116     case FXDIB_Rgb: {
117       int index = 0;
118       for (int i = 0; i < m_Width; i++) {
119         (*dest_buf)[index++] = m_RampB[*(src_buf++)];
120         (*dest_buf)[index++] = m_RampG[*(src_buf++)];
121         (*dest_buf)[index++] = m_RampR[*(src_buf++)];
122 #if defined(OS_MACOSX)
123         index++;
124 #endif
125       }
126       break;
127     }
128     case FXDIB_Rgb32:
129       bSkip = true;
130       FALLTHROUGH;
131     case FXDIB_Argb: {
132       int index = 0;
133       for (int i = 0; i < m_Width; i++) {
134         (*dest_buf)[index++] = m_RampB[*(src_buf++)];
135         (*dest_buf)[index++] = m_RampG[*(src_buf++)];
136         (*dest_buf)[index++] = m_RampR[*(src_buf++)];
137         if (!bSkip) {
138           (*dest_buf)[index++] = *src_buf;
139 #if defined(OS_MACOSX)
140         } else {
141           index++;
142 #endif
143         }
144         src_buf++;
145       }
146       break;
147     }
148     default:
149       break;
150   }
151 }
152 
TranslateDownSamples(uint8_t * dest_buf,const uint8_t * src_buf,int pixels,int Bpp) const153 void CPDF_TransferFuncDIB::TranslateDownSamples(uint8_t* dest_buf,
154                                                 const uint8_t* src_buf,
155                                                 int pixels,
156                                                 int Bpp) const {
157   if (Bpp == 8) {
158     for (int i = 0; i < pixels; i++)
159       *dest_buf++ = m_RampR[*(src_buf++)];
160   } else if (Bpp == 24) {
161     for (int i = 0; i < pixels; i++) {
162       *dest_buf++ = m_RampB[*(src_buf++)];
163       *dest_buf++ = m_RampG[*(src_buf++)];
164       *dest_buf++ = m_RampR[*(src_buf++)];
165     }
166   } else {
167 #if defined(OS_MACOSX)
168     if (!m_pSrc->HasAlpha()) {
169       for (int i = 0; i < pixels; i++) {
170         *dest_buf++ = m_RampB[*(src_buf++)];
171         *dest_buf++ = m_RampG[*(src_buf++)];
172         *dest_buf++ = m_RampR[*(src_buf++)];
173         dest_buf++;
174         src_buf++;
175       }
176     } else {
177 #endif
178       for (int i = 0; i < pixels; i++) {
179         *dest_buf++ = m_RampB[*(src_buf++)];
180         *dest_buf++ = m_RampG[*(src_buf++)];
181         *dest_buf++ = m_RampR[*(src_buf++)];
182         *dest_buf++ = *(src_buf++);
183       }
184 #if defined(OS_MACOSX)
185     }
186 #endif
187   }
188 }
189 
GetScanline(int line) const190 const uint8_t* CPDF_TransferFuncDIB::GetScanline(int line) const {
191   TranslateScanline(m_pSrc->GetScanline(line), &m_Scanline);
192   return m_Scanline.data();
193 }
194 
DownSampleScanline(int line,uint8_t * dest_scan,int dest_bpp,int dest_width,bool bFlipX,int clip_left,int clip_width) const195 void CPDF_TransferFuncDIB::DownSampleScanline(int line,
196                                               uint8_t* dest_scan,
197                                               int dest_bpp,
198                                               int dest_width,
199                                               bool bFlipX,
200                                               int clip_left,
201                                               int clip_width) const {
202   m_pSrc->DownSampleScanline(line, dest_scan, dest_bpp, dest_width, bFlipX,
203                              clip_left, clip_width);
204   TranslateDownSamples(dest_scan, dest_scan, clip_width, dest_bpp);
205 }
206