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