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