Reapply Foxit's libopenjpeg modifications.
[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           filter == FX_BSTRC("DCTDecode")) {
962         m_bpc = 8;
963       }
964     } else if (pFilter->GetType() == PDFOBJ_ARRAY) {
965       CPDF_Array* pArray = (CPDF_Array*)pFilter;
966       if (pArray->GetString(pArray->GetCount() - 1) ==
967               FX_BSTRC("CCITTFaxDecode") ||
968           pArray->GetString(pArray->GetCount() - 1) ==
969               FX_BSTRC("JBIG2Decode")) {
970         m_bpc = 1;
971         m_nComponents = 1;
972       }
973       if (pArray->GetString(pArray->GetCount() - 1) == FX_BSTRC("DCTDecode")) {
974         // Previously, pArray->GetString(pArray->GetCount() - 1) ==
975         // FX_BSTRC("RunLengthDecode") was checked in the "if" statement as
976         // well,
977         // but too many documents don't conform to it.
978         m_bpc = 8;
979       }
980     }
981   }
982   if (m_bpc != 1 && m_bpc != 2 && m_bpc != 4 && m_bpc != 8 && m_bpc != 16) {
983     m_bpc = 0;
984   }
985 }
986 #define NORMALCOLOR_MAX(color, max) \
987   (color) > (max) ? (max) : (color) < 0 ? 0 : (color);
988 void CPDF_DIBSource::TranslateScanline24bpp(uint8_t* dest_scan,
989                                             const uint8_t* src_scan) const {
990   if (m_bpc == 0) {
991     return;
992   }
993   int max_data = (1 << m_bpc) - 1;
994   if (m_bDefaultDecode) {
995     if (m_Family == PDFCS_DEVICERGB || m_Family == PDFCS_CALRGB) {
996       const uint8_t* src_pos = src_scan;
997       switch (m_bpc) {
998         case 16:
999           for (int col = 0; col < m_Width; col++) {
1000             *dest_scan++ = src_pos[4];
1001             *dest_scan++ = src_pos[2];
1002             *dest_scan++ = *src_pos;
1003             src_pos += 6;
1004           }
1005           break;
1006         case 8:
1007           for (int column = 0; column < m_Width; column++) {
1008             *dest_scan++ = src_pos[2];
1009             *dest_scan++ = src_pos[1];
1010             *dest_scan++ = *src_pos;
1011             src_pos += 3;
1012           }
1013           break;
1014         default:
1015           int src_bit_pos = 0;
1016           int dest_byte_pos = 0;
1017           for (int column = 0; column < m_Width; column++) {
1018             int R = _GetBits8(src_scan, src_bit_pos, m_bpc);
1019             src_bit_pos += m_bpc;
1020             int G = _GetBits8(src_scan, src_bit_pos, m_bpc);
1021             src_bit_pos += m_bpc;
1022             int B = _GetBits8(src_scan, src_bit_pos, m_bpc);
1023             src_bit_pos += m_bpc;
1024             R = NORMALCOLOR_MAX(R, max_data);
1025             G = NORMALCOLOR_MAX(G, max_data);
1026             B = NORMALCOLOR_MAX(B, max_data);
1027             dest_scan[dest_byte_pos] = B * 255 / max_data;
1028             dest_scan[dest_byte_pos + 1] = G * 255 / max_data;
1029             dest_scan[dest_byte_pos + 2] = R * 255 / max_data;
1030             dest_byte_pos += 3;
1031           }
1032           break;
1033       }
1034       return;
1035     }
1036     if (m_bpc == 8) {
1037       if (m_nComponents == m_pColorSpace->CountComponents())
1038         m_pColorSpace->TranslateImageLine(dest_scan, src_scan, m_Width, m_Width,
1039                                           m_Height, TransMask());
1040       return;
1041     }
1042   }
1043   CFX_FixedBufGrow<FX_FLOAT, 16> color_values1(m_nComponents);
1044   FX_FLOAT* color_values = color_values1;
1045   FX_FLOAT R = 0.0f, G = 0.0f, B = 0.0f;
1046   if (m_bpc == 8) {
1047     int src_byte_pos = 0;
1048     int dest_byte_pos = 0;
1049     for (int column = 0; column < m_Width; column++) {
1050       for (FX_DWORD color = 0; color < m_nComponents; color++) {
1051         int data = src_scan[src_byte_pos++];
1052         color_values[color] = m_pCompData[color].m_DecodeMin +
1053                               m_pCompData[color].m_DecodeStep * data;
1054       }
1055       if (TransMask()) {
1056         FX_FLOAT k = 1.0f - color_values[3];
1057         R = (1.0f - color_values[0]) * k;
1058         G = (1.0f - color_values[1]) * k;
1059         B = (1.0f - color_values[2]) * k;
1060       } else {
1061         m_pColorSpace->GetRGB(color_values, R, G, B);
1062       }
1063       R = NORMALCOLOR_MAX(R, 1);
1064       G = NORMALCOLOR_MAX(G, 1);
1065       B = NORMALCOLOR_MAX(B, 1);
1066       dest_scan[dest_byte_pos] = (int32_t)(B * 255);
1067       dest_scan[dest_byte_pos + 1] = (int32_t)(G * 255);
1068       dest_scan[dest_byte_pos + 2] = (int32_t)(R * 255);
1069       dest_byte_pos += 3;
1070     }
1071   } else {
1072     int src_bit_pos = 0;
1073     int dest_byte_pos = 0;
1074     for (int column = 0; column < m_Width; column++) {
1075       for (FX_DWORD color = 0; color < m_nComponents; color++) {
1076         int data = _GetBits8(src_scan, src_bit_pos, m_bpc);
1077         color_values[color] = m_pCompData[color].m_DecodeMin +
1078                               m_pCompData[color].m_DecodeStep * data;
1079         src_bit_pos += m_bpc;
1080       }
1081       if (TransMask()) {
1082         FX_FLOAT k = 1.0f - color_values[3];
1083         R = (1.0f - color_values[0]) * k;
1084         G = (1.0f - color_values[1]) * k;
1085         B = (1.0f - color_values[2]) * k;
1086       } else {
1087         m_pColorSpace->GetRGB(color_values, R, G, B);
1088       }
1089       R = NORMALCOLOR_MAX(R, 1);
1090       G = NORMALCOLOR_MAX(G, 1);
1091       B = NORMALCOLOR_MAX(B, 1);
1092       dest_scan[dest_byte_pos] = (int32_t)(B * 255);
1093       dest_scan[dest_byte_pos + 1] = (int32_t)(G * 255);
1094       dest_scan[dest_byte_pos + 2] = (int32_t)(R * 255);
1095       dest_byte_pos += 3;
1096     }
1097   }
1098 }
1099 uint8_t* CPDF_DIBSource::GetBuffer() const {
1100   if (m_pCachedBitmap) {
1101     return m_pCachedBitmap->GetBuffer();
1102   }
1103   return NULL;
1104 }
1105 const uint8_t* CPDF_DIBSource::GetScanline(int line) const {
1106   if (m_bpc == 0) {
1107     return NULL;
1108   }
1109   FX_SAFE_DWORD src_pitch = CalculatePitch8(m_bpc, m_nComponents, m_Width, 1);
1110   if (!src_pitch.IsValid())
1111     return NULL;
1112   FX_DWORD src_pitch_value = src_pitch.ValueOrDie();
1113   const uint8_t* pSrcLine = NULL;
1114   if (m_pCachedBitmap) {
1115     if (line >= m_pCachedBitmap->GetHeight()) {
1116       line = m_pCachedBitmap->GetHeight() - 1;
1117     }
1118     pSrcLine = m_pCachedBitmap->GetScanline(line);
1119   } else if (m_pDecoder) {
1120     pSrcLine = m_pDecoder->GetScanline(line);
1121   } else {
1122     if (m_pStreamAcc->GetSize() >= (line + 1) * src_pitch_value) {
1123       pSrcLine = m_pStreamAcc->GetData() + line * src_pitch_value;
1124     }
1125   }
1126   if (pSrcLine == NULL) {
1127     uint8_t* pLineBuf = m_pMaskedLine ? m_pMaskedLine : m_pLineBuf;
1128     FXSYS_memset(pLineBuf, 0xFF, m_Pitch);
1129     return pLineBuf;
1130   }
1131   if (m_bpc * m_nComponents == 1) {
1132     if (m_bImageMask && m_bDefaultDecode) {
1133       for (FX_DWORD i = 0; i < src_pitch_value; i++) {
1134         m_pLineBuf[i] = ~pSrcLine[i];
1135       }
1136     } else if (m_bColorKey) {
1137       FX_DWORD reset_argb, set_argb;
1138       reset_argb = m_pPalette ? m_pPalette[0] : 0xFF000000;
1139       set_argb = m_pPalette ? m_pPalette[1] : 0xFFFFFFFF;
1140       if (m_pCompData[0].m_ColorKeyMin == 0) {
1141         reset_argb = 0;
1142       }
1143       if (m_pCompData[0].m_ColorKeyMax == 1) {
1144         set_argb = 0;
1145       }
1146       set_argb = FXARGB_TODIB(set_argb);
1147       reset_argb = FXARGB_TODIB(reset_argb);
1148       FX_DWORD* dest_scan = (FX_DWORD*)m_pMaskedLine;
1149       for (int col = 0; col < m_Width; col++) {
1150         if (pSrcLine[col / 8] & (1 << (7 - col % 8))) {
1151           *dest_scan = set_argb;
1152         } else {
1153           *dest_scan = reset_argb;
1154         }
1155         dest_scan++;
1156       }
1157       return m_pMaskedLine;
1158     } else {
1159       FXSYS_memcpy(m_pLineBuf, pSrcLine, src_pitch_value);
1160     }
1161     return m_pLineBuf;
1162   }
1163   if (m_bpc * m_nComponents <= 8) {
1164     if (m_bpc == 8) {
1165       FXSYS_memcpy(m_pLineBuf, pSrcLine, src_pitch_value);
1166     } else {
1167       int src_bit_pos = 0;
1168       for (int col = 0; col < m_Width; col++) {
1169         int color_index = 0;
1170         for (FX_DWORD color = 0; color < m_nComponents; color++) {
1171           int data = _GetBits8(pSrcLine, src_bit_pos, m_bpc);
1172           color_index |= data << (color * m_bpc);
1173           src_bit_pos += m_bpc;
1174         }
1175         m_pLineBuf[col] = color_index;
1176       }
1177     }
1178     if (m_bColorKey) {
1179       uint8_t* pDestPixel = m_pMaskedLine;
1180       const uint8_t* pSrcPixel = m_pLineBuf;
1181       for (int col = 0; col < m_Width; col++) {
1182         uint8_t index = *pSrcPixel++;
1183         if (m_pPalette) {
1184           *pDestPixel++ = FXARGB_B(m_pPalette[index]);
1185           *pDestPixel++ = FXARGB_G(m_pPalette[index]);
1186           *pDestPixel++ = FXARGB_R(m_pPalette[index]);
1187         } else {
1188           *pDestPixel++ = index;
1189           *pDestPixel++ = index;
1190           *pDestPixel++ = index;
1191         }
1192         *pDestPixel = (index < m_pCompData[0].m_ColorKeyMin ||
1193                        index > m_pCompData[0].m_ColorKeyMax)
1194                           ? 0xFF
1195                           : 0;
1196         pDestPixel++;
1197       }
1198       return m_pMaskedLine;
1199     }
1200     return m_pLineBuf;
1201   }
1202   if (m_bColorKey) {
1203     if (m_nComponents == 3 && m_bpc == 8) {
1204       uint8_t* alpha_channel = m_pMaskedLine + 3;
1205       for (int col = 0; col < m_Width; col++) {
1206         const uint8_t* pPixel = pSrcLine + col * 3;
1207         alpha_channel[col * 4] = (pPixel[0] < m_pCompData[0].m_ColorKeyMin ||
1208                                   pPixel[0] > m_pCompData[0].m_ColorKeyMax ||
1209                                   pPixel[1] < m_pCompData[1].m_ColorKeyMin ||
1210                                   pPixel[1] > m_pCompData[1].m_ColorKeyMax ||
1211                                   pPixel[2] < m_pCompData[2].m_ColorKeyMin ||
1212                                   pPixel[2] > m_pCompData[2].m_ColorKeyMax)
1213                                      ? 0xFF
1214                                      : 0;
1215       }
1216     } else {
1217       FXSYS_memset(m_pMaskedLine, 0xFF, m_Pitch);
1218     }
1219   }
1220   if (m_pColorSpace) {
1221     TranslateScanline24bpp(m_pLineBuf, pSrcLine);
1222     pSrcLine = m_pLineBuf;
1223   }
1224   if (m_bColorKey) {
1225     const uint8_t* pSrcPixel = pSrcLine;
1226     uint8_t* pDestPixel = m_pMaskedLine;
1227     for (int col = 0; col < m_Width; col++) {
1228       *pDestPixel++ = *pSrcPixel++;
1229       *pDestPixel++ = *pSrcPixel++;
1230       *pDestPixel++ = *pSrcPixel++;
1231       pDestPixel++;
1232     }
1233     return m_pMaskedLine;
1234   }
1235   return pSrcLine;
1236 }
1237
1238 FX_BOOL CPDF_DIBSource::SkipToScanline(int line, IFX_Pause* pPause) const {
1239   return m_pDecoder && m_pDecoder->SkipToScanline(line, pPause);
1240 }
1241
1242 void CPDF_DIBSource::DownSampleScanline(int line,
1243                                         uint8_t* dest_scan,
1244                                         int dest_bpp,
1245                                         int dest_width,
1246                                         FX_BOOL bFlipX,
1247                                         int clip_left,
1248                                         int clip_width) const {
1249   if (line < 0 || !dest_scan || dest_bpp <= 0 || dest_width <= 0 ||
1250       clip_left < 0 || clip_width <= 0) {
1251     return;
1252   }
1253
1254   FX_DWORD src_width = m_Width;
1255   FX_SAFE_DWORD pitch = CalculatePitch8(m_bpc, m_nComponents, m_Width, 1);
1256   if (!pitch.IsValid())
1257     return;
1258
1259   const uint8_t* pSrcLine = nullptr;
1260   if (m_pCachedBitmap) {
1261     pSrcLine = m_pCachedBitmap->GetScanline(line);
1262   } else if (m_pDecoder) {
1263     pSrcLine = m_pDecoder->GetScanline(line);
1264   } else {
1265     FX_DWORD src_pitch = pitch.ValueOrDie();
1266     pitch *= (line + 1);
1267     if (!pitch.IsValid()) {
1268       return;
1269     }
1270
1271     if (m_pStreamAcc->GetSize() >= pitch.ValueOrDie()) {
1272       pSrcLine = m_pStreamAcc->GetData() + line * src_pitch;
1273     }
1274   }
1275   int orig_Bpp = m_bpc * m_nComponents / 8;
1276   int dest_Bpp = dest_bpp / 8;
1277   if (!pSrcLine) {
1278     FXSYS_memset(dest_scan, 0xFF, dest_Bpp * clip_width);
1279     return;
1280   }
1281
1282   FX_SAFE_INT32 max_src_x = clip_left;
1283   max_src_x += clip_width - 1;
1284   max_src_x *= src_width;
1285   max_src_x /= dest_width;
1286   if (!max_src_x.IsValid())
1287     return;
1288
1289   if (m_bpc * m_nComponents == 1) {
1290     DownSampleScanline1Bit(orig_Bpp, dest_Bpp, src_width, pSrcLine, dest_scan,
1291                            dest_width, bFlipX, clip_left, clip_width);
1292   } else if (m_bpc * m_nComponents <= 8) {
1293     DownSampleScanline8Bit(orig_Bpp, dest_Bpp, src_width, pSrcLine, dest_scan,
1294                            dest_width, bFlipX, clip_left, clip_width);
1295   } else {
1296     DownSampleScanline32Bit(orig_Bpp, dest_Bpp, src_width, pSrcLine, dest_scan,
1297                             dest_width, bFlipX, clip_left, clip_width);
1298   }
1299 }
1300
1301 void CPDF_DIBSource::DownSampleScanline1Bit(int orig_Bpp,
1302                                             int dest_Bpp,
1303                                             FX_DWORD src_width,
1304                                             const uint8_t* pSrcLine,
1305                                             uint8_t* dest_scan,
1306                                             int dest_width,
1307                                             FX_BOOL bFlipX,
1308                                             int clip_left,
1309                                             int clip_width) const {
1310   FX_DWORD set_argb = (FX_DWORD)-1;
1311   FX_DWORD reset_argb = 0;
1312   if (m_bImageMask) {
1313     if (m_bDefaultDecode) {
1314       set_argb = 0;
1315       reset_argb = (FX_DWORD)-1;
1316     }
1317   } else if (m_bColorKey) {
1318     reset_argb = m_pPalette ? m_pPalette[0] : 0xFF000000;
1319     set_argb = m_pPalette ? m_pPalette[1] : 0xFFFFFFFF;
1320     if (m_pCompData[0].m_ColorKeyMin == 0) {
1321       reset_argb = 0;
1322     }
1323     if (m_pCompData[0].m_ColorKeyMax == 1) {
1324       set_argb = 0;
1325     }
1326     set_argb = FXARGB_TODIB(set_argb);
1327     reset_argb = FXARGB_TODIB(reset_argb);
1328     for (int i = 0; i < clip_width; i++) {
1329       FX_DWORD src_x = (clip_left + i) * src_width / dest_width;
1330       if (bFlipX) {
1331         src_x = src_width - src_x - 1;
1332       }
1333       src_x %= src_width;
1334       if (pSrcLine[src_x / 8] & (1 << (7 - src_x % 8))) {
1335         ((FX_DWORD*)dest_scan)[i] = set_argb;
1336       } else {
1337         ((FX_DWORD*)dest_scan)[i] = reset_argb;
1338       }
1339     }
1340     return;
1341   } else {
1342     if (dest_Bpp == 1) {
1343     } else if (m_pPalette) {
1344       reset_argb = m_pPalette[0];
1345       set_argb = m_pPalette[1];
1346     }
1347   }
1348   for (int i = 0; i < clip_width; i++) {
1349     FX_DWORD src_x = (clip_left + i) * src_width / dest_width;
1350     if (bFlipX) {
1351       src_x = src_width - src_x - 1;
1352     }
1353     src_x %= src_width;
1354     int dest_pos = i * dest_Bpp;
1355     if (pSrcLine[src_x / 8] & (1 << (7 - src_x % 8))) {
1356       if (dest_Bpp == 1) {
1357         dest_scan[dest_pos] = (uint8_t)set_argb;
1358       } else if (dest_Bpp == 3) {
1359         dest_scan[dest_pos] = FXARGB_B(set_argb);
1360         dest_scan[dest_pos + 1] = FXARGB_G(set_argb);
1361         dest_scan[dest_pos + 2] = FXARGB_R(set_argb);
1362       } else {
1363         *(FX_DWORD*)(dest_scan + dest_pos) = set_argb;
1364       }
1365     } else {
1366       if (dest_Bpp == 1) {
1367         dest_scan[dest_pos] = (uint8_t)reset_argb;
1368       } else if (dest_Bpp == 3) {
1369         dest_scan[dest_pos] = FXARGB_B(reset_argb);
1370         dest_scan[dest_pos + 1] = FXARGB_G(reset_argb);
1371         dest_scan[dest_pos + 2] = FXARGB_R(reset_argb);
1372       } else {
1373         *(FX_DWORD*)(dest_scan + dest_pos) = reset_argb;
1374       }
1375     }
1376   }
1377 }
1378
1379 void CPDF_DIBSource::DownSampleScanline8Bit(int orig_Bpp,
1380                                             int dest_Bpp,
1381                                             FX_DWORD src_width,
1382                                             const uint8_t* pSrcLine,
1383                                             uint8_t* dest_scan,
1384                                             int dest_width,
1385                                             FX_BOOL bFlipX,
1386                                             int clip_left,
1387                                             int clip_width) const {
1388   if (m_bpc < 8) {
1389     int src_bit_pos = 0;
1390     for (FX_DWORD col = 0; col < src_width; col++) {
1391       int color_index = 0;
1392       for (FX_DWORD color = 0; color < m_nComponents; color++) {
1393         int data = _GetBits8(pSrcLine, src_bit_pos, m_bpc);
1394         color_index |= data << (color * m_bpc);
1395         src_bit_pos += m_bpc;
1396       }
1397       m_pLineBuf[col] = color_index;
1398     }
1399     pSrcLine = m_pLineBuf;
1400   }
1401   if (m_bColorKey) {
1402     for (int i = 0; i < clip_width; i++) {
1403       FX_DWORD src_x = (clip_left + i) * src_width / dest_width;
1404       if (bFlipX) {
1405         src_x = src_width - src_x - 1;
1406       }
1407       src_x %= src_width;
1408       uint8_t* pDestPixel = dest_scan + i * 4;
1409       uint8_t index = pSrcLine[src_x];
1410       if (m_pPalette) {
1411         *pDestPixel++ = FXARGB_B(m_pPalette[index]);
1412         *pDestPixel++ = FXARGB_G(m_pPalette[index]);
1413         *pDestPixel++ = FXARGB_R(m_pPalette[index]);
1414       } else {
1415         *pDestPixel++ = index;
1416         *pDestPixel++ = index;
1417         *pDestPixel++ = index;
1418       }
1419       *pDestPixel = (index < m_pCompData[0].m_ColorKeyMin ||
1420                      index > m_pCompData[0].m_ColorKeyMax)
1421                         ? 0xFF
1422                         : 0;
1423     }
1424     return;
1425   }
1426   for (int i = 0; i < clip_width; i++) {
1427     FX_DWORD src_x = (clip_left + i) * src_width / dest_width;
1428     if (bFlipX) {
1429       src_x = src_width - src_x - 1;
1430     }
1431     src_x %= src_width;
1432     uint8_t index = pSrcLine[src_x];
1433     if (dest_Bpp == 1) {
1434       dest_scan[i] = index;
1435     } else {
1436       int dest_pos = i * dest_Bpp;
1437       FX_ARGB argb = m_pPalette[index];
1438       dest_scan[dest_pos] = FXARGB_B(argb);
1439       dest_scan[dest_pos + 1] = FXARGB_G(argb);
1440       dest_scan[dest_pos + 2] = FXARGB_R(argb);
1441     }
1442   }
1443 }
1444
1445 void CPDF_DIBSource::DownSampleScanline32Bit(int orig_Bpp,
1446                                              int dest_Bpp,
1447                                              FX_DWORD src_width,
1448                                              const uint8_t* pSrcLine,
1449                                              uint8_t* dest_scan,
1450                                              int dest_width,
1451                                              FX_BOOL bFlipX,
1452                                              int clip_left,
1453                                              int clip_width) const {
1454   int last_src_x = -1;
1455   FX_ARGB last_argb = FXARGB_MAKE(0xFF, 0xFF, 0xFF, 0xFF);
1456   FX_FLOAT orig_Not8Bpp = (FX_FLOAT)m_bpc * (FX_FLOAT)m_nComponents / 8.0f;
1457   FX_FLOAT unit_To8Bpc = 255.0f / ((1 << m_bpc) - 1);
1458   for (int i = 0; i < clip_width; i++) {
1459     int dest_x = clip_left + i;
1460     FX_DWORD src_x = (bFlipX ? (dest_width - dest_x - 1) : dest_x) *
1461                      (int64_t)src_width / dest_width;
1462     src_x %= src_width;
1463     const uint8_t* pSrcPixel = nullptr;
1464     if (m_bpc % 8 == 0) {
1465       pSrcPixel = pSrcLine + src_x * orig_Bpp;
1466     } else {
1467       pSrcPixel = pSrcLine + (int)(src_x * orig_Not8Bpp);
1468     }
1469     uint8_t* pDestPixel = dest_scan + i * dest_Bpp;
1470     FX_ARGB argb;
1471     if (src_x == last_src_x) {
1472       argb = last_argb;
1473     } else {
1474       if (m_pColorSpace) {
1475         CFX_FixedBufGrow<uint8_t, 128> temp(orig_Bpp);
1476         uint8_t color[4];
1477         const FX_BOOL bTransMask = TransMask();
1478         if (m_bDefaultDecode) {
1479           if (m_bpc < 8) {
1480             int src_bit_pos = 0;
1481             if (src_x % 2) {
1482               src_bit_pos = 4;
1483             }
1484             for (FX_DWORD j = 0; j < m_nComponents; ++j) {
1485               temp[j] = (uint8_t)(_GetBits8(pSrcPixel, src_bit_pos, m_bpc) *
1486                                   unit_To8Bpc);
1487               src_bit_pos += m_bpc;
1488             }
1489             m_pColorSpace->TranslateImageLine(color, temp, 1, 0, 0, bTransMask);
1490           } else {
1491             m_pColorSpace->TranslateImageLine(color, pSrcPixel, 1, 0, 0,
1492                                               bTransMask);
1493           }
1494         } else {
1495           for (int j = 0; j < m_nComponents; ++j) {
1496             int color_value =
1497                 (int)((m_pCompData[j].m_DecodeMin +
1498                        m_pCompData[j].m_DecodeStep * (FX_FLOAT)pSrcPixel[j]) *
1499                           255.0f +
1500                       0.5f);
1501             temp[j] =
1502                 color_value > 255 ? 255 : (color_value < 0 ? 0 : color_value);
1503           }
1504           m_pColorSpace->TranslateImageLine(color, temp, 1, 0, 0, bTransMask);
1505         }
1506         argb = FXARGB_MAKE(0xFF, color[2], color[1], color[0]);
1507       } else {
1508         argb = FXARGB_MAKE(0xFf, pSrcPixel[2], pSrcPixel[1], pSrcPixel[0]);
1509       }
1510       if (m_bColorKey) {
1511         int alpha = 0xFF;
1512         if (m_nComponents == 3 && m_bpc == 8) {
1513           alpha = (pSrcPixel[0] < m_pCompData[0].m_ColorKeyMin ||
1514                    pSrcPixel[0] > m_pCompData[0].m_ColorKeyMax ||
1515                    pSrcPixel[1] < m_pCompData[1].m_ColorKeyMin ||
1516                    pSrcPixel[1] > m_pCompData[1].m_ColorKeyMax ||
1517                    pSrcPixel[2] < m_pCompData[2].m_ColorKeyMin ||
1518                    pSrcPixel[2] > m_pCompData[2].m_ColorKeyMax)
1519                       ? 0xFF
1520                       : 0;
1521         }
1522         argb &= 0xFFFFFF;
1523         argb |= alpha << 24;
1524       }
1525       last_src_x = src_x;
1526       last_argb = argb;
1527     }
1528     if (dest_Bpp == 4) {
1529       *(FX_DWORD*)pDestPixel = FXARGB_TODIB(argb);
1530     } else {
1531       *pDestPixel++ = FXARGB_B(argb);
1532       *pDestPixel++ = FXARGB_G(argb);
1533       *pDestPixel = FXARGB_R(argb);
1534     }
1535   }
1536 }
1537
1538 FX_BOOL CPDF_DIBSource::TransMask() const {
1539   return m_bLoadMask && m_GroupFamily == PDFCS_DEVICECMYK &&
1540          m_Family == PDFCS_DEVICECMYK;
1541 }
1542
1543 void CPDF_DIBSource::SetDownSampleSize(int dest_width, int dest_height) const {
1544   if (m_pDecoder) {
1545     m_pDecoder->DownScale(dest_width, dest_height);
1546     ((CPDF_DIBSource*)this)->m_Width = m_pDecoder->GetWidth();
1547     ((CPDF_DIBSource*)this)->m_Height = m_pDecoder->GetHeight();
1548   }
1549 }
1550
1551 void CPDF_DIBSource::ClearImageData() {
1552   if (m_pDecoder) {
1553     m_pDecoder->ClearImageData();
1554   }
1555 }
1556
1557 CPDF_ProgressiveImageLoaderHandle::CPDF_ProgressiveImageLoaderHandle() {
1558   m_pImageLoader = NULL;
1559   m_pCache = NULL;
1560   m_pImage = NULL;
1561 }
1562 CPDF_ProgressiveImageLoaderHandle::~CPDF_ProgressiveImageLoaderHandle() {}
1563 FX_BOOL CPDF_ProgressiveImageLoaderHandle::Start(
1564     CPDF_ImageLoader* pImageLoader,
1565     const CPDF_ImageObject* pImage,
1566     CPDF_PageRenderCache* pCache,
1567     FX_BOOL bStdCS,
1568     FX_DWORD GroupFamily,
1569     FX_BOOL bLoadMask,
1570     CPDF_RenderStatus* pRenderStatus,
1571     int32_t nDownsampleWidth,
1572     int32_t nDownsampleHeight) {
1573   m_pImageLoader = pImageLoader;
1574   m_pCache = pCache;
1575   m_pImage = (CPDF_ImageObject*)pImage;
1576   m_nDownsampleWidth = nDownsampleWidth;
1577   m_nDownsampleHeight = nDownsampleHeight;
1578   FX_BOOL ret;
1579   if (pCache) {
1580     ret = pCache->StartGetCachedBitmap(pImage->m_pImage->GetStream(), bStdCS,
1581                                        GroupFamily, bLoadMask, pRenderStatus,
1582                                        m_nDownsampleWidth, m_nDownsampleHeight);
1583     if (ret == FALSE) {
1584       m_pImageLoader->m_bCached = TRUE;
1585       m_pImageLoader->m_pBitmap = pCache->m_pCurImageCache->DetachBitmap();
1586       m_pImageLoader->m_pMask = pCache->m_pCurImageCache->DetachMask();
1587       m_pImageLoader->m_MatteColor = pCache->m_pCurImageCache->m_MatteColor;
1588     }
1589   } else {
1590     ret = pImage->m_pImage->StartLoadDIBSource(pRenderStatus->m_pFormResource,
1591                                                pRenderStatus->m_pPageResource,
1592                                                bStdCS, GroupFamily, bLoadMask);
1593     if (ret == FALSE) {
1594       m_pImageLoader->m_bCached = FALSE;
1595       m_pImageLoader->m_pBitmap = m_pImage->m_pImage->DetachBitmap();
1596       m_pImageLoader->m_pMask = m_pImage->m_pImage->DetachMask();
1597       m_pImageLoader->m_MatteColor = m_pImage->m_pImage->m_MatteColor;
1598     }
1599   }
1600   return ret;
1601 }
1602 FX_BOOL CPDF_ProgressiveImageLoaderHandle::Continue(IFX_Pause* pPause) {
1603   FX_BOOL ret;
1604   if (m_pCache) {
1605     ret = m_pCache->Continue(pPause);
1606     if (ret == FALSE) {
1607       m_pImageLoader->m_bCached = TRUE;
1608       m_pImageLoader->m_pBitmap = m_pCache->m_pCurImageCache->DetachBitmap();
1609       m_pImageLoader->m_pMask = m_pCache->m_pCurImageCache->DetachMask();
1610       m_pImageLoader->m_MatteColor = m_pCache->m_pCurImageCache->m_MatteColor;
1611     }
1612   } else {
1613     ret = m_pImage->m_pImage->Continue(pPause);
1614     if (ret == FALSE) {
1615       m_pImageLoader->m_bCached = FALSE;
1616       m_pImageLoader->m_pBitmap = m_pImage->m_pImage->DetachBitmap();
1617       m_pImageLoader->m_pMask = m_pImage->m_pImage->DetachMask();
1618       m_pImageLoader->m_MatteColor = m_pImage->m_pImage->m_MatteColor;
1619     }
1620   }
1621   return ret;
1622 }
1623 FX_BOOL CPDF_ImageLoader::Load(const CPDF_ImageObject* pImage,
1624                                CPDF_PageRenderCache* pCache,
1625                                FX_BOOL bStdCS,
1626                                FX_DWORD GroupFamily,
1627                                FX_BOOL bLoadMask,
1628                                CPDF_RenderStatus* pRenderStatus) {
1629   if (pImage == NULL) {
1630     return FALSE;
1631   }
1632   if (pCache) {
1633     pCache->GetCachedBitmap(pImage->m_pImage->GetStream(), m_pBitmap, m_pMask,
1634                             m_MatteColor, bStdCS, GroupFamily, bLoadMask,
1635                             pRenderStatus, m_nDownsampleWidth,
1636                             m_nDownsampleHeight);
1637     m_bCached = TRUE;
1638   } else {
1639     m_pBitmap = pImage->m_pImage->LoadDIBSource(&m_pMask, &m_MatteColor, bStdCS,
1640                                                 GroupFamily, bLoadMask);
1641     m_bCached = FALSE;
1642   }
1643   return FALSE;
1644 }
1645 FX_BOOL CPDF_ImageLoader::StartLoadImage(const CPDF_ImageObject* pImage,
1646                                          CPDF_PageRenderCache* pCache,
1647                                          void*& LoadHandle,
1648                                          FX_BOOL bStdCS,
1649                                          FX_DWORD GroupFamily,
1650                                          FX_BOOL bLoadMask,
1651                                          CPDF_RenderStatus* pRenderStatus,
1652                                          int32_t nDownsampleWidth,
1653                                          int32_t nDownsampleHeight) {
1654   m_nDownsampleWidth = nDownsampleWidth;
1655   m_nDownsampleHeight = nDownsampleHeight;
1656   CPDF_ProgressiveImageLoaderHandle* pLoaderHandle =
1657       new CPDF_ProgressiveImageLoaderHandle;
1658   FX_BOOL ret = pLoaderHandle->Start(this, pImage, pCache, bStdCS, GroupFamily,
1659                                      bLoadMask, pRenderStatus,
1660                                      m_nDownsampleWidth, m_nDownsampleHeight);
1661   LoadHandle = pLoaderHandle;
1662   return ret;
1663 }
1664 FX_BOOL CPDF_ImageLoader::Continue(void* LoadHandle, IFX_Pause* pPause) {
1665   return ((CPDF_ProgressiveImageLoaderHandle*)LoadHandle)->Continue(pPause);
1666 }
1667 CPDF_ImageLoader::~CPDF_ImageLoader() {
1668   if (!m_bCached) {
1669     delete m_pBitmap;
1670     delete m_pMask;
1671   }
1672 }