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