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