blob: 561660ad2093cc7f88318d320d56d7b9e48facb5 [file] [log] [blame]
// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
#ifndef CORE_FXCODEC_PROGRESSIVE_DECODER_H_
#define CORE_FXCODEC_PROGRESSIVE_DECODER_H_
#include <memory>
#include <utility>
#include <vector>
#include "core/fxcodec/fx_codec_def.h"
#include "core/fxcodec/jpeg/jpegmodule.h"
#include "core/fxcodec/progressive_decoder_iface.h"
#include "core/fxcrt/fx_memory_wrappers.h"
#include "core/fxcrt/fx_system.h"
#include "core/fxcrt/retain_ptr.h"
#include "core/fxge/dib/fx_dib.h"
#ifdef PDF_ENABLE_XFA_BMP
#include "core/fxcodec/bmp/bmp_decoder.h"
#endif // PDF_ENABLE_XFA_BMP
#ifdef PDF_ENABLE_XFA_GIF
#include "core/fxcodec/gif/gif_decoder.h"
#endif // PDF_ENABLE_XFA_GIF
#ifdef PDF_ENABLE_XFA_PNG
#include "core/fxcodec/png/png_decoder.h"
#endif // PDF_ENABLE_XFA_PNG
class CFX_DIBitmap;
class IFX_SeekableReadStream;
namespace fxcodec {
class CFX_DIBAttribute;
class Dummy {}; // Placeholder to work around C++ syntax issues
class ProgressiveDecoder :
#ifdef PDF_ENABLE_XFA_BMP
public BmpDecoder::Delegate,
#endif // PDF_ENABLE_XFA_BMP
#ifdef PDF_ENABLE_XFA_GIF
public GifDecoder::Delegate,
#endif // PDF_ENABLE_XFA_GIF
#ifdef PDF_ENABLE_XFA_PNG
public PngDecoder::Delegate,
#endif // PDF_ENABLE_XFA_PNG
public Dummy {
public:
enum FXCodec_Format {
FXCodec_Invalid = 0,
FXCodec_1bppGray = 0x101,
FXCodec_1bppRgb = 0x001,
FXCodec_8bppGray = 0x108,
FXCodec_8bppRgb = 0x008,
FXCodec_Rgb = 0x018,
FXCodec_Rgb32 = 0x020,
FXCodec_Argb = 0x220,
FXCodec_Cmyk = 0x120
};
ProgressiveDecoder();
virtual ~ProgressiveDecoder();
FXCODEC_STATUS LoadImageInfo(const RetainPtr<IFX_SeekableReadStream>& pFile,
FXCODEC_IMAGE_TYPE imageType,
CFX_DIBAttribute* pAttribute,
bool bSkipImageTypeCheck);
FXCODEC_IMAGE_TYPE GetType() const { return m_imageType; }
int32_t GetWidth() const { return m_SrcWidth; }
int32_t GetHeight() const { return m_SrcHeight; }
int32_t GetNumComponents() const { return m_SrcComponents; }
int32_t GetBPC() const { return m_SrcBPC; }
void SetClipBox(FX_RECT* clip);
std::pair<FXCODEC_STATUS, size_t> GetFrames();
FXCODEC_STATUS StartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap,
int start_x,
int start_y,
int size_x,
int size_y);
FXCODEC_STATUS ContinueDecode();
class CFXCODEC_WeightTable {
public:
CFXCODEC_WeightTable();
~CFXCODEC_WeightTable();
void Calc(int dest_len, int src_len);
PixelWeight* GetPixelWeight(int pixel) {
return reinterpret_cast<PixelWeight*>(m_pWeightTables.data() +
(pixel - m_DestMin) * m_ItemSize);
}
int m_DestMin;
int m_ItemSize;
std::vector<uint8_t, FxAllocAllocator<uint8_t>> m_pWeightTables;
};
class CFXCODEC_HorzTable {
public:
CFXCODEC_HorzTable();
~CFXCODEC_HorzTable();
void Calc(int dest_len, int src_len);
PixelWeight* GetPixelWeight(int pixel) {
return reinterpret_cast<PixelWeight*>(m_pWeightTables.data() +
pixel * m_ItemSize);
}
int m_ItemSize;
std::vector<uint8_t, FxAllocAllocator<uint8_t>> m_pWeightTables;
};
class CFXCODEC_VertTable {
public:
CFXCODEC_VertTable();
~CFXCODEC_VertTable();
void Calc(int dest_len, int src_len);
PixelWeight* GetPixelWeight(int pixel) {
return reinterpret_cast<PixelWeight*>(m_pWeightTables.data() +
pixel * m_ItemSize);
}
int m_ItemSize;
std::vector<uint8_t, FxAllocAllocator<uint8_t>> m_pWeightTables;
};
#ifdef PDF_ENABLE_XFA_PNG
// PngDecoder::Delegate
bool PngReadHeader(int width,
int height,
int bpc,
int pass,
int* color_type,
double* gamma) override;
bool PngAskScanlineBuf(int line, uint8_t** pSrcBuf) override;
void PngFillScanlineBufCompleted(int pass, int line) override;
#endif // PDF_ENABLE_XFA_PNG
#ifdef PDF_ENABLE_XFA_GIF
// GifDecoder::Delegate
void GifRecordCurrentPosition(uint32_t& cur_pos) override;
bool GifInputRecordPositionBuf(uint32_t rcd_pos,
const FX_RECT& img_rc,
int32_t pal_num,
CFX_GifPalette* pal_ptr,
int32_t delay_time,
bool user_input,
int32_t trans_index,
int32_t disposal_method,
bool interlace) override;
void GifReadScanline(int32_t row_num, uint8_t* row_buf) override;
#endif // PDF_ENABLE_XFA_GIF
#ifdef PDF_ENABLE_XFA_BMP
// BmpDecoder::Delegate
bool BmpInputImagePositionBuf(uint32_t rcd_pos) override;
void BmpReadScanline(uint32_t row_num,
pdfium::span<const uint8_t> row_buf) override;
#endif // PDF_ENABLE_XFA_BMP
private:
#ifdef PDF_ENABLE_XFA_BMP
bool BmpReadMoreData(ProgressiveDecoderIface::Context* pBmpContext,
FXCODEC_STATUS* err_status);
bool BmpDetectImageTypeInBuffer(CFX_DIBAttribute* pAttribute);
FXCODEC_STATUS BmpStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap);
FXCODEC_STATUS BmpContinueDecode();
#endif // PDF_ENABLE_XFA_BMP
#ifdef PDF_ENABLE_XFA_GIF
bool GifReadMoreData(FXCODEC_STATUS* err_status);
bool GifDetectImageTypeInBuffer();
FXCODEC_STATUS GifStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap);
FXCODEC_STATUS GifContinueDecode();
void GifDoubleLineResampleVert(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
double scale_y,
int dest_row);
#endif // PDF_ENABLE_XFA_GIF
#ifdef PDF_ENABLE_XFA_PNG
void PngOneOneMapResampleHorz(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
int32_t dest_line,
uint8_t* src_scan,
FXCodec_Format src_format);
bool PngDetectImageTypeInBuffer(CFX_DIBAttribute* pAttribute);
FXCODEC_STATUS PngStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap);
FXCODEC_STATUS PngContinueDecode();
#endif // PDF_ENABLE_XFA_PNG
#ifdef PDF_ENABLE_XFA_TIFF
bool TiffDetectImageTypeFromFile(CFX_DIBAttribute* pAttribute);
FXCODEC_STATUS TiffContinueDecode();
#endif // PDF_ENABLE_XFA_TIFF
bool JpegReadMoreData(FXCODEC_STATUS* err_status);
bool JpegDetectImageTypeInBuffer(CFX_DIBAttribute* pAttribute);
FXCODEC_STATUS JpegStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap);
FXCODEC_STATUS JpegContinueDecode();
bool DetectImageType(FXCODEC_IMAGE_TYPE imageType,
CFX_DIBAttribute* pAttribute);
bool ReadMoreData(ProgressiveDecoderIface* pModule,
ProgressiveDecoderIface::Context* pContext,
bool invalidate_buffer,
FXCODEC_STATUS* err_status);
int GetDownScale();
void GetTransMethod(FXDIB_Format dest_format, FXCodec_Format src_format);
void ReSampleScanline(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
int32_t dest_line,
uint8_t* src_scan,
FXCodec_Format src_format);
void Resample(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
int32_t src_line,
uint8_t* src_scan,
FXCodec_Format src_format);
void ResampleVert(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
double scale_y,
int dest_row);
void ResampleVertBT(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
double scale_y,
int dest_row);
FXCODEC_STATUS m_status = FXCODEC_STATUS_DECODE_FINISH;
FXCODEC_IMAGE_TYPE m_imageType = FXCODEC_IMAGE_UNKNOWN;
RetainPtr<IFX_SeekableReadStream> m_pFile;
RetainPtr<CFX_DIBitmap> m_pDeviceBitmap;
RetainPtr<CFX_CodecMemory> m_pCodecMemory;
std::unique_ptr<uint8_t, FxFreeDeleter> m_pDecodeBuf;
std::unique_ptr<FX_ARGB, FxFreeDeleter> m_pSrcPalette;
std::unique_ptr<ProgressiveDecoderIface::Context> m_pJpegContext;
#ifdef PDF_ENABLE_XFA_BMP
std::unique_ptr<ProgressiveDecoderIface::Context> m_pBmpContext;
#endif // PDF_ENABLE_XFA_BMP
#ifdef PDF_ENABLE_XFA_GIF
std::unique_ptr<ProgressiveDecoderIface::Context> m_pGifContext;
#endif // PDF_ENABLE_XFA_GIF
#ifdef PDF_ENABLE_XFA_PNG
std::unique_ptr<ProgressiveDecoderIface::Context> m_pPngContext;
#endif // PDF_ENABLE_XFA_PNG
#ifdef PDF_ENABLE_XFA_TIFF
std::unique_ptr<ProgressiveDecoderIface::Context> m_pTiffContext;
#endif // PDF_ENABLE_XFA_TIFF
uint32_t m_offSet = 0;
int m_ScanlineSize = 0;
CFXCODEC_WeightTable m_WeightHorz;
CFXCODEC_VertTable m_WeightVert;
CFXCODEC_HorzTable m_WeightHorzOO;
int m_SrcWidth = 0;
int m_SrcHeight = 0;
int m_SrcComponents = 0;
int m_SrcBPC = 0;
FX_RECT m_clipBox;
int m_startX = 0;
int m_startY = 0;
int m_sizeX = 0;
int m_sizeY = 0;
int m_TransMethod = -1;
int m_SrcPaletteNumber = 0;
int m_SrcRow = 0;
FXCodec_Format m_SrcFormat = FXCodec_Invalid;
int m_SrcPassNumber = 0;
size_t m_FrameNumber = 0;
size_t m_FrameCur = 0;
#ifdef PDF_ENABLE_XFA_GIF
int m_GifBgIndex = 0;
CFX_GifPalette* m_pGifPalette = nullptr;
int32_t m_GifPltNumber = 0;
int m_GifTransIndex = -1;
FX_RECT m_GifFrameRect;
bool m_InvalidateGifBuffer = true;
#endif // PDF_ENABLE_XFA_GIF
#ifdef PDF_ENABLE_XFA_BMP
bool m_BmpIsTopBottom = false;
#endif // PDF_ENABLE_XFA_BMP
};
} // namespace fxcodec
using ProgressiveDecoder = fxcodec::ProgressiveDecoder;
#endif // CORE_FXCODEC_PROGRESSIVE_DECODER_H_