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 #include <utility>
9
10 #include "core/fxcodec/fx_codec.h"
11 #include "core/fxcrt/cfx_maybe_owned.h"
12 #include "core/fxge/fx_dib.h"
13 #include "third_party/base/ptr_util.h"
14
15 class CFX_Palette {
16 public:
17 CFX_Palette();
18 ~CFX_Palette();
19
20 bool BuildPalette(const CFX_DIBSource* pBitmap);
GetPalette() const21 uint32_t* GetPalette() const { return m_pPalette; }
GetColorLut() const22 uint32_t* GetColorLut() const { return m_cLut; }
GetAmountLut() const23 uint32_t* GetAmountLut() const { return m_aLut; }
Getlut() const24 int32_t Getlut() const { return m_lut; }
25
26 protected:
27 uint32_t* m_pPalette;
28 uint32_t* m_cLut;
29 uint32_t* m_aLut;
30 int m_lut;
31 };
_Partition(uint32_t * alut,uint32_t * clut,int l,int r)32 int _Partition(uint32_t* alut, uint32_t* clut, int l, int r) {
33 uint32_t p_a = alut[l];
34 uint32_t p_c = clut[l];
35 while (l < r) {
36 while (l < r && alut[r] >= p_a) {
37 r--;
38 }
39 if (l < r) {
40 alut[l] = alut[r];
41 clut[l++] = clut[r];
42 }
43 while (l < r && alut[l] <= p_a) {
44 l++;
45 }
46 if (l < r) {
47 alut[r] = alut[l];
48 clut[r--] = clut[l];
49 }
50 }
51 alut[l] = p_a;
52 clut[l] = p_c;
53 return l;
54 }
55
_Qsort(uint32_t * alut,uint32_t * clut,int l,int r)56 void _Qsort(uint32_t* alut, uint32_t* clut, int l, int r) {
57 if (l < r) {
58 int pI = _Partition(alut, clut, l, r);
59 _Qsort(alut, clut, l, pI - 1);
60 _Qsort(alut, clut, pI + 1, r);
61 }
62 }
63
_ColorDecode(uint32_t pal_v,uint8_t & r,uint8_t & g,uint8_t & b)64 void _ColorDecode(uint32_t pal_v, uint8_t& r, uint8_t& g, uint8_t& b) {
65 r = (uint8_t)((pal_v & 0xf00) >> 4);
66 g = (uint8_t)(pal_v & 0x0f0);
67 b = (uint8_t)((pal_v & 0x00f) << 4);
68 }
69
_Obtain_Pal(uint32_t * aLut,uint32_t * cLut,uint32_t * dest_pal,uint32_t lut)70 void _Obtain_Pal(uint32_t* aLut,
71 uint32_t* cLut,
72 uint32_t* dest_pal,
73 uint32_t lut) {
74 uint32_t lut_1 = lut - 1;
75 for (int row = 0; row < 256; row++) {
76 int lut_offset = lut_1 - row;
77 if (lut_offset < 0) {
78 lut_offset += 256;
79 }
80 uint32_t color = cLut[lut_offset];
81 uint8_t r;
82 uint8_t g;
83 uint8_t b;
84 _ColorDecode(color, r, g, b);
85 dest_pal[row] = ((uint32_t)r << 16) | ((uint32_t)g << 8) | b | 0xff000000;
86 aLut[lut_offset] = row;
87 }
88 }
89
CFX_Palette()90 CFX_Palette::CFX_Palette() {
91 m_pPalette = nullptr;
92 m_cLut = nullptr;
93 m_aLut = nullptr;
94 m_lut = 0;
95 }
96
~CFX_Palette()97 CFX_Palette::~CFX_Palette() {
98 FX_Free(m_pPalette);
99 FX_Free(m_cLut);
100 FX_Free(m_aLut);
101 m_lut = 0;
102 }
103
BuildPalette(const CFX_DIBSource * pBitmap)104 bool CFX_Palette::BuildPalette(const CFX_DIBSource* pBitmap) {
105 if (!pBitmap) {
106 return false;
107 }
108 FX_Free(m_pPalette);
109 m_pPalette = FX_Alloc(uint32_t, 256);
110 int bpp = pBitmap->GetBPP() / 8;
111 int width = pBitmap->GetWidth();
112 int height = pBitmap->GetHeight();
113 FX_Free(m_cLut);
114 m_cLut = nullptr;
115 FX_Free(m_aLut);
116 m_aLut = nullptr;
117 m_cLut = FX_Alloc(uint32_t, 4096);
118 m_aLut = FX_Alloc(uint32_t, 4096);
119 int row, col;
120 m_lut = 0;
121 for (row = 0; row < height; row++) {
122 uint8_t* scan_line = (uint8_t*)pBitmap->GetScanline(row);
123 for (col = 0; col < width; col++) {
124 uint8_t* src_port = scan_line + col * bpp;
125 uint32_t b = src_port[0] & 0xf0;
126 uint32_t g = src_port[1] & 0xf0;
127 uint32_t r = src_port[2] & 0xf0;
128 uint32_t index = (r << 4) + g + (b >> 4);
129 m_aLut[index]++;
130 }
131 }
132 for (row = 0; row < 4096; row++) {
133 if (m_aLut[row] != 0) {
134 m_aLut[m_lut] = m_aLut[row];
135 m_cLut[m_lut] = row;
136 m_lut++;
137 }
138 }
139 _Qsort(m_aLut, m_cLut, 0, m_lut - 1);
140 _Obtain_Pal(m_aLut, m_cLut, m_pPalette, m_lut);
141 return true;
142 }
143
ConvertBuffer_1bppMask2Gray(uint8_t * dest_buf,int dest_pitch,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top)144 bool ConvertBuffer_1bppMask2Gray(uint8_t* dest_buf,
145 int dest_pitch,
146 int width,
147 int height,
148 const CFX_DIBSource* pSrcBitmap,
149 int src_left,
150 int src_top) {
151 uint8_t set_gray, reset_gray;
152 set_gray = 0xff;
153 reset_gray = 0x00;
154 for (int row = 0; row < height; row++) {
155 uint8_t* dest_scan = dest_buf + row * dest_pitch;
156 FXSYS_memset(dest_scan, reset_gray, width);
157 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
158 for (int col = src_left; col < src_left + width; col++) {
159 if (src_scan[col / 8] & (1 << (7 - col % 8))) {
160 *dest_scan = set_gray;
161 }
162 dest_scan++;
163 }
164 }
165 return true;
166 }
167
ConvertBuffer_8bppMask2Gray(uint8_t * dest_buf,int dest_pitch,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top)168 bool ConvertBuffer_8bppMask2Gray(uint8_t* dest_buf,
169 int dest_pitch,
170 int width,
171 int height,
172 const CFX_DIBSource* pSrcBitmap,
173 int src_left,
174 int src_top) {
175 for (int row = 0; row < height; row++) {
176 uint8_t* dest_scan = dest_buf + row * dest_pitch;
177 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left;
178 FXSYS_memcpy(dest_scan, src_scan, width);
179 }
180 return true;
181 }
182
ConvertBuffer_1bppPlt2Gray(uint8_t * dest_buf,int dest_pitch,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top)183 bool ConvertBuffer_1bppPlt2Gray(uint8_t* dest_buf,
184 int dest_pitch,
185 int width,
186 int height,
187 const CFX_DIBSource* pSrcBitmap,
188 int src_left,
189 int src_top) {
190 uint32_t* src_plt = pSrcBitmap->GetPalette();
191 uint8_t gray[2];
192 uint8_t reset_r;
193 uint8_t reset_g;
194 uint8_t reset_b;
195 uint8_t set_r;
196 uint8_t set_g;
197 uint8_t set_b;
198 if (pSrcBitmap->IsCmykImage()) {
199 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(src_plt[0]), FXSYS_GetMValue(src_plt[0]),
200 FXSYS_GetYValue(src_plt[0]), FXSYS_GetKValue(src_plt[0]),
201 reset_r, reset_g, reset_b);
202 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(src_plt[1]), FXSYS_GetMValue(src_plt[1]),
203 FXSYS_GetYValue(src_plt[1]), FXSYS_GetKValue(src_plt[1]),
204 set_r, set_g, set_b);
205 } else {
206 reset_r = FXARGB_R(src_plt[0]);
207 reset_g = FXARGB_G(src_plt[0]);
208 reset_b = FXARGB_B(src_plt[0]);
209 set_r = FXARGB_R(src_plt[1]);
210 set_g = FXARGB_G(src_plt[1]);
211 set_b = FXARGB_B(src_plt[1]);
212 }
213 gray[0] = FXRGB2GRAY(reset_r, reset_g, reset_b);
214 gray[1] = FXRGB2GRAY(set_r, set_g, set_b);
215
216 for (int row = 0; row < height; row++) {
217 uint8_t* dest_scan = dest_buf + row * dest_pitch;
218 FXSYS_memset(dest_scan, gray[0], width);
219 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
220 for (int col = src_left; col < src_left + width; col++) {
221 if (src_scan[col / 8] & (1 << (7 - col % 8))) {
222 *dest_scan = gray[1];
223 }
224 dest_scan++;
225 }
226 }
227 return true;
228 }
229
ConvertBuffer_8bppPlt2Gray(uint8_t * dest_buf,int dest_pitch,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top)230 bool ConvertBuffer_8bppPlt2Gray(uint8_t* dest_buf,
231 int dest_pitch,
232 int width,
233 int height,
234 const CFX_DIBSource* pSrcBitmap,
235 int src_left,
236 int src_top) {
237 uint32_t* src_plt = pSrcBitmap->GetPalette();
238 uint8_t gray[256];
239 if (pSrcBitmap->IsCmykImage()) {
240 uint8_t r;
241 uint8_t g;
242 uint8_t b;
243 for (size_t i = 0; i < FX_ArraySize(gray); i++) {
244 AdobeCMYK_to_sRGB1(
245 FXSYS_GetCValue(src_plt[i]), FXSYS_GetMValue(src_plt[i]),
246 FXSYS_GetYValue(src_plt[i]), FXSYS_GetKValue(src_plt[i]), r, g, b);
247 gray[i] = FXRGB2GRAY(r, g, b);
248 }
249 } else {
250 for (size_t i = 0; i < FX_ArraySize(gray); i++) {
251 gray[i] = FXRGB2GRAY(FXARGB_R(src_plt[i]), FXARGB_G(src_plt[i]),
252 FXARGB_B(src_plt[i]));
253 }
254 }
255
256 for (int row = 0; row < height; row++) {
257 uint8_t* dest_scan = dest_buf + row * dest_pitch;
258 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left;
259 for (int col = 0; col < width; col++) {
260 *dest_scan++ = gray[*src_scan++];
261 }
262 }
263 return true;
264 }
265
ConvertBuffer_RgbOrCmyk2Gray(uint8_t * dest_buf,int dest_pitch,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top)266 bool ConvertBuffer_RgbOrCmyk2Gray(uint8_t* dest_buf,
267 int dest_pitch,
268 int width,
269 int height,
270 const CFX_DIBSource* pSrcBitmap,
271 int src_left,
272 int src_top) {
273 int Bpp = pSrcBitmap->GetBPP() / 8;
274 if (pSrcBitmap->IsCmykImage()) {
275 for (int row = 0; row < height; row++) {
276 uint8_t* dest_scan = dest_buf + row * dest_pitch;
277 const uint8_t* src_scan =
278 pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
279 for (int col = 0; col < width; col++) {
280 uint8_t r, g, b;
281 AdobeCMYK_to_sRGB1(FXSYS_GetCValue((uint32_t)src_scan[0]),
282 FXSYS_GetMValue((uint32_t)src_scan[1]),
283 FXSYS_GetYValue((uint32_t)src_scan[2]),
284 FXSYS_GetKValue((uint32_t)src_scan[3]), r, g, b);
285 *dest_scan++ = FXRGB2GRAY(r, g, b);
286 src_scan += 4;
287 }
288 }
289 } else {
290 for (int row = 0; row < height; row++) {
291 uint8_t* dest_scan = dest_buf + row * dest_pitch;
292 const uint8_t* src_scan =
293 pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp;
294 for (int col = 0; col < width; col++) {
295 *dest_scan++ = FXRGB2GRAY(src_scan[2], src_scan[1], src_scan[0]);
296 src_scan += Bpp;
297 }
298 }
299 }
300 return true;
301 }
302
ConvertBuffer_IndexCopy(uint8_t * dest_buf,int dest_pitch,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top)303 void ConvertBuffer_IndexCopy(uint8_t* dest_buf,
304 int dest_pitch,
305 int width,
306 int height,
307 const CFX_DIBSource* pSrcBitmap,
308 int src_left,
309 int src_top) {
310 if (pSrcBitmap->GetBPP() == 1) {
311 for (int row = 0; row < height; row++) {
312 uint8_t* dest_scan = dest_buf + row * dest_pitch;
313 FXSYS_memset(dest_scan, 0, width);
314 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
315 for (int col = src_left; col < src_left + width; col++) {
316 if (src_scan[col / 8] & (1 << (7 - col % 8))) {
317 *dest_scan = 1;
318 }
319 dest_scan++;
320 }
321 }
322 } else {
323 for (int row = 0; row < height; row++) {
324 uint8_t* dest_scan = dest_buf + row * dest_pitch;
325 const uint8_t* src_scan =
326 pSrcBitmap->GetScanline(src_top + row) + src_left;
327 FXSYS_memcpy(dest_scan, src_scan, width);
328 }
329 }
330 }
331
ConvertBuffer_Plt2PltRgb8(uint8_t * dest_buf,int dest_pitch,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top,uint32_t * dst_plt)332 bool ConvertBuffer_Plt2PltRgb8(uint8_t* dest_buf,
333 int dest_pitch,
334 int width,
335 int height,
336 const CFX_DIBSource* pSrcBitmap,
337 int src_left,
338 int src_top,
339 uint32_t* dst_plt) {
340 ConvertBuffer_IndexCopy(dest_buf, dest_pitch, width, height, pSrcBitmap,
341 src_left, src_top);
342 uint32_t* src_plt = pSrcBitmap->GetPalette();
343 int plt_size = pSrcBitmap->GetPaletteSize();
344 if (pSrcBitmap->IsCmykImage()) {
345 for (int i = 0; i < plt_size; i++) {
346 uint8_t r;
347 uint8_t g;
348 uint8_t b;
349 AdobeCMYK_to_sRGB1(
350 FXSYS_GetCValue(src_plt[i]), FXSYS_GetMValue(src_plt[i]),
351 FXSYS_GetYValue(src_plt[i]), FXSYS_GetKValue(src_plt[i]), r, g, b);
352 dst_plt[i] = FXARGB_MAKE(0xff, r, g, b);
353 }
354 } else {
355 FXSYS_memcpy(dst_plt, src_plt, plt_size * 4);
356 }
357 return true;
358 }
359
ConvertBuffer_Rgb2PltRgb8(uint8_t * dest_buf,int dest_pitch,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top,uint32_t * dst_plt)360 bool ConvertBuffer_Rgb2PltRgb8(uint8_t* dest_buf,
361 int dest_pitch,
362 int width,
363 int height,
364 const CFX_DIBSource* pSrcBitmap,
365 int src_left,
366 int src_top,
367 uint32_t* dst_plt) {
368 int bpp = pSrcBitmap->GetBPP() / 8;
369 CFX_Palette palette;
370 palette.BuildPalette(pSrcBitmap);
371 uint32_t* cLut = palette.GetColorLut();
372 uint32_t* aLut = palette.GetAmountLut();
373 if (!cLut || !aLut) {
374 return false;
375 }
376 int lut = palette.Getlut();
377 uint32_t* pPalette = palette.GetPalette();
378 if (lut > 256) {
379 int err, min_err;
380 int lut_256 = lut - 256;
381 for (int row = 0; row < lut_256; row++) {
382 min_err = 1000000;
383 uint8_t r, g, b;
384 _ColorDecode(cLut[row], r, g, b);
385 int clrindex = 0;
386 for (int col = 0; col < 256; col++) {
387 uint32_t p_color = *(pPalette + col);
388 int d_r = r - (uint8_t)(p_color >> 16);
389 int d_g = g - (uint8_t)(p_color >> 8);
390 int d_b = b - (uint8_t)(p_color);
391 err = d_r * d_r + d_g * d_g + d_b * d_b;
392 if (err < min_err) {
393 min_err = err;
394 clrindex = col;
395 }
396 }
397 aLut[row] = clrindex;
398 }
399 }
400 int32_t lut_1 = lut - 1;
401 for (int row = 0; row < height; row++) {
402 uint8_t* src_scan =
403 (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left;
404 uint8_t* dest_scan = dest_buf + row * dest_pitch;
405 for (int col = 0; col < width; col++) {
406 uint8_t* src_port = src_scan + col * bpp;
407 int r = src_port[2] & 0xf0;
408 int g = src_port[1] & 0xf0;
409 int b = src_port[0] & 0xf0;
410 uint32_t clrindex = (r << 4) + g + (b >> 4);
411 for (int i = lut_1; i >= 0; i--)
412 if (clrindex == cLut[i]) {
413 *(dest_scan + col) = (uint8_t)(aLut[i]);
414 break;
415 }
416 }
417 }
418 FXSYS_memcpy(dst_plt, pPalette, sizeof(uint32_t) * 256);
419 return true;
420 }
421
ConvertBuffer_1bppMask2Rgb(FXDIB_Format dst_format,uint8_t * dest_buf,int dest_pitch,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top)422 bool ConvertBuffer_1bppMask2Rgb(FXDIB_Format dst_format,
423 uint8_t* dest_buf,
424 int dest_pitch,
425 int width,
426 int height,
427 const CFX_DIBSource* pSrcBitmap,
428 int src_left,
429 int src_top) {
430 int comps = (dst_format & 0xff) / 8;
431 uint8_t set_gray, reset_gray;
432 set_gray = 0xff;
433 reset_gray = 0x00;
434 for (int row = 0; row < height; row++) {
435 uint8_t* dest_scan = dest_buf + row * dest_pitch;
436 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
437 for (int col = src_left; col < src_left + width; col++) {
438 if (src_scan[col / 8] & (1 << (7 - col % 8))) {
439 dest_scan[0] = set_gray;
440 dest_scan[1] = set_gray;
441 dest_scan[2] = set_gray;
442 } else {
443 dest_scan[0] = reset_gray;
444 dest_scan[1] = reset_gray;
445 dest_scan[2] = reset_gray;
446 }
447 dest_scan += comps;
448 }
449 }
450 return true;
451 }
452
ConvertBuffer_8bppMask2Rgb(FXDIB_Format dst_format,uint8_t * dest_buf,int dest_pitch,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top)453 bool ConvertBuffer_8bppMask2Rgb(FXDIB_Format dst_format,
454 uint8_t* dest_buf,
455 int dest_pitch,
456 int width,
457 int height,
458 const CFX_DIBSource* pSrcBitmap,
459 int src_left,
460 int src_top) {
461 int comps = (dst_format & 0xff) / 8;
462 for (int row = 0; row < height; row++) {
463 uint8_t* dest_scan = dest_buf + row * dest_pitch;
464 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left;
465 uint8_t src_pixel;
466 for (int col = 0; col < width; col++) {
467 src_pixel = *src_scan++;
468 *dest_scan++ = src_pixel;
469 *dest_scan++ = src_pixel;
470 *dest_scan = src_pixel;
471 dest_scan += comps - 2;
472 }
473 }
474 return true;
475 }
476
ConvertBuffer_1bppPlt2Rgb(FXDIB_Format dst_format,uint8_t * dest_buf,int dest_pitch,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top)477 bool ConvertBuffer_1bppPlt2Rgb(FXDIB_Format dst_format,
478 uint8_t* dest_buf,
479 int dest_pitch,
480 int width,
481 int height,
482 const CFX_DIBSource* pSrcBitmap,
483 int src_left,
484 int src_top) {
485 int comps = (dst_format & 0xff) / 8;
486 uint32_t* src_plt = pSrcBitmap->GetPalette();
487 uint32_t plt[2];
488 uint8_t* bgr_ptr = (uint8_t*)plt;
489 if (pSrcBitmap->IsCmykImage()) {
490 plt[0] = FXCMYK_TODIB(src_plt[0]);
491 plt[1] = FXCMYK_TODIB(src_plt[1]);
492 } else {
493 bgr_ptr[0] = FXARGB_B(src_plt[0]);
494 bgr_ptr[1] = FXARGB_G(src_plt[0]);
495 bgr_ptr[2] = FXARGB_R(src_plt[0]);
496 bgr_ptr[3] = FXARGB_B(src_plt[1]);
497 bgr_ptr[4] = FXARGB_G(src_plt[1]);
498 bgr_ptr[5] = FXARGB_R(src_plt[1]);
499 }
500
501 if (pSrcBitmap->IsCmykImage()) {
502 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(src_plt[0]), FXSYS_GetMValue(src_plt[0]),
503 FXSYS_GetYValue(src_plt[0]), FXSYS_GetKValue(src_plt[0]),
504 bgr_ptr[2], bgr_ptr[1], bgr_ptr[0]);
505 AdobeCMYK_to_sRGB1(FXSYS_GetCValue(src_plt[1]), FXSYS_GetMValue(src_plt[1]),
506 FXSYS_GetYValue(src_plt[1]), FXSYS_GetKValue(src_plt[1]),
507 bgr_ptr[5], bgr_ptr[4], bgr_ptr[3]);
508 }
509
510 for (int row = 0; row < height; row++) {
511 uint8_t* dest_scan = dest_buf + row * dest_pitch;
512 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row);
513 for (int col = src_left; col < src_left + width; col++) {
514 if (src_scan[col / 8] & (1 << (7 - col % 8))) {
515 *dest_scan++ = bgr_ptr[3];
516 *dest_scan++ = bgr_ptr[4];
517 *dest_scan = bgr_ptr[5];
518 } else {
519 *dest_scan++ = bgr_ptr[0];
520 *dest_scan++ = bgr_ptr[1];
521 *dest_scan = bgr_ptr[2];
522 }
523 dest_scan += comps - 2;
524 }
525 }
526 return true;
527 }
528
ConvertBuffer_8bppPlt2Rgb(FXDIB_Format dst_format,uint8_t * dest_buf,int dest_pitch,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top)529 bool ConvertBuffer_8bppPlt2Rgb(FXDIB_Format dst_format,
530 uint8_t* dest_buf,
531 int dest_pitch,
532 int width,
533 int height,
534 const CFX_DIBSource* pSrcBitmap,
535 int src_left,
536 int src_top) {
537 int comps = (dst_format & 0xff) / 8;
538 uint32_t* src_plt = pSrcBitmap->GetPalette();
539 uint32_t plt[256];
540 uint8_t* bgr_ptr = (uint8_t*)plt;
541 if (!pSrcBitmap->IsCmykImage()) {
542 for (int i = 0; i < 256; i++) {
543 *bgr_ptr++ = FXARGB_B(src_plt[i]);
544 *bgr_ptr++ = FXARGB_G(src_plt[i]);
545 *bgr_ptr++ = FXARGB_R(src_plt[i]);
546 }
547 bgr_ptr = (uint8_t*)plt;
548 }
549
550 if (pSrcBitmap->IsCmykImage()) {
551 for (int i = 0; i < 256; i++) {
552 AdobeCMYK_to_sRGB1(
553 FXSYS_GetCValue(src_plt[i]), FXSYS_GetMValue(src_plt[i]),
554 FXSYS_GetYValue(src_plt[i]), FXSYS_GetKValue(src_plt[i]), bgr_ptr[2],
555 bgr_ptr[1], bgr_ptr[0]);
556 bgr_ptr += 3;
557 }
558 bgr_ptr = (uint8_t*)plt;
559 }
560
561 for (int row = 0; row < height; row++) {
562 uint8_t* dest_scan = dest_buf + row * dest_pitch;
563 const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left;
564 for (int col = 0; col < width; col++) {
565 uint8_t* src_pixel = bgr_ptr + 3 * (*src_scan++);
566 *dest_scan++ = *src_pixel++;
567 *dest_scan++ = *src_pixel++;
568 *dest_scan = *src_pixel++;
569 dest_scan += comps - 2;
570 }
571 }
572 return true;
573 }
574
ConvertBuffer_24bppRgb2Rgb24(uint8_t * dest_buf,int dest_pitch,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top)575 bool ConvertBuffer_24bppRgb2Rgb24(uint8_t* dest_buf,
576 int dest_pitch,
577 int width,
578 int height,
579 const CFX_DIBSource* pSrcBitmap,
580 int src_left,
581 int src_top) {
582 for (int row = 0; row < height; row++) {
583 uint8_t* dest_scan = dest_buf + row * dest_pitch;
584 const uint8_t* src_scan =
585 pSrcBitmap->GetScanline(src_top + row) + src_left * 3;
586 FXSYS_memcpy(dest_scan, src_scan, width * 3);
587 }
588 return true;
589 }
590
ConvertBuffer_32bppRgb2Rgb24(uint8_t * dest_buf,int dest_pitch,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top)591 bool ConvertBuffer_32bppRgb2Rgb24(uint8_t* dest_buf,
592 int dest_pitch,
593 int width,
594 int height,
595 const CFX_DIBSource* pSrcBitmap,
596 int src_left,
597 int src_top) {
598 for (int row = 0; row < height; row++) {
599 uint8_t* dest_scan = dest_buf + row * dest_pitch;
600 const uint8_t* src_scan =
601 pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
602 for (int col = 0; col < width; col++) {
603 *dest_scan++ = *src_scan++;
604 *dest_scan++ = *src_scan++;
605 *dest_scan++ = *src_scan++;
606 src_scan++;
607 }
608 }
609 return true;
610 }
611
ConvertBuffer_Rgb2Rgb32(uint8_t * dest_buf,int dest_pitch,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top)612 bool ConvertBuffer_Rgb2Rgb32(uint8_t* dest_buf,
613 int dest_pitch,
614 int width,
615 int height,
616 const CFX_DIBSource* pSrcBitmap,
617 int src_left,
618 int src_top) {
619 int comps = pSrcBitmap->GetBPP() / 8;
620 for (int row = 0; row < height; row++) {
621 uint8_t* dest_scan = dest_buf + row * dest_pitch;
622 const uint8_t* src_scan =
623 pSrcBitmap->GetScanline(src_top + row) + src_left * comps;
624 for (int col = 0; col < width; col++) {
625 *dest_scan++ = *src_scan++;
626 *dest_scan++ = *src_scan++;
627 *dest_scan++ = *src_scan++;
628 dest_scan++;
629 src_scan += comps - 3;
630 }
631 }
632 return true;
633 }
634
ConvertBuffer_32bppCmyk2Rgb32(uint8_t * dest_buf,int dest_pitch,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top)635 bool ConvertBuffer_32bppCmyk2Rgb32(uint8_t* dest_buf,
636 int dest_pitch,
637 int width,
638 int height,
639 const CFX_DIBSource* pSrcBitmap,
640 int src_left,
641 int src_top) {
642 for (int row = 0; row < height; row++) {
643 uint8_t* dest_scan = dest_buf + row * dest_pitch;
644 const uint8_t* src_scan =
645 pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
646 for (int col = 0; col < width; col++) {
647 AdobeCMYK_to_sRGB1(src_scan[0], src_scan[1], src_scan[2], src_scan[3],
648 dest_scan[2], dest_scan[1], dest_scan[0]);
649 dest_scan += 4;
650 src_scan += 4;
651 }
652 }
653 return true;
654 }
655
ConvertBuffer(FXDIB_Format dest_format,uint8_t * dest_buf,int dest_pitch,int width,int height,const CFX_DIBSource * pSrcBitmap,int src_left,int src_top,std::unique_ptr<uint32_t,FxFreeDeleter> * p_pal)656 bool ConvertBuffer(FXDIB_Format dest_format,
657 uint8_t* dest_buf,
658 int dest_pitch,
659 int width,
660 int height,
661 const CFX_DIBSource* pSrcBitmap,
662 int src_left,
663 int src_top,
664 std::unique_ptr<uint32_t, FxFreeDeleter>* p_pal) {
665 FXDIB_Format src_format = pSrcBitmap->GetFormat();
666 switch (dest_format) {
667 case FXDIB_Invalid:
668 case FXDIB_1bppCmyk:
669 case FXDIB_1bppMask:
670 case FXDIB_1bppRgb:
671 ASSERT(false);
672 return false;
673 case FXDIB_8bppMask: {
674 if ((src_format & 0xff) == 1) {
675 if (pSrcBitmap->GetPalette()) {
676 return ConvertBuffer_1bppPlt2Gray(dest_buf, dest_pitch, width, height,
677 pSrcBitmap, src_left, src_top);
678 }
679 return ConvertBuffer_1bppMask2Gray(dest_buf, dest_pitch, width, height,
680 pSrcBitmap, src_left, src_top);
681 }
682 if ((src_format & 0xff) == 8) {
683 if (pSrcBitmap->GetPalette()) {
684 return ConvertBuffer_8bppPlt2Gray(dest_buf, dest_pitch, width, height,
685 pSrcBitmap, src_left, src_top);
686 }
687 return ConvertBuffer_8bppMask2Gray(dest_buf, dest_pitch, width, height,
688 pSrcBitmap, src_left, src_top);
689 }
690 if ((src_format & 0xff) >= 24) {
691 return ConvertBuffer_RgbOrCmyk2Gray(dest_buf, dest_pitch, width, height,
692 pSrcBitmap, src_left, src_top);
693 }
694 return false;
695 }
696 case FXDIB_8bppRgb:
697 case FXDIB_8bppRgba: {
698 if ((src_format & 0xff) == 8 && !pSrcBitmap->GetPalette()) {
699 return ConvertBuffer(FXDIB_8bppMask, dest_buf, dest_pitch, width,
700 height, pSrcBitmap, src_left, src_top, p_pal);
701 }
702 p_pal->reset(FX_Alloc(uint32_t, 256));
703 if (((src_format & 0xff) == 1 || (src_format & 0xff) == 8) &&
704 pSrcBitmap->GetPalette()) {
705 return ConvertBuffer_Plt2PltRgb8(dest_buf, dest_pitch, width, height,
706 pSrcBitmap, src_left, src_top,
707 p_pal->get());
708 }
709 if ((src_format & 0xff) >= 24) {
710 return ConvertBuffer_Rgb2PltRgb8(dest_buf, dest_pitch, width, height,
711 pSrcBitmap, src_left, src_top,
712 p_pal->get());
713 }
714 return false;
715 }
716 case FXDIB_Rgb:
717 case FXDIB_Rgba: {
718 if ((src_format & 0xff) == 1) {
719 if (pSrcBitmap->GetPalette()) {
720 return ConvertBuffer_1bppPlt2Rgb(dest_format, dest_buf, dest_pitch,
721 width, height, pSrcBitmap, src_left,
722 src_top);
723 }
724 return ConvertBuffer_1bppMask2Rgb(dest_format, dest_buf, dest_pitch,
725 width, height, pSrcBitmap, src_left,
726 src_top);
727 }
728 if ((src_format & 0xff) == 8) {
729 if (pSrcBitmap->GetPalette()) {
730 return ConvertBuffer_8bppPlt2Rgb(dest_format, dest_buf, dest_pitch,
731 width, height, pSrcBitmap, src_left,
732 src_top);
733 }
734 return ConvertBuffer_8bppMask2Rgb(dest_format, dest_buf, dest_pitch,
735 width, height, pSrcBitmap, src_left,
736 src_top);
737 }
738 if ((src_format & 0xff) == 24) {
739 return ConvertBuffer_24bppRgb2Rgb24(dest_buf, dest_pitch, width, height,
740 pSrcBitmap, src_left, src_top);
741 }
742 if ((src_format & 0xff) == 32) {
743 return ConvertBuffer_32bppRgb2Rgb24(dest_buf, dest_pitch, width, height,
744 pSrcBitmap, src_left, src_top);
745 }
746 return false;
747 }
748 case FXDIB_Argb:
749 case FXDIB_Rgb32: {
750 if ((src_format & 0xff) == 1) {
751 if (pSrcBitmap->GetPalette()) {
752 return ConvertBuffer_1bppPlt2Rgb(dest_format, dest_buf, dest_pitch,
753 width, height, pSrcBitmap, src_left,
754 src_top);
755 }
756 return ConvertBuffer_1bppMask2Rgb(dest_format, dest_buf, dest_pitch,
757 width, height, pSrcBitmap, src_left,
758 src_top);
759 }
760 if ((src_format & 0xff) == 8) {
761 if (pSrcBitmap->GetPalette()) {
762 return ConvertBuffer_8bppPlt2Rgb(dest_format, dest_buf, dest_pitch,
763 width, height, pSrcBitmap, src_left,
764 src_top);
765 }
766 return ConvertBuffer_8bppMask2Rgb(dest_format, dest_buf, dest_pitch,
767 width, height, pSrcBitmap, src_left,
768 src_top);
769 }
770 if ((src_format & 0xff) >= 24) {
771 if (src_format & 0x0400) {
772 return ConvertBuffer_32bppCmyk2Rgb32(dest_buf, dest_pitch, width,
773 height, pSrcBitmap, src_left,
774 src_top);
775 }
776 return ConvertBuffer_Rgb2Rgb32(dest_buf, dest_pitch, width, height,
777 pSrcBitmap, src_left, src_top);
778 }
779 return false;
780 }
781 default:
782 return false;
783 }
784 }
785
CloneConvert(FXDIB_Format dest_format) const786 std::unique_ptr<CFX_DIBitmap> CFX_DIBSource::CloneConvert(
787 FXDIB_Format dest_format) const {
788 if (dest_format == GetFormat())
789 return Clone(nullptr);
790
791 std::unique_ptr<CFX_DIBitmap> pClone = pdfium::MakeUnique<CFX_DIBitmap>();
792 if (!pClone->Create(m_Width, m_Height, dest_format))
793 return nullptr;
794
795 CFX_MaybeOwned<CFX_DIBitmap> pSrcAlpha;
796 if (HasAlpha()) {
797 if (GetFormat() == FXDIB_Argb)
798 pSrcAlpha = CloneAlphaMask();
799 else
800 pSrcAlpha = m_pAlphaMask;
801
802 if (!pSrcAlpha)
803 return nullptr;
804 }
805 bool ret = true;
806 if (dest_format & 0x0200) {
807 if (dest_format == FXDIB_Argb) {
808 ret = pSrcAlpha
809 ? pClone->LoadChannel(FXDIB_Alpha, pSrcAlpha.Get(), FXDIB_Alpha)
810 : pClone->LoadChannel(FXDIB_Alpha, 0xff);
811 } else {
812 ret = pClone->SetAlphaMask(pSrcAlpha.Get());
813 }
814 }
815 if (!ret)
816 return nullptr;
817
818 std::unique_ptr<uint32_t, FxFreeDeleter> pal_8bpp;
819 if (!ConvertBuffer(dest_format, pClone->GetBuffer(), pClone->GetPitch(),
820 m_Width, m_Height, this, 0, 0, &pal_8bpp)) {
821 return nullptr;
822 }
823 if (pal_8bpp)
824 pClone->SetPalette(pal_8bpp.get());
825
826 return pClone;
827 }
828
ConvertFormat(FXDIB_Format dest_format)829 bool CFX_DIBitmap::ConvertFormat(FXDIB_Format dest_format) {
830 FXDIB_Format src_format = GetFormat();
831 if (dest_format == src_format)
832 return true;
833
834 if (dest_format == FXDIB_8bppMask && src_format == FXDIB_8bppRgb &&
835 !m_pPalette) {
836 m_AlphaFlag = 1;
837 return true;
838 }
839 if (dest_format == FXDIB_Argb && src_format == FXDIB_Rgb32) {
840 m_AlphaFlag = 2;
841 for (int row = 0; row < m_Height; row++) {
842 uint8_t* scanline = m_pBuffer + row * m_Pitch + 3;
843 for (int col = 0; col < m_Width; col++) {
844 *scanline = 0xff;
845 scanline += 4;
846 }
847 }
848 return true;
849 }
850 int dest_bpp = dest_format & 0xff;
851 int dest_pitch = (dest_bpp * m_Width + 31) / 32 * 4;
852 uint8_t* dest_buf = FX_TryAlloc(uint8_t, dest_pitch * m_Height + 4);
853 if (!dest_buf) {
854 return false;
855 }
856 CFX_DIBitmap* pAlphaMask = nullptr;
857 if (dest_format == FXDIB_Argb) {
858 FXSYS_memset(dest_buf, 0xff, dest_pitch * m_Height + 4);
859 if (m_pAlphaMask) {
860 for (int row = 0; row < m_Height; row++) {
861 uint8_t* pDstScanline = dest_buf + row * dest_pitch + 3;
862 const uint8_t* pSrcScanline = m_pAlphaMask->GetScanline(row);
863 for (int col = 0; col < m_Width; col++) {
864 *pDstScanline = *pSrcScanline++;
865 pDstScanline += 4;
866 }
867 }
868 }
869 } else if (dest_format & 0x0200) {
870 if (src_format == FXDIB_Argb) {
871 pAlphaMask = CloneAlphaMask().release();
872 if (!pAlphaMask) {
873 FX_Free(dest_buf);
874 return false;
875 }
876 } else {
877 if (!m_pAlphaMask) {
878 if (!BuildAlphaMask()) {
879 FX_Free(dest_buf);
880 return false;
881 }
882 pAlphaMask = m_pAlphaMask;
883 m_pAlphaMask = nullptr;
884 } else {
885 pAlphaMask = m_pAlphaMask;
886 }
887 }
888 }
889 bool ret = false;
890 std::unique_ptr<uint32_t, FxFreeDeleter> pal_8bpp;
891 ret = ConvertBuffer(dest_format, dest_buf, dest_pitch, m_Width, m_Height,
892 this, 0, 0, &pal_8bpp);
893 if (!ret) {
894 if (pAlphaMask != m_pAlphaMask)
895 delete pAlphaMask;
896 FX_Free(dest_buf);
897 return false;
898 }
899 if (m_pAlphaMask && pAlphaMask != m_pAlphaMask)
900 delete m_pAlphaMask;
901 m_pAlphaMask = pAlphaMask;
902 m_pPalette = std::move(pal_8bpp);
903 if (!m_bExtBuf)
904 FX_Free(m_pBuffer);
905 m_bExtBuf = false;
906 m_pBuffer = dest_buf;
907 m_bpp = (uint8_t)dest_format;
908 m_AlphaFlag = (uint8_t)(dest_format >> 8);
909 m_Pitch = dest_pitch;
910 return true;
911 }
912