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