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 "render_int.h" 8 9 #include <algorithm> 10 #include <memory> 11 #include <vector> 12 13 #include "core/include/fpdfapi/fpdf_module.h" 14 #include "core/include/fpdfapi/fpdf_pageobj.h" 15 #include "core/include/fpdfapi/fpdf_render.h" 16 #include "core/include/fxcodec/fx_codec.h" 17 #include "core/include/fxcrt/fx_safe_types.h" 18 #include "core/include/fxge/fx_ge.h" 19 #include "core/src/fpdfapi/fpdf_page/pageint.h" 20 21 namespace { 22 23 unsigned int GetBits8(const uint8_t* pData, uint64_t bitpos, size_t nbits) { 24 ASSERT(nbits == 1 || nbits == 2 || nbits == 4 || nbits == 8 || nbits == 16); 25 ASSERT((bitpos & (nbits - 1)) == 0); 26 unsigned int byte = pData[bitpos / 8]; 27 if (nbits == 8) { 28 return byte; 29 } 30 if (nbits == 4) { 31 return (bitpos % 8) ? (byte & 0x0f) : (byte >> 4); 32 } 33 if (nbits == 2) { 34 return (byte >> (6 - bitpos % 8)) & 0x03; 35 } 36 if (nbits == 1) { 37 return (byte >> (7 - bitpos % 8)) & 0x01; 38 } 39 if (nbits == 16) { 40 return byte * 256 + pData[bitpos / 8 + 1]; 41 } 42 return 0; 43 } 44 45 FX_SAFE_DWORD CalculatePitch8(FX_DWORD bpc, FX_DWORD components, int width) { 46 FX_SAFE_DWORD pitch = bpc; 47 pitch *= components; 48 pitch *= width; 49 pitch += 7; 50 pitch /= 8; 51 return pitch; 52 } 53 54 FX_SAFE_DWORD CalculatePitch32(int bpp, int width) { 55 FX_SAFE_DWORD pitch = bpp; 56 pitch *= width; 57 pitch += 31; 58 pitch /= 32; // quantized to number of 32-bit words. 59 pitch *= 4; // and then back to bytes, (not just /8 in one step). 60 return pitch; 61 } 62 63 bool IsAllowedBPCValue(int bpc) { 64 return bpc == 1 || bpc == 2 || bpc == 4 || bpc == 8 || bpc == 16; 65 } 66 67 // Wrapper class to use with std::unique_ptr for CJPX_Decoder. 68 class JpxBitMapContext { 69 public: 70 explicit JpxBitMapContext(ICodec_JpxModule* jpx_module) 71 : jpx_module_(jpx_module), decoder_(nullptr) {} 72 73 ~JpxBitMapContext() { 74 jpx_module_->DestroyDecoder(decoder_); 75 } 76 77 // Takes ownership of |decoder|. 78 void set_decoder(CJPX_Decoder* decoder) { decoder_ = decoder; } 79 80 CJPX_Decoder* decoder() { return decoder_; } 81 82 private: 83 ICodec_JpxModule* const jpx_module_; // Weak pointer. 84 CJPX_Decoder* decoder_; // Decoder, owned. 85 86 // Disallow evil constructors 87 JpxBitMapContext(const JpxBitMapContext&); 88 void operator=(const JpxBitMapContext&); 89 }; 90 91 const int kMaxImageDimension = 0x01FFFF; 92 93 } // namespace 94 95 CFX_DIBSource* CPDF_Image::LoadDIBSource(CFX_DIBSource** ppMask, 96 FX_DWORD* pMatteColor, 97 FX_BOOL bStdCS, 98 FX_DWORD GroupFamily, 99 FX_BOOL bLoadMask) const { 100 CPDF_DIBSource* pSource = new CPDF_DIBSource; 101 if (pSource->Load(m_pDocument, m_pStream, (CPDF_DIBSource**)ppMask, 102 pMatteColor, NULL, NULL, bStdCS, GroupFamily, bLoadMask)) { 103 return pSource; 104 } 105 delete pSource; 106 return NULL; 107 } 108 CFX_DIBSource* CPDF_Image::DetachBitmap() { 109 CFX_DIBSource* pBitmap = m_pDIBSource; 110 m_pDIBSource = NULL; 111 return pBitmap; 112 } 113 CFX_DIBSource* CPDF_Image::DetachMask() { 114 CFX_DIBSource* pBitmap = m_pMask; 115 m_pMask = NULL; 116 return pBitmap; 117 } 118 FX_BOOL CPDF_Image::StartLoadDIBSource(CPDF_Dictionary* pFormResource, 119 CPDF_Dictionary* pPageResource, 120 FX_BOOL bStdCS, 121 FX_DWORD GroupFamily, 122 FX_BOOL bLoadMask) { 123 m_pDIBSource = new CPDF_DIBSource; 124 int ret = 125 ((CPDF_DIBSource*)m_pDIBSource) 126 ->StartLoadDIBSource(m_pDocument, m_pStream, TRUE, pFormResource, 127 pPageResource, bStdCS, GroupFamily, bLoadMask); 128 if (ret == 2) { 129 return TRUE; 130 } 131 if (!ret) { 132 delete m_pDIBSource; 133 m_pDIBSource = NULL; 134 return FALSE; 135 } 136 m_pMask = ((CPDF_DIBSource*)m_pDIBSource)->DetachMask(); 137 m_MatteColor = ((CPDF_DIBSource*)m_pDIBSource)->m_MatteColor; 138 return FALSE; 139 } 140 FX_BOOL CPDF_Image::Continue(IFX_Pause* pPause) { 141 int ret = ((CPDF_DIBSource*)m_pDIBSource)->ContinueLoadDIBSource(pPause); 142 if (ret == 2) { 143 return TRUE; 144 } 145 if (!ret) { 146 delete m_pDIBSource; 147 m_pDIBSource = NULL; 148 return FALSE; 149 } 150 m_pMask = ((CPDF_DIBSource*)m_pDIBSource)->DetachMask(); 151 m_MatteColor = ((CPDF_DIBSource*)m_pDIBSource)->m_MatteColor; 152 return FALSE; 153 } 154 CPDF_DIBSource::CPDF_DIBSource() { 155 m_pDocument = NULL; 156 m_pStreamAcc = NULL; 157 m_pDict = NULL; 158 m_bpp = 0; 159 m_Width = m_Height = 0; 160 m_pColorSpace = NULL; 161 m_bDefaultDecode = TRUE; 162 m_bImageMask = FALSE; 163 m_bDoBpcCheck = TRUE; 164 m_pPalette = NULL; 165 m_pCompData = NULL; 166 m_bColorKey = FALSE; 167 m_pMaskedLine = m_pLineBuf = NULL; 168 m_pDecoder = NULL; 169 m_nComponents = 0; 170 m_bpc = 0; 171 m_bLoadMask = FALSE; 172 m_Family = 0; 173 m_pMask = NULL; 174 m_MatteColor = 0; 175 m_pJbig2Context = NULL; 176 m_pGlobalStream = NULL; 177 m_bStdCS = FALSE; 178 m_pMaskStream = NULL; 179 m_Status = 0; 180 m_bHasMask = FALSE; 181 } 182 CPDF_DIBSource::~CPDF_DIBSource() { 183 delete m_pStreamAcc; 184 FX_Free(m_pMaskedLine); 185 FX_Free(m_pLineBuf); 186 m_pCachedBitmap.reset(); 187 delete m_pDecoder; 188 FX_Free(m_pCompData); 189 CPDF_ColorSpace* pCS = m_pColorSpace; 190 if (pCS && m_pDocument) { 191 m_pDocument->GetPageData()->ReleaseColorSpace(pCS->GetArray()); 192 } 193 if (m_pJbig2Context) { 194 ICodec_Jbig2Module* pJbig2Module = CPDF_ModuleMgr::Get()->GetJbig2Module(); 195 pJbig2Module->DestroyJbig2Context(m_pJbig2Context); 196 } 197 delete m_pGlobalStream; 198 } 199 CFX_DIBitmap* CPDF_DIBSource::GetBitmap() const { 200 return m_pCachedBitmap ? m_pCachedBitmap.get() : Clone(); 201 } 202 void CPDF_DIBSource::ReleaseBitmap(CFX_DIBitmap* pBitmap) const { 203 if (pBitmap && pBitmap != m_pCachedBitmap.get()) { 204 delete pBitmap; 205 } 206 } 207 FX_BOOL CPDF_DIBSource::Load(CPDF_Document* pDoc, 208 const CPDF_Stream* pStream, 209 CPDF_DIBSource** ppMask, 210 FX_DWORD* pMatteColor, 211 CPDF_Dictionary* pFormResources, 212 CPDF_Dictionary* pPageResources, 213 FX_BOOL bStdCS, 214 FX_DWORD GroupFamily, 215 FX_BOOL bLoadMask) { 216 if (!pStream) { 217 return FALSE; 218 } 219 m_pDocument = pDoc; 220 m_pDict = pStream->GetDict(); 221 if (!m_pDict) { 222 return FALSE; 223 } 224 m_pStream = pStream; 225 m_Width = m_pDict->GetInteger("Width"); 226 m_Height = m_pDict->GetInteger("Height"); 227 if (m_Width <= 0 || m_Height <= 0 || m_Width > kMaxImageDimension || 228 m_Height > kMaxImageDimension) { 229 return FALSE; 230 } 231 m_GroupFamily = GroupFamily; 232 m_bLoadMask = bLoadMask; 233 if (!LoadColorInfo(m_pStream->GetObjNum() != 0 ? NULL : pFormResources, 234 pPageResources)) { 235 return FALSE; 236 } 237 if (m_bDoBpcCheck && (m_bpc == 0 || m_nComponents == 0)) { 238 return FALSE; 239 } 240 FX_SAFE_DWORD src_size = 241 CalculatePitch8(m_bpc, m_nComponents, m_Width) * m_Height; 242 if (!src_size.IsValid()) { 243 return FALSE; 244 } 245 m_pStreamAcc = new CPDF_StreamAcc; 246 m_pStreamAcc->LoadAllData(pStream, FALSE, src_size.ValueOrDie(), TRUE); 247 if (m_pStreamAcc->GetSize() == 0 || !m_pStreamAcc->GetData()) { 248 return FALSE; 249 } 250 if (!CreateDecoder()) { 251 return FALSE; 252 } 253 if (m_bImageMask) { 254 m_bpp = 1; 255 m_bpc = 1; 256 m_nComponents = 1; 257 m_AlphaFlag = 1; 258 } else if (m_bpc * m_nComponents == 1) { 259 m_bpp = 1; 260 } else if (m_bpc * m_nComponents <= 8) { 261 m_bpp = 8; 262 } else { 263 m_bpp = 24; 264 } 265 FX_SAFE_DWORD pitch = CalculatePitch32(m_bpp, m_Width); 266 if (!pitch.IsValid()) { 267 return FALSE; 268 } 269 m_pLineBuf = FX_Alloc(uint8_t, pitch.ValueOrDie()); 270 if (m_pColorSpace && bStdCS) { 271 m_pColorSpace->EnableStdConversion(TRUE); 272 } 273 LoadPalette(); 274 if (m_bColorKey) { 275 m_bpp = 32; 276 m_AlphaFlag = 2; 277 pitch = CalculatePitch32(m_bpp, m_Width); 278 if (!pitch.IsValid()) { 279 return FALSE; 280 } 281 m_pMaskedLine = FX_Alloc(uint8_t, pitch.ValueOrDie()); 282 } 283 m_Pitch = pitch.ValueOrDie(); 284 if (ppMask) { 285 *ppMask = LoadMask(*pMatteColor); 286 } 287 if (m_pColorSpace && bStdCS) { 288 m_pColorSpace->EnableStdConversion(FALSE); 289 } 290 return TRUE; 291 } 292 int CPDF_DIBSource::ContinueToLoadMask() { 293 if (m_bImageMask) { 294 m_bpp = 1; 295 m_bpc = 1; 296 m_nComponents = 1; 297 m_AlphaFlag = 1; 298 } else if (m_bpc * m_nComponents == 1) { 299 m_bpp = 1; 300 } else if (m_bpc * m_nComponents <= 8) { 301 m_bpp = 8; 302 } else { 303 m_bpp = 24; 304 } 305 if (!m_bpc || !m_nComponents) { 306 return 0; 307 } 308 FX_SAFE_DWORD pitch = CalculatePitch32(m_bpp, m_Width); 309 if (!pitch.IsValid()) { 310 return 0; 311 } 312 m_pLineBuf = FX_Alloc(uint8_t, pitch.ValueOrDie()); 313 if (m_pColorSpace && m_bStdCS) { 314 m_pColorSpace->EnableStdConversion(TRUE); 315 } 316 LoadPalette(); 317 if (m_bColorKey) { 318 m_bpp = 32; 319 m_AlphaFlag = 2; 320 pitch = CalculatePitch32(m_bpp, m_Width); 321 if (!pitch.IsValid()) { 322 return 0; 323 } 324 m_pMaskedLine = FX_Alloc(uint8_t, pitch.ValueOrDie()); 325 } 326 m_Pitch = pitch.ValueOrDie(); 327 return 1; 328 } 329 int CPDF_DIBSource::StartLoadDIBSource(CPDF_Document* pDoc, 330 const CPDF_Stream* pStream, 331 FX_BOOL bHasMask, 332 CPDF_Dictionary* pFormResources, 333 CPDF_Dictionary* pPageResources, 334 FX_BOOL bStdCS, 335 FX_DWORD GroupFamily, 336 FX_BOOL bLoadMask) { 337 if (!pStream) { 338 return 0; 339 } 340 m_pDocument = pDoc; 341 m_pDict = pStream->GetDict(); 342 m_pStream = pStream; 343 m_bStdCS = bStdCS; 344 m_bHasMask = bHasMask; 345 m_Width = m_pDict->GetInteger("Width"); 346 m_Height = m_pDict->GetInteger("Height"); 347 if (m_Width <= 0 || m_Height <= 0 || m_Width > kMaxImageDimension || 348 m_Height > kMaxImageDimension) { 349 return 0; 350 } 351 m_GroupFamily = GroupFamily; 352 m_bLoadMask = bLoadMask; 353 if (!LoadColorInfo(m_pStream->GetObjNum() != 0 ? NULL : pFormResources, 354 pPageResources)) { 355 return 0; 356 } 357 if (m_bDoBpcCheck && (m_bpc == 0 || m_nComponents == 0)) { 358 return 0; 359 } 360 FX_SAFE_DWORD src_size = 361 CalculatePitch8(m_bpc, m_nComponents, m_Width) * m_Height; 362 if (!src_size.IsValid()) { 363 return 0; 364 } 365 m_pStreamAcc = new CPDF_StreamAcc; 366 m_pStreamAcc->LoadAllData(pStream, FALSE, src_size.ValueOrDie(), TRUE); 367 if (m_pStreamAcc->GetSize() == 0 || !m_pStreamAcc->GetData()) { 368 return 0; 369 } 370 int ret = CreateDecoder(); 371 if (ret != 1) { 372 if (!ret) { 373 return ret; 374 } 375 if (!ContinueToLoadMask()) { 376 return 0; 377 } 378 if (m_bHasMask) { 379 StratLoadMask(); 380 } 381 return ret; 382 } 383 if (!ContinueToLoadMask()) { 384 return 0; 385 } 386 if (m_bHasMask) { 387 ret = StratLoadMask(); 388 } 389 if (ret == 2) { 390 return ret; 391 } 392 if (m_pColorSpace && m_bStdCS) { 393 m_pColorSpace->EnableStdConversion(FALSE); 394 } 395 return ret; 396 } 397 int CPDF_DIBSource::ContinueLoadDIBSource(IFX_Pause* pPause) { 398 FXCODEC_STATUS ret; 399 if (m_Status == 1) { 400 const CFX_ByteString& decoder = m_pStreamAcc->GetImageDecoder(); 401 if (decoder == "JPXDecode") { 402 return 0; 403 } 404 ICodec_Jbig2Module* pJbig2Module = CPDF_ModuleMgr::Get()->GetJbig2Module(); 405 if (!m_pJbig2Context) { 406 m_pJbig2Context = pJbig2Module->CreateJbig2Context(); 407 if (m_pStreamAcc->GetImageParam()) { 408 CPDF_Stream* pGlobals = 409 m_pStreamAcc->GetImageParam()->GetStream("JBIG2Globals"); 410 if (pGlobals) { 411 m_pGlobalStream = new CPDF_StreamAcc; 412 m_pGlobalStream->LoadAllData(pGlobals, FALSE); 413 } 414 } 415 ret = pJbig2Module->StartDecode(m_pJbig2Context, m_pDocument, m_Width, 416 m_Height, m_pStreamAcc, m_pGlobalStream, 417 m_pCachedBitmap->GetBuffer(), 418 m_pCachedBitmap->GetPitch(), pPause); 419 if (ret < 0) { 420 m_pCachedBitmap.reset(); 421 delete m_pGlobalStream; 422 m_pGlobalStream = NULL; 423 pJbig2Module->DestroyJbig2Context(m_pJbig2Context); 424 m_pJbig2Context = NULL; 425 return 0; 426 } 427 if (ret == FXCODEC_STATUS_DECODE_TOBECONTINUE) { 428 return 2; 429 } 430 int ret1 = 1; 431 if (m_bHasMask) { 432 ret1 = ContinueLoadMaskDIB(pPause); 433 m_Status = 2; 434 } 435 if (ret1 == 2) { 436 return ret1; 437 } 438 if (m_pColorSpace && m_bStdCS) { 439 m_pColorSpace->EnableStdConversion(FALSE); 440 } 441 return ret1; 442 } 443 FXCODEC_STATUS ret = pJbig2Module->ContinueDecode(m_pJbig2Context, pPause); 444 if (ret < 0) { 445 m_pCachedBitmap.reset(); 446 delete m_pGlobalStream; 447 m_pGlobalStream = NULL; 448 pJbig2Module->DestroyJbig2Context(m_pJbig2Context); 449 m_pJbig2Context = NULL; 450 return 0; 451 } 452 if (ret == FXCODEC_STATUS_DECODE_TOBECONTINUE) { 453 return 2; 454 } 455 int ret1 = 1; 456 if (m_bHasMask) { 457 ret1 = ContinueLoadMaskDIB(pPause); 458 m_Status = 2; 459 } 460 if (ret1 == 2) { 461 return ret1; 462 } 463 if (m_pColorSpace && m_bStdCS) { 464 m_pColorSpace->EnableStdConversion(FALSE); 465 } 466 return ret1; 467 } 468 if (m_Status == 2) { 469 return ContinueLoadMaskDIB(pPause); 470 } 471 return 0; 472 } 473 474 bool CPDF_DIBSource::LoadColorInfo(const CPDF_Dictionary* pFormResources, 475 const CPDF_Dictionary* pPageResources) { 476 m_bpc_orig = m_pDict->GetInteger("BitsPerComponent"); 477 if (m_pDict->GetInteger("ImageMask")) 478 m_bImageMask = TRUE; 479 480 if (m_bImageMask || !m_pDict->KeyExist("ColorSpace")) { 481 if (!m_bImageMask) { 482 CPDF_Object* pFilter = m_pDict->GetElementValue("Filter"); 483 if (pFilter) { 484 CFX_ByteString filter; 485 if (pFilter->IsName()) { 486 filter = pFilter->GetString(); 487 } else if (CPDF_Array* pArray = pFilter->AsArray()) { 488 filter = pArray->GetString(pArray->GetCount() - 1); 489 } 490 491 if (filter == "JPXDecode") { 492 m_bDoBpcCheck = FALSE; 493 return true; 494 } 495 } 496 } 497 m_bImageMask = TRUE; 498 m_bpc = m_nComponents = 1; 499 CPDF_Array* pDecode = m_pDict->GetArray("Decode"); 500 m_bDefaultDecode = !pDecode || !pDecode->GetInteger(0); 501 return true; 502 } 503 504 CPDF_Object* pCSObj = m_pDict->GetElementValue("ColorSpace"); 505 if (!pCSObj) 506 return false; 507 508 CPDF_DocPageData* pDocPageData = m_pDocument->GetPageData(); 509 if (pFormResources) 510 m_pColorSpace = pDocPageData->GetColorSpace(pCSObj, pFormResources); 511 if (!m_pColorSpace) 512 m_pColorSpace = pDocPageData->GetColorSpace(pCSObj, pPageResources); 513 if (!m_pColorSpace) 514 return false; 515 516 m_Family = m_pColorSpace->GetFamily(); 517 m_nComponents = m_pColorSpace->CountComponents(); 518 if (m_Family == PDFCS_ICCBASED && pCSObj->IsName()) { 519 CFX_ByteString cs = pCSObj->GetString(); 520 if (cs == "DeviceGray") { 521 m_nComponents = 1; 522 } else if (cs == "DeviceRGB") { 523 m_nComponents = 3; 524 } else if (cs == "DeviceCMYK") { 525 m_nComponents = 4; 526 } 527 } 528 ValidateDictParam(); 529 m_pCompData = GetDecodeAndMaskArray(m_bDefaultDecode, m_bColorKey); 530 return !!m_pCompData; 531 } 532 533 DIB_COMP_DATA* CPDF_DIBSource::GetDecodeAndMaskArray(FX_BOOL& bDefaultDecode, 534 FX_BOOL& bColorKey) { 535 if (!m_pColorSpace) { 536 return NULL; 537 } 538 DIB_COMP_DATA* pCompData = FX_Alloc(DIB_COMP_DATA, m_nComponents); 539 int max_data = (1 << m_bpc) - 1; 540 CPDF_Array* pDecode = m_pDict->GetArray("Decode"); 541 if (pDecode) { 542 for (FX_DWORD i = 0; i < m_nComponents; i++) { 543 pCompData[i].m_DecodeMin = pDecode->GetNumber(i * 2); 544 FX_FLOAT max = pDecode->GetNumber(i * 2 + 1); 545 pCompData[i].m_DecodeStep = (max - pCompData[i].m_DecodeMin) / max_data; 546 FX_FLOAT def_value, def_min, def_max; 547 m_pColorSpace->GetDefaultValue(i, def_value, def_min, def_max); 548 if (m_Family == PDFCS_INDEXED) { 549 def_max = (FX_FLOAT)max_data; 550 } 551 if (def_min != pCompData[i].m_DecodeMin || def_max != max) { 552 bDefaultDecode = FALSE; 553 } 554 } 555 } else { 556 for (FX_DWORD i = 0; i < m_nComponents; i++) { 557 FX_FLOAT def_value; 558 m_pColorSpace->GetDefaultValue(i, def_value, pCompData[i].m_DecodeMin, 559 pCompData[i].m_DecodeStep); 560 if (m_Family == PDFCS_INDEXED) { 561 pCompData[i].m_DecodeStep = (FX_FLOAT)max_data; 562 } 563 pCompData[i].m_DecodeStep = 564 (pCompData[i].m_DecodeStep - pCompData[i].m_DecodeMin) / max_data; 565 } 566 } 567 if (!m_pDict->KeyExist("SMask")) { 568 CPDF_Object* pMask = m_pDict->GetElementValue("Mask"); 569 if (!pMask) { 570 return pCompData; 571 } 572 if (CPDF_Array* pArray = pMask->AsArray()) { 573 if (pArray->GetCount() >= m_nComponents * 2) { 574 for (FX_DWORD i = 0; i < m_nComponents; i++) { 575 int min_num = pArray->GetInteger(i * 2); 576 int max_num = pArray->GetInteger(i * 2 + 1); 577 pCompData[i].m_ColorKeyMin = std::max(min_num, 0); 578 pCompData[i].m_ColorKeyMax = std::min(max_num, max_data); 579 } 580 } 581 bColorKey = TRUE; 582 } 583 } 584 return pCompData; 585 } 586 ICodec_ScanlineDecoder* FPDFAPI_CreateFaxDecoder( 587 const uint8_t* src_buf, 588 FX_DWORD src_size, 589 int width, 590 int height, 591 const CPDF_Dictionary* pParams); 592 ICodec_ScanlineDecoder* FPDFAPI_CreateFlateDecoder( 593 const uint8_t* src_buf, 594 FX_DWORD src_size, 595 int width, 596 int height, 597 int nComps, 598 int bpc, 599 const CPDF_Dictionary* pParams); 600 int CPDF_DIBSource::CreateDecoder() { 601 const CFX_ByteString& decoder = m_pStreamAcc->GetImageDecoder(); 602 if (decoder.IsEmpty()) { 603 return 1; 604 } 605 if (m_bDoBpcCheck && m_bpc == 0) { 606 return 0; 607 } 608 const uint8_t* src_data = m_pStreamAcc->GetData(); 609 FX_DWORD src_size = m_pStreamAcc->GetSize(); 610 const CPDF_Dictionary* pParams = m_pStreamAcc->GetImageParam(); 611 if (decoder == "CCITTFaxDecode") { 612 m_pDecoder = FPDFAPI_CreateFaxDecoder(src_data, src_size, m_Width, m_Height, 613 pParams); 614 } else if (decoder == "DCTDecode") { 615 m_pDecoder = CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder( 616 src_data, src_size, m_Width, m_Height, m_nComponents, 617 pParams ? pParams->GetInteger("ColorTransform", 1) : 1); 618 if (!m_pDecoder) { 619 FX_BOOL bTransform = FALSE; 620 int comps, bpc; 621 ICodec_JpegModule* pJpegModule = CPDF_ModuleMgr::Get()->GetJpegModule(); 622 if (pJpegModule->LoadInfo(src_data, src_size, m_Width, m_Height, comps, 623 bpc, bTransform)) { 624 if (m_nComponents != comps) { 625 FX_Free(m_pCompData); 626 m_nComponents = comps; 627 if (m_Family == PDFCS_LAB && m_nComponents != 3) { 628 m_pCompData = NULL; 629 return 0; 630 } 631 m_pCompData = GetDecodeAndMaskArray(m_bDefaultDecode, m_bColorKey); 632 if (!m_pCompData) { 633 return 0; 634 } 635 } 636 m_bpc = bpc; 637 m_pDecoder = CPDF_ModuleMgr::Get()->GetJpegModule()->CreateDecoder( 638 src_data, src_size, m_Width, m_Height, m_nComponents, bTransform); 639 } 640 } 641 } else if (decoder == "FlateDecode") { 642 m_pDecoder = FPDFAPI_CreateFlateDecoder( 643 src_data, src_size, m_Width, m_Height, m_nComponents, m_bpc, pParams); 644 } else if (decoder == "JPXDecode") { 645 LoadJpxBitmap(); 646 return m_pCachedBitmap ? 1 : 0; 647 } else if (decoder == "JBIG2Decode") { 648 m_pCachedBitmap.reset(new CFX_DIBitmap); 649 if (!m_pCachedBitmap->Create( 650 m_Width, m_Height, m_bImageMask ? FXDIB_1bppMask : FXDIB_1bppRgb)) { 651 m_pCachedBitmap.reset(); 652 return 0; 653 } 654 m_Status = 1; 655 return 2; 656 } else if (decoder == "RunLengthDecode") { 657 m_pDecoder = CPDF_ModuleMgr::Get() 658 ->GetCodecModule() 659 ->GetBasicModule() 660 ->CreateRunLengthDecoder(src_data, src_size, m_Width, 661 m_Height, m_nComponents, m_bpc); 662 } 663 if (!m_pDecoder) 664 return 0; 665 666 FX_SAFE_DWORD requested_pitch = 667 CalculatePitch8(m_bpc, m_nComponents, m_Width); 668 if (!requested_pitch.IsValid()) { 669 return 0; 670 } 671 FX_SAFE_DWORD provided_pitch = CalculatePitch8( 672 m_pDecoder->GetBPC(), m_pDecoder->CountComps(), m_pDecoder->GetWidth()); 673 if (!provided_pitch.IsValid()) { 674 return 0; 675 } 676 if (provided_pitch.ValueOrDie() < requested_pitch.ValueOrDie()) { 677 return 0; 678 } 679 return 1; 680 } 681 void CPDF_DIBSource::LoadJpxBitmap() { 682 ICodec_JpxModule* pJpxModule = CPDF_ModuleMgr::Get()->GetJpxModule(); 683 if (!pJpxModule) 684 return; 685 686 std::unique_ptr<JpxBitMapContext> context(new JpxBitMapContext(pJpxModule)); 687 context->set_decoder(pJpxModule->CreateDecoder( 688 m_pStreamAcc->GetData(), m_pStreamAcc->GetSize(), m_pColorSpace)); 689 if (!context->decoder()) 690 return; 691 692 FX_DWORD width = 0; 693 FX_DWORD height = 0; 694 FX_DWORD components = 0; 695 pJpxModule->GetImageInfo(context->decoder(), &width, &height, &components); 696 if ((int)width < m_Width || (int)height < m_Height) 697 return; 698 699 FX_BOOL bSwapRGB = FALSE; 700 if (m_pColorSpace) { 701 if (components != (FX_DWORD)m_pColorSpace->CountComponents()) 702 return; 703 704 if (m_pColorSpace == CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB)) { 705 bSwapRGB = TRUE; 706 m_pColorSpace = nullptr; 707 } 708 } else { 709 if (components == 3) { 710 bSwapRGB = TRUE; 711 } else if (components == 4) { 712 m_pColorSpace = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICECMYK); 713 } 714 m_nComponents = components; 715 } 716 717 FXDIB_Format format; 718 if (components == 1) { 719 format = FXDIB_8bppRgb; 720 } else if (components <= 3) { 721 format = FXDIB_Rgb; 722 } else if (components == 4) { 723 format = FXDIB_Rgb32; 724 } else { 725 width = (width * components + 2) / 3; 726 format = FXDIB_Rgb; 727 } 728 729 m_pCachedBitmap.reset(new CFX_DIBitmap); 730 if (!m_pCachedBitmap->Create(width, height, format)) { 731 m_pCachedBitmap.reset(); 732 return; 733 } 734 m_pCachedBitmap->Clear(0xFFFFFFFF); 735 std::vector<uint8_t> output_offsets(components); 736 for (FX_DWORD i = 0; i < components; ++i) 737 output_offsets[i] = i; 738 if (bSwapRGB) { 739 output_offsets[0] = 2; 740 output_offsets[2] = 0; 741 } 742 if (!pJpxModule->Decode(context->decoder(), m_pCachedBitmap->GetBuffer(), 743 m_pCachedBitmap->GetPitch(), output_offsets)) { 744 m_pCachedBitmap.reset(); 745 return; 746 } 747 if (m_pColorSpace && m_pColorSpace->GetFamily() == PDFCS_INDEXED && 748 m_bpc < 8) { 749 int scale = 8 - m_bpc; 750 for (FX_DWORD row = 0; row < height; ++row) { 751 uint8_t* scanline = (uint8_t*)m_pCachedBitmap->GetScanline(row); 752 for (FX_DWORD col = 0; col < width; ++col) { 753 *scanline = (*scanline) >> scale; 754 ++scanline; 755 } 756 } 757 } 758 m_bpc = 8; 759 } 760 CPDF_DIBSource* CPDF_DIBSource::LoadMask(FX_DWORD& MatteColor) { 761 MatteColor = 0xFFFFFFFF; 762 CPDF_Stream* pSoftMask = m_pDict->GetStream("SMask"); 763 if (pSoftMask) { 764 CPDF_Array* pMatte = pSoftMask->GetDict()->GetArray("Matte"); 765 if (pMatte && m_pColorSpace && 766 (FX_DWORD)m_pColorSpace->CountComponents() <= m_nComponents) { 767 FX_FLOAT* pColor = FX_Alloc(FX_FLOAT, m_nComponents); 768 for (FX_DWORD i = 0; i < m_nComponents; i++) { 769 pColor[i] = pMatte->GetFloat(i); 770 } 771 FX_FLOAT R, G, B; 772 m_pColorSpace->GetRGB(pColor, R, G, B); 773 FX_Free(pColor); 774 MatteColor = FXARGB_MAKE(0, FXSYS_round(R * 255), FXSYS_round(G * 255), 775 FXSYS_round(B * 255)); 776 } 777 return LoadMaskDIB(pSoftMask); 778 } 779 780 if (CPDF_Stream* pStream = ToStream(m_pDict->GetElementValue("Mask"))) 781 return LoadMaskDIB(pStream); 782 783 return nullptr; 784 } 785 int CPDF_DIBSource::StratLoadMask() { 786 m_MatteColor = 0XFFFFFFFF; 787 m_pMaskStream = m_pDict->GetStream("SMask"); 788 if (m_pMaskStream) { 789 CPDF_Array* pMatte = m_pMaskStream->GetDict()->GetArray("Matte"); 790 if (pMatte && m_pColorSpace && 791 (FX_DWORD)m_pColorSpace->CountComponents() <= m_nComponents) { 792 FX_FLOAT R, G, B; 793 FX_FLOAT* pColor = FX_Alloc(FX_FLOAT, m_nComponents); 794 for (FX_DWORD i = 0; i < m_nComponents; i++) { 795 pColor[i] = pMatte->GetFloat(i); 796 } 797 m_pColorSpace->GetRGB(pColor, R, G, B); 798 FX_Free(pColor); 799 m_MatteColor = FXARGB_MAKE(0, FXSYS_round(R * 255), FXSYS_round(G * 255), 800 FXSYS_round(B * 255)); 801 } 802 return StartLoadMaskDIB(); 803 } 804 805 m_pMaskStream = ToStream(m_pDict->GetElementValue("Mask")); 806 return m_pMaskStream ? StartLoadMaskDIB() : 1; 807 } 808 int CPDF_DIBSource::ContinueLoadMaskDIB(IFX_Pause* pPause) { 809 if (!m_pMask) { 810 return 1; 811 } 812 int ret = m_pMask->ContinueLoadDIBSource(pPause); 813 if (ret == 2) { 814 return ret; 815 } 816 if (m_pColorSpace && m_bStdCS) { 817 m_pColorSpace->EnableStdConversion(FALSE); 818 } 819 if (!ret) { 820 delete m_pMask; 821 m_pMask = NULL; 822 return ret; 823 } 824 return 1; 825 } 826 CPDF_DIBSource* CPDF_DIBSource::DetachMask() { 827 CPDF_DIBSource* pDIBSource = m_pMask; 828 m_pMask = NULL; 829 return pDIBSource; 830 } 831 CPDF_DIBSource* CPDF_DIBSource::LoadMaskDIB(CPDF_Stream* pMask) { 832 CPDF_DIBSource* pMaskSource = new CPDF_DIBSource; 833 if (!pMaskSource->Load(m_pDocument, pMask, NULL, NULL, NULL, NULL, TRUE)) { 834 delete pMaskSource; 835 return NULL; 836 } 837 return pMaskSource; 838 } 839 int CPDF_DIBSource::StartLoadMaskDIB() { 840 m_pMask = new CPDF_DIBSource; 841 int ret = m_pMask->StartLoadDIBSource(m_pDocument, m_pMaskStream, FALSE, 842 nullptr, nullptr, TRUE); 843 if (ret == 2) { 844 if (m_Status == 0) 845 m_Status = 2; 846 return 2; 847 } 848 if (!ret) { 849 delete m_pMask; 850 m_pMask = nullptr; 851 return 1; 852 } 853 return 1; 854 } 855 void CPDF_DIBSource::LoadPalette() { 856 if (m_bpc == 0) { 857 return; 858 } 859 if (m_bpc * m_nComponents > 8) { 860 return; 861 } 862 if (!m_pColorSpace) { 863 return; 864 } 865 if (m_bpc * m_nComponents == 1) { 866 if (m_bDefaultDecode && 867 (m_Family == PDFCS_DEVICEGRAY || m_Family == PDFCS_DEVICERGB)) { 868 return; 869 } 870 if (m_pColorSpace->CountComponents() > 3) { 871 return; 872 } 873 FX_FLOAT color_values[3]; 874 color_values[0] = m_pCompData[0].m_DecodeMin; 875 color_values[1] = color_values[2] = color_values[0]; 876 FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; 877 m_pColorSpace->GetRGB(color_values, R, G, B); 878 FX_ARGB argb0 = ArgbEncode(255, FXSYS_round(R * 255), FXSYS_round(G * 255), 879 FXSYS_round(B * 255)); 880 color_values[0] += m_pCompData[0].m_DecodeStep; 881 color_values[1] += m_pCompData[0].m_DecodeStep; 882 color_values[2] += m_pCompData[0].m_DecodeStep; 883 m_pColorSpace->GetRGB(color_values, R, G, B); 884 FX_ARGB argb1 = ArgbEncode(255, FXSYS_round(R * 255), FXSYS_round(G * 255), 885 FXSYS_round(B * 255)); 886 if (argb0 != 0xFF000000 || argb1 != 0xFFFFFFFF) { 887 SetPaletteArgb(0, argb0); 888 SetPaletteArgb(1, argb1); 889 } 890 return; 891 } 892 if (m_pColorSpace == CPDF_ColorSpace::GetStockCS(PDFCS_DEVICEGRAY) && 893 m_bpc == 8 && m_bDefaultDecode) { 894 } else { 895 int palette_count = 1 << (m_bpc * m_nComponents); 896 CFX_FixedBufGrow<FX_FLOAT, 16> color_values(m_nComponents); 897 FX_FLOAT* color_value = color_values; 898 for (int i = 0; i < palette_count; i++) { 899 int color_data = i; 900 for (FX_DWORD j = 0; j < m_nComponents; j++) { 901 int encoded_component = color_data % (1 << m_bpc); 902 color_data /= 1 << m_bpc; 903 color_value[j] = m_pCompData[j].m_DecodeMin + 904 m_pCompData[j].m_DecodeStep * encoded_component; 905 } 906 FX_FLOAT R = 0, G = 0, B = 0; 907 if (m_nComponents == 1 && m_Family == PDFCS_ICCBASED && 908 m_pColorSpace->CountComponents() > 1) { 909 int nComponents = m_pColorSpace->CountComponents(); 910 FX_FLOAT* temp_buf = FX_Alloc(FX_FLOAT, nComponents); 911 for (int i = 0; i < nComponents; i++) { 912 temp_buf[i] = *color_value; 913 } 914 m_pColorSpace->GetRGB(temp_buf, R, G, B); 915 FX_Free(temp_buf); 916 } else { 917 m_pColorSpace->GetRGB(color_value, R, G, B); 918 } 919 SetPaletteArgb(i, ArgbEncode(255, FXSYS_round(R * 255), 920 FXSYS_round(G * 255), FXSYS_round(B * 255))); 921 } 922 } 923 } 924 925 void CPDF_DIBSource::ValidateDictParam() { 926 m_bpc = m_bpc_orig; 927 CPDF_Object* pFilter = m_pDict->GetElementValue("Filter"); 928 if (pFilter) { 929 if (pFilter->IsName()) { 930 CFX_ByteString filter = pFilter->GetString(); 931 if (filter == "CCITTFaxDecode" || filter == "JBIG2Decode") { 932 m_bpc = 1; 933 m_nComponents = 1; 934 } else if (filter == "RunLengthDecode") { 935 if (m_bpc != 1) { 936 m_bpc = 8; 937 } 938 } else if (filter == "DCTDecode") { 939 m_bpc = 8; 940 } 941 } else if (CPDF_Array* pArray = pFilter->AsArray()) { 942 CFX_ByteString filter = pArray->GetString(pArray->GetCount() - 1); 943 if (filter == "CCITTFaxDecode" || filter == "JBIG2Decode") { 944 m_bpc = 1; 945 m_nComponents = 1; 946 } else if (filter == "DCTDecode") { 947 // Previously, filter == "RunLengthDecode" was checked in the "if" 948 // statement as well, but too many documents don't conform to it. 949 m_bpc = 8; 950 } 951 } 952 } 953 954 if (!IsAllowedBPCValue(m_bpc)) 955 m_bpc = 0; 956 } 957 958 #define NORMALCOLOR_MAX(color, max) \ 959 (color) > (max) ? (max) : (color) < 0 ? 0 : (color); 960 void CPDF_DIBSource::TranslateScanline24bpp(uint8_t* dest_scan, 961 const uint8_t* src_scan) const { 962 if (m_bpc == 0) { 963 return; 964 } 965 int max_data = (1 << m_bpc) - 1; 966 if (m_bDefaultDecode) { 967 if (m_Family == PDFCS_DEVICERGB || m_Family == PDFCS_CALRGB) { 968 const uint8_t* src_pos = src_scan; 969 switch (m_bpc) { 970 case 16: 971 for (int col = 0; col < m_Width; col++) { 972 *dest_scan++ = src_pos[4]; 973 *dest_scan++ = src_pos[2]; 974 *dest_scan++ = *src_pos; 975 src_pos += 6; 976 } 977 break; 978 case 8: 979 for (int column = 0; column < m_Width; column++) { 980 *dest_scan++ = src_pos[2]; 981 *dest_scan++ = src_pos[1]; 982 *dest_scan++ = *src_pos; 983 src_pos += 3; 984 } 985 break; 986 default: 987 int src_bit_pos = 0; 988 int dest_byte_pos = 0; 989 for (int column = 0; column < m_Width; column++) { 990 int R = GetBits8(src_scan, src_bit_pos, m_bpc); 991 src_bit_pos += m_bpc; 992 int G = GetBits8(src_scan, src_bit_pos, m_bpc); 993 src_bit_pos += m_bpc; 994 int B = GetBits8(src_scan, src_bit_pos, m_bpc); 995 src_bit_pos += m_bpc; 996 R = NORMALCOLOR_MAX(R, max_data); 997 G = NORMALCOLOR_MAX(G, max_data); 998 B = NORMALCOLOR_MAX(B, max_data); 999 dest_scan[dest_byte_pos] = B * 255 / max_data; 1000 dest_scan[dest_byte_pos + 1] = G * 255 / max_data; 1001 dest_scan[dest_byte_pos + 2] = R * 255 / max_data; 1002 dest_byte_pos += 3; 1003 } 1004 break; 1005 } 1006 return; 1007 } 1008 if (m_bpc == 8) { 1009 if (m_nComponents == m_pColorSpace->CountComponents()) 1010 m_pColorSpace->TranslateImageLine(dest_scan, src_scan, m_Width, m_Width, 1011 m_Height, TransMask()); 1012 return; 1013 } 1014 } 1015 CFX_FixedBufGrow<FX_FLOAT, 16> color_values1(m_nComponents); 1016 FX_FLOAT* color_values = color_values1; 1017 FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f; 1018 if (m_bpc == 8) { 1019 int src_byte_pos = 0; 1020 int dest_byte_pos = 0; 1021 for (int column = 0; column < m_Width; column++) { 1022 for (FX_DWORD color = 0; color < m_nComponents; color++) { 1023 int data = src_scan[src_byte_pos++]; 1024 color_values[color] = m_pCompData[color].m_DecodeMin + 1025 m_pCompData[color].m_DecodeStep * data; 1026 } 1027 if (TransMask()) { 1028 FX_FLOAT k = 1.0f - color_values[3]; 1029 R = (1.0f - color_values[0]) * k; 1030 G = (1.0f - color_values[1]) * k; 1031 B = (1.0f - color_values[2]) * k; 1032 } else { 1033 m_pColorSpace->GetRGB(color_values, R, G, B); 1034 } 1035 R = NORMALCOLOR_MAX(R, 1); 1036 G = NORMALCOLOR_MAX(G, 1); 1037 B = NORMALCOLOR_MAX(B, 1); 1038 dest_scan[dest_byte_pos] = (int32_t)(B * 255); 1039 dest_scan[dest_byte_pos + 1] = (int32_t)(G * 255); 1040 dest_scan[dest_byte_pos + 2] = (int32_t)(R * 255); 1041 dest_byte_pos += 3; 1042 } 1043 } else { 1044 int src_bit_pos = 0; 1045 int dest_byte_pos = 0; 1046 for (int column = 0; column < m_Width; column++) { 1047 for (FX_DWORD color = 0; color < m_nComponents; color++) { 1048 int data = GetBits8(src_scan, src_bit_pos, m_bpc); 1049 color_values[color] = m_pCompData[color].m_DecodeMin + 1050 m_pCompData[color].m_DecodeStep * data; 1051 src_bit_pos += m_bpc; 1052 } 1053 if (TransMask()) { 1054 FX_FLOAT k = 1.0f - color_values[3]; 1055 R = (1.0f - color_values[0]) * k; 1056 G = (1.0f - color_values[1]) * k; 1057 B = (1.0f - color_values[2]) * k; 1058 } else { 1059 m_pColorSpace->GetRGB(color_values, R, G, B); 1060 } 1061 R = NORMALCOLOR_MAX(R, 1); 1062 G = NORMALCOLOR_MAX(G, 1); 1063 B = NORMALCOLOR_MAX(B, 1); 1064 dest_scan[dest_byte_pos] = (int32_t)(B * 255); 1065 dest_scan[dest_byte_pos + 1] = (int32_t)(G * 255); 1066 dest_scan[dest_byte_pos + 2] = (int32_t)(R * 255); 1067 dest_byte_pos += 3; 1068 } 1069 } 1070 } 1071 uint8_t* CPDF_DIBSource::GetBuffer() const { 1072 if (m_pCachedBitmap) { 1073 return m_pCachedBitmap->GetBuffer(); 1074 } 1075 return NULL; 1076 } 1077 const uint8_t* CPDF_DIBSource::GetScanline(int line) const { 1078 if (m_bpc == 0) { 1079 return nullptr; 1080 } 1081 FX_SAFE_DWORD src_pitch = CalculatePitch8(m_bpc, m_nComponents, m_Width); 1082 if (!src_pitch.IsValid()) 1083 return nullptr; 1084 FX_DWORD src_pitch_value = src_pitch.ValueOrDie(); 1085 const uint8_t* pSrcLine = nullptr; 1086 if (m_pCachedBitmap && src_pitch_value <= m_pCachedBitmap->GetPitch()) { 1087 if (line >= m_pCachedBitmap->GetHeight()) { 1088 line = m_pCachedBitmap->GetHeight() - 1; 1089 } 1090 pSrcLine = m_pCachedBitmap->GetScanline(line); 1091 } else if (m_pDecoder) { 1092 pSrcLine = m_pDecoder->GetScanline(line); 1093 } else { 1094 if (m_pStreamAcc->GetSize() >= (line + 1) * src_pitch_value) { 1095 pSrcLine = m_pStreamAcc->GetData() + line * src_pitch_value; 1096 } 1097 } 1098 if (!pSrcLine) { 1099 uint8_t* pLineBuf = m_pMaskedLine ? m_pMaskedLine : m_pLineBuf; 1100 FXSYS_memset(pLineBuf, 0xFF, m_Pitch); 1101 return pLineBuf; 1102 } 1103 if (m_bpc * m_nComponents == 1) { 1104 if (m_bImageMask && m_bDefaultDecode) { 1105 for (FX_DWORD i = 0; i < src_pitch_value; i++) { 1106 m_pLineBuf[i] = ~pSrcLine[i]; 1107 } 1108 } else if (m_bColorKey) { 1109 FX_DWORD reset_argb, set_argb; 1110 reset_argb = m_pPalette ? m_pPalette[0] : 0xFF000000; 1111 set_argb = m_pPalette ? m_pPalette[1] : 0xFFFFFFFF; 1112 if (m_pCompData[0].m_ColorKeyMin == 0) { 1113 reset_argb = 0; 1114 } 1115 if (m_pCompData[0].m_ColorKeyMax == 1) { 1116 set_argb = 0; 1117 } 1118 set_argb = FXARGB_TODIB(set_argb); 1119 reset_argb = FXARGB_TODIB(reset_argb); 1120 FX_DWORD* dest_scan = (FX_DWORD*)m_pMaskedLine; 1121 for (int col = 0; col < m_Width; col++) { 1122 if (pSrcLine[col / 8] & (1 << (7 - col % 8))) { 1123 *dest_scan = set_argb; 1124 } else { 1125 *dest_scan = reset_argb; 1126 } 1127 dest_scan++; 1128 } 1129 return m_pMaskedLine; 1130 } else { 1131 FXSYS_memcpy(m_pLineBuf, pSrcLine, src_pitch_value); 1132 } 1133 return m_pLineBuf; 1134 } 1135 if (m_bpc * m_nComponents <= 8) { 1136 if (m_bpc == 8) { 1137 FXSYS_memcpy(m_pLineBuf, pSrcLine, src_pitch_value); 1138 } else { 1139 int src_bit_pos = 0; 1140 for (int col = 0; col < m_Width; col++) { 1141 int color_index = 0; 1142 for (FX_DWORD color = 0; color < m_nComponents; color++) { 1143 int data = GetBits8(pSrcLine, src_bit_pos, m_bpc); 1144 color_index |= data << (color * m_bpc); 1145 src_bit_pos += m_bpc; 1146 } 1147 m_pLineBuf[col] = color_index; 1148 } 1149 } 1150 if (m_bColorKey) { 1151 uint8_t* pDestPixel = m_pMaskedLine; 1152 const uint8_t* pSrcPixel = m_pLineBuf; 1153 for (int col = 0; col < m_Width; col++) { 1154 uint8_t index = *pSrcPixel++; 1155 if (m_pPalette) { 1156 *pDestPixel++ = FXARGB_B(m_pPalette[index]); 1157 *pDestPixel++ = FXARGB_G(m_pPalette[index]); 1158 *pDestPixel++ = FXARGB_R(m_pPalette[index]); 1159 } else { 1160 *pDestPixel++ = index; 1161 *pDestPixel++ = index; 1162 *pDestPixel++ = index; 1163 } 1164 *pDestPixel = (index < m_pCompData[0].m_ColorKeyMin || 1165 index > m_pCompData[0].m_ColorKeyMax) 1166 ? 0xFF 1167 : 0; 1168 pDestPixel++; 1169 } 1170 return m_pMaskedLine; 1171 } 1172 return m_pLineBuf; 1173 } 1174 if (m_bColorKey) { 1175 if (m_nComponents == 3 && m_bpc == 8) { 1176 uint8_t* alpha_channel = m_pMaskedLine + 3; 1177 for (int col = 0; col < m_Width; col++) { 1178 const uint8_t* pPixel = pSrcLine + col * 3; 1179 alpha_channel[col * 4] = (pPixel[0] < m_pCompData[0].m_ColorKeyMin || 1180 pPixel[0] > m_pCompData[0].m_ColorKeyMax || 1181 pPixel[1] < m_pCompData[1].m_ColorKeyMin || 1182 pPixel[1] > m_pCompData[1].m_ColorKeyMax || 1183 pPixel[2] < m_pCompData[2].m_ColorKeyMin || 1184 pPixel[2] > m_pCompData[2].m_ColorKeyMax) 1185 ? 0xFF 1186 : 0; 1187 } 1188 } else { 1189 FXSYS_memset(m_pMaskedLine, 0xFF, m_Pitch); 1190 } 1191 } 1192 if (m_pColorSpace) { 1193 TranslateScanline24bpp(m_pLineBuf, pSrcLine); 1194 pSrcLine = m_pLineBuf; 1195 } 1196 if (m_bColorKey) { 1197 const uint8_t* pSrcPixel = pSrcLine; 1198 uint8_t* pDestPixel = m_pMaskedLine; 1199 for (int col = 0; col < m_Width; col++) { 1200 *pDestPixel++ = *pSrcPixel++; 1201 *pDestPixel++ = *pSrcPixel++; 1202 *pDestPixel++ = *pSrcPixel++; 1203 pDestPixel++; 1204 } 1205 return m_pMaskedLine; 1206 } 1207 return pSrcLine; 1208 } 1209 1210 FX_BOOL CPDF_DIBSource::SkipToScanline(int line, IFX_Pause* pPause) const { 1211 return m_pDecoder && m_pDecoder->SkipToScanline(line, pPause); 1212 } 1213 1214 void CPDF_DIBSource::DownSampleScanline(int line, 1215 uint8_t* dest_scan, 1216 int dest_bpp, 1217 int dest_width, 1218 FX_BOOL bFlipX, 1219 int clip_left, 1220 int clip_width) const { 1221 if (line < 0 || !dest_scan || dest_bpp <= 0 || dest_width <= 0 || 1222 clip_left < 0 || clip_width <= 0) { 1223 return; 1224 } 1225 1226 FX_DWORD src_width = m_Width; 1227 FX_SAFE_DWORD pitch = CalculatePitch8(m_bpc, m_nComponents, m_Width); 1228 if (!pitch.IsValid()) 1229 return; 1230 1231 const uint8_t* pSrcLine = nullptr; 1232 if (m_pCachedBitmap) { 1233 pSrcLine = m_pCachedBitmap->GetScanline(line); 1234 } else if (m_pDecoder) { 1235 pSrcLine = m_pDecoder->GetScanline(line); 1236 } else { 1237 FX_DWORD src_pitch = pitch.ValueOrDie(); 1238 pitch *= (line + 1); 1239 if (!pitch.IsValid()) { 1240 return; 1241 } 1242 1243 if (m_pStreamAcc->GetSize() >= pitch.ValueOrDie()) { 1244 pSrcLine = m_pStreamAcc->GetData() + line * src_pitch; 1245 } 1246 } 1247 int orig_Bpp = m_bpc * m_nComponents / 8; 1248 int dest_Bpp = dest_bpp / 8; 1249 if (!pSrcLine) { 1250 FXSYS_memset(dest_scan, 0xFF, dest_Bpp * clip_width); 1251 return; 1252 } 1253 1254 FX_SAFE_INT32 max_src_x = clip_left; 1255 max_src_x += clip_width - 1; 1256 max_src_x *= src_width; 1257 max_src_x /= dest_width; 1258 if (!max_src_x.IsValid()) 1259 return; 1260 1261 if (m_bpc * m_nComponents == 1) { 1262 DownSampleScanline1Bit(orig_Bpp, dest_Bpp, src_width, pSrcLine, dest_scan, 1263 dest_width, bFlipX, clip_left, clip_width); 1264 } else if (m_bpc * m_nComponents <= 8) { 1265 DownSampleScanline8Bit(orig_Bpp, dest_Bpp, src_width, pSrcLine, dest_scan, 1266 dest_width, bFlipX, clip_left, clip_width); 1267 } else { 1268 DownSampleScanline32Bit(orig_Bpp, dest_Bpp, src_width, pSrcLine, dest_scan, 1269 dest_width, bFlipX, clip_left, clip_width); 1270 } 1271 } 1272 1273 void CPDF_DIBSource::DownSampleScanline1Bit(int orig_Bpp, 1274 int dest_Bpp, 1275 FX_DWORD src_width, 1276 const uint8_t* pSrcLine, 1277 uint8_t* dest_scan, 1278 int dest_width, 1279 FX_BOOL bFlipX, 1280 int clip_left, 1281 int clip_width) const { 1282 FX_DWORD set_argb = (FX_DWORD)-1; 1283 FX_DWORD reset_argb = 0; 1284 if (m_bImageMask) { 1285 if (m_bDefaultDecode) { 1286 set_argb = 0; 1287 reset_argb = (FX_DWORD)-1; 1288 } 1289 } else if (m_bColorKey) { 1290 reset_argb = m_pPalette ? m_pPalette[0] : 0xFF000000; 1291 set_argb = m_pPalette ? m_pPalette[1] : 0xFFFFFFFF; 1292 if (m_pCompData[0].m_ColorKeyMin == 0) { 1293 reset_argb = 0; 1294 } 1295 if (m_pCompData[0].m_ColorKeyMax == 1) { 1296 set_argb = 0; 1297 } 1298 set_argb = FXARGB_TODIB(set_argb); 1299 reset_argb = FXARGB_TODIB(reset_argb); 1300 for (int i = 0; i < clip_width; i++) { 1301 FX_DWORD src_x = (clip_left + i) * src_width / dest_width; 1302 if (bFlipX) { 1303 src_x = src_width - src_x - 1; 1304 } 1305 src_x %= src_width; 1306 if (pSrcLine[src_x / 8] & (1 << (7 - src_x % 8))) { 1307 ((FX_DWORD*)dest_scan)[i] = set_argb; 1308 } else { 1309 ((FX_DWORD*)dest_scan)[i] = reset_argb; 1310 } 1311 } 1312 return; 1313 } else { 1314 if (dest_Bpp == 1) { 1315 } else if (m_pPalette) { 1316 reset_argb = m_pPalette[0]; 1317 set_argb = m_pPalette[1]; 1318 } 1319 } 1320 for (int i = 0; i < clip_width; i++) { 1321 FX_DWORD src_x = (clip_left + i) * src_width / dest_width; 1322 if (bFlipX) { 1323 src_x = src_width - src_x - 1; 1324 } 1325 src_x %= src_width; 1326 int dest_pos = i * dest_Bpp; 1327 if (pSrcLine[src_x / 8] & (1 << (7 - src_x % 8))) { 1328 if (dest_Bpp == 1) { 1329 dest_scan[dest_pos] = (uint8_t)set_argb; 1330 } else if (dest_Bpp == 3) { 1331 dest_scan[dest_pos] = FXARGB_B(set_argb); 1332 dest_scan[dest_pos + 1] = FXARGB_G(set_argb); 1333 dest_scan[dest_pos + 2] = FXARGB_R(set_argb); 1334 } else { 1335 *(FX_DWORD*)(dest_scan + dest_pos) = set_argb; 1336 } 1337 } else { 1338 if (dest_Bpp == 1) { 1339 dest_scan[dest_pos] = (uint8_t)reset_argb; 1340 } else if (dest_Bpp == 3) { 1341 dest_scan[dest_pos] = FXARGB_B(reset_argb); 1342 dest_scan[dest_pos + 1] = FXARGB_G(reset_argb); 1343 dest_scan[dest_pos + 2] = FXARGB_R(reset_argb); 1344 } else { 1345 *(FX_DWORD*)(dest_scan + dest_pos) = reset_argb; 1346 } 1347 } 1348 } 1349 } 1350 1351 void CPDF_DIBSource::DownSampleScanline8Bit(int orig_Bpp, 1352 int dest_Bpp, 1353 FX_DWORD src_width, 1354 const uint8_t* pSrcLine, 1355 uint8_t* dest_scan, 1356 int dest_width, 1357 FX_BOOL bFlipX, 1358 int clip_left, 1359 int clip_width) const { 1360 if (m_bpc < 8) { 1361 int src_bit_pos = 0; 1362 for (FX_DWORD col = 0; col < src_width; col++) { 1363 int color_index = 0; 1364 for (FX_DWORD color = 0; color < m_nComponents; color++) { 1365 int data = GetBits8(pSrcLine, src_bit_pos, m_bpc); 1366 color_index |= data << (color * m_bpc); 1367 src_bit_pos += m_bpc; 1368 } 1369 m_pLineBuf[col] = color_index; 1370 } 1371 pSrcLine = m_pLineBuf; 1372 } 1373 if (m_bColorKey) { 1374 for (int i = 0; i < clip_width; i++) { 1375 FX_DWORD src_x = (clip_left + i) * src_width / dest_width; 1376 if (bFlipX) { 1377 src_x = src_width - src_x - 1; 1378 } 1379 src_x %= src_width; 1380 uint8_t* pDestPixel = dest_scan + i * 4; 1381 uint8_t index = pSrcLine[src_x]; 1382 if (m_pPalette) { 1383 *pDestPixel++ = FXARGB_B(m_pPalette[index]); 1384 *pDestPixel++ = FXARGB_G(m_pPalette[index]); 1385 *pDestPixel++ = FXARGB_R(m_pPalette[index]); 1386 } else { 1387 *pDestPixel++ = index; 1388 *pDestPixel++ = index; 1389 *pDestPixel++ = index; 1390 } 1391 *pDestPixel = (index < m_pCompData[0].m_ColorKeyMin || 1392 index > m_pCompData[0].m_ColorKeyMax) 1393 ? 0xFF 1394 : 0; 1395 } 1396 return; 1397 } 1398 for (int i = 0; i < clip_width; i++) { 1399 FX_DWORD src_x = (clip_left + i) * src_width / dest_width; 1400 if (bFlipX) { 1401 src_x = src_width - src_x - 1; 1402 } 1403 src_x %= src_width; 1404 uint8_t index = pSrcLine[src_x]; 1405 if (dest_Bpp == 1) { 1406 dest_scan[i] = index; 1407 } else { 1408 int dest_pos = i * dest_Bpp; 1409 FX_ARGB argb = m_pPalette[index]; 1410 dest_scan[dest_pos] = FXARGB_B(argb); 1411 dest_scan[dest_pos + 1] = FXARGB_G(argb); 1412 dest_scan[dest_pos + 2] = FXARGB_R(argb); 1413 } 1414 } 1415 } 1416 1417 void CPDF_DIBSource::DownSampleScanline32Bit(int orig_Bpp, 1418 int dest_Bpp, 1419 FX_DWORD src_width, 1420 const uint8_t* pSrcLine, 1421 uint8_t* dest_scan, 1422 int dest_width, 1423 FX_BOOL bFlipX, 1424 int clip_left, 1425 int clip_width) const { 1426 int last_src_x = -1; 1427 FX_ARGB last_argb = FXARGB_MAKE(0xFF, 0xFF, 0xFF, 0xFF); 1428 FX_FLOAT unit_To8Bpc = 255.0f / ((1 << m_bpc) - 1); 1429 for (int i = 0; i < clip_width; i++) { 1430 int dest_x = clip_left + i; 1431 FX_DWORD src_x = (bFlipX ? (dest_width - dest_x - 1) : dest_x) * 1432 (int64_t)src_width / dest_width; 1433 src_x %= src_width; 1434 1435 // No need to check for 32-bit overflow, as |src_x| is bounded by 1436 // |src_width| and DownSampleScanline already checked for overflow with the 1437 // pitch calculation. 1438 const uint8_t* pSrcPixel = nullptr; 1439 size_t bit_offset = 0; 1440 if (m_bpc % 8 == 0) { 1441 pSrcPixel = pSrcLine + src_x * orig_Bpp; 1442 } else { 1443 size_t num_bits = src_x * m_bpc * m_nComponents; 1444 pSrcPixel = pSrcLine + num_bits / 8; 1445 bit_offset = num_bits % 8; 1446 } 1447 1448 uint8_t* pDestPixel = dest_scan + i * dest_Bpp; 1449 FX_ARGB argb; 1450 if (src_x == last_src_x) { 1451 argb = last_argb; 1452 } else { 1453 CFX_FixedBufGrow<uint8_t, 128> extracted_components(m_nComponents); 1454 if (m_bpc % 8 != 0) { 1455 uint64_t src_bit_pos = bit_offset; 1456 for (FX_DWORD j = 0; j < m_nComponents; ++j) { 1457 extracted_components[j] = static_cast<uint8_t>( 1458 GetBits8(pSrcPixel, src_bit_pos, m_bpc) * unit_To8Bpc); 1459 src_bit_pos += m_bpc; 1460 } 1461 pSrcPixel = extracted_components; 1462 } 1463 1464 if (m_pColorSpace) { 1465 uint8_t color[4]; 1466 const FX_BOOL bTransMask = TransMask(); 1467 if (m_bDefaultDecode) { 1468 m_pColorSpace->TranslateImageLine(color, pSrcPixel, 1, 0, 0, 1469 bTransMask); 1470 } else { 1471 for (FX_DWORD j = 0; j < m_nComponents; ++j) { 1472 FX_FLOAT component_value = 1473 static_cast<FX_FLOAT>(extracted_components[j]); 1474 int color_value = 1475 (int)((m_pCompData[j].m_DecodeMin + 1476 m_pCompData[j].m_DecodeStep * component_value) * 1477 255.0f + 1478 0.5f); 1479 extracted_components[j] = 1480 color_value > 255 ? 255 : (color_value < 0 ? 0 : color_value); 1481 } 1482 m_pColorSpace->TranslateImageLine(color, extracted_components, 1, 0, 1483 0, bTransMask); 1484 } 1485 argb = FXARGB_MAKE(0xFF, color[2], color[1], color[0]); 1486 } else { 1487 argb = FXARGB_MAKE(0xFF, pSrcPixel[2], pSrcPixel[1], pSrcPixel[0]); 1488 } 1489 if (m_bColorKey) { 1490 int alpha = 0xFF; 1491 if (m_nComponents == 3 && m_bpc == 8) { 1492 alpha = (pSrcPixel[0] < m_pCompData[0].m_ColorKeyMin || 1493 pSrcPixel[0] > m_pCompData[0].m_ColorKeyMax || 1494 pSrcPixel[1] < m_pCompData[1].m_ColorKeyMin || 1495 pSrcPixel[1] > m_pCompData[1].m_ColorKeyMax || 1496 pSrcPixel[2] < m_pCompData[2].m_ColorKeyMin || 1497 pSrcPixel[2] > m_pCompData[2].m_ColorKeyMax) 1498 ? 0xFF 1499 : 0; 1500 } 1501 argb &= 0xFFFFFF; 1502 argb |= alpha << 24; 1503 } 1504 last_src_x = src_x; 1505 last_argb = argb; 1506 } 1507 if (dest_Bpp == 4) { 1508 *(FX_DWORD*)pDestPixel = FXARGB_TODIB(argb); 1509 } else { 1510 *pDestPixel++ = FXARGB_B(argb); 1511 *pDestPixel++ = FXARGB_G(argb); 1512 *pDestPixel = FXARGB_R(argb); 1513 } 1514 } 1515 } 1516 1517 FX_BOOL CPDF_DIBSource::TransMask() const { 1518 return m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK && 1519 m_Family == PDFCS_DEVICECMYK; 1520 } 1521 1522 void CPDF_DIBSource::SetDownSampleSize(int dest_width, int dest_height) const { 1523 if (m_pDecoder) { 1524 m_pDecoder->DownScale(dest_width, dest_height); 1525 ((CPDF_DIBSource*)this)->m_Width = m_pDecoder->GetWidth(); 1526 ((CPDF_DIBSource*)this)->m_Height = m_pDecoder->GetHeight(); 1527 } 1528 } 1529 1530 void CPDF_DIBSource::ClearImageData() { 1531 if (m_pDecoder) { 1532 m_pDecoder->ClearImageData(); 1533 } 1534 } 1535 1536 CPDF_ImageLoaderHandle::CPDF_ImageLoaderHandle() { 1537 m_pImageLoader = NULL; 1538 m_pCache = NULL; 1539 m_pImage = NULL; 1540 } 1541 CPDF_ImageLoaderHandle::~CPDF_ImageLoaderHandle() {} 1542 FX_BOOL CPDF_ImageLoaderHandle::Start(CPDF_ImageLoader* pImageLoader, 1543 const CPDF_ImageObject* pImage, 1544 CPDF_PageRenderCache* pCache, 1545 FX_BOOL bStdCS, 1546 FX_DWORD GroupFamily, 1547 FX_BOOL bLoadMask, 1548 CPDF_RenderStatus* pRenderStatus, 1549 int32_t nDownsampleWidth, 1550 int32_t nDownsampleHeight) { 1551 m_pImageLoader = pImageLoader; 1552 m_pCache = pCache; 1553 m_pImage = (CPDF_ImageObject*)pImage; 1554 m_nDownsampleWidth = nDownsampleWidth; 1555 m_nDownsampleHeight = nDownsampleHeight; 1556 FX_BOOL ret; 1557 if (pCache) { 1558 ret = pCache->StartGetCachedBitmap(pImage->m_pImage->GetStream(), bStdCS, 1559 GroupFamily, bLoadMask, pRenderStatus, 1560 m_nDownsampleWidth, m_nDownsampleHeight); 1561 if (!ret) { 1562 m_pImageLoader->m_bCached = TRUE; 1563 m_pImageLoader->m_pBitmap = 1564 pCache->GetCurImageCacheEntry()->DetachBitmap(); 1565 m_pImageLoader->m_pMask = pCache->GetCurImageCacheEntry()->DetachMask(); 1566 m_pImageLoader->m_MatteColor = 1567 pCache->GetCurImageCacheEntry()->m_MatteColor; 1568 } 1569 } else { 1570 ret = pImage->m_pImage->StartLoadDIBSource(pRenderStatus->m_pFormResource, 1571 pRenderStatus->m_pPageResource, 1572 bStdCS, GroupFamily, bLoadMask); 1573 if (!ret) { 1574 m_pImageLoader->m_bCached = FALSE; 1575 m_pImageLoader->m_pBitmap = m_pImage->m_pImage->DetachBitmap(); 1576 m_pImageLoader->m_pMask = m_pImage->m_pImage->DetachMask(); 1577 m_pImageLoader->m_MatteColor = m_pImage->m_pImage->m_MatteColor; 1578 } 1579 } 1580 return ret; 1581 } 1582 FX_BOOL CPDF_ImageLoaderHandle::Continue(IFX_Pause* pPause) { 1583 FX_BOOL ret; 1584 if (m_pCache) { 1585 ret = m_pCache->Continue(pPause); 1586 if (!ret) { 1587 m_pImageLoader->m_bCached = TRUE; 1588 m_pImageLoader->m_pBitmap = 1589 m_pCache->GetCurImageCacheEntry()->DetachBitmap(); 1590 m_pImageLoader->m_pMask = m_pCache->GetCurImageCacheEntry()->DetachMask(); 1591 m_pImageLoader->m_MatteColor = 1592 m_pCache->GetCurImageCacheEntry()->m_MatteColor; 1593 } 1594 } else { 1595 ret = m_pImage->m_pImage->Continue(pPause); 1596 if (!ret) { 1597 m_pImageLoader->m_bCached = FALSE; 1598 m_pImageLoader->m_pBitmap = m_pImage->m_pImage->DetachBitmap(); 1599 m_pImageLoader->m_pMask = m_pImage->m_pImage->DetachMask(); 1600 m_pImageLoader->m_MatteColor = m_pImage->m_pImage->m_MatteColor; 1601 } 1602 } 1603 return ret; 1604 } 1605 FX_BOOL CPDF_ImageLoader::Start(const CPDF_ImageObject* pImage, 1606 CPDF_PageRenderCache* pCache, 1607 CPDF_ImageLoaderHandle*& LoadHandle, 1608 FX_BOOL bStdCS, 1609 FX_DWORD GroupFamily, 1610 FX_BOOL bLoadMask, 1611 CPDF_RenderStatus* pRenderStatus, 1612 int32_t nDownsampleWidth, 1613 int32_t nDownsampleHeight) { 1614 m_nDownsampleWidth = nDownsampleWidth; 1615 m_nDownsampleHeight = nDownsampleHeight; 1616 LoadHandle = new CPDF_ImageLoaderHandle; 1617 return LoadHandle->Start(this, pImage, pCache, bStdCS, GroupFamily, bLoadMask, 1618 pRenderStatus, m_nDownsampleWidth, 1619 m_nDownsampleHeight); 1620 } 1621 FX_BOOL CPDF_ImageLoader::Continue(CPDF_ImageLoaderHandle* LoadHandle, 1622 IFX_Pause* pPause) { 1623 return LoadHandle->Continue(pPause); 1624 } 1625 CPDF_ImageLoader::~CPDF_ImageLoader() { 1626 if (!m_bCached) { 1627 delete m_pBitmap; 1628 delete m_pMask; 1629 } 1630 } 1631