Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(412)

Side by Side Diff: core/src/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp

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

Powered by Google App Engine
This is Rietveld 408576698