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 #ifndef CORE_FXCODEC_PROGRESSIVEDECODER_H_
8 #define CORE_FXCODEC_PROGRESSIVEDECODER_H_
9 
10 #include <memory>
11 #include <utility>
12 #include <vector>
13 
14 #include "core/fxcodec/fx_codec_def.h"
15 #include "core/fxcodec/jpeg/jpegmodule.h"
16 #include "core/fxcrt/fx_memory_wrappers.h"
17 #include "core/fxcrt/fx_system.h"
18 #include "core/fxcrt/retain_ptr.h"
19 #include "core/fxcrt/unowned_ptr.h"
20 #include "core/fxge/fx_dib.h"
21 
22 #ifdef PDF_ENABLE_XFA_BMP
23 #include "core/fxcodec/bmp/bmpmodule.h"
24 #endif  // PDF_ENABLE_XFA_BMP
25 
26 #ifdef PDF_ENABLE_XFA_GIF
27 #include "core/fxcodec/gif/gifmodule.h"
28 #endif  // PDF_ENABLE_XFA_GIF
29 
30 #ifdef PDF_ENABLE_XFA_PNG
31 #include "core/fxcodec/png/pngmodule.h"
32 #endif  // PDF_ENABLE_XFA_PNG
33 
34 #ifdef PDF_ENABLE_XFA_TIFF
35 #include "core/fxcodec/tiff/tiffmodule.h"
36 #endif  // PDF_ENABLE_XFA_TIFF
37 
38 class CFX_DIBitmap;
39 class IFX_SeekableReadStream;
40 
41 namespace fxcodec {
42 
43 class CFX_DIBAttribute;
44 class ModuleMgr;
45 
46 class Dummy {};  // Placeholder to work around C++ syntax issues
47 
48 class ProgressiveDecoder :
49 #ifdef PDF_ENABLE_XFA_BMP
50     public BmpModule::Delegate,
51 #endif  // PDF_ENABLE_XFA_BMP
52 #ifdef PDF_ENABLE_XFA_GIF
53     public GifModule::Delegate,
54 #endif  // PDF_ENABLE_XFA_GIF
55 #ifdef PDF_ENABLE_XFA_PNG
56     public PngModule::Delegate,
57 #endif  // PDF_ENABLE_XFA_PNG
58     public Dummy {
59  public:
60   enum FXCodec_Format {
61     FXCodec_Invalid = 0,
62     FXCodec_1bppGray = 0x101,
63     FXCodec_1bppRgb = 0x001,
64     FXCodec_8bppGray = 0x108,
65     FXCodec_8bppRgb = 0x008,
66     FXCodec_Rgb = 0x018,
67     FXCodec_Rgb32 = 0x020,
68     FXCodec_Argb = 0x220,
69     FXCodec_Cmyk = 0x120
70   };
71 
72   explicit ProgressiveDecoder(ModuleMgr* pCodecMgr);
73   virtual ~ProgressiveDecoder();
74 
75   FXCODEC_STATUS LoadImageInfo(const RetainPtr<IFX_SeekableReadStream>& pFile,
76                                FXCODEC_IMAGE_TYPE imageType,
77                                CFX_DIBAttribute* pAttribute,
78                                bool bSkipImageTypeCheck);
79 
GetType()80   FXCODEC_IMAGE_TYPE GetType() const { return m_imageType; }
GetWidth()81   int32_t GetWidth() const { return m_SrcWidth; }
GetHeight()82   int32_t GetHeight() const { return m_SrcHeight; }
GetNumComponents()83   int32_t GetNumComponents() const { return m_SrcComponents; }
GetBPC()84   int32_t GetBPC() const { return m_SrcBPC; }
85   void SetClipBox(FX_RECT* clip);
86 
87   std::pair<FXCODEC_STATUS, size_t> GetFrames();
88   FXCODEC_STATUS StartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap,
89                              int start_x,
90                              int start_y,
91                              int size_x,
92                              int size_y);
93 
94   FXCODEC_STATUS ContinueDecode();
95 
96   struct PixelWeight {
97     int m_SrcStart;
98     int m_SrcEnd;
99     int m_Weights[1];
100   };
101 
102   class CFXCODEC_WeightTable {
103    public:
104     CFXCODEC_WeightTable();
105     ~CFXCODEC_WeightTable();
106 
107     void Calc(int dest_len, int src_len);
GetPixelWeight(int pixel)108     PixelWeight* GetPixelWeight(int pixel) {
109       return reinterpret_cast<PixelWeight*>(m_pWeightTables.data() +
110                                             (pixel - m_DestMin) * m_ItemSize);
111     }
112 
113     int m_DestMin;
114     int m_ItemSize;
115     std::vector<uint8_t> m_pWeightTables;
116   };
117 
118   class CFXCODEC_HorzTable {
119    public:
120     CFXCODEC_HorzTable();
121     ~CFXCODEC_HorzTable();
122 
123     void Calc(int dest_len, int src_len);
GetPixelWeight(int pixel)124     PixelWeight* GetPixelWeight(int pixel) {
125       return reinterpret_cast<PixelWeight*>(m_pWeightTables.data() +
126                                             pixel * m_ItemSize);
127     }
128 
129     int m_ItemSize;
130     std::vector<uint8_t> m_pWeightTables;
131   };
132 
133   class CFXCODEC_VertTable {
134    public:
135     CFXCODEC_VertTable();
136     ~CFXCODEC_VertTable();
137 
138     void Calc(int dest_len, int src_len);
GetPixelWeight(int pixel)139     PixelWeight* GetPixelWeight(int pixel) {
140       return reinterpret_cast<PixelWeight*>(m_pWeightTables.data() +
141                                             pixel * m_ItemSize);
142     }
143     int m_ItemSize;
144     std::vector<uint8_t> m_pWeightTables;
145   };
146 
147 #ifdef PDF_ENABLE_XFA_PNG
148   // PngModule::Delegate
149   bool PngReadHeader(int width,
150                      int height,
151                      int bpc,
152                      int pass,
153                      int* color_type,
154                      double* gamma) override;
155   bool PngAskScanlineBuf(int line, uint8_t** pSrcBuf) override;
156   void PngFillScanlineBufCompleted(int pass, int line) override;
157 #endif  // PDF_ENABLE_XFA_PNG
158 
159 #ifdef PDF_ENABLE_XFA_GIF
160   // GifModule::Delegate
161   void GifRecordCurrentPosition(uint32_t& cur_pos) override;
162   bool GifInputRecordPositionBuf(uint32_t rcd_pos,
163                                  const FX_RECT& img_rc,
164                                  int32_t pal_num,
165                                  CFX_GifPalette* pal_ptr,
166                                  int32_t delay_time,
167                                  bool user_input,
168                                  int32_t trans_index,
169                                  int32_t disposal_method,
170                                  bool interlace) override;
171   void GifReadScanline(int32_t row_num, uint8_t* row_buf) override;
172 #endif  // PDF_ENABLE_XFA_GIF
173 
174 #ifdef PDF_ENABLE_XFA_BMP
175   // BmpModule::Delegate
176   bool BmpInputImagePositionBuf(uint32_t rcd_pos) override;
177   void BmpReadScanline(uint32_t row_num,
178                        pdfium::span<const uint8_t> row_buf) override;
179 #endif  // PDF_ENABLE_XFA_BMP
180 
181  private:
182 #ifdef PDF_ENABLE_XFA_BMP
183   bool BmpReadMoreData(BmpModule* pBmpModule,
184                        ModuleIface::Context* pBmpContext,
185                        FXCODEC_STATUS& err_status);
186   bool BmpDetectImageTypeInBuffer(CFX_DIBAttribute* pAttribute);
187   FXCODEC_STATUS BmpStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap);
188   FXCODEC_STATUS BmpContinueDecode();
189 #endif  // PDF_ENABLE_XFA_BMP
190 
191 #ifdef PDF_ENABLE_XFA_GIF
192   bool GifReadMoreData(GifModule* pGifModule, FXCODEC_STATUS& err_status);
193   bool GifDetectImageTypeInBuffer();
194   FXCODEC_STATUS GifStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap);
195   FXCODEC_STATUS GifContinueDecode();
196   void GifDoubleLineResampleVert(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
197                                  double scale_y,
198                                  int dest_row);
199 #endif  // PDF_ENABLE_XFA_GIF
200 
201 #ifdef PDF_ENABLE_XFA_PNG
202   void PngOneOneMapResampleHorz(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
203                                 int32_t dest_line,
204                                 uint8_t* src_scan,
205                                 FXCodec_Format src_format);
206   bool PngDetectImageTypeInBuffer(CFX_DIBAttribute* pAttribute);
207   FXCODEC_STATUS PngStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap);
208   FXCODEC_STATUS PngContinueDecode();
209 #endif  // PDF_ENABLE_XFA_PNG
210 
211 #ifdef PDF_ENABLE_XFA_TIFF
212   bool TiffDetectImageTypeFromFile(CFX_DIBAttribute* pAttribute);
213   FXCODEC_STATUS TiffContinueDecode();
214 #endif  // PDF_ENABLE_XFA_TIFF
215 
216   bool JpegReadMoreData(JpegModule* pJpegModule, FXCODEC_STATUS& err_status);
217   bool JpegDetectImageTypeInBuffer(CFX_DIBAttribute* pAttribute);
218   FXCODEC_STATUS JpegStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap);
219   FXCODEC_STATUS JpegContinueDecode();
220 
221   bool DetectImageType(FXCODEC_IMAGE_TYPE imageType,
222                        CFX_DIBAttribute* pAttribute);
223   bool ReadMoreData(ModuleIface* pModule,
224                     ModuleIface::Context* pContext,
225                     bool invalidate_buffer,
226                     FXCODEC_STATUS& err_status);
227 
228   void GetDownScale(int& down_scale);
229   void GetTransMethod(FXDIB_Format dest_format, FXCodec_Format src_format);
230 
231   void ReSampleScanline(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
232                         int32_t dest_line,
233                         uint8_t* src_scan,
234                         FXCodec_Format src_format);
235   void Resample(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
236                 int32_t src_line,
237                 uint8_t* src_scan,
238                 FXCodec_Format src_format);
239   void ResampleVert(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
240                     double scale_y,
241                     int dest_row);
242   void ResampleVertBT(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
243                       double scale_y,
244                       int dest_row);
245 
246   FXCODEC_STATUS m_status = FXCODEC_STATUS_DECODE_FINISH;
247   FXCODEC_IMAGE_TYPE m_imageType = FXCODEC_IMAGE_UNKNOWN;
248   RetainPtr<IFX_SeekableReadStream> m_pFile;
249   RetainPtr<CFX_DIBitmap> m_pDeviceBitmap;
250   UnownedPtr<ModuleMgr> m_pCodecMgr;
251   RetainPtr<CFX_CodecMemory> m_pCodecMemory;
252   std::unique_ptr<uint8_t, FxFreeDeleter> m_pDecodeBuf;
253   std::unique_ptr<FX_ARGB, FxFreeDeleter> m_pSrcPalette;
254   std::unique_ptr<ModuleIface::Context> m_pJpegContext;
255 #ifdef PDF_ENABLE_XFA_BMP
256   std::unique_ptr<ModuleIface::Context> m_pBmpContext;
257 #endif  // PDF_ENABLE_XFA_BMP
258 #ifdef PDF_ENABLE_XFA_GIF
259   std::unique_ptr<ModuleIface::Context> m_pGifContext;
260 #endif  // PDF_ENABLE_XFA_GIF
261 #ifdef PDF_ENABLE_XFA_PNG
262   std::unique_ptr<ModuleIface::Context> m_pPngContext;
263 #endif  // PDF_ENABLE_XFA_PNG
264 #ifdef PDF_ENABLE_XFA_TIFF
265   std::unique_ptr<ModuleIface::Context> m_pTiffContext;
266 #endif  // PDF_ENABLE_XFA_TIFF
267   uint32_t m_offSet = 0;
268   int m_ScanlineSize = 0;
269   CFXCODEC_WeightTable m_WeightHorz;
270   CFXCODEC_VertTable m_WeightVert;
271   CFXCODEC_HorzTable m_WeightHorzOO;
272   int m_SrcWidth = 0;
273   int m_SrcHeight = 0;
274   int m_SrcComponents = 0;
275   int m_SrcBPC = 0;
276   FX_RECT m_clipBox;
277   int m_startX = 0;
278   int m_startY = 0;
279   int m_sizeX = 0;
280   int m_sizeY = 0;
281   int m_TransMethod = -1;
282   int m_SrcPaletteNumber = 0;
283   int m_SrcRow = 0;
284   FXCodec_Format m_SrcFormat = FXCodec_Invalid;
285   int m_SrcPassNumber = 0;
286   size_t m_FrameNumber = 0;
287   size_t m_FrameCur = 0;
288 #ifdef PDF_ENABLE_XFA_GIF
289   int m_GifBgIndex = 0;
290   CFX_GifPalette* m_pGifPalette = nullptr;
291   int32_t m_GifPltNumber = 0;
292   int m_GifTransIndex = -1;
293   FX_RECT m_GifFrameRect;
294   bool m_InvalidateGifBuffer = true;
295 #endif  // PDF_ENABLE_XFA_GIF
296 #ifdef PDF_ENABLE_XFA_BMP
297   bool m_BmpIsTopBottom = false;
298 #endif  // PDF_ENABLE_XFA_BMP
299 };
300 
301 }  // namespace fxcodec
302 
303 using ProgressiveDecoder = fxcodec::ProgressiveDecoder;
304 
305 #endif  // CORE_FXCODEC_PROGRESSIVEDECODER_H_
306