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

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

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

Powered by Google App Engine
This is Rietveld 408576698