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); 21 uint32_t* GetPalette() const { return m_pPalette; } 22 uint32_t* GetColorLut() const { return m_cLut; } 23 uint32_t* GetAmountLut() const { return m_aLut; } 24 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 }; 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 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 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 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 90 CFX_Palette::CFX_Palette() { 91 m_pPalette = nullptr; 92 m_cLut = nullptr; 93 m_aLut = nullptr; 94 m_lut = 0; 95 } 96 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 786 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 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