• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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