• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 
7 #include "core/fxcodec/codec/ccodec_progressivedecoder.h"
8 
9 #include <algorithm>
10 #include <memory>
11 #include <utility>
12 #include <vector>
13 
14 #include "core/fxcodec/fx_codec.h"
15 #include "core/fxcrt/fx_stream.h"
16 #include "core/fxge/dib/cfx_dibitmap.h"
17 #include "core/fxge/fx_dib.h"
18 #include "third_party/base/logging.h"
19 #include "third_party/base/numerics/safe_math.h"
20 #include "third_party/base/ptr_util.h"
21 
22 #define FXCODEC_BLOCK_SIZE 4096
23 
24 namespace {
25 
26 #if _FX_OS_ == _FX_OS_MACOSX_
27 const double kPngGamma = 1.7;
28 #else   // _FX_OS_ == _FX_OS_MACOSX_
29 const double kPngGamma = 2.2;
30 #endif  // _FX_OS_ == _FX_OS_MACOSX_
31 
RGB2BGR(uint8_t * buffer,int width=1)32 void RGB2BGR(uint8_t* buffer, int width = 1) {
33   if (buffer && width > 0) {
34     uint8_t temp;
35     int i = 0;
36     int j = 0;
37     for (; i < width; i++, j += 3) {
38       temp = buffer[j];
39       buffer[j] = buffer[j + 2];
40       buffer[j + 2] = temp;
41     }
42   }
43 }
44 
45 }  // namespace
46 
CFXCODEC_WeightTable()47 CCodec_ProgressiveDecoder::CFXCODEC_WeightTable::CFXCODEC_WeightTable() {}
48 
~CFXCODEC_WeightTable()49 CCodec_ProgressiveDecoder::CFXCODEC_WeightTable::~CFXCODEC_WeightTable() {}
50 
Calc(int dest_len,int dest_min,int dest_max,int src_len,int src_min,int src_max)51 void CCodec_ProgressiveDecoder::CFXCODEC_WeightTable::Calc(int dest_len,
52                                                            int dest_min,
53                                                            int dest_max,
54                                                            int src_len,
55                                                            int src_min,
56                                                            int src_max) {
57   double scale, base;
58   scale = (float)src_len / (float)dest_len;
59   if (dest_len < 0) {
60     base = (float)(src_len);
61   } else {
62     base = 0.0f;
63   }
64   m_ItemSize =
65       (int)(sizeof(int) * 2 + sizeof(int) * (ceil(fabs((float)scale)) + 1));
66   m_DestMin = dest_min;
67   m_pWeightTables.resize((dest_max - dest_min) * m_ItemSize + 4);
68   if (fabs((float)scale) < 1.0f) {
69     for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel++) {
70       PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel);
71       double src_pos = dest_pixel * scale + scale / 2 + base;
72       pixel_weights.m_SrcStart = (int)floor((float)src_pos - 1.0f / 2);
73       pixel_weights.m_SrcEnd = (int)floor((float)src_pos + 1.0f / 2);
74       if (pixel_weights.m_SrcStart < src_min) {
75         pixel_weights.m_SrcStart = src_min;
76       }
77       if (pixel_weights.m_SrcEnd >= src_max) {
78         pixel_weights.m_SrcEnd = src_max - 1;
79       }
80       if (pixel_weights.m_SrcStart == pixel_weights.m_SrcEnd) {
81         pixel_weights.m_Weights[0] = 65536;
82       } else {
83         pixel_weights.m_Weights[1] = FXSYS_round(
84             (float)(src_pos - pixel_weights.m_SrcStart - 1.0f / 2) * 65536);
85         pixel_weights.m_Weights[0] = 65536 - pixel_weights.m_Weights[1];
86       }
87     }
88     return;
89   }
90   for (int dest_pixel = dest_min; dest_pixel < dest_max; dest_pixel++) {
91     PixelWeight& pixel_weights = *GetPixelWeight(dest_pixel);
92     double src_start = dest_pixel * scale + base;
93     double src_end = src_start + scale;
94     int start_i, end_i;
95     if (src_start < src_end) {
96       start_i = (int)floor((float)src_start);
97       end_i = (int)ceil((float)src_end);
98     } else {
99       start_i = (int)floor((float)src_end);
100       end_i = (int)ceil((float)src_start);
101     }
102     if (start_i < src_min) {
103       start_i = src_min;
104     }
105     if (end_i >= src_max) {
106       end_i = src_max - 1;
107     }
108     if (start_i > end_i) {
109       pixel_weights.m_SrcStart = start_i;
110       pixel_weights.m_SrcEnd = start_i;
111       continue;
112     }
113     pixel_weights.m_SrcStart = start_i;
114     pixel_weights.m_SrcEnd = end_i;
115     for (int j = start_i; j <= end_i; j++) {
116       double dest_start = ((float)j - base) / scale;
117       double dest_end = ((float)(j + 1) - base) / scale;
118       if (dest_start > dest_end) {
119         double temp = dest_start;
120         dest_start = dest_end;
121         dest_end = temp;
122       }
123       double area_start =
124           dest_start > (float)(dest_pixel) ? dest_start : (float)(dest_pixel);
125       double area_end = dest_end > (float)(dest_pixel + 1)
126                             ? (float)(dest_pixel + 1)
127                             : dest_end;
128       double weight = area_start >= area_end ? 0.0f : area_end - area_start;
129       if (weight == 0 && j == end_i) {
130         pixel_weights.m_SrcEnd--;
131         break;
132       }
133       pixel_weights.m_Weights[j - start_i] =
134           FXSYS_round((float)(weight * 65536));
135     }
136   }
137 }
138 
CFXCODEC_HorzTable()139 CCodec_ProgressiveDecoder::CFXCODEC_HorzTable::CFXCODEC_HorzTable() {}
140 
~CFXCODEC_HorzTable()141 CCodec_ProgressiveDecoder::CFXCODEC_HorzTable::~CFXCODEC_HorzTable() {}
142 
Calc(int dest_len,int src_len)143 void CCodec_ProgressiveDecoder::CFXCODEC_HorzTable::Calc(int dest_len,
144                                                          int src_len) {
145   double scale = (double)dest_len / (double)src_len;
146   m_ItemSize = sizeof(int) * 4;
147   int size = dest_len * m_ItemSize + 4;
148   m_pWeightTables.resize(size, 0);
149   if (scale > 1) {
150     int pre_des_col = 0;
151     for (int src_col = 0; src_col < src_len; src_col++) {
152       double des_col_f = src_col * scale;
153       int des_col = FXSYS_round((float)des_col_f);
154       PixelWeight* pWeight = GetPixelWeight(des_col);
155       pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col;
156       pWeight->m_Weights[0] = 65536;
157       pWeight->m_Weights[1] = 0;
158       if (src_col == src_len - 1 && des_col < dest_len - 1) {
159         for (int des_col_index = pre_des_col + 1; des_col_index < dest_len;
160              des_col_index++) {
161           pWeight = GetPixelWeight(des_col_index);
162           pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col;
163           pWeight->m_Weights[0] = 65536;
164           pWeight->m_Weights[1] = 0;
165         }
166         return;
167       }
168       int des_col_len = des_col - pre_des_col;
169       for (int des_col_index = pre_des_col + 1; des_col_index < des_col;
170            des_col_index++) {
171         pWeight = GetPixelWeight(des_col_index);
172         pWeight->m_SrcStart = src_col - 1;
173         pWeight->m_SrcEnd = src_col;
174         pWeight->m_Weights[0] =
175             FXSYS_round((float)(((float)des_col - (float)des_col_index) /
176                                 (float)des_col_len * 65536));
177         pWeight->m_Weights[1] = 65536 - pWeight->m_Weights[0];
178       }
179       pre_des_col = des_col;
180     }
181     return;
182   }
183   for (int des_col = 0; des_col < dest_len; des_col++) {
184     double src_col_f = des_col / scale;
185     int src_col = FXSYS_round((float)src_col_f);
186     PixelWeight* pWeight = GetPixelWeight(des_col);
187     pWeight->m_SrcStart = pWeight->m_SrcEnd = src_col;
188     pWeight->m_Weights[0] = 65536;
189     pWeight->m_Weights[1] = 0;
190   }
191 }
192 
CFXCODEC_VertTable()193 CCodec_ProgressiveDecoder::CFXCODEC_VertTable::CFXCODEC_VertTable() {}
194 
~CFXCODEC_VertTable()195 CCodec_ProgressiveDecoder::CFXCODEC_VertTable::~CFXCODEC_VertTable() {}
196 
Calc(int dest_len,int src_len)197 void CCodec_ProgressiveDecoder::CFXCODEC_VertTable::Calc(int dest_len,
198                                                          int src_len) {
199   double scale = (double)dest_len / (double)src_len;
200   m_ItemSize = sizeof(int) * 4;
201   int size = dest_len * m_ItemSize + 4;
202   m_pWeightTables.resize(size, 0);
203   if (scale <= 1) {
204     for (int des_row = 0; des_row < dest_len; des_row++) {
205       PixelWeight* pWeight = GetPixelWeight(des_row);
206       pWeight->m_SrcStart = des_row;
207       pWeight->m_SrcEnd = des_row;
208       pWeight->m_Weights[0] = 65536;
209       pWeight->m_Weights[1] = 0;
210     }
211     return;
212   }
213 
214   double step = 0.0;
215   int src_row = 0;
216   while (step < (double)dest_len) {
217     int start_step = (int)step;
218     step = scale * (++src_row);
219     int end_step = (int)step;
220     if (end_step >= dest_len) {
221       end_step = dest_len;
222       for (int des_row = start_step; des_row < end_step; des_row++) {
223         PixelWeight* pWeight = GetPixelWeight(des_row);
224         pWeight->m_SrcStart = start_step;
225         pWeight->m_SrcEnd = start_step;
226         pWeight->m_Weights[0] = 65536;
227         pWeight->m_Weights[1] = 0;
228       }
229       return;
230     }
231     int length = end_step - start_step;
232     {
233       PixelWeight* pWeight = GetPixelWeight(start_step);
234       pWeight->m_SrcStart = start_step;
235       pWeight->m_SrcEnd = start_step;
236       pWeight->m_Weights[0] = 65536;
237       pWeight->m_Weights[1] = 0;
238     }
239     for (int des_row = start_step + 1; des_row < end_step; des_row++) {
240       PixelWeight* pWeight = GetPixelWeight(des_row);
241       pWeight->m_SrcStart = start_step;
242       pWeight->m_SrcEnd = end_step;
243       pWeight->m_Weights[0] =
244           FXSYS_round((float)(end_step - des_row) / (float)length * 65536);
245       pWeight->m_Weights[1] = 65536 - pWeight->m_Weights[0];
246     }
247   }
248 }
249 
CCodec_ProgressiveDecoder(CCodec_ModuleMgr * pCodecMgr)250 CCodec_ProgressiveDecoder::CCodec_ProgressiveDecoder(
251     CCodec_ModuleMgr* pCodecMgr) {
252   m_pFile = nullptr;
253   m_pJpegContext = nullptr;
254   m_pPngContext = nullptr;
255   m_pBmpContext = nullptr;
256   m_pTiffContext = nullptr;
257   m_pCodecMgr = nullptr;
258   m_pSrcBuf = nullptr;
259   m_pDecodeBuf = nullptr;
260   m_pDeviceBitmap = nullptr;
261   m_pSrcPalette = nullptr;
262   m_pCodecMgr = pCodecMgr;
263   m_offSet = 0;
264   m_SrcSize = 0;
265   m_ScanlineSize = 0;
266   m_SrcWidth = 0;
267   m_SrcHeight = 0;
268   m_SrcComponents = 0;
269   m_SrcBPC = 0;
270   m_SrcPassNumber = 0;
271   m_clipBox = FX_RECT(0, 0, 0, 0);
272   m_imagType = FXCODEC_IMAGE_UNKNOWN;
273   m_status = FXCODEC_STATUS_DECODE_FINISH;
274   m_TransMethod = -1;
275   m_SrcRow = 0;
276   m_SrcFormat = FXCodec_Invalid;
277   m_FrameNumber = 0;
278   m_FrameCur = 0;
279   m_SrcPaletteNumber = 0;
280   m_GifPltNumber = 0;
281   m_GifBgIndex = 0;
282   m_pGifPalette = nullptr;
283   m_GifTransIndex = -1;
284   m_GifFrameRect = FX_RECT(0, 0, 0, 0);
285   m_BmpIsTopBottom = false;
286 }
287 
~CCodec_ProgressiveDecoder()288 CCodec_ProgressiveDecoder::~CCodec_ProgressiveDecoder() {
289   FX_Free(m_pSrcBuf);
290   FX_Free(m_pDecodeBuf);
291   FX_Free(m_pSrcPalette);
292 }
293 
JpegReadMoreData(CCodec_JpegModule * pJpegModule,FXCODEC_STATUS & err_status)294 bool CCodec_ProgressiveDecoder::JpegReadMoreData(CCodec_JpegModule* pJpegModule,
295                                                  FXCODEC_STATUS& err_status) {
296   uint32_t dwSize = (uint32_t)m_pFile->GetSize();
297   if (dwSize <= m_offSet) {
298     return false;
299   }
300   dwSize = dwSize - m_offSet;
301   uint32_t dwAvail = pJpegModule->GetAvailInput(m_pJpegContext.get(), nullptr);
302   if (dwAvail == m_SrcSize) {
303     if (dwSize > FXCODEC_BLOCK_SIZE) {
304       dwSize = FXCODEC_BLOCK_SIZE;
305     }
306     m_SrcSize = (dwSize + dwAvail + FXCODEC_BLOCK_SIZE - 1) /
307                 FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE;
308     m_pSrcBuf = FX_Realloc(uint8_t, m_pSrcBuf, m_SrcSize);
309     if (!m_pSrcBuf) {
310       err_status = FXCODEC_STATUS_ERR_MEMORY;
311       return false;
312     }
313   } else {
314     uint32_t dwConsume = m_SrcSize - dwAvail;
315     if (dwAvail) {
316       memmove(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail);
317     }
318     if (dwSize > dwConsume) {
319       dwSize = dwConsume;
320     }
321   }
322   if (!m_pFile->ReadBlock(m_pSrcBuf + dwAvail, m_offSet, dwSize)) {
323     err_status = FXCODEC_STATUS_ERR_READ;
324     return false;
325   }
326   m_offSet += dwSize;
327   pJpegModule->Input(m_pJpegContext.get(), m_pSrcBuf, dwSize + dwAvail);
328   return true;
329 }
330 
PngReadHeader(int width,int height,int bpc,int pass,int * color_type,double * gamma)331 bool CCodec_ProgressiveDecoder::PngReadHeader(int width,
332                                               int height,
333                                               int bpc,
334                                               int pass,
335                                               int* color_type,
336                                               double* gamma) {
337   if (!m_pDeviceBitmap) {
338     m_SrcWidth = width;
339     m_SrcHeight = height;
340     m_SrcBPC = bpc;
341     m_SrcPassNumber = pass;
342     switch (*color_type) {
343       case 0:
344         m_SrcComponents = 1;
345         break;
346       case 4:
347         m_SrcComponents = 2;
348         break;
349       case 2:
350         m_SrcComponents = 3;
351         break;
352       case 3:
353       case 6:
354         m_SrcComponents = 4;
355         break;
356       default:
357         m_SrcComponents = 0;
358         break;
359     }
360     m_clipBox = FX_RECT(0, 0, width, height);
361     return false;
362   }
363   FXDIB_Format format = m_pDeviceBitmap->GetFormat();
364   switch (format) {
365     case FXDIB_1bppMask:
366     case FXDIB_1bppRgb:
367       NOTREACHED();
368       return false;
369     case FXDIB_8bppMask:
370     case FXDIB_8bppRgb:
371       *color_type = 0;
372       break;
373     case FXDIB_Rgb:
374       *color_type = 2;
375       break;
376     case FXDIB_Rgb32:
377     case FXDIB_Argb:
378       *color_type = 6;
379       break;
380     default:
381       NOTREACHED();
382       return false;
383   }
384   *gamma = kPngGamma;
385   return true;
386 }
387 
PngAskScanlineBuf(int line,uint8_t ** pSrcBuf)388 bool CCodec_ProgressiveDecoder::PngAskScanlineBuf(int line, uint8_t** pSrcBuf) {
389   RetainPtr<CFX_DIBitmap> pDIBitmap = m_pDeviceBitmap;
390   if (!pDIBitmap) {
391     NOTREACHED();
392     return false;
393   }
394   if (line >= m_clipBox.top && line < m_clipBox.bottom) {
395     double scale_y = (double)m_sizeY / (double)m_clipBox.Height();
396     int32_t row = (int32_t)((line - m_clipBox.top) * scale_y) + m_startY;
397     uint8_t* src_scan = (uint8_t*)pDIBitmap->GetScanline(row);
398     uint8_t* des_scan = m_pDecodeBuf;
399     *pSrcBuf = m_pDecodeBuf;
400     int32_t src_Bpp = pDIBitmap->GetBPP() >> 3;
401     int32_t des_Bpp = (m_SrcFormat & 0xff) >> 3;
402     int32_t src_left = m_startX;
403     int32_t des_left = m_clipBox.left;
404     src_scan += src_left * src_Bpp;
405     des_scan += des_left * des_Bpp;
406     for (int32_t src_col = 0; src_col < m_sizeX; src_col++) {
407       PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(src_col);
408       if (pPixelWeights->m_SrcStart != pPixelWeights->m_SrcEnd) {
409         continue;
410       }
411       switch (pDIBitmap->GetFormat()) {
412         case FXDIB_1bppMask:
413         case FXDIB_1bppRgb:
414           NOTREACHED();
415           return false;
416         case FXDIB_8bppMask:
417         case FXDIB_8bppRgb: {
418           if (pDIBitmap->GetPalette()) {
419             return false;
420           }
421           uint32_t des_g = 0;
422           des_g += pPixelWeights->m_Weights[0] * src_scan[src_col];
423           des_scan[pPixelWeights->m_SrcStart] = (uint8_t)(des_g >> 16);
424         } break;
425         case FXDIB_Rgb:
426         case FXDIB_Rgb32: {
427           uint32_t des_b = 0, des_g = 0, des_r = 0;
428           const uint8_t* p = src_scan + src_col * src_Bpp;
429           des_b += pPixelWeights->m_Weights[0] * (*p++);
430           des_g += pPixelWeights->m_Weights[0] * (*p++);
431           des_r += pPixelWeights->m_Weights[0] * (*p);
432           uint8_t* pDes = &des_scan[pPixelWeights->m_SrcStart * des_Bpp];
433           *pDes++ = (uint8_t)((des_b) >> 16);
434           *pDes++ = (uint8_t)((des_g) >> 16);
435           *pDes = (uint8_t)((des_r) >> 16);
436         } break;
437         case FXDIB_Argb: {
438           uint32_t des_r = 0, des_g = 0, des_b = 0;
439           const uint8_t* p = src_scan + src_col * src_Bpp;
440           des_b += pPixelWeights->m_Weights[0] * (*p++);
441           des_g += pPixelWeights->m_Weights[0] * (*p++);
442           des_r += pPixelWeights->m_Weights[0] * (*p++);
443           uint8_t* pDes = &des_scan[pPixelWeights->m_SrcStart * des_Bpp];
444           *pDes++ = (uint8_t)((des_b) >> 16);
445           *pDes++ = (uint8_t)((des_g) >> 16);
446           *pDes++ = (uint8_t)((des_r) >> 16);
447           *pDes = *p;
448         } break;
449         default:
450           return false;
451       }
452     }
453   }
454   return true;
455 }
456 
PngOneOneMapResampleHorz(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,int32_t des_line,uint8_t * src_scan,FXCodec_Format src_format)457 void CCodec_ProgressiveDecoder::PngOneOneMapResampleHorz(
458     const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
459     int32_t des_line,
460     uint8_t* src_scan,
461     FXCodec_Format src_format) {
462   uint8_t* des_scan = (uint8_t*)pDeviceBitmap->GetScanline(des_line);
463   int32_t src_Bpp = (m_SrcFormat & 0xff) >> 3;
464   int32_t des_Bpp = pDeviceBitmap->GetBPP() >> 3;
465   int32_t src_left = m_clipBox.left;
466   int32_t des_left = m_startX;
467   src_scan += src_left * src_Bpp;
468   des_scan += des_left * des_Bpp;
469   for (int32_t des_col = 0; des_col < m_sizeX; des_col++) {
470     PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(des_col);
471     switch (pDeviceBitmap->GetFormat()) {
472       case FXDIB_1bppMask:
473       case FXDIB_1bppRgb:
474         NOTREACHED();
475         return;
476       case FXDIB_8bppMask:
477       case FXDIB_8bppRgb: {
478         if (pDeviceBitmap->GetPalette()) {
479           return;
480         }
481         uint32_t des_g = 0;
482         des_g +=
483             pPixelWeights->m_Weights[0] * src_scan[pPixelWeights->m_SrcStart];
484         des_g +=
485             pPixelWeights->m_Weights[1] * src_scan[pPixelWeights->m_SrcEnd];
486         *des_scan++ = (uint8_t)(des_g >> 16);
487       } break;
488       case FXDIB_Rgb:
489       case FXDIB_Rgb32: {
490         uint32_t des_b = 0, des_g = 0, des_r = 0;
491         const uint8_t* p = src_scan;
492         p = src_scan + pPixelWeights->m_SrcStart * src_Bpp;
493         des_b += pPixelWeights->m_Weights[0] * (*p++);
494         des_g += pPixelWeights->m_Weights[0] * (*p++);
495         des_r += pPixelWeights->m_Weights[0] * (*p);
496         p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp;
497         des_b += pPixelWeights->m_Weights[1] * (*p++);
498         des_g += pPixelWeights->m_Weights[1] * (*p++);
499         des_r += pPixelWeights->m_Weights[1] * (*p);
500         *des_scan++ = (uint8_t)((des_b) >> 16);
501         *des_scan++ = (uint8_t)((des_g) >> 16);
502         *des_scan++ = (uint8_t)((des_r) >> 16);
503         des_scan += des_Bpp - 3;
504       } break;
505       case FXDIB_Argb: {
506         uint32_t des_a = 0, des_b = 0, des_g = 0, des_r = 0;
507         const uint8_t* p = src_scan;
508         p = src_scan + pPixelWeights->m_SrcStart * src_Bpp;
509         des_b += pPixelWeights->m_Weights[0] * (*p++);
510         des_g += pPixelWeights->m_Weights[0] * (*p++);
511         des_r += pPixelWeights->m_Weights[0] * (*p++);
512         des_a += pPixelWeights->m_Weights[0] * (*p);
513         p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp;
514         des_b += pPixelWeights->m_Weights[1] * (*p++);
515         des_g += pPixelWeights->m_Weights[1] * (*p++);
516         des_r += pPixelWeights->m_Weights[1] * (*p++);
517         des_a += pPixelWeights->m_Weights[1] * (*p);
518         *des_scan++ = (uint8_t)((des_b) >> 16);
519         *des_scan++ = (uint8_t)((des_g) >> 16);
520         *des_scan++ = (uint8_t)((des_r) >> 16);
521         *des_scan++ = (uint8_t)((des_a) >> 16);
522       } break;
523       default:
524         return;
525     }
526   }
527 }
528 
PngFillScanlineBufCompleted(int pass,int line)529 void CCodec_ProgressiveDecoder::PngFillScanlineBufCompleted(int pass,
530                                                             int line) {
531   RetainPtr<CFX_DIBitmap> pDIBitmap = m_pDeviceBitmap;
532   ASSERT(pDIBitmap);
533   int src_top = m_clipBox.top;
534   int src_bottom = m_clipBox.bottom;
535   int des_top = m_startY;
536   int src_hei = m_clipBox.Height();
537   int des_hei = m_sizeY;
538   if (line >= src_top && line < src_bottom) {
539     double scale_y = (double)des_hei / (double)src_hei;
540     int src_row = line - src_top;
541     int des_row = (int)(src_row * scale_y) + des_top;
542     if (des_row >= des_top + des_hei) {
543       return;
544     }
545     PngOneOneMapResampleHorz(pDIBitmap, des_row, m_pDecodeBuf, m_SrcFormat);
546     if (m_SrcPassNumber == 1 && scale_y > 1.0) {
547       ResampleVert(pDIBitmap, scale_y, des_row);
548       return;
549     }
550     if (pass == 6 && scale_y > 1.0) {
551       ResampleVert(pDIBitmap, scale_y, des_row);
552     }
553   }
554 }
555 
GifReadMoreData(CCodec_GifModule * pGifModule,FXCODEC_STATUS & err_status)556 bool CCodec_ProgressiveDecoder::GifReadMoreData(CCodec_GifModule* pGifModule,
557                                                 FXCODEC_STATUS& err_status) {
558   uint32_t dwSize = (uint32_t)m_pFile->GetSize();
559   if (dwSize <= m_offSet) {
560     return false;
561   }
562   dwSize = dwSize - m_offSet;
563   uint32_t dwAvail = pGifModule->GetAvailInput(m_pGifContext.get(), nullptr);
564   if (dwAvail == m_SrcSize) {
565     if (dwSize > FXCODEC_BLOCK_SIZE) {
566       dwSize = FXCODEC_BLOCK_SIZE;
567     }
568     m_SrcSize = (dwSize + dwAvail + FXCODEC_BLOCK_SIZE - 1) /
569                 FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE;
570     m_pSrcBuf = FX_Realloc(uint8_t, m_pSrcBuf, m_SrcSize);
571     if (!m_pSrcBuf) {
572       err_status = FXCODEC_STATUS_ERR_MEMORY;
573       return false;
574     }
575   } else {
576     uint32_t dwConsume = m_SrcSize - dwAvail;
577     if (dwAvail) {
578       memmove(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail);
579     }
580     if (dwSize > dwConsume) {
581       dwSize = dwConsume;
582     }
583   }
584   if (!m_pFile->ReadBlock(m_pSrcBuf + dwAvail, m_offSet, dwSize)) {
585     err_status = FXCODEC_STATUS_ERR_READ;
586     return false;
587   }
588   m_offSet += dwSize;
589   pGifModule->Input(m_pGifContext.get(), m_pSrcBuf, dwSize + dwAvail);
590   return true;
591 }
592 
GifRecordCurrentPosition(uint32_t & cur_pos)593 void CCodec_ProgressiveDecoder::GifRecordCurrentPosition(uint32_t& cur_pos) {
594   uint32_t remain_size =
595       m_pCodecMgr->GetGifModule()->GetAvailInput(m_pGifContext.get());
596   cur_pos = m_offSet - remain_size;
597 }
598 
GifInputRecordPositionBuf(uint32_t rcd_pos,const FX_RECT & img_rc,int32_t pal_num,void * pal_ptr,int32_t delay_time,bool user_input,int32_t trans_index,int32_t disposal_method,bool interlace)599 bool CCodec_ProgressiveDecoder::GifInputRecordPositionBuf(
600     uint32_t rcd_pos,
601     const FX_RECT& img_rc,
602     int32_t pal_num,
603     void* pal_ptr,
604     int32_t delay_time,
605     bool user_input,
606     int32_t trans_index,
607     int32_t disposal_method,
608     bool interlace) {
609   m_offSet = rcd_pos;
610   FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR;
611   if (!GifReadMoreData(m_pCodecMgr->GetGifModule(), error_status)) {
612     return false;
613   }
614   uint8_t* pPalette = nullptr;
615   if (pal_num != 0 && pal_ptr) {
616     pPalette = (uint8_t*)pal_ptr;
617   } else {
618     if (!m_pGifPalette)
619       return false;
620     pal_num = m_GifPltNumber;
621     pPalette = m_pGifPalette;
622   }
623   if (!m_pSrcPalette)
624     m_pSrcPalette = FX_Alloc(FX_ARGB, pal_num);
625   else if (pal_num > m_SrcPaletteNumber)
626     m_pSrcPalette = FX_Realloc(FX_ARGB, m_pSrcPalette, pal_num);
627   if (!m_pSrcPalette)
628     return false;
629 
630   m_SrcPaletteNumber = pal_num;
631   for (int i = 0; i < pal_num; i++) {
632     uint32_t j = i * 3;
633     m_pSrcPalette[i] =
634         ArgbEncode(0xff, pPalette[j], pPalette[j + 1], pPalette[j + 2]);
635   }
636   m_GifTransIndex = trans_index;
637   m_GifFrameRect = img_rc;
638   m_SrcPassNumber = interlace ? 4 : 1;
639   int32_t pal_index = m_GifBgIndex;
640   RetainPtr<CFX_DIBitmap> pDevice = m_pDeviceBitmap;
641   if (trans_index >= pal_num)
642     trans_index = -1;
643   if (trans_index != -1) {
644     m_pSrcPalette[trans_index] &= 0x00ffffff;
645     if (pDevice->HasAlpha())
646       pal_index = trans_index;
647   }
648   if (pal_index >= pal_num)
649     return false;
650 
651   int startX = m_startX;
652   int startY = m_startY;
653   int sizeX = m_sizeX;
654   int sizeY = m_sizeY;
655   int Bpp = pDevice->GetBPP() / 8;
656   FX_ARGB argb = m_pSrcPalette[pal_index];
657   for (int row = 0; row < sizeY; row++) {
658     uint8_t* pScanline =
659         (uint8_t*)pDevice->GetScanline(row + startY) + startX * Bpp;
660     switch (m_TransMethod) {
661       case 3: {
662         uint8_t gray =
663             FXRGB2GRAY(FXARGB_R(argb), FXARGB_G(argb), FXARGB_B(argb));
664         memset(pScanline, gray, sizeX);
665         break;
666       }
667       case 8: {
668         for (int col = 0; col < sizeX; col++) {
669           *pScanline++ = FXARGB_B(argb);
670           *pScanline++ = FXARGB_G(argb);
671           *pScanline++ = FXARGB_R(argb);
672           pScanline += Bpp - 3;
673         }
674         break;
675       }
676       case 12: {
677         for (int col = 0; col < sizeX; col++) {
678           FXARGB_SETDIB(pScanline, argb);
679           pScanline += 4;
680         }
681         break;
682       }
683     }
684   }
685   return true;
686 }
687 
GifReadScanline(int32_t row_num,uint8_t * row_buf)688 void CCodec_ProgressiveDecoder::GifReadScanline(int32_t row_num,
689                                                 uint8_t* row_buf) {
690   RetainPtr<CFX_DIBitmap> pDIBitmap = m_pDeviceBitmap;
691   ASSERT(pDIBitmap);
692   int32_t img_width = m_GifFrameRect.Width();
693   if (!pDIBitmap->HasAlpha()) {
694     uint8_t* byte_ptr = row_buf;
695     for (int i = 0; i < img_width; i++) {
696       if (*byte_ptr == m_GifTransIndex) {
697         *byte_ptr = m_GifBgIndex;
698       }
699       byte_ptr++;
700     }
701   }
702   int32_t pal_index = m_GifBgIndex;
703   if (m_GifTransIndex != -1 && m_pDeviceBitmap->HasAlpha()) {
704     pal_index = m_GifTransIndex;
705   }
706   memset(m_pDecodeBuf, pal_index, m_SrcWidth);
707   bool bLastPass = (row_num % 2) == 1;
708   int32_t line = row_num + m_GifFrameRect.top;
709   int32_t left = m_GifFrameRect.left;
710   memcpy(m_pDecodeBuf + left, row_buf, img_width);
711   int src_top = m_clipBox.top;
712   int src_bottom = m_clipBox.bottom;
713   int des_top = m_startY;
714   int src_hei = m_clipBox.Height();
715   int des_hei = m_sizeY;
716   if (line < src_top || line >= src_bottom)
717     return;
718 
719   double scale_y = (double)des_hei / (double)src_hei;
720   int src_row = line - src_top;
721   int des_row = (int)(src_row * scale_y) + des_top;
722   if (des_row >= des_top + des_hei)
723     return;
724 
725   ReSampleScanline(pDIBitmap, des_row, m_pDecodeBuf, m_SrcFormat);
726   if (scale_y > 1.0 && m_SrcPassNumber == 1) {
727     ResampleVert(pDIBitmap, scale_y, des_row);
728     return;
729   }
730   if (scale_y <= 1.0)
731     return;
732 
733   int des_bottom = des_top + m_sizeY;
734   int des_Bpp = pDIBitmap->GetBPP() >> 3;
735   uint32_t des_ScanOffet = m_startX * des_Bpp;
736   if (des_row + (int)scale_y >= des_bottom - 1) {
737     uint8_t* scan_src =
738         (uint8_t*)pDIBitmap->GetScanline(des_row) + des_ScanOffet;
739     int cur_row = des_row;
740     while (++cur_row < des_bottom) {
741       uint8_t* scan_des =
742           (uint8_t*)pDIBitmap->GetScanline(cur_row) + des_ScanOffet;
743       uint32_t size = m_sizeX * des_Bpp;
744       memmove(scan_des, scan_src, size);
745     }
746   }
747   if (bLastPass)
748     GifDoubleLineResampleVert(pDIBitmap, scale_y, des_row);
749 }
750 
GifDoubleLineResampleVert(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,double scale_y,int des_row)751 void CCodec_ProgressiveDecoder::GifDoubleLineResampleVert(
752     const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
753     double scale_y,
754     int des_row) {
755   int des_Bpp = pDeviceBitmap->GetBPP() >> 3;
756   uint32_t des_ScanOffet = m_startX * des_Bpp;
757   int des_top = m_startY;
758   pdfium::base::CheckedNumeric<double> scale_y2 = scale_y;
759   scale_y2 *= 2;
760   pdfium::base::CheckedNumeric<int> check_des_row_1 = des_row;
761   check_des_row_1 -= scale_y2.ValueOrDie();
762   int des_row_1 = check_des_row_1.ValueOrDie();
763   des_row_1 = std::max(des_row_1, des_top);
764   for (; des_row_1 < des_row; des_row_1++) {
765     uint8_t* scan_des =
766         (uint8_t*)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet;
767     PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top);
768     const uint8_t* scan_src1 =
769         pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) +
770         des_ScanOffet;
771     const uint8_t* scan_src2 =
772         pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + des_top) + des_ScanOffet;
773     for (int des_col = 0; des_col < m_sizeX; des_col++) {
774       switch (pDeviceBitmap->GetFormat()) {
775         case FXDIB_Invalid:
776         case FXDIB_1bppMask:
777         case FXDIB_1bppRgb:
778           return;
779         case FXDIB_8bppMask:
780         case FXDIB_8bppRgb: {
781           if (pDeviceBitmap->GetPalette()) {
782             return;
783           }
784           int des_g = 0;
785           des_g += pWeight->m_Weights[0] * (*scan_src1++);
786           des_g += pWeight->m_Weights[1] * (*scan_src2++);
787           *scan_des++ = (uint8_t)(des_g >> 16);
788         } break;
789         case FXDIB_Rgb:
790         case FXDIB_Rgb32: {
791           uint32_t des_b = 0, des_g = 0, des_r = 0;
792           des_b += pWeight->m_Weights[0] * (*scan_src1++);
793           des_g += pWeight->m_Weights[0] * (*scan_src1++);
794           des_r += pWeight->m_Weights[0] * (*scan_src1++);
795           scan_src1 += des_Bpp - 3;
796           des_b += pWeight->m_Weights[1] * (*scan_src2++);
797           des_g += pWeight->m_Weights[1] * (*scan_src2++);
798           des_r += pWeight->m_Weights[1] * (*scan_src2++);
799           scan_src2 += des_Bpp - 3;
800           *scan_des++ = (uint8_t)((des_b) >> 16);
801           *scan_des++ = (uint8_t)((des_g) >> 16);
802           *scan_des++ = (uint8_t)((des_r) >> 16);
803           scan_des += des_Bpp - 3;
804         } break;
805         case FXDIB_Argb: {
806           uint32_t des_a = 0, des_b = 0, des_g = 0, des_r = 0;
807           des_b += pWeight->m_Weights[0] * (*scan_src1++);
808           des_g += pWeight->m_Weights[0] * (*scan_src1++);
809           des_r += pWeight->m_Weights[0] * (*scan_src1++);
810           des_a += pWeight->m_Weights[0] * (*scan_src1++);
811           des_b += pWeight->m_Weights[1] * (*scan_src2++);
812           des_g += pWeight->m_Weights[1] * (*scan_src2++);
813           des_r += pWeight->m_Weights[1] * (*scan_src2++);
814           des_a += pWeight->m_Weights[1] * (*scan_src2++);
815           *scan_des++ = (uint8_t)((des_b) >> 16);
816           *scan_des++ = (uint8_t)((des_g) >> 16);
817           *scan_des++ = (uint8_t)((des_r) >> 16);
818           *scan_des++ = (uint8_t)((des_a) >> 16);
819         } break;
820         default:
821           return;
822       }
823     }
824   }
825   int des_bottom = des_top + m_sizeY - 1;
826   if (des_row + (int)(2 * scale_y) >= des_bottom &&
827       des_row + (int)scale_y < des_bottom) {
828     GifDoubleLineResampleVert(pDeviceBitmap, scale_y, des_row + (int)scale_y);
829   }
830 }
831 
BmpReadMoreData(CCodec_BmpModule * pBmpModule,FXCODEC_STATUS & err_status)832 bool CCodec_ProgressiveDecoder::BmpReadMoreData(CCodec_BmpModule* pBmpModule,
833                                                 FXCODEC_STATUS& err_status) {
834   uint32_t dwSize = (uint32_t)m_pFile->GetSize();
835   if (dwSize <= m_offSet)
836     return false;
837 
838   dwSize = dwSize - m_offSet;
839   uint32_t dwAvail = pBmpModule->GetAvailInput(m_pBmpContext.get(), nullptr);
840   if (dwAvail == m_SrcSize) {
841     if (dwSize > FXCODEC_BLOCK_SIZE) {
842       dwSize = FXCODEC_BLOCK_SIZE;
843     }
844     m_SrcSize = (dwSize + dwAvail + FXCODEC_BLOCK_SIZE - 1) /
845                 FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE;
846     m_pSrcBuf = FX_Realloc(uint8_t, m_pSrcBuf, m_SrcSize);
847     if (!m_pSrcBuf) {
848       err_status = FXCODEC_STATUS_ERR_MEMORY;
849       return false;
850     }
851   } else {
852     uint32_t dwConsume = m_SrcSize - dwAvail;
853     if (dwAvail) {
854       memmove(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail);
855     }
856     if (dwSize > dwConsume) {
857       dwSize = dwConsume;
858     }
859   }
860   if (!m_pFile->ReadBlock(m_pSrcBuf + dwAvail, m_offSet, dwSize)) {
861     err_status = FXCODEC_STATUS_ERR_READ;
862     return false;
863   }
864   m_offSet += dwSize;
865   pBmpModule->Input(m_pBmpContext.get(), m_pSrcBuf, dwSize + dwAvail);
866   return true;
867 }
868 
BmpInputImagePositionBuf(uint32_t rcd_pos)869 bool CCodec_ProgressiveDecoder::BmpInputImagePositionBuf(uint32_t rcd_pos) {
870   m_offSet = rcd_pos;
871   FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR;
872   return BmpReadMoreData(m_pCodecMgr->GetBmpModule(), error_status);
873 }
874 
BmpReadScanline(uint32_t row_num,const std::vector<uint8_t> & row_buf)875 void CCodec_ProgressiveDecoder::BmpReadScanline(
876     uint32_t row_num,
877     const std::vector<uint8_t>& row_buf) {
878   RetainPtr<CFX_DIBitmap> pDIBitmap = m_pDeviceBitmap;
879   ASSERT(pDIBitmap);
880   std::copy(row_buf.begin(), row_buf.begin() + m_ScanlineSize, m_pDecodeBuf);
881   int src_top = m_clipBox.top;
882   int src_bottom = m_clipBox.bottom;
883   int des_top = m_startY;
884   int src_hei = m_clipBox.Height();
885   int des_hei = m_sizeY;
886   if ((src_top >= 0 && row_num < static_cast<uint32_t>(src_top)) ||
887       src_bottom < 0 || row_num >= static_cast<uint32_t>(src_bottom)) {
888     return;
889   }
890 
891   double scale_y = (double)des_hei / (double)src_hei;
892   int src_row = row_num - src_top;
893   int des_row = (int)(src_row * scale_y) + des_top;
894   if (des_row >= des_top + des_hei)
895     return;
896 
897   ReSampleScanline(pDIBitmap, des_row, m_pDecodeBuf, m_SrcFormat);
898   if (scale_y <= 1.0)
899     return;
900 
901   if (m_BmpIsTopBottom) {
902     ResampleVert(pDIBitmap, scale_y, des_row);
903     return;
904   }
905   ResampleVertBT(pDIBitmap, scale_y, des_row);
906 }
907 
ResampleVertBT(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,double scale_y,int des_row)908 void CCodec_ProgressiveDecoder::ResampleVertBT(
909     const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
910     double scale_y,
911     int des_row) {
912   int des_Bpp = pDeviceBitmap->GetBPP() >> 3;
913   uint32_t des_ScanOffet = m_startX * des_Bpp;
914   int des_top = m_startY;
915   int des_bottom = m_startY + m_sizeY;
916   pdfium::base::CheckedNumeric<int> check_des_row_1 = des_row;
917   check_des_row_1 += pdfium::base::checked_cast<int>(scale_y);
918   int des_row_1 = check_des_row_1.ValueOrDie();
919   if (des_row_1 >= des_bottom - 1) {
920     uint8_t* scan_src =
921         (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
922     while (++des_row < des_bottom) {
923       uint8_t* scan_des =
924           (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
925       uint32_t size = m_sizeX * des_Bpp;
926       memmove(scan_des, scan_src, size);
927     }
928     return;
929   }
930   for (; des_row_1 > des_row; des_row_1--) {
931     uint8_t* scan_des =
932         (uint8_t*)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet;
933     PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top);
934     const uint8_t* scan_src1 =
935         pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) +
936         des_ScanOffet;
937     const uint8_t* scan_src2 =
938         pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + des_top) + des_ScanOffet;
939     for (int des_col = 0; des_col < m_sizeX; des_col++) {
940       switch (pDeviceBitmap->GetFormat()) {
941         case FXDIB_Invalid:
942         case FXDIB_1bppMask:
943         case FXDIB_1bppRgb:
944           return;
945         case FXDIB_8bppMask:
946         case FXDIB_8bppRgb: {
947           if (pDeviceBitmap->GetPalette()) {
948             return;
949           }
950           int des_g = 0;
951           des_g += pWeight->m_Weights[0] * (*scan_src1++);
952           des_g += pWeight->m_Weights[1] * (*scan_src2++);
953           *scan_des++ = (uint8_t)(des_g >> 16);
954         } break;
955         case FXDIB_Rgb:
956         case FXDIB_Rgb32: {
957           uint32_t des_b = 0, des_g = 0, des_r = 0;
958           des_b += pWeight->m_Weights[0] * (*scan_src1++);
959           des_g += pWeight->m_Weights[0] * (*scan_src1++);
960           des_r += pWeight->m_Weights[0] * (*scan_src1++);
961           scan_src1 += des_Bpp - 3;
962           des_b += pWeight->m_Weights[1] * (*scan_src2++);
963           des_g += pWeight->m_Weights[1] * (*scan_src2++);
964           des_r += pWeight->m_Weights[1] * (*scan_src2++);
965           scan_src2 += des_Bpp - 3;
966           *scan_des++ = (uint8_t)((des_b) >> 16);
967           *scan_des++ = (uint8_t)((des_g) >> 16);
968           *scan_des++ = (uint8_t)((des_r) >> 16);
969           scan_des += des_Bpp - 3;
970         } break;
971         case FXDIB_Argb: {
972           uint32_t des_a = 0, des_b = 0, des_g = 0, des_r = 0;
973           des_b += pWeight->m_Weights[0] * (*scan_src1++);
974           des_g += pWeight->m_Weights[0] * (*scan_src1++);
975           des_r += pWeight->m_Weights[0] * (*scan_src1++);
976           des_a += pWeight->m_Weights[0] * (*scan_src1++);
977           des_b += pWeight->m_Weights[1] * (*scan_src2++);
978           des_g += pWeight->m_Weights[1] * (*scan_src2++);
979           des_r += pWeight->m_Weights[1] * (*scan_src2++);
980           des_a += pWeight->m_Weights[1] * (*scan_src2++);
981           *scan_des++ = (uint8_t)((des_b) >> 16);
982           *scan_des++ = (uint8_t)((des_g) >> 16);
983           *scan_des++ = (uint8_t)((des_r) >> 16);
984           *scan_des++ = (uint8_t)((des_a) >> 16);
985         } break;
986         default:
987           return;
988       }
989     }
990   }
991 }
992 
DetectImageType(FXCODEC_IMAGE_TYPE imageType,CFX_DIBAttribute * pAttribute)993 bool CCodec_ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType,
994                                                 CFX_DIBAttribute* pAttribute) {
995   m_offSet = 0;
996   uint32_t size = (uint32_t)m_pFile->GetSize();
997   if (size > FXCODEC_BLOCK_SIZE) {
998     size = FXCODEC_BLOCK_SIZE;
999   }
1000   FX_Free(m_pSrcBuf);
1001   m_pSrcBuf = FX_Alloc(uint8_t, size);
1002   memset(m_pSrcBuf, 0, size);
1003   m_SrcSize = size;
1004   switch (imageType) {
1005     case FXCODEC_IMAGE_BMP:
1006       return BmpDetectImageType(pAttribute, size);
1007     case FXCODEC_IMAGE_JPG:
1008       return JpegDetectImageType(pAttribute, size);
1009     case FXCODEC_IMAGE_PNG:
1010       return PngDetectImageType(pAttribute, size);
1011     case FXCODEC_IMAGE_GIF:
1012       return GifDetectImageType(pAttribute, size);
1013     case FXCODEC_IMAGE_TIF:
1014       return TifDetectImageType(pAttribute, size);
1015     default:
1016       m_status = FXCODEC_STATUS_ERR_FORMAT;
1017       return false;
1018   }
1019 }
1020 
BmpDetectImageType(CFX_DIBAttribute * pAttribute,uint32_t size)1021 bool CCodec_ProgressiveDecoder::BmpDetectImageType(CFX_DIBAttribute* pAttribute,
1022                                                    uint32_t size) {
1023   CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule();
1024   if (!pBmpModule) {
1025     m_status = FXCODEC_STATUS_ERR_MEMORY;
1026     return false;
1027   }
1028 
1029   m_pBmpContext = pBmpModule->Start(this);
1030   if (!m_pBmpContext) {
1031     m_status = FXCODEC_STATUS_ERR_MEMORY;
1032     return false;
1033   }
1034 
1035   if (!m_pFile->ReadBlock(m_pSrcBuf, 0, size)) {
1036     m_status = FXCODEC_STATUS_ERR_READ;
1037     return false;
1038   }
1039 
1040   m_offSet += size;
1041   pBmpModule->Input(m_pBmpContext.get(), m_pSrcBuf, size);
1042   std::vector<uint32_t> palette;
1043   int32_t readResult = pBmpModule->ReadHeader(
1044       m_pBmpContext.get(), &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom,
1045       &m_SrcComponents, &m_SrcPaletteNumber, &palette, pAttribute);
1046   while (readResult == 2) {
1047     FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT;
1048     if (!BmpReadMoreData(pBmpModule, error_status)) {
1049       m_status = error_status;
1050       return false;
1051     }
1052     readResult = pBmpModule->ReadHeader(
1053         m_pBmpContext.get(), &m_SrcWidth, &m_SrcHeight, &m_BmpIsTopBottom,
1054         &m_SrcComponents, &m_SrcPaletteNumber, &palette, pAttribute);
1055   }
1056 
1057   if (readResult != 1) {
1058     m_pBmpContext.reset();
1059     m_status = FXCODEC_STATUS_ERR_FORMAT;
1060     return false;
1061   }
1062 
1063   FXDIB_Format format = FXDIB_Invalid;
1064   switch (m_SrcComponents) {
1065     case 1:
1066       m_SrcFormat = FXCodec_8bppRgb;
1067       format = FXDIB_8bppRgb;
1068       break;
1069     case 3:
1070       m_SrcFormat = FXCodec_Rgb;
1071       format = FXDIB_Rgb;
1072       break;
1073     case 4:
1074       m_SrcFormat = FXCodec_Rgb32;
1075       format = FXDIB_Rgb32;
1076       break;
1077     default:
1078       m_pBmpContext.reset();
1079       m_status = FXCODEC_STATUS_ERR_FORMAT;
1080       return false;
1081   }
1082 
1083   uint32_t pitch = 0;
1084   uint32_t neededData = 0;
1085   if (!CFX_DIBitmap::CalculatePitchAndSize(m_SrcWidth, m_SrcHeight, format,
1086                                            &pitch, &neededData)) {
1087     m_pBmpContext.reset();
1088     m_status = FXCODEC_STATUS_ERR_FORMAT;
1089     return false;
1090   }
1091 
1092   uint32_t availableData = m_SrcSize > m_offSet ? m_SrcSize - m_offSet : 0;
1093   if (neededData > availableData) {
1094     m_pBmpContext.reset();
1095     m_status = FXCODEC_STATUS_ERR_FORMAT;
1096     return false;
1097   }
1098 
1099   m_SrcBPC = 8;
1100   m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
1101   FX_Free(m_pSrcPalette);
1102   if (m_SrcPaletteNumber) {
1103     m_pSrcPalette = FX_Alloc(FX_ARGB, m_SrcPaletteNumber);
1104     memcpy(m_pSrcPalette, palette.data(), m_SrcPaletteNumber * sizeof(FX_ARGB));
1105   } else {
1106     m_pSrcPalette = nullptr;
1107   }
1108   return true;
1109 }
1110 
JpegDetectImageType(CFX_DIBAttribute * pAttribute,uint32_t size)1111 bool CCodec_ProgressiveDecoder::JpegDetectImageType(
1112     CFX_DIBAttribute* pAttribute,
1113     uint32_t size) {
1114   CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
1115   // Setting jump marker before calling Start or ReadHeader, since a longjmp
1116   // to the marker indicates a fatal error in these functions.
1117   if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) {
1118     m_status = FXCODEC_STATUS_ERROR;
1119     return false;
1120   }
1121 
1122   m_pJpegContext = pJpegModule->Start();
1123   if (!m_pJpegContext) {
1124     m_status = FXCODEC_STATUS_ERR_MEMORY;
1125     return false;
1126   }
1127   if (!m_pFile->ReadBlock(m_pSrcBuf, 0, size)) {
1128     m_status = FXCODEC_STATUS_ERR_READ;
1129     return false;
1130   }
1131   m_offSet += size;
1132   pJpegModule->Input(m_pJpegContext.get(), m_pSrcBuf, size);
1133   // Setting jump marker before calling ReadHeader, since a longjmp to
1134   // the marker indicates a fatal error.
1135   if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) {
1136     m_pJpegContext.reset();
1137     m_status = FXCODEC_STATUS_ERR_FORMAT;
1138     return false;
1139   }
1140 
1141   int32_t readResult =
1142       pJpegModule->ReadHeader(m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight,
1143                               &m_SrcComponents, pAttribute);
1144   while (readResult == 2) {
1145     FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT;
1146     if (!JpegReadMoreData(pJpegModule, error_status)) {
1147       m_status = error_status;
1148       return false;
1149     }
1150     readResult =
1151         pJpegModule->ReadHeader(m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight,
1152                                 &m_SrcComponents, pAttribute);
1153   }
1154   if (!readResult) {
1155     m_SrcBPC = 8;
1156     m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
1157     return true;
1158   }
1159   m_pJpegContext.reset();
1160   m_status = FXCODEC_STATUS_ERR_FORMAT;
1161   return false;
1162 }
1163 
PngDetectImageType(CFX_DIBAttribute * pAttribute,uint32_t size)1164 bool CCodec_ProgressiveDecoder::PngDetectImageType(CFX_DIBAttribute* pAttribute,
1165                                                    uint32_t size) {
1166   CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule();
1167   if (!pPngModule) {
1168     m_status = FXCODEC_STATUS_ERR_MEMORY;
1169     return false;
1170   }
1171   m_pPngContext = pPngModule->Start(this);
1172   if (!m_pPngContext) {
1173     m_status = FXCODEC_STATUS_ERR_MEMORY;
1174     return false;
1175   }
1176   bool bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size);
1177   if (!bResult) {
1178     m_status = FXCODEC_STATUS_ERR_READ;
1179     return false;
1180   }
1181   m_offSet += size;
1182   bResult = pPngModule->Input(m_pPngContext.get(), m_pSrcBuf, size, pAttribute);
1183   while (bResult) {
1184     uint32_t remain_size = static_cast<uint32_t>(m_pFile->GetSize()) - m_offSet;
1185     uint32_t input_size =
1186         remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size;
1187     if (input_size == 0) {
1188       m_pPngContext.reset();
1189       m_status = FXCODEC_STATUS_ERR_FORMAT;
1190       return false;
1191     }
1192     if (m_pSrcBuf && input_size > m_SrcSize) {
1193       FX_Free(m_pSrcBuf);
1194       m_pSrcBuf = FX_Alloc(uint8_t, input_size);
1195       memset(m_pSrcBuf, 0, input_size);
1196       m_SrcSize = input_size;
1197     }
1198     bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size);
1199     if (!bResult) {
1200       m_status = FXCODEC_STATUS_ERR_READ;
1201       return false;
1202     }
1203     m_offSet += input_size;
1204     bResult = pPngModule->Input(m_pPngContext.get(), m_pSrcBuf, input_size,
1205                                 pAttribute);
1206   }
1207   ASSERT(!bResult);
1208   m_pPngContext.reset();
1209   if (m_SrcPassNumber == 0) {
1210     m_status = FXCODEC_STATUS_ERR_FORMAT;
1211     return false;
1212   }
1213   return true;
1214 }
1215 
GifDetectImageType(CFX_DIBAttribute * pAttribute,uint32_t size)1216 bool CCodec_ProgressiveDecoder::GifDetectImageType(CFX_DIBAttribute* pAttribute,
1217                                                    uint32_t size) {
1218   CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule();
1219   if (!pGifModule) {
1220     m_status = FXCODEC_STATUS_ERR_MEMORY;
1221     return false;
1222   }
1223   m_pGifContext = pGifModule->Start(this);
1224   bool bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size);
1225   if (!bResult) {
1226     m_status = FXCODEC_STATUS_ERR_READ;
1227     return false;
1228   }
1229   m_offSet += size;
1230   pGifModule->Input(m_pGifContext.get(), m_pSrcBuf, size);
1231   m_SrcComponents = 1;
1232   CFX_GifDecodeStatus readResult = pGifModule->ReadHeader(
1233       m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight, &m_GifPltNumber,
1234       (void**)&m_pGifPalette, &m_GifBgIndex, nullptr);
1235   while (readResult == CFX_GifDecodeStatus::Unfinished) {
1236     FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT;
1237     if (!GifReadMoreData(pGifModule, error_status)) {
1238       m_pGifContext = nullptr;
1239       m_status = error_status;
1240       return false;
1241     }
1242     readResult = pGifModule->ReadHeader(
1243         m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight, &m_GifPltNumber,
1244         (void**)&m_pGifPalette, &m_GifBgIndex, nullptr);
1245   }
1246   if (readResult == CFX_GifDecodeStatus::Success) {
1247     m_SrcBPC = 8;
1248     m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
1249     return true;
1250   }
1251   m_pGifContext = nullptr;
1252   m_status = FXCODEC_STATUS_ERR_FORMAT;
1253   return false;
1254 }
1255 
TifDetectImageType(CFX_DIBAttribute * pAttribute,uint32_t size)1256 bool CCodec_ProgressiveDecoder::TifDetectImageType(CFX_DIBAttribute* pAttribute,
1257                                                    uint32_t size) {
1258   CCodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule();
1259   if (!pTiffModule) {
1260     m_status = FXCODEC_STATUS_ERR_FORMAT;
1261     return false;
1262   }
1263   m_pTiffContext = pTiffModule->CreateDecoder(m_pFile);
1264   if (!m_pTiffContext) {
1265     m_status = FXCODEC_STATUS_ERR_FORMAT;
1266     return false;
1267   }
1268   int32_t dummy_bpc;
1269   bool ret = pTiffModule->LoadFrameInfo(m_pTiffContext.get(), 0, &m_SrcWidth,
1270                                         &m_SrcHeight, &m_SrcComponents,
1271                                         &dummy_bpc, pAttribute);
1272   m_SrcComponents = 4;
1273   m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight);
1274   if (!ret) {
1275     m_pTiffContext.reset();
1276     m_status = FXCODEC_STATUS_ERR_FORMAT;
1277     return false;
1278   }
1279   return true;
1280 }
1281 
LoadImageInfo(const RetainPtr<IFX_SeekableReadStream> & pFile,FXCODEC_IMAGE_TYPE imageType,CFX_DIBAttribute * pAttribute,bool bSkipImageTypeCheck)1282 FXCODEC_STATUS CCodec_ProgressiveDecoder::LoadImageInfo(
1283     const RetainPtr<IFX_SeekableReadStream>& pFile,
1284     FXCODEC_IMAGE_TYPE imageType,
1285     CFX_DIBAttribute* pAttribute,
1286     bool bSkipImageTypeCheck) {
1287   switch (m_status) {
1288     case FXCODEC_STATUS_FRAME_READY:
1289     case FXCODEC_STATUS_FRAME_TOBECONTINUE:
1290     case FXCODEC_STATUS_DECODE_READY:
1291     case FXCODEC_STATUS_DECODE_TOBECONTINUE:
1292       return FXCODEC_STATUS_ERROR;
1293     default:
1294       break;
1295   }
1296   if (!pFile) {
1297     m_status = FXCODEC_STATUS_ERR_PARAMS;
1298     m_pFile = nullptr;
1299     return m_status;
1300   }
1301   m_pFile = pFile;
1302   m_offSet = 0;
1303   m_SrcWidth = m_SrcHeight = 0;
1304   m_SrcComponents = m_SrcBPC = 0;
1305   m_clipBox = FX_RECT(0, 0, 0, 0);
1306   m_startX = m_startY = 0;
1307   m_sizeX = m_sizeY = 0;
1308   m_SrcPassNumber = 0;
1309   if (imageType != FXCODEC_IMAGE_UNKNOWN &&
1310       DetectImageType(imageType, pAttribute)) {
1311     m_imagType = imageType;
1312     m_status = FXCODEC_STATUS_FRAME_READY;
1313     return m_status;
1314   }
1315   // If we got here then the image data does not match the requested decoder.
1316   // If we're skipping the type check then bail out at this point and return
1317   // the failed status.
1318   if (bSkipImageTypeCheck)
1319     return m_status;
1320 
1321   for (int type = FXCODEC_IMAGE_BMP; type < FXCODEC_IMAGE_MAX; type++) {
1322     if (DetectImageType((FXCODEC_IMAGE_TYPE)type, pAttribute)) {
1323       m_imagType = (FXCODEC_IMAGE_TYPE)type;
1324       m_status = FXCODEC_STATUS_FRAME_READY;
1325       return m_status;
1326     }
1327   }
1328   m_status = FXCODEC_STATUS_ERR_FORMAT;
1329   m_pFile = nullptr;
1330   return m_status;
1331 }
1332 
SetClipBox(FX_RECT * clip)1333 void CCodec_ProgressiveDecoder::SetClipBox(FX_RECT* clip) {
1334   if (m_status != FXCODEC_STATUS_FRAME_READY)
1335     return;
1336 
1337   if (clip->IsEmpty()) {
1338     m_clipBox = FX_RECT(0, 0, 0, 0);
1339     return;
1340   }
1341   clip->left = std::max(clip->left, 0);
1342   clip->right = std::min(clip->right, m_SrcWidth);
1343   clip->top = std::max(clip->top, 0);
1344   clip->bottom = std::min(clip->bottom, m_SrcHeight);
1345   if (clip->IsEmpty()) {
1346     m_clipBox = FX_RECT(0, 0, 0, 0);
1347     return;
1348   }
1349   m_clipBox = *clip;
1350 }
1351 
GetDownScale(int & down_scale)1352 void CCodec_ProgressiveDecoder::GetDownScale(int& down_scale) {
1353   down_scale = 1;
1354   int ratio_w = m_clipBox.Width() / m_sizeX;
1355   int ratio_h = m_clipBox.Height() / m_sizeY;
1356   int ratio = (ratio_w > ratio_h) ? ratio_h : ratio_w;
1357   if (ratio >= 8) {
1358     down_scale = 8;
1359   } else if (ratio >= 4) {
1360     down_scale = 4;
1361   } else if (ratio >= 2) {
1362     down_scale = 2;
1363   }
1364   m_clipBox.left /= down_scale;
1365   m_clipBox.right /= down_scale;
1366   m_clipBox.top /= down_scale;
1367   m_clipBox.bottom /= down_scale;
1368   if (m_clipBox.right == m_clipBox.left) {
1369     m_clipBox.right = m_clipBox.left + 1;
1370   }
1371   if (m_clipBox.bottom == m_clipBox.top) {
1372     m_clipBox.bottom = m_clipBox.top + 1;
1373   }
1374 }
1375 
GetTransMethod(FXDIB_Format des_format,FXCodec_Format src_format)1376 void CCodec_ProgressiveDecoder::GetTransMethod(FXDIB_Format des_format,
1377                                                FXCodec_Format src_format) {
1378   switch (des_format) {
1379     case FXDIB_1bppMask:
1380     case FXDIB_1bppRgb: {
1381       switch (src_format) {
1382         case FXCodec_1bppGray:
1383           m_TransMethod = 0;
1384           break;
1385         default:
1386           m_TransMethod = -1;
1387       }
1388     } break;
1389     case FXDIB_8bppMask:
1390     case FXDIB_8bppRgb: {
1391       switch (src_format) {
1392         case FXCodec_1bppGray:
1393           m_TransMethod = 1;
1394           break;
1395         case FXCodec_8bppGray:
1396           m_TransMethod = 2;
1397           break;
1398         case FXCodec_1bppRgb:
1399         case FXCodec_8bppRgb:
1400           m_TransMethod = 3;
1401           break;
1402         case FXCodec_Rgb:
1403         case FXCodec_Rgb32:
1404         case FXCodec_Argb:
1405           m_TransMethod = 4;
1406           break;
1407         case FXCodec_Cmyk:
1408           m_TransMethod = 5;
1409           break;
1410         default:
1411           m_TransMethod = -1;
1412       }
1413     } break;
1414     case FXDIB_Rgb: {
1415       switch (src_format) {
1416         case FXCodec_1bppGray:
1417           m_TransMethod = 6;
1418           break;
1419         case FXCodec_8bppGray:
1420           m_TransMethod = 7;
1421           break;
1422         case FXCodec_1bppRgb:
1423         case FXCodec_8bppRgb:
1424           m_TransMethod = 8;
1425           break;
1426         case FXCodec_Rgb:
1427         case FXCodec_Rgb32:
1428         case FXCodec_Argb:
1429           m_TransMethod = 9;
1430           break;
1431         case FXCodec_Cmyk:
1432           m_TransMethod = 10;
1433           break;
1434         default:
1435           m_TransMethod = -1;
1436       }
1437     } break;
1438     case FXDIB_Rgb32:
1439     case FXDIB_Argb: {
1440       switch (src_format) {
1441         case FXCodec_1bppGray:
1442           m_TransMethod = 6;
1443           break;
1444         case FXCodec_8bppGray:
1445           m_TransMethod = 7;
1446           break;
1447         case FXCodec_1bppRgb:
1448         case FXCodec_8bppRgb:
1449           if (des_format == FXDIB_Argb) {
1450             m_TransMethod = 12;
1451           } else {
1452             m_TransMethod = 8;
1453           }
1454           break;
1455         case FXCodec_Rgb:
1456         case FXCodec_Rgb32:
1457           m_TransMethod = 9;
1458           break;
1459         case FXCodec_Cmyk:
1460           m_TransMethod = 10;
1461           break;
1462         case FXCodec_Argb:
1463           m_TransMethod = 11;
1464           break;
1465         default:
1466           m_TransMethod = -1;
1467       }
1468     } break;
1469     default:
1470       m_TransMethod = -1;
1471   }
1472 }
1473 
ReSampleScanline(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,int des_line,uint8_t * src_scan,FXCodec_Format src_format)1474 void CCodec_ProgressiveDecoder::ReSampleScanline(
1475     const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1476     int des_line,
1477     uint8_t* src_scan,
1478     FXCodec_Format src_format) {
1479   int src_left = m_clipBox.left;
1480   int des_left = m_startX;
1481   uint8_t* des_scan =
1482       pDeviceBitmap->GetBuffer() + des_line * pDeviceBitmap->GetPitch();
1483   int src_bpp = src_format & 0xff;
1484   int des_bpp = pDeviceBitmap->GetBPP();
1485   int src_Bpp = src_bpp >> 3;
1486   int des_Bpp = des_bpp >> 3;
1487   src_scan += src_left * src_Bpp;
1488   des_scan += des_left * des_Bpp;
1489   for (int des_col = 0; des_col < m_sizeX; des_col++) {
1490     PixelWeight* pPixelWeights = m_WeightHorz.GetPixelWeight(des_col);
1491     switch (m_TransMethod) {
1492       case -1:
1493         return;
1494       case 0:
1495         return;
1496       case 1:
1497         return;
1498       case 2: {
1499         uint32_t des_g = 0;
1500         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1501              j++) {
1502           int pixel_weight =
1503               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1504           des_g += pixel_weight * src_scan[j];
1505         }
1506         *des_scan++ = (uint8_t)(des_g >> 16);
1507       } break;
1508       case 3: {
1509         int des_r = 0, des_g = 0, des_b = 0;
1510         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1511              j++) {
1512           int pixel_weight =
1513               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1514           unsigned long argb = m_pSrcPalette[src_scan[j]];
1515           des_r += pixel_weight * (uint8_t)(argb >> 16);
1516           des_g += pixel_weight * (uint8_t)(argb >> 8);
1517           des_b += pixel_weight * (uint8_t)argb;
1518         }
1519         *des_scan++ =
1520             (uint8_t)FXRGB2GRAY((des_r >> 16), (des_g >> 16), (des_b >> 16));
1521       } break;
1522       case 4: {
1523         uint32_t des_b = 0, des_g = 0, des_r = 0;
1524         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1525              j++) {
1526           int pixel_weight =
1527               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1528           const uint8_t* src_pixel = src_scan + j * src_Bpp;
1529           des_b += pixel_weight * (*src_pixel++);
1530           des_g += pixel_weight * (*src_pixel++);
1531           des_r += pixel_weight * (*src_pixel);
1532         }
1533         *des_scan++ =
1534             (uint8_t)FXRGB2GRAY((des_r >> 16), (des_g >> 16), (des_b >> 16));
1535       } break;
1536       case 5: {
1537         uint32_t des_b = 0, des_g = 0, des_r = 0;
1538         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1539              j++) {
1540           int pixel_weight =
1541               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1542           const uint8_t* src_pixel = src_scan + j * src_Bpp;
1543           uint8_t src_b = 0;
1544           uint8_t src_g = 0;
1545           uint8_t src_r = 0;
1546           std::tie(src_r, src_g, src_b) =
1547               AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1],
1548                                  255 - src_pixel[2], 255 - src_pixel[3]);
1549           des_b += pixel_weight * src_b;
1550           des_g += pixel_weight * src_g;
1551           des_r += pixel_weight * src_r;
1552         }
1553         *des_scan++ =
1554             (uint8_t)FXRGB2GRAY((des_r >> 16), (des_g >> 16), (des_b >> 16));
1555       } break;
1556       case 6:
1557         return;
1558       case 7: {
1559         uint32_t des_g = 0;
1560         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1561              j++) {
1562           int pixel_weight =
1563               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1564           des_g += pixel_weight * src_scan[j];
1565         }
1566         memset(des_scan, (uint8_t)(des_g >> 16), 3);
1567         des_scan += des_Bpp;
1568       } break;
1569       case 8: {
1570         int des_r = 0, des_g = 0, des_b = 0;
1571         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1572              j++) {
1573           int pixel_weight =
1574               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1575           unsigned long argb = m_pSrcPalette[src_scan[j]];
1576           des_r += pixel_weight * (uint8_t)(argb >> 16);
1577           des_g += pixel_weight * (uint8_t)(argb >> 8);
1578           des_b += pixel_weight * (uint8_t)argb;
1579         }
1580         *des_scan++ = (uint8_t)((des_b) >> 16);
1581         *des_scan++ = (uint8_t)((des_g) >> 16);
1582         *des_scan++ = (uint8_t)((des_r) >> 16);
1583         des_scan += des_Bpp - 3;
1584       } break;
1585       case 12: {
1586         if (m_pBmpContext) {
1587           int des_r = 0, des_g = 0, des_b = 0;
1588           for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1589                j++) {
1590             int pixel_weight =
1591                 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1592             unsigned long argb = m_pSrcPalette[src_scan[j]];
1593             des_r += pixel_weight * (uint8_t)(argb >> 16);
1594             des_g += pixel_weight * (uint8_t)(argb >> 8);
1595             des_b += pixel_weight * (uint8_t)argb;
1596           }
1597           *des_scan++ = (uint8_t)((des_b) >> 16);
1598           *des_scan++ = (uint8_t)((des_g) >> 16);
1599           *des_scan++ = (uint8_t)((des_r) >> 16);
1600           *des_scan++ = 0xFF;
1601         } else {
1602           int des_a = 0, des_r = 0, des_g = 0, des_b = 0;
1603           for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1604                j++) {
1605             int pixel_weight =
1606                 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1607             unsigned long argb = m_pSrcPalette[src_scan[j]];
1608             des_a += pixel_weight * (uint8_t)(argb >> 24);
1609             des_r += pixel_weight * (uint8_t)(argb >> 16);
1610             des_g += pixel_weight * (uint8_t)(argb >> 8);
1611             des_b += pixel_weight * (uint8_t)argb;
1612           }
1613           *des_scan++ = (uint8_t)((des_b) >> 16);
1614           *des_scan++ = (uint8_t)((des_g) >> 16);
1615           *des_scan++ = (uint8_t)((des_r) >> 16);
1616           *des_scan++ = (uint8_t)((des_a) >> 16);
1617         }
1618       } break;
1619       case 9: {
1620         uint32_t des_b = 0, des_g = 0, des_r = 0;
1621         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1622              j++) {
1623           int pixel_weight =
1624               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1625           const uint8_t* src_pixel = src_scan + j * src_Bpp;
1626           des_b += pixel_weight * (*src_pixel++);
1627           des_g += pixel_weight * (*src_pixel++);
1628           des_r += pixel_weight * (*src_pixel);
1629         }
1630         *des_scan++ = (uint8_t)((des_b) >> 16);
1631         *des_scan++ = (uint8_t)((des_g) >> 16);
1632         *des_scan++ = (uint8_t)((des_r) >> 16);
1633         des_scan += des_Bpp - 3;
1634       } break;
1635       case 10: {
1636         uint32_t des_b = 0, des_g = 0, des_r = 0;
1637         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1638              j++) {
1639           int pixel_weight =
1640               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1641           const uint8_t* src_pixel = src_scan + j * src_Bpp;
1642           uint8_t src_b = 0;
1643           uint8_t src_g = 0;
1644           uint8_t src_r = 0;
1645           std::tie(src_r, src_g, src_b) =
1646               AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1],
1647                                  255 - src_pixel[2], 255 - src_pixel[3]);
1648           des_b += pixel_weight * src_b;
1649           des_g += pixel_weight * src_g;
1650           des_r += pixel_weight * src_r;
1651         }
1652         *des_scan++ = (uint8_t)((des_b) >> 16);
1653         *des_scan++ = (uint8_t)((des_g) >> 16);
1654         *des_scan++ = (uint8_t)((des_r) >> 16);
1655         des_scan += des_Bpp - 3;
1656       } break;
1657       case 11: {
1658         uint32_t des_alpha = 0, des_r = 0, des_g = 0, des_b = 0;
1659         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1660              j++) {
1661           int pixel_weight =
1662               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1663           const uint8_t* src_pixel = src_scan + j * src_Bpp;
1664           pixel_weight = pixel_weight * src_pixel[3] / 255;
1665           des_b += pixel_weight * (*src_pixel++);
1666           des_g += pixel_weight * (*src_pixel++);
1667           des_r += pixel_weight * (*src_pixel);
1668           des_alpha += pixel_weight;
1669         }
1670         *des_scan++ = (uint8_t)((des_b) >> 16);
1671         *des_scan++ = (uint8_t)((des_g) >> 16);
1672         *des_scan++ = (uint8_t)((des_r) >> 16);
1673         *des_scan++ = (uint8_t)((des_alpha * 255) >> 16);
1674       } break;
1675       default:
1676         return;
1677     }
1678   }
1679 }
1680 
ResampleVert(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,double scale_y,int des_row)1681 void CCodec_ProgressiveDecoder::ResampleVert(
1682     const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1683     double scale_y,
1684     int des_row) {
1685   int des_Bpp = pDeviceBitmap->GetBPP() >> 3;
1686   uint32_t des_ScanOffet = m_startX * des_Bpp;
1687   int des_top = m_startY;
1688   pdfium::base::CheckedNumeric<int> check_des_row_1 = des_row;
1689   check_des_row_1 -= pdfium::base::checked_cast<int>(scale_y);
1690   int des_row_1 = check_des_row_1.ValueOrDie();
1691   if (des_row_1 < des_top) {
1692     int des_bottom = des_top + m_sizeY;
1693     if (des_row + (int)scale_y >= des_bottom - 1) {
1694       uint8_t* scan_src =
1695           (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
1696       while (++des_row < des_bottom) {
1697         uint8_t* scan_des =
1698             (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
1699         uint32_t size = m_sizeX * des_Bpp;
1700         memmove(scan_des, scan_src, size);
1701       }
1702     }
1703     return;
1704   }
1705   for (; des_row_1 < des_row; des_row_1++) {
1706     uint8_t* scan_des =
1707         (uint8_t*)pDeviceBitmap->GetScanline(des_row_1) + des_ScanOffet;
1708     PixelWeight* pWeight = m_WeightVert.GetPixelWeight(des_row_1 - des_top);
1709     const uint8_t* scan_src1 =
1710         pDeviceBitmap->GetScanline(pWeight->m_SrcStart + des_top) +
1711         des_ScanOffet;
1712     const uint8_t* scan_src2 =
1713         pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + des_top) + des_ScanOffet;
1714     for (int des_col = 0; des_col < m_sizeX; des_col++) {
1715       switch (pDeviceBitmap->GetFormat()) {
1716         case FXDIB_Invalid:
1717         case FXDIB_1bppMask:
1718         case FXDIB_1bppRgb:
1719           return;
1720         case FXDIB_8bppMask:
1721         case FXDIB_8bppRgb: {
1722           if (pDeviceBitmap->GetPalette()) {
1723             return;
1724           }
1725           int des_g = 0;
1726           des_g += pWeight->m_Weights[0] * (*scan_src1++);
1727           des_g += pWeight->m_Weights[1] * (*scan_src2++);
1728           *scan_des++ = (uint8_t)(des_g >> 16);
1729         } break;
1730         case FXDIB_Rgb:
1731         case FXDIB_Rgb32: {
1732           uint32_t des_b = 0, des_g = 0, des_r = 0;
1733           des_b += pWeight->m_Weights[0] * (*scan_src1++);
1734           des_g += pWeight->m_Weights[0] * (*scan_src1++);
1735           des_r += pWeight->m_Weights[0] * (*scan_src1++);
1736           scan_src1 += des_Bpp - 3;
1737           des_b += pWeight->m_Weights[1] * (*scan_src2++);
1738           des_g += pWeight->m_Weights[1] * (*scan_src2++);
1739           des_r += pWeight->m_Weights[1] * (*scan_src2++);
1740           scan_src2 += des_Bpp - 3;
1741           *scan_des++ = (uint8_t)((des_b) >> 16);
1742           *scan_des++ = (uint8_t)((des_g) >> 16);
1743           *scan_des++ = (uint8_t)((des_r) >> 16);
1744           scan_des += des_Bpp - 3;
1745         } break;
1746         case FXDIB_Argb: {
1747           uint32_t des_a = 0, des_b = 0, des_g = 0, des_r = 0;
1748           des_b += pWeight->m_Weights[0] * (*scan_src1++);
1749           des_g += pWeight->m_Weights[0] * (*scan_src1++);
1750           des_r += pWeight->m_Weights[0] * (*scan_src1++);
1751           des_a += pWeight->m_Weights[0] * (*scan_src1++);
1752           des_b += pWeight->m_Weights[1] * (*scan_src2++);
1753           des_g += pWeight->m_Weights[1] * (*scan_src2++);
1754           des_r += pWeight->m_Weights[1] * (*scan_src2++);
1755           des_a += pWeight->m_Weights[1] * (*scan_src2++);
1756           *scan_des++ = (uint8_t)((des_b) >> 16);
1757           *scan_des++ = (uint8_t)((des_g) >> 16);
1758           *scan_des++ = (uint8_t)((des_r) >> 16);
1759           *scan_des++ = (uint8_t)((des_a) >> 16);
1760         } break;
1761         default:
1762           return;
1763       }
1764     }
1765   }
1766   int des_bottom = des_top + m_sizeY;
1767   if (des_row + (int)scale_y >= des_bottom - 1) {
1768     uint8_t* scan_src =
1769         (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
1770     while (++des_row < des_bottom) {
1771       uint8_t* scan_des =
1772           (uint8_t*)pDeviceBitmap->GetScanline(des_row) + des_ScanOffet;
1773       uint32_t size = m_sizeX * des_Bpp;
1774       memmove(scan_des, scan_src, size);
1775     }
1776   }
1777 }
1778 
Resample(const RetainPtr<CFX_DIBitmap> & pDeviceBitmap,int32_t src_line,uint8_t * src_scan,FXCodec_Format src_format)1779 void CCodec_ProgressiveDecoder::Resample(
1780     const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1781     int32_t src_line,
1782     uint8_t* src_scan,
1783     FXCodec_Format src_format) {
1784   int src_top = m_clipBox.top;
1785   int des_top = m_startY;
1786   int src_hei = m_clipBox.Height();
1787   int des_hei = m_sizeY;
1788   if (src_line >= src_top) {
1789     double scale_y = (double)des_hei / (double)src_hei;
1790     int src_row = src_line - src_top;
1791     int des_row = (int)(src_row * scale_y) + des_top;
1792     if (des_row >= des_top + des_hei) {
1793       return;
1794     }
1795     ReSampleScanline(pDeviceBitmap, des_row, m_pDecodeBuf, src_format);
1796     if (scale_y > 1.0) {
1797       ResampleVert(pDeviceBitmap, scale_y, des_row);
1798     }
1799   }
1800 }
1801 
GetFrames()1802 std::pair<FXCODEC_STATUS, size_t> CCodec_ProgressiveDecoder::GetFrames() {
1803   if (!(m_status == FXCODEC_STATUS_FRAME_READY ||
1804         m_status == FXCODEC_STATUS_FRAME_TOBECONTINUE)) {
1805     return {FXCODEC_STATUS_ERROR, 0};
1806   }
1807 
1808   switch (m_imagType) {
1809     case FXCODEC_IMAGE_JPG:
1810     case FXCODEC_IMAGE_BMP:
1811     case FXCODEC_IMAGE_PNG:
1812     case FXCODEC_IMAGE_TIF:
1813       m_FrameNumber = 1;
1814       m_status = FXCODEC_STATUS_DECODE_READY;
1815       return {m_status, 1};
1816     case FXCODEC_IMAGE_GIF: {
1817       CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule();
1818       if (!pGifModule) {
1819         m_status = FXCODEC_STATUS_ERR_MEMORY;
1820         return {m_status, 0};
1821       }
1822       while (true) {
1823         CFX_GifDecodeStatus readResult;
1824         std::tie(readResult, m_FrameNumber) =
1825             pGifModule->LoadFrameInfo(m_pGifContext.get());
1826         while (readResult == CFX_GifDecodeStatus::Unfinished) {
1827           FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_READ;
1828           if (!GifReadMoreData(pGifModule, error_status))
1829             return {error_status, 0};
1830 
1831           std::tie(readResult, m_FrameNumber) =
1832               pGifModule->LoadFrameInfo(m_pGifContext.get());
1833         }
1834         if (readResult == CFX_GifDecodeStatus::Success) {
1835           m_status = FXCODEC_STATUS_DECODE_READY;
1836           return {m_status, m_FrameNumber};
1837         }
1838         m_pGifContext = nullptr;
1839         m_status = FXCODEC_STATUS_ERROR;
1840         return {m_status, 0};
1841       }
1842     }
1843     default:
1844       return {FXCODEC_STATUS_ERROR, 0};
1845   }
1846 }
1847 
StartDecode(const RetainPtr<CFX_DIBitmap> & pDIBitmap,int start_x,int start_y,int size_x,int size_y)1848 FXCODEC_STATUS CCodec_ProgressiveDecoder::StartDecode(
1849     const RetainPtr<CFX_DIBitmap>& pDIBitmap,
1850     int start_x,
1851     int start_y,
1852     int size_x,
1853     int size_y) {
1854   if (m_status != FXCODEC_STATUS_DECODE_READY)
1855     return FXCODEC_STATUS_ERROR;
1856 
1857   if (!pDIBitmap || pDIBitmap->GetBPP() < 8 || m_FrameNumber == 0)
1858     return FXCODEC_STATUS_ERR_PARAMS;
1859 
1860   m_pDeviceBitmap = pDIBitmap;
1861   if (m_clipBox.IsEmpty())
1862     return FXCODEC_STATUS_ERR_PARAMS;
1863   if (size_x <= 0 || size_x > 65535 || size_y <= 0 || size_y > 65535)
1864     return FXCODEC_STATUS_ERR_PARAMS;
1865 
1866   FX_RECT device_rc =
1867       FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y);
1868   int32_t out_range_x = device_rc.right - pDIBitmap->GetWidth();
1869   int32_t out_range_y = device_rc.bottom - pDIBitmap->GetHeight();
1870   device_rc.Intersect(
1871       FX_RECT(0, 0, pDIBitmap->GetWidth(), pDIBitmap->GetHeight()));
1872   if (device_rc.IsEmpty())
1873     return FXCODEC_STATUS_ERR_PARAMS;
1874 
1875   m_startX = device_rc.left;
1876   m_startY = device_rc.top;
1877   m_sizeX = device_rc.Width();
1878   m_sizeY = device_rc.Height();
1879   m_FrameCur = 0;
1880   if (start_x < 0 || out_range_x > 0) {
1881     float scaleX = (float)m_clipBox.Width() / (float)size_x;
1882     if (start_x < 0) {
1883       m_clipBox.left -= (int32_t)ceil((float)start_x * scaleX);
1884     }
1885     if (out_range_x > 0) {
1886       m_clipBox.right -= (int32_t)floor((float)out_range_x * scaleX);
1887     }
1888   }
1889   if (start_y < 0 || out_range_y > 0) {
1890     float scaleY = (float)m_clipBox.Height() / (float)size_y;
1891     if (start_y < 0) {
1892       m_clipBox.top -= (int32_t)ceil((float)start_y * scaleY);
1893     }
1894     if (out_range_y > 0) {
1895       m_clipBox.bottom -= (int32_t)floor((float)out_range_y * scaleY);
1896     }
1897   }
1898   if (m_clipBox.IsEmpty()) {
1899     return FXCODEC_STATUS_ERR_PARAMS;
1900   }
1901   switch (m_imagType) {
1902     case FXCODEC_IMAGE_JPG:
1903       return JpegStartDecode(pDIBitmap);
1904     case FXCODEC_IMAGE_PNG:
1905       return PngStartDecode(pDIBitmap);
1906     case FXCODEC_IMAGE_GIF:
1907       return GifStartDecode(pDIBitmap);
1908     case FXCODEC_IMAGE_BMP:
1909       return BmpStartDecode(pDIBitmap);
1910     case FXCODEC_IMAGE_TIF:
1911       m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
1912       return m_status;
1913     default:
1914       return FXCODEC_STATUS_ERROR;
1915   }
1916 }
1917 
JpegStartDecode(const RetainPtr<CFX_DIBitmap> & pDIBitmap)1918 FXCODEC_STATUS CCodec_ProgressiveDecoder::JpegStartDecode(
1919     const RetainPtr<CFX_DIBitmap>& pDIBitmap) {
1920   int down_scale = 1;
1921   GetDownScale(down_scale);
1922   // Setting jump marker before calling StartScanLine, since a longjmp to
1923   // the marker indicates a fatal error.
1924   if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) {
1925     m_pJpegContext.reset();
1926     m_status = FXCODEC_STATUS_ERROR;
1927     return FXCODEC_STATUS_ERROR;
1928   }
1929 
1930   CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
1931   bool startStatus =
1932       pJpegModule->StartScanline(m_pJpegContext.get(), down_scale);
1933   while (!startStatus) {
1934     FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR;
1935     if (!JpegReadMoreData(pJpegModule, error_status)) {
1936       m_pDeviceBitmap = nullptr;
1937       m_pFile = nullptr;
1938       m_status = error_status;
1939       return m_status;
1940     }
1941 
1942     startStatus = pJpegModule->StartScanline(m_pJpegContext.get(), down_scale);
1943   }
1944   int scanline_size = (m_SrcWidth + down_scale - 1) / down_scale;
1945   scanline_size = (scanline_size * m_SrcComponents + 3) / 4 * 4;
1946   FX_Free(m_pDecodeBuf);
1947   m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size);
1948   memset(m_pDecodeBuf, 0, scanline_size);
1949   m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0,
1950                     m_clipBox.Width());
1951   m_WeightVert.Calc(m_sizeY, m_clipBox.Height());
1952   switch (m_SrcComponents) {
1953     case 1:
1954       m_SrcFormat = FXCodec_8bppGray;
1955       break;
1956     case 3:
1957       m_SrcFormat = FXCodec_Rgb;
1958       break;
1959     case 4:
1960       m_SrcFormat = FXCodec_Cmyk;
1961       break;
1962   }
1963   GetTransMethod(pDIBitmap->GetFormat(), m_SrcFormat);
1964   m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
1965   return m_status;
1966 }
1967 
PngStartDecode(const RetainPtr<CFX_DIBitmap> & pDIBitmap)1968 FXCODEC_STATUS CCodec_ProgressiveDecoder::PngStartDecode(
1969     const RetainPtr<CFX_DIBitmap>& pDIBitmap) {
1970   CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule();
1971   if (!pPngModule) {
1972     m_pDeviceBitmap = nullptr;
1973     m_pFile = nullptr;
1974     m_status = FXCODEC_STATUS_ERR_MEMORY;
1975     return m_status;
1976   }
1977   m_pPngContext = pPngModule->Start(this);
1978   if (!m_pPngContext) {
1979     m_pDeviceBitmap = nullptr;
1980     m_pFile = nullptr;
1981     m_status = FXCODEC_STATUS_ERR_MEMORY;
1982     return m_status;
1983   }
1984   m_offSet = 0;
1985   switch (m_pDeviceBitmap->GetFormat()) {
1986     case FXDIB_8bppMask:
1987     case FXDIB_8bppRgb:
1988       m_SrcComponents = 1;
1989       m_SrcFormat = FXCodec_8bppGray;
1990       break;
1991     case FXDIB_Rgb:
1992       m_SrcComponents = 3;
1993       m_SrcFormat = FXCodec_Rgb;
1994       break;
1995     case FXDIB_Rgb32:
1996     case FXDIB_Argb:
1997       m_SrcComponents = 4;
1998       m_SrcFormat = FXCodec_Argb;
1999       break;
2000     default: {
2001       m_pDeviceBitmap = nullptr;
2002       m_pFile = nullptr;
2003       m_status = FXCODEC_STATUS_ERR_PARAMS;
2004       return m_status;
2005     }
2006   }
2007   GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
2008   int scanline_size = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4;
2009   FX_Free(m_pDecodeBuf);
2010   m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size);
2011   memset(m_pDecodeBuf, 0, scanline_size);
2012   m_WeightHorzOO.Calc(m_sizeX, m_clipBox.Width());
2013   m_WeightVert.Calc(m_sizeY, m_clipBox.Height());
2014   m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
2015   return m_status;
2016 }
2017 
GifStartDecode(const RetainPtr<CFX_DIBitmap> & pDIBitmap)2018 FXCODEC_STATUS CCodec_ProgressiveDecoder::GifStartDecode(
2019     const RetainPtr<CFX_DIBitmap>& pDIBitmap) {
2020   CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule();
2021   if (!pGifModule) {
2022     m_pDeviceBitmap = nullptr;
2023     m_pFile = nullptr;
2024     m_status = FXCODEC_STATUS_ERR_MEMORY;
2025     return m_status;
2026   }
2027   m_SrcFormat = FXCodec_8bppRgb;
2028   GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
2029   int scanline_size = (m_SrcWidth + 3) / 4 * 4;
2030   FX_Free(m_pDecodeBuf);
2031   m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size);
2032   memset(m_pDecodeBuf, 0, scanline_size);
2033   m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0,
2034                     m_clipBox.Width());
2035   m_WeightVert.Calc(m_sizeY, m_clipBox.Height());
2036   m_FrameCur = 0;
2037   m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
2038   return m_status;
2039 }
2040 
BmpStartDecode(const RetainPtr<CFX_DIBitmap> & pDIBitmap)2041 FXCODEC_STATUS CCodec_ProgressiveDecoder::BmpStartDecode(
2042     const RetainPtr<CFX_DIBitmap>& pDIBitmap) {
2043   CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule();
2044   if (!pBmpModule) {
2045     m_pDeviceBitmap = nullptr;
2046     m_pFile = nullptr;
2047     m_status = FXCODEC_STATUS_ERR_MEMORY;
2048     return m_status;
2049   }
2050   GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat);
2051   m_ScanlineSize = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4;
2052   FX_Free(m_pDecodeBuf);
2053   m_pDecodeBuf = FX_Alloc(uint8_t, m_ScanlineSize);
2054   memset(m_pDecodeBuf, 0, m_ScanlineSize);
2055   m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0,
2056                     m_clipBox.Width());
2057   m_WeightVert.Calc(m_sizeY, m_clipBox.Height());
2058   m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE;
2059   return m_status;
2060 }
2061 
ContinueDecode()2062 FXCODEC_STATUS CCodec_ProgressiveDecoder::ContinueDecode() {
2063   if (m_status != FXCODEC_STATUS_DECODE_TOBECONTINUE)
2064     return FXCODEC_STATUS_ERROR;
2065 
2066   switch (m_imagType) {
2067     case FXCODEC_IMAGE_JPG:
2068       return JpegContinueDecode();
2069     case FXCODEC_IMAGE_PNG:
2070       return PngContinueDecode();
2071     case FXCODEC_IMAGE_GIF:
2072       return GifContinueDecode();
2073     case FXCODEC_IMAGE_BMP:
2074       return BmpContinueDecode();
2075     case FXCODEC_IMAGE_TIF:
2076       return TifContinueDecode();
2077     default:
2078       return FXCODEC_STATUS_ERROR;
2079   }
2080 }
2081 
JpegContinueDecode()2082 FXCODEC_STATUS CCodec_ProgressiveDecoder::JpegContinueDecode() {
2083   CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule();
2084   // Setting jump marker before calling ReadScanLine, since a longjmp to
2085   // the marker indicates a fatal error.
2086   if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) {
2087     m_pJpegContext.reset();
2088     m_status = FXCODEC_STATUS_ERROR;
2089     return FXCODEC_STATUS_ERROR;
2090   }
2091 
2092   while (true) {
2093     bool readRes =
2094         pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf);
2095     while (!readRes) {
2096       FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH;
2097       if (!JpegReadMoreData(pJpegModule, error_status)) {
2098         m_pDeviceBitmap = nullptr;
2099         m_pFile = nullptr;
2100         m_status = error_status;
2101         return m_status;
2102       }
2103       readRes = pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf);
2104     }
2105     if (m_SrcFormat == FXCodec_Rgb) {
2106       int src_Bpp = (m_SrcFormat & 0xff) >> 3;
2107       RGB2BGR(m_pDecodeBuf + m_clipBox.left * src_Bpp, m_clipBox.Width());
2108     }
2109     if (m_SrcRow >= m_clipBox.bottom) {
2110       m_pDeviceBitmap = nullptr;
2111       m_pFile = nullptr;
2112       m_status = FXCODEC_STATUS_DECODE_FINISH;
2113       return m_status;
2114     }
2115     Resample(m_pDeviceBitmap, m_SrcRow, m_pDecodeBuf, m_SrcFormat);
2116     m_SrcRow++;
2117   }
2118 }
2119 
PngContinueDecode()2120 FXCODEC_STATUS CCodec_ProgressiveDecoder::PngContinueDecode() {
2121   CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule();
2122   if (!pPngModule) {
2123     m_status = FXCODEC_STATUS_ERR_MEMORY;
2124     return m_status;
2125   }
2126   while (true) {
2127     uint32_t remain_size = (uint32_t)m_pFile->GetSize() - m_offSet;
2128     uint32_t input_size =
2129         remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size;
2130     if (input_size == 0) {
2131       m_pPngContext.reset();
2132       m_pDeviceBitmap = nullptr;
2133       m_pFile = nullptr;
2134       m_status = FXCODEC_STATUS_DECODE_FINISH;
2135       return m_status;
2136     }
2137     if (m_pSrcBuf && input_size > m_SrcSize) {
2138       FX_Free(m_pSrcBuf);
2139       m_pSrcBuf = FX_Alloc(uint8_t, input_size);
2140       memset(m_pSrcBuf, 0, input_size);
2141       m_SrcSize = input_size;
2142     }
2143     bool bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size);
2144     if (!bResult) {
2145       m_pDeviceBitmap = nullptr;
2146       m_pFile = nullptr;
2147       m_status = FXCODEC_STATUS_ERR_READ;
2148       return m_status;
2149     }
2150     m_offSet += input_size;
2151     bResult =
2152         pPngModule->Input(m_pPngContext.get(), m_pSrcBuf, input_size, nullptr);
2153     if (!bResult) {
2154       m_pDeviceBitmap = nullptr;
2155       m_pFile = nullptr;
2156       m_status = FXCODEC_STATUS_ERROR;
2157       return m_status;
2158     }
2159   }
2160 }
2161 
GifContinueDecode()2162 FXCODEC_STATUS CCodec_ProgressiveDecoder::GifContinueDecode() {
2163   CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule();
2164   if (!pGifModule) {
2165     m_pDeviceBitmap = nullptr;
2166     m_pFile = nullptr;
2167     m_status = FXCODEC_STATUS_ERR_MEMORY;
2168     return m_status;
2169   }
2170 
2171   CFX_GifDecodeStatus readRes =
2172       pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr);
2173   while (readRes == CFX_GifDecodeStatus::Unfinished) {
2174     FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH;
2175     if (!GifReadMoreData(pGifModule, error_status)) {
2176       m_pDeviceBitmap = nullptr;
2177       m_pFile = nullptr;
2178       m_status = error_status;
2179       return m_status;
2180     }
2181     readRes = pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr);
2182   }
2183 
2184   if (readRes == CFX_GifDecodeStatus::Success) {
2185     m_pDeviceBitmap = nullptr;
2186     m_pFile = nullptr;
2187     m_status = FXCODEC_STATUS_DECODE_FINISH;
2188     return m_status;
2189   }
2190 
2191   m_pDeviceBitmap = nullptr;
2192   m_pFile = nullptr;
2193   m_status = FXCODEC_STATUS_ERROR;
2194   return m_status;
2195 }
2196 
BmpContinueDecode()2197 FXCODEC_STATUS CCodec_ProgressiveDecoder::BmpContinueDecode() {
2198   CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule();
2199   if (!pBmpModule) {
2200     m_status = FXCODEC_STATUS_ERR_MEMORY;
2201     return m_status;
2202   }
2203   while (true) {
2204     int32_t readRes = pBmpModule->LoadImage(m_pBmpContext.get());
2205     while (readRes == 2) {
2206       FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH;
2207       if (!BmpReadMoreData(pBmpModule, error_status)) {
2208         m_pDeviceBitmap = nullptr;
2209         m_pFile = nullptr;
2210         m_status = error_status;
2211         return m_status;
2212       }
2213       readRes = pBmpModule->LoadImage(m_pBmpContext.get());
2214     }
2215     if (readRes == 1) {
2216       m_pDeviceBitmap = nullptr;
2217       m_pFile = nullptr;
2218       m_status = FXCODEC_STATUS_DECODE_FINISH;
2219       return m_status;
2220     }
2221     m_pDeviceBitmap = nullptr;
2222     m_pFile = nullptr;
2223     m_status = FXCODEC_STATUS_ERROR;
2224     return m_status;
2225   }
2226 }
2227 
TifContinueDecode()2228 FXCODEC_STATUS CCodec_ProgressiveDecoder::TifContinueDecode() {
2229   CCodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule();
2230   if (!pTiffModule) {
2231     m_status = FXCODEC_STATUS_ERR_MEMORY;
2232     return m_status;
2233   }
2234   bool ret = false;
2235   if (m_pDeviceBitmap->GetBPP() == 32 &&
2236       m_pDeviceBitmap->GetWidth() == m_SrcWidth && m_SrcWidth == m_sizeX &&
2237       m_pDeviceBitmap->GetHeight() == m_SrcHeight && m_SrcHeight == m_sizeY &&
2238       m_startX == 0 && m_startY == 0 && m_clipBox.left == 0 &&
2239       m_clipBox.top == 0 && m_clipBox.right == m_SrcWidth &&
2240       m_clipBox.bottom == m_SrcHeight) {
2241     ret = pTiffModule->Decode(m_pTiffContext.get(), m_pDeviceBitmap);
2242     m_pDeviceBitmap = nullptr;
2243     m_pFile = nullptr;
2244     if (!ret) {
2245       m_status = FXCODEC_STATUS_ERROR;
2246       return m_status;
2247     }
2248     m_status = FXCODEC_STATUS_DECODE_FINISH;
2249     return m_status;
2250   }
2251 
2252   auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
2253   pDIBitmap->Create(m_SrcWidth, m_SrcHeight, FXDIB_Argb);
2254   if (!pDIBitmap->GetBuffer()) {
2255     m_pDeviceBitmap = nullptr;
2256     m_pFile = nullptr;
2257     m_status = FXCODEC_STATUS_ERR_MEMORY;
2258     return m_status;
2259   }
2260   ret = pTiffModule->Decode(m_pTiffContext.get(), pDIBitmap);
2261   if (!ret) {
2262     m_pDeviceBitmap = nullptr;
2263     m_pFile = nullptr;
2264     m_status = FXCODEC_STATUS_ERROR;
2265     return m_status;
2266   }
2267   RetainPtr<CFX_DIBitmap> pClipBitmap =
2268       (m_clipBox.left == 0 && m_clipBox.top == 0 &&
2269        m_clipBox.right == m_SrcWidth && m_clipBox.bottom == m_SrcHeight)
2270           ? pDIBitmap
2271           : pDIBitmap->Clone(&m_clipBox);
2272   if (!pClipBitmap) {
2273     m_pDeviceBitmap = nullptr;
2274     m_pFile = nullptr;
2275     m_status = FXCODEC_STATUS_ERR_MEMORY;
2276     return m_status;
2277   }
2278   RetainPtr<CFX_DIBitmap> pFormatBitmap;
2279   switch (m_pDeviceBitmap->GetFormat()) {
2280     case FXDIB_8bppRgb:
2281       pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
2282       pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
2283                             FXDIB_8bppRgb);
2284       break;
2285     case FXDIB_8bppMask:
2286       pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
2287       pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
2288                             FXDIB_8bppMask);
2289       break;
2290     case FXDIB_Rgb:
2291       pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
2292       pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
2293                             FXDIB_Rgb);
2294       break;
2295     case FXDIB_Rgb32:
2296       pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>();
2297       pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(),
2298                             FXDIB_Rgb32);
2299       break;
2300     case FXDIB_Argb:
2301       pFormatBitmap = pClipBitmap;
2302       break;
2303     default:
2304       break;
2305   }
2306   switch (m_pDeviceBitmap->GetFormat()) {
2307     case FXDIB_8bppRgb:
2308     case FXDIB_8bppMask: {
2309       for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) {
2310         uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row);
2311         uint8_t* des_line = (uint8_t*)pFormatBitmap->GetScanline(row);
2312         for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) {
2313           uint8_t _a = 255 - src_line[3];
2314           uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
2315           uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255;
2316           uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255;
2317           *des_line++ = FXRGB2GRAY(r, g, b);
2318           src_line += 4;
2319         }
2320       }
2321     } break;
2322     case FXDIB_Rgb:
2323     case FXDIB_Rgb32: {
2324       int32_t desBpp = (m_pDeviceBitmap->GetFormat() == FXDIB_Rgb) ? 3 : 4;
2325       for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) {
2326         uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row);
2327         uint8_t* des_line = (uint8_t*)pFormatBitmap->GetScanline(row);
2328         for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) {
2329           uint8_t _a = 255 - src_line[3];
2330           uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
2331           uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255;
2332           uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255;
2333           *des_line++ = b;
2334           *des_line++ = g;
2335           *des_line++ = r;
2336           des_line += desBpp - 3;
2337           src_line += 4;
2338         }
2339       }
2340     } break;
2341     default:
2342       break;
2343   }
2344   if (!pFormatBitmap) {
2345     m_pDeviceBitmap = nullptr;
2346     m_pFile = nullptr;
2347     m_status = FXCODEC_STATUS_ERR_MEMORY;
2348     return m_status;
2349   }
2350   RetainPtr<CFX_DIBitmap> pStrechBitmap =
2351       pFormatBitmap->StretchTo(m_sizeX, m_sizeY, FXDIB_INTERPOL, nullptr);
2352   pFormatBitmap = nullptr;
2353   if (!pStrechBitmap) {
2354     m_pDeviceBitmap = nullptr;
2355     m_pFile = nullptr;
2356     m_status = FXCODEC_STATUS_ERR_MEMORY;
2357     return m_status;
2358   }
2359   m_pDeviceBitmap->TransferBitmap(m_startX, m_startY, m_sizeX, m_sizeY,
2360                                   pStrechBitmap, 0, 0);
2361   m_pDeviceBitmap = nullptr;
2362   m_pFile = nullptr;
2363   m_status = FXCODEC_STATUS_DECODE_FINISH;
2364   return m_status;
2365 }
2366 
2367 std::unique_ptr<CCodec_ProgressiveDecoder>
CreateProgressiveDecoder()2368 CCodec_ModuleMgr::CreateProgressiveDecoder() {
2369   return pdfium::MakeUnique<CCodec_ProgressiveDecoder>(this);
2370 }
2371