• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 The PDFium Authors
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 <stdint.h>
10 
11 #include <algorithm>
12 #include <memory>
13 #include <utility>
14 #include <vector>
15 
16 #include "core/fpdfapi/page/cpdf_colorspace.h"
17 #include "core/fpdfapi/page/cpdf_docpagedata.h"
18 #include "core/fpdfapi/page/cpdf_image.h"
19 #include "core/fpdfapi/page/cpdf_imageobject.h"
20 #include "core/fpdfapi/page/cpdf_indexedcs.h"
21 #include "core/fpdfapi/parser/cpdf_array.h"
22 #include "core/fpdfapi/parser/cpdf_dictionary.h"
23 #include "core/fpdfapi/parser/cpdf_document.h"
24 #include "core/fpdfapi/parser/cpdf_name.h"
25 #include "core/fpdfapi/parser/cpdf_number.h"
26 #include "core/fpdfapi/parser/cpdf_stream.h"
27 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
28 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
29 #include "core/fpdfapi/parser/fpdf_parser_utility.h"
30 #include "core/fxcodec/basic/basicmodule.h"
31 #include "core/fxcodec/jbig2/jbig2_decoder.h"
32 #include "core/fxcodec/jpeg/jpegmodule.h"
33 #include "core/fxcodec/jpx/cjpx_decoder.h"
34 #include "core/fxcodec/scanlinedecoder.h"
35 #include "core/fxcrt/data_vector.h"
36 #include "core/fxcrt/fx_safe_types.h"
37 #include "core/fxcrt/span_util.h"
38 #include "core/fxge/calculate_pitch.h"
39 #include "core/fxge/dib/cfx_dibitmap.h"
40 #include "third_party/base/check.h"
41 #include "third_party/base/check_op.h"
42 #include "third_party/base/cxx17_backports.h"
43 #include "third_party/base/notreached.h"
44 
45 namespace {
46 
IsValidDimension(int value)47 bool IsValidDimension(int value) {
48   constexpr int kMaxImageDimension = 0x01FFFF;
49   return value > 0 && value <= kMaxImageDimension;
50 }
51 
GetBits8(const uint8_t * pData,uint64_t bitpos,size_t nbits)52 unsigned int GetBits8(const uint8_t* pData, uint64_t bitpos, size_t nbits) {
53   DCHECK(nbits == 1 || nbits == 2 || nbits == 4 || nbits == 8 || nbits == 16);
54   DCHECK_EQ((bitpos & (nbits - 1)), 0);
55   unsigned int byte = pData[bitpos / 8];
56   if (nbits == 8)
57     return byte;
58 
59   if (nbits == 16)
60     return byte * 256 + pData[bitpos / 8 + 1];
61 
62   return (byte >> (8 - nbits - (bitpos % 8))) & ((1 << nbits) - 1);
63 }
64 
GetBitValue(const uint8_t * pSrc,uint32_t pos)65 bool GetBitValue(const uint8_t* pSrc, uint32_t pos) {
66   return pSrc[pos / 8] & (1 << (7 - pos % 8));
67 }
68 
69 // Just to sanity check and filter out obvious bad values.
IsMaybeValidBitsPerComponent(int bpc)70 bool IsMaybeValidBitsPerComponent(int bpc) {
71   return bpc >= 0 && bpc <= 16;
72 }
73 
IsAllowedBitsPerComponent(int bpc)74 bool IsAllowedBitsPerComponent(int bpc) {
75   return bpc == 1 || bpc == 2 || bpc == 4 || bpc == 8 || bpc == 16;
76 }
77 
IsColorIndexOutOfBounds(uint8_t index,const DIB_COMP_DATA & comp_datum)78 bool IsColorIndexOutOfBounds(uint8_t index, const DIB_COMP_DATA& comp_datum) {
79   return index < comp_datum.m_ColorKeyMin || index > comp_datum.m_ColorKeyMax;
80 }
81 
AreColorIndicesOutOfBounds(const uint8_t * indices,const DIB_COMP_DATA * comp_data,size_t count)82 bool AreColorIndicesOutOfBounds(const uint8_t* indices,
83                                 const DIB_COMP_DATA* comp_data,
84                                 size_t count) {
85   for (size_t i = 0; i < count; ++i) {
86     if (IsColorIndexOutOfBounds(indices[i], comp_data[i]))
87       return true;
88   }
89   return false;
90 }
91 
CalculateBitsPerPixel(uint32_t bpc,uint32_t comps)92 int CalculateBitsPerPixel(uint32_t bpc, uint32_t comps) {
93   // TODO(thestig): Can |bpp| be 0 here? Add an DCHECK() or handle it?
94   uint32_t bpp = bpc * comps;
95   if (bpp == 1)
96     return 1;
97   if (bpp <= 8)
98     return 8;
99   return 24;
100 }
101 
ColorSpaceOptionFromColorSpace(CPDF_ColorSpace * pCS)102 CJPX_Decoder::ColorSpaceOption ColorSpaceOptionFromColorSpace(
103     CPDF_ColorSpace* pCS) {
104   if (!pCS)
105     return CJPX_Decoder::kNoColorSpace;
106   if (pCS->GetFamily() == CPDF_ColorSpace::Family::kIndexed)
107     return CJPX_Decoder::kIndexedColorSpace;
108   return CJPX_Decoder::kNormalColorSpace;
109 }
110 
111 enum class JpxDecodeAction {
112   kFail,
113   kDoNothing,
114   kUseGray,
115   kUseRgb,
116   kUseCmyk,
117   kConvertArgbToRgb,
118 };
119 
120 // Decides which JpxDecodeAction to use based on the colorspace information from
121 // the PDF and the JPX image. Called only when the PDF's image object contains a
122 // "/ColorSpace" entry.
GetJpxDecodeActionFromColorSpaces(const CJPX_Decoder::JpxImageInfo & jpx_info,const CPDF_ColorSpace * pdf_colorspace)123 JpxDecodeAction GetJpxDecodeActionFromColorSpaces(
124     const CJPX_Decoder::JpxImageInfo& jpx_info,
125     const CPDF_ColorSpace* pdf_colorspace) {
126   if (pdf_colorspace ==
127       CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceGray)) {
128     if (jpx_info.colorspace != OPJ_CLRSPC_GRAY &&
129         jpx_info.colorspace != OPJ_CLRSPC_UNSPECIFIED) {
130       return JpxDecodeAction::kFail;
131     }
132     return JpxDecodeAction::kUseGray;
133   }
134 
135   if (pdf_colorspace ==
136       CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceRGB)) {
137     if (jpx_info.colorspace != OPJ_CLRSPC_SRGB &&
138         jpx_info.colorspace != OPJ_CLRSPC_UNSPECIFIED) {
139       return JpxDecodeAction::kFail;
140     }
141 
142     // The channel count of a JPX image can be different from the PDF color
143     // space's component count.
144     if (jpx_info.channels > 3) {
145       return JpxDecodeAction::kConvertArgbToRgb;
146     }
147     return JpxDecodeAction::kUseRgb;
148   }
149 
150   if (pdf_colorspace ==
151       CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceCMYK)) {
152     if (jpx_info.colorspace != OPJ_CLRSPC_CMYK &&
153         jpx_info.colorspace != OPJ_CLRSPC_UNSPECIFIED) {
154       return JpxDecodeAction::kFail;
155     }
156     return JpxDecodeAction::kUseCmyk;
157   }
158 
159   return JpxDecodeAction::kDoNothing;
160 }
161 
GetJpxDecodeActionFromImageColorSpace(const CJPX_Decoder::JpxImageInfo & jpx_info)162 JpxDecodeAction GetJpxDecodeActionFromImageColorSpace(
163     const CJPX_Decoder::JpxImageInfo& jpx_info) {
164   switch (jpx_info.colorspace) {
165     case OPJ_CLRSPC_SYCC:
166     case OPJ_CLRSPC_EYCC:
167     case OPJ_CLRSPC_UNKNOWN:
168     case OPJ_CLRSPC_UNSPECIFIED:
169       return JpxDecodeAction::kDoNothing;
170 
171     case OPJ_CLRSPC_SRGB:
172       if (jpx_info.channels > 3) {
173         return JpxDecodeAction::kConvertArgbToRgb;
174       }
175 
176       return JpxDecodeAction::kUseRgb;
177 
178     case OPJ_CLRSPC_GRAY:
179       return JpxDecodeAction::kUseGray;
180 
181     case OPJ_CLRSPC_CMYK:
182       return JpxDecodeAction::kUseCmyk;
183 
184     default:
185       NOTREACHED_NORETURN();
186   }
187 }
188 
GetJpxDecodeAction(const CJPX_Decoder::JpxImageInfo & jpx_info,const CPDF_ColorSpace * pdf_colorspace)189 JpxDecodeAction GetJpxDecodeAction(const CJPX_Decoder::JpxImageInfo& jpx_info,
190                                    const CPDF_ColorSpace* pdf_colorspace) {
191   if (pdf_colorspace) {
192     return GetJpxDecodeActionFromColorSpaces(jpx_info, pdf_colorspace);
193   }
194 
195   // When PDF does not provide a color space, check the image color space.
196   return GetJpxDecodeActionFromImageColorSpace(jpx_info);
197 }
198 
GetComponentCountFromOpjColorSpace(OPJ_COLOR_SPACE colorspace)199 int GetComponentCountFromOpjColorSpace(OPJ_COLOR_SPACE colorspace) {
200   switch (colorspace) {
201     case OPJ_CLRSPC_GRAY:
202       return 1;
203 
204     case OPJ_CLRSPC_SRGB:
205     case OPJ_CLRSPC_SYCC:
206     case OPJ_CLRSPC_EYCC:
207       return 3;
208 
209     case OPJ_CLRSPC_CMYK:
210       return 4;
211 
212     default:
213       return 0;
214   }
215 }
216 
217 }  // namespace
218 
CPDF_DIB(CPDF_Document * pDoc,RetainPtr<const CPDF_Stream> pStream)219 CPDF_DIB::CPDF_DIB(CPDF_Document* pDoc, RetainPtr<const CPDF_Stream> pStream)
220     : m_pDocument(pDoc), m_pStream(std::move(pStream)) {}
221 
222 CPDF_DIB::~CPDF_DIB() = default;
223 
224 CPDF_DIB::JpxSMaskInlineData::JpxSMaskInlineData() = default;
225 
226 CPDF_DIB::JpxSMaskInlineData::~JpxSMaskInlineData() = default;
227 
Load()228 bool CPDF_DIB::Load() {
229   if (!LoadInternal(nullptr, nullptr))
230     return false;
231 
232   if (CreateDecoder(0) == LoadState::kFail)
233     return false;
234 
235   return ContinueInternal();
236 }
237 
ContinueToLoadMask()238 bool CPDF_DIB::ContinueToLoadMask() {
239   if (m_pColorSpace && m_bStdCS)
240     m_pColorSpace->EnableStdConversion(true);
241 
242   return ContinueInternal();
243 }
244 
ContinueInternal()245 bool CPDF_DIB::ContinueInternal() {
246   if (m_bImageMask) {
247     SetMaskProperties();
248   } else {
249     if (!m_bpc || !m_nComponents)
250       return false;
251 
252     m_Format = MakeRGBFormat(CalculateBitsPerPixel(m_bpc, m_nComponents));
253   }
254 
255   absl::optional<uint32_t> pitch =
256       fxge::CalculatePitch32(GetBppFromFormat(m_Format), m_Width);
257   if (!pitch.has_value())
258     return false;
259 
260   m_LineBuf = DataVector<uint8_t>(pitch.value());
261   LoadPalette();
262   if (m_bColorKey) {
263     m_Format = FXDIB_Format::kArgb;
264     pitch = fxge::CalculatePitch32(GetBppFromFormat(m_Format), m_Width);
265     if (!pitch.has_value())
266       return false;
267     m_MaskBuf = DataVector<uint8_t>(pitch.value());
268   }
269   m_Pitch = pitch.value();
270   return true;
271 }
272 
StartLoadDIBBase(bool bHasMask,const CPDF_Dictionary * pFormResources,const CPDF_Dictionary * pPageResources,bool bStdCS,CPDF_ColorSpace::Family GroupFamily,bool bLoadMask,const CFX_Size & max_size_required)273 CPDF_DIB::LoadState CPDF_DIB::StartLoadDIBBase(
274     bool bHasMask,
275     const CPDF_Dictionary* pFormResources,
276     const CPDF_Dictionary* pPageResources,
277     bool bStdCS,
278     CPDF_ColorSpace::Family GroupFamily,
279     bool bLoadMask,
280     const CFX_Size& max_size_required) {
281   m_bStdCS = bStdCS;
282   m_bHasMask = bHasMask;
283   m_GroupFamily = GroupFamily;
284   m_bLoadMask = bLoadMask;
285 
286   if (!m_pStream->IsInline())
287     pFormResources = nullptr;
288 
289   if (!LoadInternal(pFormResources, pPageResources))
290     return LoadState::kFail;
291 
292   uint8_t resolution_levels_to_skip = 0;
293   if (max_size_required.width != 0 && max_size_required.height != 0) {
294     resolution_levels_to_skip = static_cast<uint8_t>(
295         std::log2(std::max(1, std::min(m_Width / max_size_required.width,
296                                        m_Height / max_size_required.height))));
297   }
298 
299   LoadState iCreatedDecoder = CreateDecoder(resolution_levels_to_skip);
300   if (iCreatedDecoder == LoadState::kFail)
301     return LoadState::kFail;
302 
303   if (!ContinueToLoadMask())
304     return LoadState::kFail;
305 
306   LoadState iLoadedMask = m_bHasMask ? StartLoadMask() : LoadState::kSuccess;
307   if (iCreatedDecoder == LoadState::kContinue ||
308       iLoadedMask == LoadState::kContinue) {
309     return LoadState::kContinue;
310   }
311 
312   DCHECK_EQ(iCreatedDecoder, LoadState::kSuccess);
313   DCHECK_EQ(iLoadedMask, LoadState::kSuccess);
314   if (m_pColorSpace && m_bStdCS)
315     m_pColorSpace->EnableStdConversion(false);
316   return LoadState::kSuccess;
317 }
318 
ContinueLoadDIBBase(PauseIndicatorIface * pPause)319 CPDF_DIB::LoadState CPDF_DIB::ContinueLoadDIBBase(PauseIndicatorIface* pPause) {
320   if (m_Status == LoadState::kContinue)
321     return ContinueLoadMaskDIB(pPause);
322 
323   ByteString decoder = m_pStreamAcc->GetImageDecoder();
324   if (decoder == "JPXDecode")
325     return LoadState::kFail;
326 
327   if (decoder != "JBIG2Decode")
328     return LoadState::kSuccess;
329 
330   if (m_Status == LoadState::kFail)
331     return LoadState::kFail;
332 
333   FXCODEC_STATUS iDecodeStatus;
334   if (!m_pJbig2Context) {
335     m_pJbig2Context = std::make_unique<Jbig2Context>();
336     if (m_pStreamAcc->GetImageParam()) {
337       RetainPtr<const CPDF_Stream> pGlobals =
338           m_pStreamAcc->GetImageParam()->GetStreamFor("JBIG2Globals");
339       if (pGlobals) {
340         m_pGlobalAcc = pdfium::MakeRetain<CPDF_StreamAcc>(std::move(pGlobals));
341         m_pGlobalAcc->LoadAllDataFiltered();
342       }
343     }
344     uint64_t nSrcKey = 0;
345     pdfium::span<const uint8_t> pSrcSpan;
346     if (m_pStreamAcc) {
347       pSrcSpan = m_pStreamAcc->GetSpan();
348       nSrcKey = m_pStreamAcc->KeyForCache();
349     }
350     uint64_t nGlobalKey = 0;
351     pdfium::span<const uint8_t> pGlobalSpan;
352     if (m_pGlobalAcc) {
353       pGlobalSpan = m_pGlobalAcc->GetSpan();
354       nGlobalKey = m_pGlobalAcc->KeyForCache();
355     }
356     iDecodeStatus = Jbig2Decoder::StartDecode(
357         m_pJbig2Context.get(), m_pDocument->GetOrCreateCodecContext(), m_Width,
358         m_Height, pSrcSpan, nSrcKey, pGlobalSpan, nGlobalKey,
359         m_pCachedBitmap->GetBuffer(), m_pCachedBitmap->GetPitch(), pPause);
360   } else {
361     iDecodeStatus = Jbig2Decoder::ContinueDecode(m_pJbig2Context.get(), pPause);
362   }
363 
364   if (iDecodeStatus == FXCODEC_STATUS::kError) {
365     m_pJbig2Context.reset();
366     m_pCachedBitmap.Reset();
367     m_pGlobalAcc.Reset();
368     return LoadState::kFail;
369   }
370   if (iDecodeStatus == FXCODEC_STATUS::kDecodeToBeContinued)
371     return LoadState::kContinue;
372 
373   LoadState iContinueStatus = LoadState::kSuccess;
374   if (m_bHasMask) {
375     if (ContinueLoadMaskDIB(pPause) == LoadState::kContinue) {
376       iContinueStatus = LoadState::kContinue;
377       m_Status = LoadState::kContinue;
378     }
379   }
380   if (iContinueStatus == LoadState::kContinue)
381     return LoadState::kContinue;
382 
383   if (m_pColorSpace && m_bStdCS)
384     m_pColorSpace->EnableStdConversion(false);
385   return iContinueStatus;
386 }
387 
LoadColorInfo(const CPDF_Dictionary * pFormResources,const CPDF_Dictionary * pPageResources)388 bool CPDF_DIB::LoadColorInfo(const CPDF_Dictionary* pFormResources,
389                              const CPDF_Dictionary* pPageResources) {
390   absl::optional<DecoderArray> decoder_array = GetDecoderArray(m_pDict);
391   if (!decoder_array.has_value())
392     return false;
393 
394   m_bpc_orig = m_pDict->GetIntegerFor("BitsPerComponent");
395   if (!IsMaybeValidBitsPerComponent(m_bpc_orig))
396     return false;
397 
398   m_bImageMask = m_pDict->GetBooleanFor("ImageMask", /*bDefault=*/false);
399 
400   if (m_bImageMask || !m_pDict->KeyExist("ColorSpace")) {
401     if (!m_bImageMask && !decoder_array.value().empty()) {
402       const ByteString& filter = decoder_array.value().back().first;
403       if (filter == "JPXDecode") {
404         m_bDoBpcCheck = false;
405         return true;
406       }
407     }
408     m_bImageMask = true;
409     m_bpc = m_nComponents = 1;
410     RetainPtr<const CPDF_Array> pDecode = m_pDict->GetArrayFor("Decode");
411     m_bDefaultDecode = !pDecode || !pDecode->GetIntegerAt(0);
412     return true;
413   }
414 
415   RetainPtr<const CPDF_Object> pCSObj =
416       m_pDict->GetDirectObjectFor("ColorSpace");
417   if (!pCSObj)
418     return false;
419 
420   auto* pDocPageData = CPDF_DocPageData::FromDocument(m_pDocument);
421   if (pFormResources)
422     m_pColorSpace = pDocPageData->GetColorSpace(pCSObj.Get(), pFormResources);
423   if (!m_pColorSpace)
424     m_pColorSpace = pDocPageData->GetColorSpace(pCSObj.Get(), pPageResources);
425   if (!m_pColorSpace)
426     return false;
427 
428   // If the checks above failed to find a colorspace, and the next line to set
429   // |m_nComponents| does not get reached, then a decoder can try to set
430   // |m_nComponents| based on the number of channels in the image being
431   // decoded.
432   m_nComponents = m_pColorSpace->CountComponents();
433   m_Family = m_pColorSpace->GetFamily();
434   if (m_Family == CPDF_ColorSpace::Family::kICCBased && pCSObj->IsName()) {
435     ByteString cs = pCSObj->GetString();
436     if (cs == "DeviceGray")
437       m_nComponents = 1;
438     else if (cs == "DeviceRGB")
439       m_nComponents = 3;
440     else if (cs == "DeviceCMYK")
441       m_nComponents = 4;
442   }
443 
444   ByteString filter;
445   if (!decoder_array.value().empty())
446     filter = decoder_array.value().back().first;
447 
448   if (!ValidateDictParam(filter))
449     return false;
450 
451   return GetDecodeAndMaskArray();
452 }
453 
GetDecodeAndMaskArray()454 bool CPDF_DIB::GetDecodeAndMaskArray() {
455   if (!m_pColorSpace)
456     return false;
457 
458   m_CompData.resize(m_nComponents);
459   int max_data = (1 << m_bpc) - 1;
460   RetainPtr<const CPDF_Array> pDecode = m_pDict->GetArrayFor("Decode");
461   if (pDecode) {
462     for (uint32_t i = 0; i < m_nComponents; i++) {
463       m_CompData[i].m_DecodeMin = pDecode->GetFloatAt(i * 2);
464       float max = pDecode->GetFloatAt(i * 2 + 1);
465       m_CompData[i].m_DecodeStep = (max - m_CompData[i].m_DecodeMin) / max_data;
466       float def_value;
467       float def_min;
468       float def_max;
469       m_pColorSpace->GetDefaultValue(i, &def_value, &def_min, &def_max);
470       if (m_Family == CPDF_ColorSpace::Family::kIndexed)
471         def_max = max_data;
472       if (def_min != m_CompData[i].m_DecodeMin || def_max != max)
473         m_bDefaultDecode = false;
474     }
475   } else {
476     for (uint32_t i = 0; i < m_nComponents; i++) {
477       float def_value;
478       m_pColorSpace->GetDefaultValue(i, &def_value, &m_CompData[i].m_DecodeMin,
479                                      &m_CompData[i].m_DecodeStep);
480       if (m_Family == CPDF_ColorSpace::Family::kIndexed)
481         m_CompData[i].m_DecodeStep = max_data;
482       m_CompData[i].m_DecodeStep =
483           (m_CompData[i].m_DecodeStep - m_CompData[i].m_DecodeMin) / max_data;
484     }
485   }
486   if (m_pDict->KeyExist("SMask"))
487     return true;
488 
489   RetainPtr<const CPDF_Object> pMask = m_pDict->GetDirectObjectFor("Mask");
490   if (!pMask)
491     return true;
492 
493   if (const CPDF_Array* pArray = pMask->AsArray()) {
494     if (pArray->size() >= m_nComponents * 2) {
495       for (uint32_t i = 0; i < m_nComponents; i++) {
496         int min_num = pArray->GetIntegerAt(i * 2);
497         int max_num = pArray->GetIntegerAt(i * 2 + 1);
498         m_CompData[i].m_ColorKeyMin = std::max(min_num, 0);
499         m_CompData[i].m_ColorKeyMax = std::min(max_num, max_data);
500       }
501     }
502     m_bColorKey = true;
503   }
504   return true;
505 }
506 
CreateDecoder(uint8_t resolution_levels_to_skip)507 CPDF_DIB::LoadState CPDF_DIB::CreateDecoder(uint8_t resolution_levels_to_skip) {
508   ByteString decoder = m_pStreamAcc->GetImageDecoder();
509   if (decoder.IsEmpty())
510     return LoadState::kSuccess;
511 
512   if (m_bDoBpcCheck && m_bpc == 0)
513     return LoadState::kFail;
514 
515   if (decoder == "JPXDecode") {
516     m_pCachedBitmap = LoadJpxBitmap(resolution_levels_to_skip);
517     return m_pCachedBitmap ? LoadState::kSuccess : LoadState::kFail;
518   }
519 
520   if (decoder == "JBIG2Decode") {
521     m_pCachedBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
522     if (!m_pCachedBitmap->Create(
523             m_Width, m_Height,
524             m_bImageMask ? FXDIB_Format::k1bppMask : FXDIB_Format::k1bppRgb)) {
525       m_pCachedBitmap.Reset();
526       return LoadState::kFail;
527     }
528     m_Status = LoadState::kSuccess;
529     return LoadState::kContinue;
530   }
531 
532   pdfium::span<const uint8_t> src_span = m_pStreamAcc->GetSpan();
533   RetainPtr<const CPDF_Dictionary> pParams = m_pStreamAcc->GetImageParam();
534   if (decoder == "CCITTFaxDecode") {
535     m_pDecoder = CreateFaxDecoder(src_span, m_Width, m_Height, pParams);
536   } else if (decoder == "FlateDecode") {
537     m_pDecoder = CreateFlateDecoder(src_span, m_Width, m_Height, m_nComponents,
538                                     m_bpc, pParams);
539   } else if (decoder == "RunLengthDecode") {
540     m_pDecoder = BasicModule::CreateRunLengthDecoder(
541         src_span, m_Width, m_Height, m_nComponents, m_bpc);
542   } else if (decoder == "DCTDecode") {
543     if (!CreateDCTDecoder(src_span, pParams))
544       return LoadState::kFail;
545   }
546   if (!m_pDecoder)
547     return LoadState::kFail;
548 
549   const absl::optional<uint32_t> requested_pitch =
550       fxge::CalculatePitch8(m_bpc, m_nComponents, m_Width);
551   if (!requested_pitch.has_value())
552     return LoadState::kFail;
553   const absl::optional<uint32_t> provided_pitch = fxge::CalculatePitch8(
554       m_pDecoder->GetBPC(), m_pDecoder->CountComps(), m_pDecoder->GetWidth());
555   if (!provided_pitch.has_value())
556     return LoadState::kFail;
557   if (provided_pitch.value() < requested_pitch.value())
558     return LoadState::kFail;
559   return LoadState::kSuccess;
560 }
561 
CreateDCTDecoder(pdfium::span<const uint8_t> src_span,const CPDF_Dictionary * pParams)562 bool CPDF_DIB::CreateDCTDecoder(pdfium::span<const uint8_t> src_span,
563                                 const CPDF_Dictionary* pParams) {
564   m_pDecoder = JpegModule::CreateDecoder(
565       src_span, m_Width, m_Height, m_nComponents,
566       !pParams || pParams->GetIntegerFor("ColorTransform", 1));
567   if (m_pDecoder)
568     return true;
569 
570   absl::optional<JpegModule::ImageInfo> info_opt =
571       JpegModule::LoadInfo(src_span);
572   if (!info_opt.has_value())
573     return false;
574 
575   const JpegModule::ImageInfo& info = info_opt.value();
576   m_Width = info.width;
577   m_Height = info.height;
578 
579   if (!CPDF_Image::IsValidJpegComponent(info.num_components) ||
580       !CPDF_Image::IsValidJpegBitsPerComponent(info.bits_per_components)) {
581     return false;
582   }
583 
584   if (m_nComponents == static_cast<uint32_t>(info.num_components)) {
585     m_bpc = info.bits_per_components;
586     m_pDecoder = JpegModule::CreateDecoder(src_span, m_Width, m_Height,
587                                            m_nComponents, info.color_transform);
588     return true;
589   }
590 
591   m_nComponents = static_cast<uint32_t>(info.num_components);
592   m_CompData.clear();
593   if (m_pColorSpace) {
594     uint32_t colorspace_comps = m_pColorSpace->CountComponents();
595     switch (m_Family) {
596       case CPDF_ColorSpace::Family::kDeviceGray:
597       case CPDF_ColorSpace::Family::kDeviceRGB:
598       case CPDF_ColorSpace::Family::kDeviceCMYK: {
599         uint32_t dwMinComps = CPDF_ColorSpace::ComponentsForFamily(m_Family);
600         if (colorspace_comps < dwMinComps || m_nComponents < dwMinComps)
601           return false;
602         break;
603       }
604       case CPDF_ColorSpace::Family::kLab: {
605         if (m_nComponents != 3 || colorspace_comps < 3)
606           return false;
607         break;
608       }
609       case CPDF_ColorSpace::Family::kICCBased: {
610         if (!CPDF_ColorSpace::IsValidIccComponents(colorspace_comps) ||
611             !CPDF_ColorSpace::IsValidIccComponents(m_nComponents) ||
612             colorspace_comps < m_nComponents) {
613           return false;
614         }
615         break;
616       }
617       default: {
618         if (colorspace_comps != m_nComponents)
619           return false;
620         break;
621       }
622     }
623   } else {
624     if (m_Family == CPDF_ColorSpace::Family::kLab && m_nComponents != 3)
625       return false;
626   }
627   if (!GetDecodeAndMaskArray())
628     return false;
629 
630   m_bpc = info.bits_per_components;
631   m_pDecoder = JpegModule::CreateDecoder(src_span, m_Width, m_Height,
632                                          m_nComponents, info.color_transform);
633   return true;
634 }
635 
LoadJpxBitmap(uint8_t resolution_levels_to_skip)636 RetainPtr<CFX_DIBitmap> CPDF_DIB::LoadJpxBitmap(
637     uint8_t resolution_levels_to_skip) {
638   std::unique_ptr<CJPX_Decoder> decoder =
639       CJPX_Decoder::Create(m_pStreamAcc->GetSpan(),
640                            ColorSpaceOptionFromColorSpace(m_pColorSpace.Get()),
641                            resolution_levels_to_skip);
642   if (!decoder)
643     return nullptr;
644 
645   m_Height >>= resolution_levels_to_skip;
646   m_Width >>= resolution_levels_to_skip;
647 
648   if (!decoder->StartDecode())
649     return nullptr;
650 
651   CJPX_Decoder::JpxImageInfo image_info = decoder->GetInfo();
652   if (static_cast<int>(image_info.width) < m_Width ||
653       static_cast<int>(image_info.height) < m_Height) {
654     return nullptr;
655   }
656 
657   RetainPtr<CPDF_ColorSpace> original_colorspace = m_pColorSpace;
658   bool swap_rgb = false;
659   bool convert_argb_to_rgb = false;
660   auto action = GetJpxDecodeAction(image_info, m_pColorSpace.Get());
661   switch (action) {
662     case JpxDecodeAction::kFail:
663       return nullptr;
664 
665     case JpxDecodeAction::kDoNothing:
666       break;
667 
668     case JpxDecodeAction::kUseGray:
669       m_pColorSpace =
670           CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceGray);
671       break;
672 
673     case JpxDecodeAction::kUseRgb:
674       DCHECK(image_info.channels >= 3);
675       swap_rgb = true;
676       m_pColorSpace = nullptr;
677       break;
678 
679     case JpxDecodeAction::kUseCmyk:
680       m_pColorSpace =
681           CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceCMYK);
682       break;
683 
684     case JpxDecodeAction::kConvertArgbToRgb:
685       swap_rgb = true;
686       convert_argb_to_rgb = true;
687       m_pColorSpace.Reset();
688   }
689 
690   // If |original_colorspace| exists, then LoadColorInfo() already set
691   // |m_nComponents|.
692   if (original_colorspace) {
693     DCHECK_NE(0, m_nComponents);
694   } else {
695     DCHECK_EQ(0, m_nComponents);
696     m_nComponents = GetComponentCountFromOpjColorSpace(image_info.colorspace);
697     if (m_nComponents == 0) {
698       return nullptr;
699     }
700   }
701 
702   FXDIB_Format format;
703   if (action == JpxDecodeAction::kUseGray) {
704     format = FXDIB_Format::k8bppRgb;
705   } else if (action == JpxDecodeAction::kUseRgb && image_info.channels == 3) {
706     format = FXDIB_Format::kRgb;
707   } else if (action == JpxDecodeAction::kConvertArgbToRgb &&
708              image_info.channels == 4) {
709     format = FXDIB_Format::kRgb32;
710   } else if (action == JpxDecodeAction::kUseRgb && image_info.channels == 4) {
711     format = FXDIB_Format::kRgb32;
712   } else {
713     image_info.width = (image_info.width * image_info.channels + 2) / 3;
714     format = FXDIB_Format::kRgb;
715   }
716 
717   auto result_bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
718   if (!result_bitmap->Create(image_info.width, image_info.height, format))
719     return nullptr;
720 
721   result_bitmap->Clear(0xFFFFFFFF);
722   if (!decoder->Decode(result_bitmap->GetBuffer(), result_bitmap->GetPitch(),
723                        swap_rgb, m_nComponents)) {
724     return nullptr;
725   }
726 
727   if (convert_argb_to_rgb) {
728     DCHECK_EQ(3, m_nComponents);
729     auto rgb_bitmap = pdfium::MakeRetain<CFX_DIBitmap>();
730     if (!rgb_bitmap->Create(image_info.width, image_info.height,
731                             FXDIB_Format::kRgb)) {
732       return nullptr;
733     }
734     if (m_pDict->GetIntegerFor("SMaskInData") == 1) {
735       // TODO(thestig): Acrobat does not support "/SMaskInData 1" combined with
736       // filters. Check for that and fail early.
737       DCHECK(m_JpxInlineData.data.empty());
738       m_JpxInlineData.width = image_info.width;
739       m_JpxInlineData.height = image_info.height;
740       m_JpxInlineData.data.reserve(image_info.width * image_info.height);
741       for (uint32_t row = 0; row < image_info.height; ++row) {
742         const uint8_t* src = result_bitmap->GetScanline(row).data();
743         uint8_t* dest = rgb_bitmap->GetWritableScanline(row).data();
744         for (uint32_t col = 0; col < image_info.width; ++col) {
745           uint8_t a = src[3];
746           m_JpxInlineData.data.push_back(a);
747           uint8_t na = 255 - a;
748           uint8_t b = (src[0] * a + 255 * na) / 255;
749           uint8_t g = (src[1] * a + 255 * na) / 255;
750           uint8_t r = (src[2] * a + 255 * na) / 255;
751           dest[0] = b;
752           dest[1] = g;
753           dest[2] = r;
754           src += 4;
755           dest += 3;
756         }
757       }
758     } else {
759       // TODO(thestig): Is there existing code that does this already?
760       for (uint32_t row = 0; row < image_info.height; ++row) {
761         const uint8_t* src = result_bitmap->GetScanline(row).data();
762         uint8_t* dest = rgb_bitmap->GetWritableScanline(row).data();
763         for (uint32_t col = 0; col < image_info.width; ++col) {
764           memcpy(dest, src, 3);
765           src += 4;
766           dest += 3;
767         }
768       }
769     }
770     result_bitmap = std::move(rgb_bitmap);
771   } else if (m_pColorSpace &&
772              m_pColorSpace->GetFamily() == CPDF_ColorSpace::Family::kIndexed &&
773              m_bpc < 8) {
774     int scale = 8 - m_bpc;
775     for (uint32_t row = 0; row < image_info.height; ++row) {
776       uint8_t* scanline = result_bitmap->GetWritableScanline(row).data();
777       for (uint32_t col = 0; col < image_info.width; ++col) {
778         *scanline = (*scanline) >> scale;
779         ++scanline;
780       }
781     }
782   }
783 
784   // TODO(crbug.com/pdfium/1747): Handle SMaskInData entries for different
785   // color space types.
786 
787   m_bpc = 8;
788   return result_bitmap;
789 }
790 
LoadInternal(const CPDF_Dictionary * pFormResources,const CPDF_Dictionary * pPageResources)791 bool CPDF_DIB::LoadInternal(const CPDF_Dictionary* pFormResources,
792                             const CPDF_Dictionary* pPageResources) {
793   if (!m_pStream)
794     return false;
795 
796   m_pDict = m_pStream->GetDict();
797   if (!m_pDict)
798     return false;
799 
800   m_Width = m_pDict->GetIntegerFor("Width");
801   m_Height = m_pDict->GetIntegerFor("Height");
802   if (!IsValidDimension(m_Width) || !IsValidDimension(m_Height))
803     return false;
804 
805   if (!LoadColorInfo(pFormResources, pPageResources))
806     return false;
807 
808   if (m_bDoBpcCheck && (m_bpc == 0 || m_nComponents == 0))
809     return false;
810 
811   const absl::optional<uint32_t> maybe_size =
812       fxge::CalculatePitch8(m_bpc, m_nComponents, m_Width);
813   if (!maybe_size.has_value())
814     return false;
815 
816   FX_SAFE_UINT32 src_size = maybe_size.value();
817   src_size *= m_Height;
818   if (!src_size.IsValid())
819     return false;
820 
821   m_pStreamAcc = pdfium::MakeRetain<CPDF_StreamAcc>(m_pStream);
822   m_pStreamAcc->LoadAllDataImageAcc(src_size.ValueOrDie());
823   return !m_pStreamAcc->GetSpan().empty();
824 }
825 
StartLoadMask()826 CPDF_DIB::LoadState CPDF_DIB::StartLoadMask() {
827   m_MatteColor = 0XFFFFFFFF;
828 
829   if (!m_JpxInlineData.data.empty()) {
830     auto dict = pdfium::MakeRetain<CPDF_Dictionary>();
831     dict->SetNewFor<CPDF_Name>("Type", "XObject");
832     dict->SetNewFor<CPDF_Name>("Subtype", "Image");
833     dict->SetNewFor<CPDF_Name>("ColorSpace", "DeviceGray");
834     dict->SetNewFor<CPDF_Number>("Width", m_JpxInlineData.width);
835     dict->SetNewFor<CPDF_Number>("Height", m_JpxInlineData.height);
836     dict->SetNewFor<CPDF_Number>("BitsPerComponent", 8);
837 
838     return StartLoadMaskDIB(
839         pdfium::MakeRetain<CPDF_Stream>(m_JpxInlineData.data, std::move(dict)));
840   }
841 
842   RetainPtr<const CPDF_Stream> mask(m_pDict->GetStreamFor("SMask"));
843   if (!mask) {
844     mask = ToStream(m_pDict->GetDirectObjectFor("Mask"));
845     return mask ? StartLoadMaskDIB(std::move(mask)) : LoadState::kSuccess;
846   }
847 
848   RetainPtr<const CPDF_Array> pMatte = mask->GetDict()->GetArrayFor("Matte");
849   if (pMatte && m_pColorSpace &&
850       m_Family != CPDF_ColorSpace::Family::kPattern &&
851       pMatte->size() == m_nComponents &&
852       m_pColorSpace->CountComponents() <= m_nComponents) {
853     std::vector<float> colors =
854         ReadArrayElementsToVector(pMatte.Get(), m_nComponents);
855 
856     float R;
857     float G;
858     float B;
859     m_pColorSpace->GetRGB(colors, &R, &G, &B);
860     m_MatteColor = ArgbEncode(0, FXSYS_roundf(R * 255), FXSYS_roundf(G * 255),
861                               FXSYS_roundf(B * 255));
862   }
863   return StartLoadMaskDIB(std::move(mask));
864 }
865 
ContinueLoadMaskDIB(PauseIndicatorIface * pPause)866 CPDF_DIB::LoadState CPDF_DIB::ContinueLoadMaskDIB(PauseIndicatorIface* pPause) {
867   if (!m_pMask)
868     return LoadState::kSuccess;
869 
870   LoadState ret = m_pMask->ContinueLoadDIBBase(pPause);
871   if (ret == LoadState::kContinue)
872     return LoadState::kContinue;
873 
874   if (m_pColorSpace && m_bStdCS)
875     m_pColorSpace->EnableStdConversion(false);
876 
877   if (ret == LoadState::kFail) {
878     m_pMask.Reset();
879     return LoadState::kFail;
880   }
881   return LoadState::kSuccess;
882 }
883 
DetachMask()884 RetainPtr<CPDF_DIB> CPDF_DIB::DetachMask() {
885   return std::move(m_pMask);
886 }
887 
IsJBigImage() const888 bool CPDF_DIB::IsJBigImage() const {
889   return m_pStreamAcc->GetImageDecoder() == "JBIG2Decode";
890 }
891 
StartLoadMaskDIB(RetainPtr<const CPDF_Stream> mask_stream)892 CPDF_DIB::LoadState CPDF_DIB::StartLoadMaskDIB(
893     RetainPtr<const CPDF_Stream> mask_stream) {
894   m_pMask = pdfium::MakeRetain<CPDF_DIB>(m_pDocument, std::move(mask_stream));
895   LoadState ret = m_pMask->StartLoadDIBBase(false, nullptr, nullptr, true,
896                                             CPDF_ColorSpace::Family::kUnknown,
897                                             false, {0, 0});
898   if (ret == LoadState::kContinue) {
899     if (m_Status == LoadState::kFail)
900       m_Status = LoadState::kContinue;
901     return LoadState::kContinue;
902   }
903   if (ret == LoadState::kFail)
904     m_pMask.Reset();
905   return LoadState::kSuccess;
906 }
907 
LoadPalette()908 void CPDF_DIB::LoadPalette() {
909   if (!m_pColorSpace || m_Family == CPDF_ColorSpace::Family::kPattern)
910     return;
911 
912   if (m_bpc == 0)
913     return;
914 
915   // Use FX_SAFE_UINT32 just to be on the safe side, in case |m_bpc| or
916   // |m_nComponents| somehow gets a bad value.
917   FX_SAFE_UINT32 safe_bits = m_bpc;
918   safe_bits *= m_nComponents;
919   uint32_t bits = safe_bits.ValueOrDefault(255);
920   if (bits > 8)
921     return;
922 
923   if (bits == 1) {
924     if (m_bDefaultDecode && (m_Family == CPDF_ColorSpace::Family::kDeviceGray ||
925                              m_Family == CPDF_ColorSpace::Family::kDeviceRGB)) {
926       return;
927     }
928     if (m_pColorSpace->CountComponents() > 3) {
929       return;
930     }
931     float color_values[3];
932     std::fill(std::begin(color_values), std::end(color_values),
933               m_CompData[0].m_DecodeMin);
934 
935     float R = 0.0f;
936     float G = 0.0f;
937     float B = 0.0f;
938     m_pColorSpace->GetRGB(color_values, &R, &G, &B);
939 
940     FX_ARGB argb0 = ArgbEncode(255, FXSYS_roundf(R * 255),
941                                FXSYS_roundf(G * 255), FXSYS_roundf(B * 255));
942     FX_ARGB argb1;
943     const CPDF_IndexedCS* indexed_cs = m_pColorSpace->AsIndexedCS();
944     if (indexed_cs && indexed_cs->GetMaxIndex() == 0) {
945       // If an indexed color space's hival value is 0, only 1 color is specified
946       // in the lookup table. Another color should be set to 0xFF000000 by
947       // default to set the range of the color space.
948       argb1 = 0xFF000000;
949     } else {
950       color_values[0] += m_CompData[0].m_DecodeStep;
951       color_values[1] += m_CompData[0].m_DecodeStep;
952       color_values[2] += m_CompData[0].m_DecodeStep;
953       m_pColorSpace->GetRGB(color_values, &R, &G, &B);
954       argb1 = ArgbEncode(255, FXSYS_roundf(R * 255), FXSYS_roundf(G * 255),
955                          FXSYS_roundf(B * 255));
956     }
957 
958     if (argb0 != 0xFF000000 || argb1 != 0xFFFFFFFF) {
959       SetPaletteArgb(0, argb0);
960       SetPaletteArgb(1, argb1);
961     }
962     return;
963   }
964   if (m_bpc == 8 && m_bDefaultDecode &&
965       m_pColorSpace ==
966           CPDF_ColorSpace::GetStockCS(CPDF_ColorSpace::Family::kDeviceGray)) {
967     return;
968   }
969 
970   int palette_count = 1 << bits;
971   // Using at least 16 elements due to the call m_pColorSpace->GetRGB().
972   std::vector<float> color_values(std::max(m_nComponents, 16u));
973   for (int i = 0; i < palette_count; i++) {
974     int color_data = i;
975     for (uint32_t j = 0; j < m_nComponents; j++) {
976       int encoded_component = color_data % (1 << m_bpc);
977       color_data /= 1 << m_bpc;
978       color_values[j] = m_CompData[j].m_DecodeMin +
979                         m_CompData[j].m_DecodeStep * encoded_component;
980     }
981     float R = 0;
982     float G = 0;
983     float B = 0;
984     if (m_nComponents == 1 && m_Family == CPDF_ColorSpace::Family::kICCBased &&
985         m_pColorSpace->CountComponents() > 1) {
986       int nComponents = m_pColorSpace->CountComponents();
987       std::vector<float> temp_buf(nComponents);
988       for (int k = 0; k < nComponents; ++k)
989         temp_buf[k] = color_values[0];
990       m_pColorSpace->GetRGB(temp_buf, &R, &G, &B);
991     } else {
992       m_pColorSpace->GetRGB(color_values, &R, &G, &B);
993     }
994     SetPaletteArgb(i, ArgbEncode(255, FXSYS_roundf(R * 255),
995                                  FXSYS_roundf(G * 255), FXSYS_roundf(B * 255)));
996   }
997 }
998 
ValidateDictParam(const ByteString & filter)999 bool CPDF_DIB::ValidateDictParam(const ByteString& filter) {
1000   m_bpc = m_bpc_orig;
1001 
1002   // Per spec, |m_bpc| should always be 8 for RunLengthDecode, but too many
1003   // documents do not conform to it. So skip this check.
1004 
1005   if (filter == "JPXDecode") {
1006     m_bDoBpcCheck = false;
1007     return true;
1008   }
1009 
1010   if (filter == "CCITTFaxDecode" || filter == "JBIG2Decode") {
1011     m_bpc = 1;
1012     m_nComponents = 1;
1013   } else if (filter == "DCTDecode") {
1014     m_bpc = 8;
1015   }
1016 
1017   if (!IsAllowedBitsPerComponent(m_bpc)) {
1018     m_bpc = 0;
1019     return false;
1020   }
1021   return true;
1022 }
1023 
TranslateScanline24bpp(pdfium::span<uint8_t> dest_scan,pdfium::span<const uint8_t> src_scan) const1024 void CPDF_DIB::TranslateScanline24bpp(
1025     pdfium::span<uint8_t> dest_scan,
1026     pdfium::span<const uint8_t> src_scan) const {
1027   if (m_bpc == 0)
1028     return;
1029 
1030   if (TranslateScanline24bppDefaultDecode(dest_scan, src_scan))
1031     return;
1032 
1033   // Using at least 16 elements due to the call m_pColorSpace->GetRGB().
1034   std::vector<float> color_values(std::max(m_nComponents, 16u));
1035   float R = 0.0f;
1036   float G = 0.0f;
1037   float B = 0.0f;
1038   uint64_t src_bit_pos = 0;
1039   uint64_t src_byte_pos = 0;
1040   size_t dest_byte_pos = 0;
1041   const bool bpp8 = m_bpc == 8;
1042   for (int column = 0; column < m_Width; column++) {
1043     for (uint32_t color = 0; color < m_nComponents; color++) {
1044       if (bpp8) {
1045         uint8_t data = src_scan[src_byte_pos++];
1046         color_values[color] = m_CompData[color].m_DecodeMin +
1047                               m_CompData[color].m_DecodeStep * data;
1048       } else {
1049         unsigned int data = GetBits8(src_scan.data(), src_bit_pos, m_bpc);
1050         color_values[color] = m_CompData[color].m_DecodeMin +
1051                               m_CompData[color].m_DecodeStep * data;
1052         src_bit_pos += m_bpc;
1053       }
1054     }
1055 
1056     if (TransMask()) {
1057       float k = 1.0f - color_values[3];
1058       R = (1.0f - color_values[0]) * k;
1059       G = (1.0f - color_values[1]) * k;
1060       B = (1.0f - color_values[2]) * k;
1061     } else if (m_Family != CPDF_ColorSpace::Family::kPattern) {
1062       m_pColorSpace->GetRGB(color_values, &R, &G, &B);
1063     }
1064     R = pdfium::clamp(R, 0.0f, 1.0f);
1065     G = pdfium::clamp(G, 0.0f, 1.0f);
1066     B = pdfium::clamp(B, 0.0f, 1.0f);
1067     dest_scan[dest_byte_pos] = static_cast<uint8_t>(B * 255);
1068     dest_scan[dest_byte_pos + 1] = static_cast<uint8_t>(G * 255);
1069     dest_scan[dest_byte_pos + 2] = static_cast<uint8_t>(R * 255);
1070     dest_byte_pos += 3;
1071   }
1072 }
1073 
TranslateScanline24bppDefaultDecode(pdfium::span<uint8_t> dest_scan,pdfium::span<const uint8_t> src_scan) const1074 bool CPDF_DIB::TranslateScanline24bppDefaultDecode(
1075     pdfium::span<uint8_t> dest_scan,
1076     pdfium::span<const uint8_t> src_scan) const {
1077   if (!m_bDefaultDecode)
1078     return false;
1079 
1080   if (m_Family != CPDF_ColorSpace::Family::kDeviceRGB &&
1081       m_Family != CPDF_ColorSpace::Family::kCalRGB) {
1082     if (m_bpc != 8)
1083       return false;
1084 
1085     if (m_nComponents == m_pColorSpace->CountComponents()) {
1086       m_pColorSpace->TranslateImageLine(dest_scan, src_scan, m_Width, m_Width,
1087                                         m_Height, TransMask());
1088     }
1089     return true;
1090   }
1091 
1092   if (m_nComponents != 3)
1093     return true;
1094 
1095   uint8_t* dest_pos = dest_scan.data();
1096   const uint8_t* src_pos = src_scan.data();
1097   switch (m_bpc) {
1098     case 8:
1099       for (int column = 0; column < m_Width; column++) {
1100         *dest_pos++ = src_pos[2];
1101         *dest_pos++ = src_pos[1];
1102         *dest_pos++ = *src_pos;
1103         src_pos += 3;
1104       }
1105       break;
1106     case 16:
1107       for (int col = 0; col < m_Width; col++) {
1108         *dest_pos++ = src_pos[4];
1109         *dest_pos++ = src_pos[2];
1110         *dest_pos++ = *src_pos;
1111         src_pos += 6;
1112       }
1113       break;
1114     default:
1115       const unsigned int max_data = (1 << m_bpc) - 1;
1116       uint64_t src_bit_pos = 0;
1117       size_t dest_byte_pos = 0;
1118       for (int column = 0; column < m_Width; column++) {
1119         unsigned int R = GetBits8(src_scan.data(), src_bit_pos, m_bpc);
1120         src_bit_pos += m_bpc;
1121         unsigned int G = GetBits8(src_scan.data(), src_bit_pos, m_bpc);
1122         src_bit_pos += m_bpc;
1123         unsigned int B = GetBits8(src_scan.data(), src_bit_pos, m_bpc);
1124         src_bit_pos += m_bpc;
1125         R = std::min(R, max_data);
1126         G = std::min(G, max_data);
1127         B = std::min(B, max_data);
1128         dest_pos[dest_byte_pos] = B * 255 / max_data;
1129         dest_pos[dest_byte_pos + 1] = G * 255 / max_data;
1130         dest_pos[dest_byte_pos + 2] = R * 255 / max_data;
1131         dest_byte_pos += 3;
1132       }
1133       break;
1134   }
1135   return true;
1136 }
1137 
GetBuffer() const1138 pdfium::span<uint8_t> CPDF_DIB::GetBuffer() const {
1139   return m_pCachedBitmap ? m_pCachedBitmap->GetBuffer()
1140                          : pdfium::span<uint8_t>();
1141 }
1142 
GetScanline(int line) const1143 pdfium::span<const uint8_t> CPDF_DIB::GetScanline(int line) const {
1144   if (m_bpc == 0)
1145     return pdfium::span<const uint8_t>();
1146 
1147   const absl::optional<uint32_t> src_pitch =
1148       fxge::CalculatePitch8(m_bpc, m_nComponents, m_Width);
1149   if (!src_pitch.has_value())
1150     return pdfium::span<const uint8_t>();
1151 
1152   uint32_t src_pitch_value = src_pitch.value();
1153   // This is used as the buffer of `pSrcLine` when the stream is truncated,
1154   // and the remaining bytes count is less than `src_pitch_value`
1155   DataVector<uint8_t> temp_buffer;
1156   pdfium::span<const uint8_t> pSrcLine;
1157 
1158   if (m_pCachedBitmap && src_pitch_value <= m_pCachedBitmap->GetPitch()) {
1159     if (line >= m_pCachedBitmap->GetHeight())
1160       line = m_pCachedBitmap->GetHeight() - 1;
1161     pSrcLine = m_pCachedBitmap->GetScanline(line);
1162   } else if (m_pDecoder) {
1163     pSrcLine = m_pDecoder->GetScanline(line);
1164   } else if (m_pStreamAcc->GetSize() > line * src_pitch_value) {
1165     pdfium::span<const uint8_t> remaining_bytes =
1166         m_pStreamAcc->GetSpan().subspan(line * src_pitch_value);
1167     if (remaining_bytes.size() >= src_pitch_value) {
1168       pSrcLine = remaining_bytes.first(src_pitch_value);
1169     } else {
1170       temp_buffer = DataVector<uint8_t>(src_pitch_value);
1171       pdfium::span<uint8_t> result = temp_buffer;
1172       fxcrt::spancpy(result, remaining_bytes);
1173       pSrcLine = result;
1174     }
1175   }
1176 
1177   if (pSrcLine.empty()) {
1178     pdfium::span<uint8_t> result = !m_MaskBuf.empty() ? m_MaskBuf : m_LineBuf;
1179     fxcrt::spanset(result, 0);
1180     return result;
1181   }
1182   if (m_bpc * m_nComponents == 1) {
1183     if (m_bImageMask && m_bDefaultDecode) {
1184       for (uint32_t i = 0; i < src_pitch_value; i++) {
1185         // TODO(tsepez): Bounds check if cost is acceptable.
1186         m_LineBuf[i] = ~pSrcLine.data()[i];
1187       }
1188       return pdfium::make_span(m_LineBuf).first(src_pitch_value);
1189     }
1190     if (!m_bColorKey) {
1191       pdfium::span<uint8_t> result = m_LineBuf;
1192       fxcrt::spancpy(result, pSrcLine.first(src_pitch_value));
1193       return result.first(src_pitch_value);
1194     }
1195     uint32_t reset_argb = Get1BitResetValue();
1196     uint32_t set_argb = Get1BitSetValue();
1197     uint32_t* dest_scan = reinterpret_cast<uint32_t*>(m_MaskBuf.data());
1198     for (int col = 0; col < m_Width; col++, dest_scan++) {
1199       *dest_scan = GetBitValue(pSrcLine.data(), col) ? set_argb : reset_argb;
1200     }
1201     return pdfium::make_span(m_MaskBuf).first(m_Width * sizeof(uint32_t));
1202   }
1203   if (m_bpc * m_nComponents <= 8) {
1204     pdfium::span<uint8_t> result = m_LineBuf;
1205     if (m_bpc == 8) {
1206       fxcrt::spancpy(result, pSrcLine.first(src_pitch_value));
1207       result = result.first(src_pitch_value);
1208     } else {
1209       uint64_t src_bit_pos = 0;
1210       for (int col = 0; col < m_Width; col++) {
1211         unsigned int color_index = 0;
1212         for (uint32_t color = 0; color < m_nComponents; color++) {
1213           unsigned int data = GetBits8(pSrcLine.data(), src_bit_pos, m_bpc);
1214           color_index |= data << (color * m_bpc);
1215           src_bit_pos += m_bpc;
1216         }
1217         m_LineBuf[col] = color_index;
1218       }
1219       result = result.first(m_Width);
1220     }
1221     if (!m_bColorKey)
1222       return result;
1223 
1224     uint8_t* pDestPixel = m_MaskBuf.data();
1225     const uint8_t* pSrcPixel = m_LineBuf.data();
1226     pdfium::span<const uint32_t> palette = GetPaletteSpan();
1227     if (HasPalette()) {
1228       for (int col = 0; col < m_Width; col++) {
1229         uint8_t index = *pSrcPixel++;
1230         *pDestPixel++ = FXARGB_B(palette[index]);
1231         *pDestPixel++ = FXARGB_G(palette[index]);
1232         *pDestPixel++ = FXARGB_R(palette[index]);
1233         *pDestPixel++ =
1234             IsColorIndexOutOfBounds(index, m_CompData[0]) ? 0xFF : 0;
1235       }
1236     } else {
1237       for (int col = 0; col < m_Width; col++) {
1238         uint8_t index = *pSrcPixel++;
1239         *pDestPixel++ = index;
1240         *pDestPixel++ = index;
1241         *pDestPixel++ = index;
1242         *pDestPixel++ =
1243             IsColorIndexOutOfBounds(index, m_CompData[0]) ? 0xFF : 0;
1244       }
1245     }
1246     return pdfium::make_span(m_MaskBuf).first(4 * m_Width);
1247   }
1248   if (m_bColorKey) {
1249     if (m_nComponents == 3 && m_bpc == 8) {
1250       uint8_t* alpha_channel = m_MaskBuf.data() + 3;
1251       for (int col = 0; col < m_Width; col++) {
1252         const uint8_t* pPixel = pSrcLine.data() + col * 3;
1253         alpha_channel[col * 4] =
1254             AreColorIndicesOutOfBounds(pPixel, m_CompData.data(), 3) ? 0xFF : 0;
1255       }
1256     } else {
1257       fxcrt::spanset(pdfium::make_span(m_MaskBuf), 0xFF);
1258     }
1259   }
1260   if (m_pColorSpace) {
1261     TranslateScanline24bpp(m_LineBuf, pSrcLine);
1262     src_pitch_value = 3 * m_Width;
1263     pSrcLine = pdfium::make_span(m_LineBuf).first(src_pitch_value);
1264   }
1265   if (!m_bColorKey)
1266     return pSrcLine;
1267 
1268   // TODO(tsepez): Bounds check if cost is acceptable.
1269   const uint8_t* pSrcPixel = pSrcLine.data();
1270   uint8_t* pDestPixel = m_MaskBuf.data();
1271   for (int col = 0; col < m_Width; col++) {
1272     *pDestPixel++ = *pSrcPixel++;
1273     *pDestPixel++ = *pSrcPixel++;
1274     *pDestPixel++ = *pSrcPixel++;
1275     pDestPixel++;
1276   }
1277   return pdfium::make_span(m_MaskBuf).first(4 * m_Width);
1278 }
1279 
SkipToScanline(int line,PauseIndicatorIface * pPause) const1280 bool CPDF_DIB::SkipToScanline(int line, PauseIndicatorIface* pPause) const {
1281   return m_pDecoder && m_pDecoder->SkipToScanline(line, pPause);
1282 }
1283 
GetEstimatedImageMemoryBurden() const1284 size_t CPDF_DIB::GetEstimatedImageMemoryBurden() const {
1285   return m_pCachedBitmap ? m_pCachedBitmap->GetEstimatedImageMemoryBurden() : 0;
1286 }
1287 
TransMask() const1288 bool CPDF_DIB::TransMask() const {
1289   return m_bLoadMask && m_GroupFamily == CPDF_ColorSpace::Family::kDeviceCMYK &&
1290          m_Family == CPDF_ColorSpace::Family::kDeviceCMYK;
1291 }
1292 
SetMaskProperties()1293 void CPDF_DIB::SetMaskProperties() {
1294   m_bpc = 1;
1295   m_nComponents = 1;
1296   m_Format = FXDIB_Format::k1bppMask;
1297 }
1298 
Get1BitSetValue() const1299 uint32_t CPDF_DIB::Get1BitSetValue() const {
1300   if (m_CompData[0].m_ColorKeyMax == 1)
1301     return 0x00000000;
1302   return HasPalette() ? GetPaletteSpan()[1] : 0xFFFFFFFF;
1303 }
1304 
Get1BitResetValue() const1305 uint32_t CPDF_DIB::Get1BitResetValue() const {
1306   if (m_CompData[0].m_ColorKeyMin == 0)
1307     return 0x00000000;
1308   return HasPalette() ? GetPaletteSpan()[0] : 0xFF000000;
1309 }
1310