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