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