From d5d48457dabbe71e7f6b0baf2eaea6aa0dc86736 Mon Sep 17 00:00:00 2001 From: Ryan Harrison Date: Wed, 9 May 2018 20:31:12 +0000 Subject: Do not build PNG when codec is disabled Currently all of the PNG related code is being built when support for the codec is disabled, it just isn't being utilized. Depending on the settings being used, this unneeded code may or may not get stripped during linking. This CL explicitly turns off building the PNG codec code if support for PNG is turned off. BUG=pdfium:1080 Change-Id: I9c5247145fcadbcb1bd2243aa83350304ba421ff Reviewed-on: https://pdfium-review.googlesource.com/32270 Reviewed-by: Tom Sepez Commit-Queue: Ryan Harrison --- core/fxcodec/codec/ccodec_progressivedecoder.h | 61 +- core/fxcodec/codec/fx_codec_progress.cpp | 2281 ++++++++++++------------ core/fxcodec/fx_codec_def.h | 3 + 3 files changed, 1188 insertions(+), 1157 deletions(-) (limited to 'core') diff --git a/core/fxcodec/codec/ccodec_progressivedecoder.h b/core/fxcodec/codec/ccodec_progressivedecoder.h index 9a0136c872..476a7c1b4a 100644 --- a/core/fxcodec/codec/ccodec_progressivedecoder.h +++ b/core/fxcodec/codec/ccodec_progressivedecoder.h @@ -14,7 +14,6 @@ #include "core/fxcodec/codec/ccodec_bmpmodule.h" #include "core/fxcodec/codec/ccodec_gifmodule.h" #include "core/fxcodec/codec/ccodec_jpegmodule.h" -#include "core/fxcodec/codec/ccodec_pngmodule.h" #include "core/fxcodec/fx_codec_def.h" #include "core/fxcrt/fx_system.h" #include "core/fxcrt/retain_ptr.h" @@ -22,6 +21,10 @@ #include "core/fxge/dib/cfx_dibitmap.h" #include "core/fxge/fx_dib.h" +#ifdef PDF_ENABLE_XFA_PNG +#include "core/fxcodec/codec/ccodec_pngmodule.h" +#endif // PDF_ENABLE_XFA_PNG + #ifdef PDF_ENABLE_XFA_TIFF #include "core/fxcodec/codec/ccodec_tiffmodule.h" #endif // PDF_ENABLE_XFA_TIFF @@ -30,9 +33,14 @@ class CCodec_ModuleMgr; class CFX_DIBAttribute; class IFX_SeekableReadStream; +class CCodec_Dummy {}; // Placeholder to work around C++ syntax issues + class CCodec_ProgressiveDecoder : public CCodec_BmpModule::Delegate, public CCodec_GifModule::Delegate, - public CCodec_PngModule::Delegate { +#ifdef PDF_ENABLE_XFA_PNG + public CCodec_PngModule::Delegate, +#endif // PDF_ENABLE_XFA_PNG + public CCodec_Dummy { public: enum FXCodec_Format { FXCodec_Invalid = 0, @@ -126,6 +134,7 @@ class CCodec_ProgressiveDecoder : public CCodec_BmpModule::Delegate, std::vector m_pWeightTables; }; +#ifdef PDF_ENABLE_XFA_PNG // CCodec_PngModule::Delegate bool PngReadHeader(int width, int height, @@ -135,6 +144,7 @@ class CCodec_ProgressiveDecoder : public CCodec_BmpModule::Delegate, double* gamma) override; bool PngAskScanlineBuf(int line, uint8_t** pSrcBuf) override; void PngFillScanlineBufCompleted(int pass, int line) override; +#endif // PDF_ENABLE_XFA_PNG // CCodec_GifModule::Delegate void GifRecordCurrentPosition(uint32_t& cur_pos) override; @@ -157,24 +167,43 @@ class CCodec_ProgressiveDecoder : public CCodec_BmpModule::Delegate, private: bool BmpReadMoreData(CCodec_BmpModule* pBmpModule, FXCODEC_STATUS& err_status); + bool BmpDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); + FXCODEC_STATUS BmpStartDecode(const RetainPtr& pDIBitmap); + FXCODEC_STATUS BmpContinueDecode(); + bool GifReadMoreData(CCodec_GifModule* pGifModule, FXCODEC_STATUS& err_status); + bool GifDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); + FXCODEC_STATUS GifStartDecode(const RetainPtr& pDIBitmap); + FXCODEC_STATUS GifContinueDecode(); + void GifDoubleLineResampleVert(const RetainPtr& pDeviceBitmap, + double scale_y, + int dest_row); + bool JpegReadMoreData(CCodec_JpegModule* pJpegModule, FXCODEC_STATUS& err_status); + bool JpegDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); + FXCODEC_STATUS JpegStartDecode(const RetainPtr& pDIBitmap); + FXCODEC_STATUS JpegContinueDecode(); + +#ifdef PDF_ENABLE_XFA_PNG void PngOneOneMapResampleHorz(const RetainPtr& pDeviceBitmap, int32_t dest_line, uint8_t* src_scan, FXCodec_Format src_format); - bool DetectImageType(FXCODEC_IMAGE_TYPE imageType, - CFX_DIBAttribute* pAttribute); - bool BmpDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); - bool JpegDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); bool PngDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); - bool GifDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); + FXCODEC_STATUS PngStartDecode(const RetainPtr& pDIBitmap); + FXCODEC_STATUS PngContinueDecode(); +#endif // PDF_ENABLE_XFA_PNG + #ifdef PDF_ENABLE_XFA_TIFF bool TiffDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); + FXCODEC_STATUS TiffContinueDecode(); #endif // PDF_ENABLE_XFA_TIFF + bool DetectImageType(FXCODEC_IMAGE_TYPE imageType, + CFX_DIBAttribute* pAttribute); + void GetDownScale(int& down_scale); void GetTransMethod(FXDIB_Format dest_format, FXCodec_Format src_format); @@ -192,28 +221,14 @@ class CCodec_ProgressiveDecoder : public CCodec_BmpModule::Delegate, void ResampleVertBT(const RetainPtr& pDeviceBitmap, double scale_y, int dest_row); - void GifDoubleLineResampleVert(const RetainPtr& pDeviceBitmap, - double scale_y, - int dest_row); - - FXCODEC_STATUS JpegStartDecode(const RetainPtr& pDIBitmap); - FXCODEC_STATUS PngStartDecode(const RetainPtr& pDIBitmap); - FXCODEC_STATUS GifStartDecode(const RetainPtr& pDIBitmap); - FXCODEC_STATUS BmpStartDecode(const RetainPtr& pDIBitmap); - - FXCODEC_STATUS JpegContinueDecode(); - FXCODEC_STATUS PngContinueDecode(); - FXCODEC_STATUS GifContinueDecode(); - FXCODEC_STATUS BmpContinueDecode(); -#ifdef PDF_ENABLE_XFA_TIFF - FXCODEC_STATUS TiffContinueDecode(); -#endif // PDF_ENABLE_XFA_TIFF RetainPtr m_pFile; RetainPtr m_pDeviceBitmap; UnownedPtr m_pCodecMgr; std::unique_ptr m_pJpegContext; +#ifdef PDF_ENABLE_XFA_PNG std::unique_ptr m_pPngContext; +#endif // PDF_ENABLE_XFA_PNG std::unique_ptr m_pGifContext; std::unique_ptr m_pBmpContext; #ifdef PDF_ENABLE_XFA_TIFF diff --git a/core/fxcodec/codec/fx_codec_progress.cpp b/core/fxcodec/codec/fx_codec_progress.cpp index e606c414bb..bfd60acd0e 100644 --- a/core/fxcodec/codec/fx_codec_progress.cpp +++ b/core/fxcodec/codec/fx_codec_progress.cpp @@ -23,11 +23,13 @@ namespace { +#ifdef PDF_ENABLE_XFA_PNG #if _FX_OS_ == _FX_OS_MACOSX_ const double kPngGamma = 1.7; #else // _FX_OS_ == _FX_OS_MACOSX_ const double kPngGamma = 2.2; #endif // _FX_OS_ == _FX_OS_MACOSX_ +#endif // PDF_ENABLE_XFA_PNG void RGB2BGR(uint8_t* buffer, int width = 1) { if (buffer && width > 0) { @@ -288,43 +290,7 @@ CCodec_ProgressiveDecoder::~CCodec_ProgressiveDecoder() { FX_Free(m_pSrcPalette); } -bool CCodec_ProgressiveDecoder::JpegReadMoreData(CCodec_JpegModule* pJpegModule, - FXCODEC_STATUS& err_status) { - uint32_t dwSize = (uint32_t)m_pFile->GetSize(); - if (dwSize <= m_offSet) { - return false; - } - dwSize = dwSize - m_offSet; - uint32_t dwAvail = pJpegModule->GetAvailInput(m_pJpegContext.get(), nullptr); - if (dwAvail == m_SrcSize) { - if (dwSize > FXCODEC_BLOCK_SIZE) { - dwSize = FXCODEC_BLOCK_SIZE; - } - m_SrcSize = (dwSize + dwAvail + FXCODEC_BLOCK_SIZE - 1) / - FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE; - m_pSrcBuf = FX_TryRealloc(uint8_t, m_pSrcBuf, m_SrcSize); - if (!m_pSrcBuf) { - err_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } - } else { - uint32_t dwConsume = m_SrcSize - dwAvail; - if (dwAvail) { - memmove(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); - } - if (dwSize > dwConsume) { - dwSize = dwConsume; - } - } - if (!m_pFile->ReadBlock(m_pSrcBuf + dwAvail, m_offSet, dwSize)) { - err_status = FXCODEC_STATUS_ERR_READ; - return false; - } - m_offSet += dwSize; - pJpegModule->Input(m_pJpegContext.get(), m_pSrcBuf, dwSize + dwAvail); - return true; -} - +#ifdef PDF_ENABLE_XFA_PNG bool CCodec_ProgressiveDecoder::PngReadHeader(int width, int height, int bpc, @@ -455,82 +421,6 @@ bool CCodec_ProgressiveDecoder::PngAskScanlineBuf(int line, uint8_t** pSrcBuf) { return true; } -void CCodec_ProgressiveDecoder::PngOneOneMapResampleHorz( - const RetainPtr& pDeviceBitmap, - int32_t dest_line, - uint8_t* src_scan, - FXCodec_Format src_format) { - uint8_t* dest_scan = (uint8_t*)pDeviceBitmap->GetScanline(dest_line); - int32_t src_Bpp = (m_SrcFormat & 0xff) >> 3; - int32_t dest_Bpp = pDeviceBitmap->GetBPP() >> 3; - int32_t src_left = m_clipBox.left; - int32_t dest_left = m_startX; - src_scan += src_left * src_Bpp; - dest_scan += dest_left * dest_Bpp; - for (int32_t dest_col = 0; dest_col < m_sizeX; dest_col++) { - PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(dest_col); - switch (pDeviceBitmap->GetFormat()) { - case FXDIB_1bppMask: - case FXDIB_1bppRgb: - NOTREACHED(); - return; - case FXDIB_8bppMask: - case FXDIB_8bppRgb: { - if (pDeviceBitmap->GetPalette()) { - return; - } - uint32_t dest_g = 0; - dest_g += - pPixelWeights->m_Weights[0] * src_scan[pPixelWeights->m_SrcStart]; - dest_g += - pPixelWeights->m_Weights[1] * src_scan[pPixelWeights->m_SrcEnd]; - *dest_scan++ = (uint8_t)(dest_g >> 16); - } break; - case FXDIB_Rgb: - case FXDIB_Rgb32: { - uint32_t dest_b = 0; - uint32_t dest_g = 0; - uint32_t dest_r = 0; - const uint8_t* p = src_scan; - p = src_scan + pPixelWeights->m_SrcStart * src_Bpp; - dest_b += pPixelWeights->m_Weights[0] * (*p++); - dest_g += pPixelWeights->m_Weights[0] * (*p++); - dest_r += pPixelWeights->m_Weights[0] * (*p); - p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp; - dest_b += pPixelWeights->m_Weights[1] * (*p++); - dest_g += pPixelWeights->m_Weights[1] * (*p++); - dest_r += pPixelWeights->m_Weights[1] * (*p); - *dest_scan++ = (uint8_t)((dest_b) >> 16); - *dest_scan++ = (uint8_t)((dest_g) >> 16); - *dest_scan++ = (uint8_t)((dest_r) >> 16); - dest_scan += dest_Bpp - 3; - } break; - case FXDIB_Argb: { - uint32_t dest_a = 0; - uint32_t dest_b = 0; - uint32_t dest_g = 0; - uint32_t dest_r = 0; - const uint8_t* p = src_scan; - p = src_scan + pPixelWeights->m_SrcStart * src_Bpp; - dest_b += pPixelWeights->m_Weights[0] * (*p++); - dest_g += pPixelWeights->m_Weights[0] * (*p++); - dest_r += pPixelWeights->m_Weights[0] * (*p++); - dest_a += pPixelWeights->m_Weights[0] * (*p); - p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp; - dest_b += pPixelWeights->m_Weights[1] * (*p++); - dest_g += pPixelWeights->m_Weights[1] * (*p++); - dest_r += pPixelWeights->m_Weights[1] * (*p++); - dest_a += pPixelWeights->m_Weights[1] * (*p); - *dest_scan++ = (uint8_t)((dest_b) >> 16); - *dest_scan++ = (uint8_t)((dest_g) >> 16); - *dest_scan++ = (uint8_t)((dest_r) >> 16); - *dest_scan++ = (uint8_t)((dest_a) >> 16); - } break; - default: - return; - } - } -} void CCodec_ProgressiveDecoder::PngFillScanlineBufCompleted(int pass, int line) { @@ -558,50 +448,7 @@ void CCodec_ProgressiveDecoder::PngFillScanlineBufCompleted(int pass, } } } - -bool CCodec_ProgressiveDecoder::GifReadMoreData(CCodec_GifModule* pGifModule, - FXCODEC_STATUS& err_status) { - if (static_cast(m_pFile->GetSize()) <= m_offSet) - return false; - - uint32_t dwFileRemaining = m_pFile->GetSize() - m_offSet; - uint32_t dwUnusedBuffer = - !m_InvalidateGifBuffer - ? pGifModule->GetAvailInput(m_pGifContext.get(), nullptr) - : 0; - uint32_t dwAmountToFetchFromFile = dwFileRemaining; - if (dwUnusedBuffer == m_SrcSize) { - if (dwFileRemaining > FXCODEC_BLOCK_SIZE) - dwAmountToFetchFromFile = FXCODEC_BLOCK_SIZE; - m_SrcSize = std::min( - (dwAmountToFetchFromFile + dwUnusedBuffer + FXCODEC_BLOCK_SIZE - 1) / - FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE, - static_cast(m_pFile->GetSize())); - m_pSrcBuf = FX_TryRealloc(uint8_t, m_pSrcBuf, m_SrcSize); - if (!m_pSrcBuf) { - err_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } - } else { - uint32_t dwConsumed = m_SrcSize - dwUnusedBuffer; - if (dwUnusedBuffer) - memmove(m_pSrcBuf, m_pSrcBuf + dwConsumed, dwUnusedBuffer); - if (dwFileRemaining > dwConsumed) - dwAmountToFetchFromFile = dwConsumed; - } - - if (!m_pFile->ReadBlock(m_pSrcBuf + dwUnusedBuffer, m_offSet, - dwAmountToFetchFromFile)) { - err_status = FXCODEC_STATUS_ERR_READ; - return false; - } - - m_offSet += dwAmountToFetchFromFile; - pGifModule->Input(m_pGifContext.get(), m_pSrcBuf, - dwAmountToFetchFromFile + dwUnusedBuffer); - m_InvalidateGifBuffer = false; - return true; -} +#endif // PDF_ENABLE_XFA_PNG void CCodec_ProgressiveDecoder::GifRecordCurrentPosition(uint32_t& cur_pos) { uint32_t remain_size = @@ -762,20 +609,68 @@ void CCodec_ProgressiveDecoder::GifReadScanline(int32_t row_num, GifDoubleLineResampleVert(pDIBitmap, scale_y, dest_row); } -void CCodec_ProgressiveDecoder::GifDoubleLineResampleVert( +bool CCodec_ProgressiveDecoder::BmpInputImagePositionBuf(uint32_t rcd_pos) { + m_offSet = rcd_pos; + FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; + return BmpReadMoreData(m_pCodecMgr->GetBmpModule(), error_status); +} + +void CCodec_ProgressiveDecoder::BmpReadScanline( + uint32_t row_num, + const std::vector& row_buf) { + RetainPtr pDIBitmap = m_pDeviceBitmap; + ASSERT(pDIBitmap); + std::copy(row_buf.begin(), row_buf.begin() + m_ScanlineSize, m_pDecodeBuf); + int src_top = m_clipBox.top; + int src_bottom = m_clipBox.bottom; + int dest_top = m_startY; + int src_height = m_clipBox.Height(); + int dest_height = m_sizeY; + if ((src_top >= 0 && row_num < static_cast(src_top)) || + src_bottom < 0 || row_num >= static_cast(src_bottom)) { + return; + } + + double scale_y = static_cast(dest_height) / src_height; + int src_row = row_num - src_top; + int dest_row = (int)(src_row * scale_y) + dest_top; + if (dest_row >= dest_top + dest_height) + return; + + ReSampleScanline(pDIBitmap, dest_row, m_pDecodeBuf, m_SrcFormat); + if (scale_y <= 1.0) + return; + + if (m_BmpIsTopBottom) { + ResampleVert(pDIBitmap, scale_y, dest_row); + return; + } + ResampleVertBT(pDIBitmap, scale_y, dest_row); +} + +void CCodec_ProgressiveDecoder::ResampleVertBT( const RetainPtr& pDeviceBitmap, double scale_y, int dest_row) { int dest_Bpp = pDeviceBitmap->GetBPP() >> 3; uint32_t dest_ScanOffet = m_startX * dest_Bpp; int dest_top = m_startY; - pdfium::base::CheckedNumeric scale_y2 = scale_y; - scale_y2 *= 2; + int dest_bottom = m_startY + m_sizeY; pdfium::base::CheckedNumeric check_dest_row_1 = dest_row; - check_dest_row_1 -= scale_y2.ValueOrDie(); + check_dest_row_1 += pdfium::base::checked_cast(scale_y); int dest_row_1 = check_dest_row_1.ValueOrDie(); - dest_row_1 = std::max(dest_row_1, dest_top); - for (; dest_row_1 < dest_row; dest_row_1++) { + if (dest_row_1 >= dest_bottom - 1) { + uint8_t* scan_src = + (uint8_t*)pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet; + while (++dest_row < dest_bottom) { + uint8_t* scan_des = + (uint8_t*)pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet; + uint32_t size = m_sizeX * dest_Bpp; + memmove(scan_des, scan_src, size); + } + return; + } + for (; dest_row_1 > dest_row; dest_row_1--) { uint8_t* scan_des = (uint8_t*)pDeviceBitmap->GetScanline(dest_row_1) + dest_ScanOffet; PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top); @@ -842,228 +737,21 @@ void CCodec_ProgressiveDecoder::GifDoubleLineResampleVert( } } } - int dest_bottom = dest_top + m_sizeY - 1; - if (dest_row + (int)(2 * scale_y) >= dest_bottom && - dest_row + (int)scale_y < dest_bottom) { - GifDoubleLineResampleVert(pDeviceBitmap, scale_y, dest_row + (int)scale_y); - } } -bool CCodec_ProgressiveDecoder::BmpReadMoreData(CCodec_BmpModule* pBmpModule, - FXCODEC_STATUS& err_status) { - uint32_t dwSize = (uint32_t)m_pFile->GetSize(); - if (dwSize <= m_offSet) +bool CCodec_ProgressiveDecoder::BmpDetectImageType(CFX_DIBAttribute* pAttribute, + uint32_t size) { + CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); + if (!pBmpModule) { + m_status = FXCODEC_STATUS_ERR_MEMORY; return false; + } - dwSize = dwSize - m_offSet; - FX_SAFE_UINT32 avail_input = - pBmpModule->GetAvailInput(m_pBmpContext.get(), nullptr); - if (!avail_input.IsValid()) + m_pBmpContext = pBmpModule->Start(this); + if (!m_pBmpContext) { + m_status = FXCODEC_STATUS_ERR_MEMORY; return false; - - uint32_t dwAvail = avail_input.ValueOrDie(); - if (dwAvail == m_SrcSize) { - if (dwSize > FXCODEC_BLOCK_SIZE) { - dwSize = FXCODEC_BLOCK_SIZE; - } - m_SrcSize = (dwSize + dwAvail + FXCODEC_BLOCK_SIZE - 1) / - FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE; - m_pSrcBuf = FX_TryRealloc(uint8_t, m_pSrcBuf, m_SrcSize); - if (!m_pSrcBuf) { - err_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } - } else { - uint32_t dwConsume = m_SrcSize - dwAvail; - if (dwAvail) { - memmove(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); - } - if (dwSize > dwConsume) { - dwSize = dwConsume; - } - } - if (!m_pFile->ReadBlock(m_pSrcBuf + dwAvail, m_offSet, dwSize)) { - err_status = FXCODEC_STATUS_ERR_READ; - return false; - } - m_offSet += dwSize; - pBmpModule->Input(m_pBmpContext.get(), m_pSrcBuf, dwSize + dwAvail); - return true; -} - -bool CCodec_ProgressiveDecoder::BmpInputImagePositionBuf(uint32_t rcd_pos) { - m_offSet = rcd_pos; - FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; - return BmpReadMoreData(m_pCodecMgr->GetBmpModule(), error_status); -} - -void CCodec_ProgressiveDecoder::BmpReadScanline( - uint32_t row_num, - const std::vector& row_buf) { - RetainPtr pDIBitmap = m_pDeviceBitmap; - ASSERT(pDIBitmap); - std::copy(row_buf.begin(), row_buf.begin() + m_ScanlineSize, m_pDecodeBuf); - int src_top = m_clipBox.top; - int src_bottom = m_clipBox.bottom; - int dest_top = m_startY; - int src_height = m_clipBox.Height(); - int dest_height = m_sizeY; - if ((src_top >= 0 && row_num < static_cast(src_top)) || - src_bottom < 0 || row_num >= static_cast(src_bottom)) { - return; - } - - double scale_y = static_cast(dest_height) / src_height; - int src_row = row_num - src_top; - int dest_row = (int)(src_row * scale_y) + dest_top; - if (dest_row >= dest_top + dest_height) - return; - - ReSampleScanline(pDIBitmap, dest_row, m_pDecodeBuf, m_SrcFormat); - if (scale_y <= 1.0) - return; - - if (m_BmpIsTopBottom) { - ResampleVert(pDIBitmap, scale_y, dest_row); - return; - } - ResampleVertBT(pDIBitmap, scale_y, dest_row); -} - -void CCodec_ProgressiveDecoder::ResampleVertBT( - const RetainPtr& pDeviceBitmap, - double scale_y, - int dest_row) { - int dest_Bpp = pDeviceBitmap->GetBPP() >> 3; - uint32_t dest_ScanOffet = m_startX * dest_Bpp; - int dest_top = m_startY; - int dest_bottom = m_startY + m_sizeY; - pdfium::base::CheckedNumeric check_dest_row_1 = dest_row; - check_dest_row_1 += pdfium::base::checked_cast(scale_y); - int dest_row_1 = check_dest_row_1.ValueOrDie(); - if (dest_row_1 >= dest_bottom - 1) { - uint8_t* scan_src = - (uint8_t*)pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet; - while (++dest_row < dest_bottom) { - uint8_t* scan_des = - (uint8_t*)pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet; - uint32_t size = m_sizeX * dest_Bpp; - memmove(scan_des, scan_src, size); - } - return; - } - for (; dest_row_1 > dest_row; dest_row_1--) { - uint8_t* scan_des = - (uint8_t*)pDeviceBitmap->GetScanline(dest_row_1) + dest_ScanOffet; - PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top); - const uint8_t* scan_src1 = - pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top) + - dest_ScanOffet; - const uint8_t* scan_src2 = - pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + dest_top) + - dest_ScanOffet; - for (int dest_col = 0; dest_col < m_sizeX; dest_col++) { - switch (pDeviceBitmap->GetFormat()) { - case FXDIB_Invalid: - case FXDIB_1bppMask: - case FXDIB_1bppRgb: - return; - case FXDIB_8bppMask: - case FXDIB_8bppRgb: { - if (pDeviceBitmap->GetPalette()) { - return; - } - int dest_g = 0; - dest_g += pWeight->m_Weights[0] * (*scan_src1++); - dest_g += pWeight->m_Weights[1] * (*scan_src2++); - *scan_des++ = (uint8_t)(dest_g >> 16); - } break; - case FXDIB_Rgb: - case FXDIB_Rgb32: { - uint32_t dest_b = 0; - uint32_t dest_g = 0; - uint32_t dest_r = 0; - dest_b += pWeight->m_Weights[0] * (*scan_src1++); - dest_g += pWeight->m_Weights[0] * (*scan_src1++); - dest_r += pWeight->m_Weights[0] * (*scan_src1++); - scan_src1 += dest_Bpp - 3; - dest_b += pWeight->m_Weights[1] * (*scan_src2++); - dest_g += pWeight->m_Weights[1] * (*scan_src2++); - dest_r += pWeight->m_Weights[1] * (*scan_src2++); - scan_src2 += dest_Bpp - 3; - *scan_des++ = (uint8_t)((dest_b) >> 16); - *scan_des++ = (uint8_t)((dest_g) >> 16); - *scan_des++ = (uint8_t)((dest_r) >> 16); - scan_des += dest_Bpp - 3; - } break; - case FXDIB_Argb: { - uint32_t dest_a = 0; - uint32_t dest_b = 0; - uint32_t dest_g = 0; - uint32_t dest_r = 0; - dest_b += pWeight->m_Weights[0] * (*scan_src1++); - dest_g += pWeight->m_Weights[0] * (*scan_src1++); - dest_r += pWeight->m_Weights[0] * (*scan_src1++); - dest_a += pWeight->m_Weights[0] * (*scan_src1++); - dest_b += pWeight->m_Weights[1] * (*scan_src2++); - dest_g += pWeight->m_Weights[1] * (*scan_src2++); - dest_r += pWeight->m_Weights[1] * (*scan_src2++); - dest_a += pWeight->m_Weights[1] * (*scan_src2++); - *scan_des++ = (uint8_t)((dest_b) >> 16); - *scan_des++ = (uint8_t)((dest_g) >> 16); - *scan_des++ = (uint8_t)((dest_r) >> 16); - *scan_des++ = (uint8_t)((dest_a) >> 16); - } break; - default: - return; - } - } - } -} - -bool CCodec_ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType, - CFX_DIBAttribute* pAttribute) { - m_offSet = 0; - uint32_t size = (uint32_t)m_pFile->GetSize(); - if (size > FXCODEC_BLOCK_SIZE) { - size = FXCODEC_BLOCK_SIZE; - } - FX_Free(m_pSrcBuf); - m_pSrcBuf = FX_Alloc(uint8_t, size); - memset(m_pSrcBuf, 0, size); - m_SrcSize = size; - switch (imageType) { - case FXCODEC_IMAGE_BMP: - return BmpDetectImageType(pAttribute, size); - case FXCODEC_IMAGE_JPG: - return JpegDetectImageType(pAttribute, size); - case FXCODEC_IMAGE_PNG: - return PngDetectImageType(pAttribute, size); - case FXCODEC_IMAGE_GIF: - return GifDetectImageType(pAttribute, size); -#ifdef PDF_ENABLE_XFA_TIFF - case FXCODEC_IMAGE_TIFF: - return TiffDetectImageType(pAttribute, size); -#endif // PDF_ENABLE_XFA_TIFF - default: - m_status = FXCODEC_STATUS_ERR_FORMAT; - return false; - } -} - -bool CCodec_ProgressiveDecoder::BmpDetectImageType(CFX_DIBAttribute* pAttribute, - uint32_t size) { - CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); - if (!pBmpModule) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } - - m_pBmpContext = pBmpModule->Start(this); - if (!m_pBmpContext) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } + } if (!m_pFile->ReadBlock(m_pSrcBuf, 0, size)) { m_status = FXCODEC_STATUS_ERR_READ; @@ -1141,102 +829,141 @@ bool CCodec_ProgressiveDecoder::BmpDetectImageType(CFX_DIBAttribute* pAttribute, return true; } -bool CCodec_ProgressiveDecoder::JpegDetectImageType( - CFX_DIBAttribute* pAttribute, - uint32_t size) { - CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); - m_pJpegContext = pJpegModule->Start(); - if (!m_pJpegContext) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } - if (!m_pFile->ReadBlock(m_pSrcBuf, 0, size)) { - m_status = FXCODEC_STATUS_ERR_READ; +bool CCodec_ProgressiveDecoder::BmpReadMoreData(CCodec_BmpModule* pBmpModule, + FXCODEC_STATUS& err_status) { + uint32_t dwSize = (uint32_t)m_pFile->GetSize(); + if (dwSize <= m_offSet) return false; - } - m_offSet += size; - pJpegModule->Input(m_pJpegContext.get(), m_pSrcBuf, size); - // Setting jump marker before calling ReadHeader, since a longjmp to - // the marker indicates a fatal error. - if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) { - m_pJpegContext.reset(); - m_status = FXCODEC_STATUS_ERR_FORMAT; + + dwSize = dwSize - m_offSet; + FX_SAFE_UINT32 avail_input = + pBmpModule->GetAvailInput(m_pBmpContext.get(), nullptr); + if (!avail_input.IsValid()) return false; - } - int32_t readResult = - pJpegModule->ReadHeader(m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight, - &m_SrcComponents, pAttribute); - while (readResult == 2) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; - if (!JpegReadMoreData(pJpegModule, error_status)) { - m_status = error_status; + uint32_t dwAvail = avail_input.ValueOrDie(); + if (dwAvail == m_SrcSize) { + if (dwSize > FXCODEC_BLOCK_SIZE) { + dwSize = FXCODEC_BLOCK_SIZE; + } + m_SrcSize = (dwSize + dwAvail + FXCODEC_BLOCK_SIZE - 1) / + FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE; + m_pSrcBuf = FX_TryRealloc(uint8_t, m_pSrcBuf, m_SrcSize); + if (!m_pSrcBuf) { + err_status = FXCODEC_STATUS_ERR_MEMORY; return false; } - readResult = - pJpegModule->ReadHeader(m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight, - &m_SrcComponents, pAttribute); + } else { + uint32_t dwConsume = m_SrcSize - dwAvail; + if (dwAvail) { + memmove(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); + } + if (dwSize > dwConsume) { + dwSize = dwConsume; + } } - if (!readResult) { - m_SrcBPC = 8; - m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); - return true; + if (!m_pFile->ReadBlock(m_pSrcBuf + dwAvail, m_offSet, dwSize)) { + err_status = FXCODEC_STATUS_ERR_READ; + return false; } - m_pJpegContext.reset(); - m_status = FXCODEC_STATUS_ERR_FORMAT; - return false; -} + m_offSet += dwSize; + pBmpModule->Input(m_pBmpContext.get(), m_pSrcBuf, dwSize + dwAvail); + return true; +} -bool CCodec_ProgressiveDecoder::PngDetectImageType(CFX_DIBAttribute* pAttribute, - uint32_t size) { - CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); - if (!pPngModule) { +FXCODEC_STATUS CCodec_ProgressiveDecoder::BmpStartDecode( + const RetainPtr& pDIBitmap) { + CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); + if (!pBmpModule) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; m_status = FXCODEC_STATUS_ERR_MEMORY; - return false; + return m_status; } - m_pPngContext = pPngModule->Start(this); - if (!m_pPngContext) { + GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); + m_ScanlineSize = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; + FX_Free(m_pDecodeBuf); + m_pDecodeBuf = FX_Alloc(uint8_t, m_ScanlineSize); + memset(m_pDecodeBuf, 0, m_ScanlineSize); + m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, + m_clipBox.Width()); + m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); + m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + return m_status; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::BmpContinueDecode() { + CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); + if (!pBmpModule) { m_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } - bool bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); - if (!bResult) { - m_status = FXCODEC_STATUS_ERR_READ; - return false; + return m_status; } - - m_offSet += size; - bResult = pPngModule->Input(m_pPngContext.get(), m_pSrcBuf, size, pAttribute); - while (bResult) { - uint32_t remain_size = static_cast(m_pFile->GetSize()) - m_offSet; - uint32_t input_size = - remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size; - if (input_size == 0) { - m_pPngContext.reset(); - m_status = FXCODEC_STATUS_ERR_FORMAT; - return false; + while (true) { + int32_t readRes = pBmpModule->LoadImage(m_pBmpContext.get()); + while (readRes == 2) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; + if (!BmpReadMoreData(pBmpModule, error_status)) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = error_status; + return m_status; + } + readRes = pBmpModule->LoadImage(m_pBmpContext.get()); } - if (m_pSrcBuf && input_size > m_SrcSize) { - FX_Free(m_pSrcBuf); - m_pSrcBuf = FX_Alloc(uint8_t, input_size); - memset(m_pSrcBuf, 0, input_size); - m_SrcSize = input_size; + if (readRes == 1) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_DECODE_FINISH; + return m_status; } - bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size); - if (!bResult) { - m_status = FXCODEC_STATUS_ERR_READ; + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERROR; + return m_status; + } +} + +bool CCodec_ProgressiveDecoder::GifReadMoreData(CCodec_GifModule* pGifModule, + FXCODEC_STATUS& err_status) { + if (static_cast(m_pFile->GetSize()) <= m_offSet) + return false; + + uint32_t dwFileRemaining = m_pFile->GetSize() - m_offSet; + uint32_t dwUnusedBuffer = + !m_InvalidateGifBuffer + ? pGifModule->GetAvailInput(m_pGifContext.get(), nullptr) + : 0; + uint32_t dwAmountToFetchFromFile = dwFileRemaining; + if (dwUnusedBuffer == m_SrcSize) { + if (dwFileRemaining > FXCODEC_BLOCK_SIZE) + dwAmountToFetchFromFile = FXCODEC_BLOCK_SIZE; + m_SrcSize = std::min( + (dwAmountToFetchFromFile + dwUnusedBuffer + FXCODEC_BLOCK_SIZE - 1) / + FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE, + static_cast(m_pFile->GetSize())); + m_pSrcBuf = FX_TryRealloc(uint8_t, m_pSrcBuf, m_SrcSize); + if (!m_pSrcBuf) { + err_status = FXCODEC_STATUS_ERR_MEMORY; return false; } - m_offSet += input_size; - bResult = pPngModule->Input(m_pPngContext.get(), m_pSrcBuf, input_size, - pAttribute); + } else { + uint32_t dwConsumed = m_SrcSize - dwUnusedBuffer; + if (dwUnusedBuffer) + memmove(m_pSrcBuf, m_pSrcBuf + dwConsumed, dwUnusedBuffer); + if (dwFileRemaining > dwConsumed) + dwAmountToFetchFromFile = dwConsumed; } - ASSERT(!bResult); - m_pPngContext.reset(); - if (m_SrcPassNumber == 0) { - m_status = FXCODEC_STATUS_ERR_FORMAT; + + if (!m_pFile->ReadBlock(m_pSrcBuf + dwUnusedBuffer, m_offSet, + dwAmountToFetchFromFile)) { + err_status = FXCODEC_STATUS_ERR_READ; return false; } + + m_offSet += dwAmountToFetchFromFile; + pGifModule->Input(m_pGifContext.get(), m_pSrcBuf, + dwAmountToFetchFromFile + dwUnusedBuffer); + m_InvalidateGifBuffer = false; return true; } @@ -1280,107 +1007,818 @@ bool CCodec_ProgressiveDecoder::GifDetectImageType(CFX_DIBAttribute* pAttribute, return false; } -#ifdef PDF_ENABLE_XFA_TIFF -bool CCodec_ProgressiveDecoder::TiffDetectImageType( - CFX_DIBAttribute* pAttribute, - uint32_t size) { - CCodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule(); - if (!pTiffModule) { - m_status = FXCODEC_STATUS_ERR_FORMAT; - return false; - } - m_pTiffContext = pTiffModule->CreateDecoder(m_pFile); - if (!m_pTiffContext) { - m_status = FXCODEC_STATUS_ERR_FORMAT; - return false; - } - int32_t dummy_bpc; - bool ret = pTiffModule->LoadFrameInfo(m_pTiffContext.get(), 0, &m_SrcWidth, - &m_SrcHeight, &m_SrcComponents, - &dummy_bpc, pAttribute); - m_SrcComponents = 4; - m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); - if (!ret) { - m_pTiffContext.reset(); - m_status = FXCODEC_STATUS_ERR_FORMAT; - return false; +FXCODEC_STATUS CCodec_ProgressiveDecoder::GifStartDecode( + const RetainPtr& pDIBitmap) { + CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); + if (!pGifModule) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; } - return true; + m_SrcFormat = FXCodec_8bppRgb; + GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); + int scanline_size = (m_SrcWidth + 3) / 4 * 4; + FX_Free(m_pDecodeBuf); + m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); + memset(m_pDecodeBuf, 0, scanline_size); + m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, + m_clipBox.Width()); + m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); + m_FrameCur = 0; + m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + return m_status; } -#endif // PDF_ENABLE_XFA_TIFF -FXCODEC_STATUS CCodec_ProgressiveDecoder::LoadImageInfo( - const RetainPtr& pFile, - FXCODEC_IMAGE_TYPE imageType, - CFX_DIBAttribute* pAttribute, - bool bSkipImageTypeCheck) { - switch (m_status) { - case FXCODEC_STATUS_FRAME_READY: - case FXCODEC_STATUS_FRAME_TOBECONTINUE: - case FXCODEC_STATUS_DECODE_READY: - case FXCODEC_STATUS_DECODE_TOBECONTINUE: - return FXCODEC_STATUS_ERROR; - default: - break; - } - if (!pFile) { - m_status = FXCODEC_STATUS_ERR_PARAMS; +FXCODEC_STATUS CCodec_ProgressiveDecoder::GifContinueDecode() { + CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); + if (!pGifModule) { + m_pDeviceBitmap = nullptr; m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; return m_status; } - m_pFile = pFile; - m_offSet = 0; - m_SrcWidth = m_SrcHeight = 0; - m_SrcComponents = m_SrcBPC = 0; - m_clipBox = FX_RECT(0, 0, 0, 0); - m_startX = m_startY = 0; - m_sizeX = m_sizeY = 0; - m_SrcPassNumber = 0; - if (imageType != FXCODEC_IMAGE_UNKNOWN && - DetectImageType(imageType, pAttribute)) { - m_imagType = imageType; - m_status = FXCODEC_STATUS_FRAME_READY; - return m_status; - } - // If we got here then the image data does not match the requested decoder. - // If we're skipping the type check then bail out at this point and return - // the failed status. - if (bSkipImageTypeCheck) - return m_status; - for (int type = FXCODEC_IMAGE_BMP; type < FXCODEC_IMAGE_MAX; type++) { - if (DetectImageType((FXCODEC_IMAGE_TYPE)type, pAttribute)) { - m_imagType = (FXCODEC_IMAGE_TYPE)type; - m_status = FXCODEC_STATUS_FRAME_READY; + CFX_GifDecodeStatus readRes = + pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr); + while (readRes == CFX_GifDecodeStatus::Unfinished) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; + if (!GifReadMoreData(pGifModule, error_status)) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = error_status; return m_status; } + readRes = pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr); } - m_status = FXCODEC_STATUS_ERR_FORMAT; - m_pFile = nullptr; - return m_status; -} - -void CCodec_ProgressiveDecoder::SetClipBox(FX_RECT* clip) { - if (m_status != FXCODEC_STATUS_FRAME_READY) - return; - if (clip->IsEmpty()) { - m_clipBox = FX_RECT(0, 0, 0, 0); - return; - } - clip->left = std::max(clip->left, 0); - clip->right = std::min(clip->right, m_SrcWidth); - clip->top = std::max(clip->top, 0); - clip->bottom = std::min(clip->bottom, m_SrcHeight); - if (clip->IsEmpty()) { - m_clipBox = FX_RECT(0, 0, 0, 0); - return; + if (readRes == CFX_GifDecodeStatus::Success) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_DECODE_FINISH; + return m_status; } - m_clipBox = *clip; + + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERROR; + return m_status; } -void CCodec_ProgressiveDecoder::GetDownScale(int& down_scale) { - down_scale = 1; +void CCodec_ProgressiveDecoder::GifDoubleLineResampleVert( + const RetainPtr& pDeviceBitmap, + double scale_y, + int dest_row) { + int dest_Bpp = pDeviceBitmap->GetBPP() >> 3; + uint32_t dest_ScanOffet = m_startX * dest_Bpp; + int dest_top = m_startY; + pdfium::base::CheckedNumeric scale_y2 = scale_y; + scale_y2 *= 2; + pdfium::base::CheckedNumeric check_dest_row_1 = dest_row; + check_dest_row_1 -= scale_y2.ValueOrDie(); + int dest_row_1 = check_dest_row_1.ValueOrDie(); + dest_row_1 = std::max(dest_row_1, dest_top); + for (; dest_row_1 < dest_row; dest_row_1++) { + uint8_t* scan_des = + (uint8_t*)pDeviceBitmap->GetScanline(dest_row_1) + dest_ScanOffet; + PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top); + const uint8_t* scan_src1 = + pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top) + + dest_ScanOffet; + const uint8_t* scan_src2 = + pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + dest_top) + + dest_ScanOffet; + for (int dest_col = 0; dest_col < m_sizeX; dest_col++) { + switch (pDeviceBitmap->GetFormat()) { + case FXDIB_Invalid: + case FXDIB_1bppMask: + case FXDIB_1bppRgb: + return; + case FXDIB_8bppMask: + case FXDIB_8bppRgb: { + if (pDeviceBitmap->GetPalette()) { + return; + } + int dest_g = 0; + dest_g += pWeight->m_Weights[0] * (*scan_src1++); + dest_g += pWeight->m_Weights[1] * (*scan_src2++); + *scan_des++ = (uint8_t)(dest_g >> 16); + } break; + case FXDIB_Rgb: + case FXDIB_Rgb32: { + uint32_t dest_b = 0; + uint32_t dest_g = 0; + uint32_t dest_r = 0; + dest_b += pWeight->m_Weights[0] * (*scan_src1++); + dest_g += pWeight->m_Weights[0] * (*scan_src1++); + dest_r += pWeight->m_Weights[0] * (*scan_src1++); + scan_src1 += dest_Bpp - 3; + dest_b += pWeight->m_Weights[1] * (*scan_src2++); + dest_g += pWeight->m_Weights[1] * (*scan_src2++); + dest_r += pWeight->m_Weights[1] * (*scan_src2++); + scan_src2 += dest_Bpp - 3; + *scan_des++ = (uint8_t)((dest_b) >> 16); + *scan_des++ = (uint8_t)((dest_g) >> 16); + *scan_des++ = (uint8_t)((dest_r) >> 16); + scan_des += dest_Bpp - 3; + } break; + case FXDIB_Argb: { + uint32_t dest_a = 0; + uint32_t dest_b = 0; + uint32_t dest_g = 0; + uint32_t dest_r = 0; + dest_b += pWeight->m_Weights[0] * (*scan_src1++); + dest_g += pWeight->m_Weights[0] * (*scan_src1++); + dest_r += pWeight->m_Weights[0] * (*scan_src1++); + dest_a += pWeight->m_Weights[0] * (*scan_src1++); + dest_b += pWeight->m_Weights[1] * (*scan_src2++); + dest_g += pWeight->m_Weights[1] * (*scan_src2++); + dest_r += pWeight->m_Weights[1] * (*scan_src2++); + dest_a += pWeight->m_Weights[1] * (*scan_src2++); + *scan_des++ = (uint8_t)((dest_b) >> 16); + *scan_des++ = (uint8_t)((dest_g) >> 16); + *scan_des++ = (uint8_t)((dest_r) >> 16); + *scan_des++ = (uint8_t)((dest_a) >> 16); + } break; + default: + return; + } + } + } + int dest_bottom = dest_top + m_sizeY - 1; + if (dest_row + (int)(2 * scale_y) >= dest_bottom && + dest_row + (int)scale_y < dest_bottom) { + GifDoubleLineResampleVert(pDeviceBitmap, scale_y, dest_row + (int)scale_y); + } +} + +bool CCodec_ProgressiveDecoder::JpegReadMoreData(CCodec_JpegModule* pJpegModule, + FXCODEC_STATUS& err_status) { + uint32_t dwSize = (uint32_t)m_pFile->GetSize(); + if (dwSize <= m_offSet) { + return false; + } + dwSize = dwSize - m_offSet; + uint32_t dwAvail = pJpegModule->GetAvailInput(m_pJpegContext.get(), nullptr); + if (dwAvail == m_SrcSize) { + if (dwSize > FXCODEC_BLOCK_SIZE) { + dwSize = FXCODEC_BLOCK_SIZE; + } + m_SrcSize = (dwSize + dwAvail + FXCODEC_BLOCK_SIZE - 1) / + FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE; + m_pSrcBuf = FX_TryRealloc(uint8_t, m_pSrcBuf, m_SrcSize); + if (!m_pSrcBuf) { + err_status = FXCODEC_STATUS_ERR_MEMORY; + return false; + } + } else { + uint32_t dwConsume = m_SrcSize - dwAvail; + if (dwAvail) { + memmove(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); + } + if (dwSize > dwConsume) { + dwSize = dwConsume; + } + } + if (!m_pFile->ReadBlock(m_pSrcBuf + dwAvail, m_offSet, dwSize)) { + err_status = FXCODEC_STATUS_ERR_READ; + return false; + } + m_offSet += dwSize; + pJpegModule->Input(m_pJpegContext.get(), m_pSrcBuf, dwSize + dwAvail); + return true; +} + +bool CCodec_ProgressiveDecoder::JpegDetectImageType( + CFX_DIBAttribute* pAttribute, + uint32_t size) { + CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); + m_pJpegContext = pJpegModule->Start(); + if (!m_pJpegContext) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return false; + } + if (!m_pFile->ReadBlock(m_pSrcBuf, 0, size)) { + m_status = FXCODEC_STATUS_ERR_READ; + return false; + } + m_offSet += size; + pJpegModule->Input(m_pJpegContext.get(), m_pSrcBuf, size); + // Setting jump marker before calling ReadHeader, since a longjmp to + // the marker indicates a fatal error. + if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) { + m_pJpegContext.reset(); + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; + } + + int32_t readResult = + pJpegModule->ReadHeader(m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight, + &m_SrcComponents, pAttribute); + while (readResult == 2) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; + if (!JpegReadMoreData(pJpegModule, error_status)) { + m_status = error_status; + return false; + } + readResult = + pJpegModule->ReadHeader(m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight, + &m_SrcComponents, pAttribute); + } + if (!readResult) { + m_SrcBPC = 8; + m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); + return true; + } + m_pJpegContext.reset(); + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::JpegStartDecode( + const RetainPtr& pDIBitmap) { + int down_scale = 1; + GetDownScale(down_scale); + // Setting jump marker before calling StartScanLine, since a longjmp to + // the marker indicates a fatal error. + if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) { + m_pJpegContext.reset(); + m_status = FXCODEC_STATUS_ERROR; + return FXCODEC_STATUS_ERROR; + } + + CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); + bool startStatus = + pJpegModule->StartScanline(m_pJpegContext.get(), down_scale); + while (!startStatus) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; + if (!JpegReadMoreData(pJpegModule, error_status)) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = error_status; + return m_status; + } + + startStatus = pJpegModule->StartScanline(m_pJpegContext.get(), down_scale); + } + int scanline_size = (m_SrcWidth + down_scale - 1) / down_scale; + scanline_size = (scanline_size * m_SrcComponents + 3) / 4 * 4; + FX_Free(m_pDecodeBuf); + m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); + memset(m_pDecodeBuf, 0, scanline_size); + m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, + m_clipBox.Width()); + m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); + switch (m_SrcComponents) { + case 1: + m_SrcFormat = FXCodec_8bppGray; + break; + case 3: + m_SrcFormat = FXCodec_Rgb; + break; + case 4: + m_SrcFormat = FXCodec_Cmyk; + break; + } + GetTransMethod(pDIBitmap->GetFormat(), m_SrcFormat); + m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + return m_status; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::JpegContinueDecode() { + CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); + // Setting jump marker before calling ReadScanLine, since a longjmp to + // the marker indicates a fatal error. + if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) { + m_pJpegContext.reset(); + m_status = FXCODEC_STATUS_ERROR; + return FXCODEC_STATUS_ERROR; + } + + while (true) { + bool readRes = + pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf); + while (!readRes) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; + if (!JpegReadMoreData(pJpegModule, error_status)) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = error_status; + return m_status; + } + readRes = pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf); + } + if (m_SrcFormat == FXCodec_Rgb) { + int src_Bpp = (m_SrcFormat & 0xff) >> 3; + RGB2BGR(m_pDecodeBuf + m_clipBox.left * src_Bpp, m_clipBox.Width()); + } + if (m_SrcRow >= m_clipBox.bottom) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_DECODE_FINISH; + return m_status; + } + Resample(m_pDeviceBitmap, m_SrcRow, m_pDecodeBuf, m_SrcFormat); + m_SrcRow++; + } +} + +#ifdef PDF_ENABLE_XFA_PNG +void CCodec_ProgressiveDecoder::PngOneOneMapResampleHorz( + const RetainPtr& pDeviceBitmap, + int32_t dest_line, + uint8_t* src_scan, + FXCodec_Format src_format) { + uint8_t* dest_scan = (uint8_t*)pDeviceBitmap->GetScanline(dest_line); + int32_t src_Bpp = (m_SrcFormat & 0xff) >> 3; + int32_t dest_Bpp = pDeviceBitmap->GetBPP() >> 3; + int32_t src_left = m_clipBox.left; + int32_t dest_left = m_startX; + src_scan += src_left * src_Bpp; + dest_scan += dest_left * dest_Bpp; + for (int32_t dest_col = 0; dest_col < m_sizeX; dest_col++) { + PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(dest_col); + switch (pDeviceBitmap->GetFormat()) { + case FXDIB_1bppMask: + case FXDIB_1bppRgb: + NOTREACHED(); + return; + case FXDIB_8bppMask: + case FXDIB_8bppRgb: { + if (pDeviceBitmap->GetPalette()) { + return; + } + uint32_t dest_g = 0; + dest_g += + pPixelWeights->m_Weights[0] * src_scan[pPixelWeights->m_SrcStart]; + dest_g += + pPixelWeights->m_Weights[1] * src_scan[pPixelWeights->m_SrcEnd]; + *dest_scan++ = (uint8_t)(dest_g >> 16); + } break; + case FXDIB_Rgb: + case FXDIB_Rgb32: { + uint32_t dest_b = 0; + uint32_t dest_g = 0; + uint32_t dest_r = 0; + const uint8_t* p = src_scan; + p = src_scan + pPixelWeights->m_SrcStart * src_Bpp; + dest_b += pPixelWeights->m_Weights[0] * (*p++); + dest_g += pPixelWeights->m_Weights[0] * (*p++); + dest_r += pPixelWeights->m_Weights[0] * (*p); + p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp; + dest_b += pPixelWeights->m_Weights[1] * (*p++); + dest_g += pPixelWeights->m_Weights[1] * (*p++); + dest_r += pPixelWeights->m_Weights[1] * (*p); + *dest_scan++ = (uint8_t)((dest_b) >> 16); + *dest_scan++ = (uint8_t)((dest_g) >> 16); + *dest_scan++ = (uint8_t)((dest_r) >> 16); + dest_scan += dest_Bpp - 3; + } break; + case FXDIB_Argb: { + uint32_t dest_a = 0; + uint32_t dest_b = 0; + uint32_t dest_g = 0; + uint32_t dest_r = 0; + const uint8_t* p = src_scan; + p = src_scan + pPixelWeights->m_SrcStart * src_Bpp; + dest_b += pPixelWeights->m_Weights[0] * (*p++); + dest_g += pPixelWeights->m_Weights[0] * (*p++); + dest_r += pPixelWeights->m_Weights[0] * (*p++); + dest_a += pPixelWeights->m_Weights[0] * (*p); + p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp; + dest_b += pPixelWeights->m_Weights[1] * (*p++); + dest_g += pPixelWeights->m_Weights[1] * (*p++); + dest_r += pPixelWeights->m_Weights[1] * (*p++); + dest_a += pPixelWeights->m_Weights[1] * (*p); + *dest_scan++ = (uint8_t)((dest_b) >> 16); + *dest_scan++ = (uint8_t)((dest_g) >> 16); + *dest_scan++ = (uint8_t)((dest_r) >> 16); + *dest_scan++ = (uint8_t)((dest_a) >> 16); + } break; + default: + return; + } + } +} + +bool CCodec_ProgressiveDecoder::PngDetectImageType(CFX_DIBAttribute* pAttribute, + uint32_t size) { + CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); + if (!pPngModule) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return false; + } + m_pPngContext = pPngModule->Start(this); + if (!m_pPngContext) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return false; + } + bool bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); + if (!bResult) { + m_status = FXCODEC_STATUS_ERR_READ; + return false; + } + + m_offSet += size; + bResult = pPngModule->Input(m_pPngContext.get(), m_pSrcBuf, size, pAttribute); + while (bResult) { + uint32_t remain_size = static_cast(m_pFile->GetSize()) - m_offSet; + uint32_t input_size = + remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size; + if (input_size == 0) { + m_pPngContext.reset(); + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; + } + if (m_pSrcBuf && input_size > m_SrcSize) { + FX_Free(m_pSrcBuf); + m_pSrcBuf = FX_Alloc(uint8_t, input_size); + memset(m_pSrcBuf, 0, input_size); + m_SrcSize = input_size; + } + bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size); + if (!bResult) { + m_status = FXCODEC_STATUS_ERR_READ; + return false; + } + m_offSet += input_size; + bResult = pPngModule->Input(m_pPngContext.get(), m_pSrcBuf, input_size, + pAttribute); + } + ASSERT(!bResult); + m_pPngContext.reset(); + if (m_SrcPassNumber == 0) { + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; + } + return true; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::PngStartDecode( + const RetainPtr& pDIBitmap) { + CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); + if (!pPngModule) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + m_pPngContext = pPngModule->Start(this); + if (!m_pPngContext) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + m_offSet = 0; + switch (m_pDeviceBitmap->GetFormat()) { + case FXDIB_8bppMask: + case FXDIB_8bppRgb: + m_SrcComponents = 1; + m_SrcFormat = FXCodec_8bppGray; + break; + case FXDIB_Rgb: + m_SrcComponents = 3; + m_SrcFormat = FXCodec_Rgb; + break; + case FXDIB_Rgb32: + case FXDIB_Argb: + m_SrcComponents = 4; + m_SrcFormat = FXCodec_Argb; + break; + default: { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_PARAMS; + return m_status; + } + } + GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); + int scanline_size = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; + FX_Free(m_pDecodeBuf); + m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); + memset(m_pDecodeBuf, 0, scanline_size); + m_WeightHorzOO.Calc(m_sizeX, m_clipBox.Width()); + m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); + m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + return m_status; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::PngContinueDecode() { + CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); + if (!pPngModule) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + while (true) { + uint32_t remain_size = (uint32_t)m_pFile->GetSize() - m_offSet; + uint32_t input_size = + remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size; + if (input_size == 0) { + m_pPngContext.reset(); + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_DECODE_FINISH; + return m_status; + } + if (m_pSrcBuf && input_size > m_SrcSize) { + FX_Free(m_pSrcBuf); + m_pSrcBuf = FX_Alloc(uint8_t, input_size); + memset(m_pSrcBuf, 0, input_size); + m_SrcSize = input_size; + } + bool bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size); + if (!bResult) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_READ; + return m_status; + } + m_offSet += input_size; + bResult = + pPngModule->Input(m_pPngContext.get(), m_pSrcBuf, input_size, nullptr); + if (!bResult) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERROR; + return m_status; + } + } +} +#endif // PDF_ENABLE_XFA_PNG + +#ifdef PDF_ENABLE_XFA_TIFF +bool CCodec_ProgressiveDecoder::TiffDetectImageType( + CFX_DIBAttribute* pAttribute, + uint32_t size) { + CCodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule(); + if (!pTiffModule) { + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; + } + m_pTiffContext = pTiffModule->CreateDecoder(m_pFile); + if (!m_pTiffContext) { + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; + } + int32_t dummy_bpc; + bool ret = pTiffModule->LoadFrameInfo(m_pTiffContext.get(), 0, &m_SrcWidth, + &m_SrcHeight, &m_SrcComponents, + &dummy_bpc, pAttribute); + m_SrcComponents = 4; + m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); + if (!ret) { + m_pTiffContext.reset(); + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; + } + return true; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::TiffContinueDecode() { + CCodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule(); + if (!pTiffModule) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + bool ret = false; + if (m_pDeviceBitmap->GetBPP() == 32 && + m_pDeviceBitmap->GetWidth() == m_SrcWidth && m_SrcWidth == m_sizeX && + m_pDeviceBitmap->GetHeight() == m_SrcHeight && m_SrcHeight == m_sizeY && + m_startX == 0 && m_startY == 0 && m_clipBox.left == 0 && + m_clipBox.top == 0 && m_clipBox.right == m_SrcWidth && + m_clipBox.bottom == m_SrcHeight) { + ret = pTiffModule->Decode(m_pTiffContext.get(), m_pDeviceBitmap); + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + if (!ret) { + m_status = FXCODEC_STATUS_ERROR; + return m_status; + } + m_status = FXCODEC_STATUS_DECODE_FINISH; + return m_status; + } + + auto pDIBitmap = pdfium::MakeRetain(); + pDIBitmap->Create(m_SrcWidth, m_SrcHeight, FXDIB_Argb); + if (!pDIBitmap->GetBuffer()) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + ret = pTiffModule->Decode(m_pTiffContext.get(), pDIBitmap); + if (!ret) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERROR; + return m_status; + } + RetainPtr pClipBitmap = + (m_clipBox.left == 0 && m_clipBox.top == 0 && + m_clipBox.right == m_SrcWidth && m_clipBox.bottom == m_SrcHeight) + ? pDIBitmap + : pDIBitmap->Clone(&m_clipBox); + if (!pClipBitmap) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + RetainPtr pFormatBitmap; + switch (m_pDeviceBitmap->GetFormat()) { + case FXDIB_8bppRgb: + pFormatBitmap = pdfium::MakeRetain(); + pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), + FXDIB_8bppRgb); + break; + case FXDIB_8bppMask: + pFormatBitmap = pdfium::MakeRetain(); + pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), + FXDIB_8bppMask); + break; + case FXDIB_Rgb: + pFormatBitmap = pdfium::MakeRetain(); + pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), + FXDIB_Rgb); + break; + case FXDIB_Rgb32: + pFormatBitmap = pdfium::MakeRetain(); + pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), + FXDIB_Rgb32); + break; + case FXDIB_Argb: + pFormatBitmap = pClipBitmap; + break; + default: + break; + } + switch (m_pDeviceBitmap->GetFormat()) { + case FXDIB_8bppRgb: + case FXDIB_8bppMask: { + for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { + uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); + uint8_t* dest_line = (uint8_t*)pFormatBitmap->GetScanline(row); + for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { + uint8_t _a = 255 - src_line[3]; + uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; + uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; + uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255; + *dest_line++ = FXRGB2GRAY(r, g, b); + src_line += 4; + } + } + } break; + case FXDIB_Rgb: + case FXDIB_Rgb32: { + int32_t desBpp = (m_pDeviceBitmap->GetFormat() == FXDIB_Rgb) ? 3 : 4; + for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { + uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); + uint8_t* dest_line = (uint8_t*)pFormatBitmap->GetScanline(row); + for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { + uint8_t _a = 255 - src_line[3]; + uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; + uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; + uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255; + *dest_line++ = b; + *dest_line++ = g; + *dest_line++ = r; + dest_line += desBpp - 3; + src_line += 4; + } + } + } break; + default: + break; + } + if (!pFormatBitmap) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + RetainPtr pStrechBitmap = + pFormatBitmap->StretchTo(m_sizeX, m_sizeY, FXDIB_INTERPOL, nullptr); + pFormatBitmap = nullptr; + if (!pStrechBitmap) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + m_pDeviceBitmap->TransferBitmap(m_startX, m_startY, m_sizeX, m_sizeY, + pStrechBitmap, 0, 0); + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_DECODE_FINISH; + return m_status; +} +#endif // PDF_ENABLE_XFA_TIFF + +bool CCodec_ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType, + CFX_DIBAttribute* pAttribute) { + m_offSet = 0; + uint32_t size = (uint32_t)m_pFile->GetSize(); + if (size > FXCODEC_BLOCK_SIZE) { + size = FXCODEC_BLOCK_SIZE; + } + FX_Free(m_pSrcBuf); + m_pSrcBuf = FX_Alloc(uint8_t, size); + memset(m_pSrcBuf, 0, size); + m_SrcSize = size; + switch (imageType) { + case FXCODEC_IMAGE_BMP: + return BmpDetectImageType(pAttribute, size); + case FXCODEC_IMAGE_JPG: + return JpegDetectImageType(pAttribute, size); +#ifdef PDF_ENABLE_XFA_PNG + case FXCODEC_IMAGE_PNG: + return PngDetectImageType(pAttribute, size); +#endif // PDF_ENABLE_XFA_PNG + case FXCODEC_IMAGE_GIF: + return GifDetectImageType(pAttribute, size); +#ifdef PDF_ENABLE_XFA_TIFF + case FXCODEC_IMAGE_TIFF: + return TiffDetectImageType(pAttribute, size); +#endif // PDF_ENABLE_XFA_TIFF + default: + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; + } +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::LoadImageInfo( + const RetainPtr& pFile, + FXCODEC_IMAGE_TYPE imageType, + CFX_DIBAttribute* pAttribute, + bool bSkipImageTypeCheck) { + switch (m_status) { + case FXCODEC_STATUS_FRAME_READY: + case FXCODEC_STATUS_FRAME_TOBECONTINUE: + case FXCODEC_STATUS_DECODE_READY: + case FXCODEC_STATUS_DECODE_TOBECONTINUE: + return FXCODEC_STATUS_ERROR; + default: + break; + } + if (!pFile) { + m_status = FXCODEC_STATUS_ERR_PARAMS; + m_pFile = nullptr; + return m_status; + } + m_pFile = pFile; + m_offSet = 0; + m_SrcWidth = m_SrcHeight = 0; + m_SrcComponents = m_SrcBPC = 0; + m_clipBox = FX_RECT(0, 0, 0, 0); + m_startX = m_startY = 0; + m_sizeX = m_sizeY = 0; + m_SrcPassNumber = 0; + if (imageType != FXCODEC_IMAGE_UNKNOWN && + DetectImageType(imageType, pAttribute)) { + m_imagType = imageType; + m_status = FXCODEC_STATUS_FRAME_READY; + return m_status; + } + // If we got here then the image data does not match the requested decoder. + // If we're skipping the type check then bail out at this point and return + // the failed status. + if (bSkipImageTypeCheck) + return m_status; + + for (int type = FXCODEC_IMAGE_BMP; type < FXCODEC_IMAGE_MAX; type++) { + if (DetectImageType((FXCODEC_IMAGE_TYPE)type, pAttribute)) { + m_imagType = (FXCODEC_IMAGE_TYPE)type; + m_status = FXCODEC_STATUS_FRAME_READY; + return m_status; + } + } + m_status = FXCODEC_STATUS_ERR_FORMAT; + m_pFile = nullptr; + return m_status; +} + +void CCodec_ProgressiveDecoder::SetClipBox(FX_RECT* clip) { + if (m_status != FXCODEC_STATUS_FRAME_READY) + return; + + if (clip->IsEmpty()) { + m_clipBox = FX_RECT(0, 0, 0, 0); + return; + } + clip->left = std::max(clip->left, 0); + clip->right = std::min(clip->right, m_SrcWidth); + clip->top = std::max(clip->top, 0); + clip->bottom = std::min(clip->bottom, m_SrcHeight); + if (clip->IsEmpty()) { + m_clipBox = FX_RECT(0, 0, 0, 0); + return; + } + m_clipBox = *clip; +} + +void CCodec_ProgressiveDecoder::GetDownScale(int& down_scale) { + down_scale = 1; int ratio_w = m_clipBox.Width() / m_sizeX; int ratio_h = m_clipBox.Height() / m_sizeY; int ratio = (ratio_w > ratio_h) ? ratio_h : ratio_w; @@ -1801,630 +2239,205 @@ void CCodec_ProgressiveDecoder::ResampleVert( uint32_t dest_r = 0; dest_b += pWeight->m_Weights[0] * (*scan_src1++); dest_g += pWeight->m_Weights[0] * (*scan_src1++); - dest_r += pWeight->m_Weights[0] * (*scan_src1++); - dest_a += pWeight->m_Weights[0] * (*scan_src1++); - dest_b += pWeight->m_Weights[1] * (*scan_src2++); - dest_g += pWeight->m_Weights[1] * (*scan_src2++); - dest_r += pWeight->m_Weights[1] * (*scan_src2++); - dest_a += pWeight->m_Weights[1] * (*scan_src2++); - *scan_des++ = (uint8_t)((dest_b) >> 16); - *scan_des++ = (uint8_t)((dest_g) >> 16); - *scan_des++ = (uint8_t)((dest_r) >> 16); - *scan_des++ = (uint8_t)((dest_a) >> 16); - } break; - default: - return; - } - } - } - int dest_bottom = dest_top + m_sizeY; - if (dest_row + (int)scale_y >= dest_bottom - 1) { - uint8_t* scan_src = - (uint8_t*)pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet; - while (++dest_row < dest_bottom) { - uint8_t* scan_des = - (uint8_t*)pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet; - uint32_t size = m_sizeX * dest_Bpp; - memmove(scan_des, scan_src, size); - } - } -} - -void CCodec_ProgressiveDecoder::Resample( - const RetainPtr& pDeviceBitmap, - int32_t src_line, - uint8_t* src_scan, - FXCodec_Format src_format) { - int src_top = m_clipBox.top; - int dest_top = m_startY; - int src_height = m_clipBox.Height(); - int dest_height = m_sizeY; - if (src_line >= src_top) { - double scale_y = static_cast(dest_height) / src_height; - int src_row = src_line - src_top; - int dest_row = (int)(src_row * scale_y) + dest_top; - if (dest_row >= dest_top + dest_height) { - return; - } - ReSampleScanline(pDeviceBitmap, dest_row, m_pDecodeBuf, src_format); - if (scale_y > 1.0) { - ResampleVert(pDeviceBitmap, scale_y, dest_row); - } - } -} - -std::pair CCodec_ProgressiveDecoder::GetFrames() { - if (!(m_status == FXCODEC_STATUS_FRAME_READY || - m_status == FXCODEC_STATUS_FRAME_TOBECONTINUE)) { - return {FXCODEC_STATUS_ERROR, 0}; - } - - switch (m_imagType) { - case FXCODEC_IMAGE_JPG: - case FXCODEC_IMAGE_BMP: - case FXCODEC_IMAGE_PNG: -#ifdef PDF_ENABLE_XFA_TIFF - case FXCODEC_IMAGE_TIFF: -#endif // PDF_ENABLE_XFA_TIFF - m_FrameNumber = 1; - m_status = FXCODEC_STATUS_DECODE_READY; - return {m_status, 1}; - case FXCODEC_IMAGE_GIF: { - CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); - if (!pGifModule) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return {m_status, 0}; - } - while (true) { - CFX_GifDecodeStatus readResult; - std::tie(readResult, m_FrameNumber) = - pGifModule->LoadFrameInfo(m_pGifContext.get()); - while (readResult == CFX_GifDecodeStatus::Unfinished) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_READ; - if (!GifReadMoreData(pGifModule, error_status)) - return {error_status, 0}; - - std::tie(readResult, m_FrameNumber) = - pGifModule->LoadFrameInfo(m_pGifContext.get()); - } - if (readResult == CFX_GifDecodeStatus::Success) { - m_status = FXCODEC_STATUS_DECODE_READY; - return {m_status, m_FrameNumber}; - } - m_pGifContext = nullptr; - m_status = FXCODEC_STATUS_ERROR; - return {m_status, 0}; - } - } - default: - return {FXCODEC_STATUS_ERROR, 0}; - } -} - -FXCODEC_STATUS CCodec_ProgressiveDecoder::StartDecode( - const RetainPtr& pDIBitmap, - int start_x, - int start_y, - int size_x, - int size_y) { - if (m_status != FXCODEC_STATUS_DECODE_READY) - return FXCODEC_STATUS_ERROR; - - if (!pDIBitmap || pDIBitmap->GetBPP() < 8 || m_FrameNumber == 0) - return FXCODEC_STATUS_ERR_PARAMS; - - m_pDeviceBitmap = pDIBitmap; - if (m_clipBox.IsEmpty()) - return FXCODEC_STATUS_ERR_PARAMS; - if (size_x <= 0 || size_x > 65535 || size_y <= 0 || size_y > 65535) - return FXCODEC_STATUS_ERR_PARAMS; - - FX_RECT device_rc = - FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y); - int32_t out_range_x = device_rc.right - pDIBitmap->GetWidth(); - int32_t out_range_y = device_rc.bottom - pDIBitmap->GetHeight(); - device_rc.Intersect( - FX_RECT(0, 0, pDIBitmap->GetWidth(), pDIBitmap->GetHeight())); - if (device_rc.IsEmpty()) - return FXCODEC_STATUS_ERR_PARAMS; - - m_startX = device_rc.left; - m_startY = device_rc.top; - m_sizeX = device_rc.Width(); - m_sizeY = device_rc.Height(); - m_FrameCur = 0; - if (start_x < 0 || out_range_x > 0) { - float scaleX = (float)m_clipBox.Width() / (float)size_x; - if (start_x < 0) { - m_clipBox.left -= (int32_t)ceil((float)start_x * scaleX); - } - if (out_range_x > 0) { - m_clipBox.right -= (int32_t)floor((float)out_range_x * scaleX); - } - } - if (start_y < 0 || out_range_y > 0) { - float scaleY = (float)m_clipBox.Height() / (float)size_y; - if (start_y < 0) { - m_clipBox.top -= (int32_t)ceil((float)start_y * scaleY); - } - if (out_range_y > 0) { - m_clipBox.bottom -= (int32_t)floor((float)out_range_y * scaleY); - } - } - if (m_clipBox.IsEmpty()) { - return FXCODEC_STATUS_ERR_PARAMS; - } - switch (m_imagType) { - case FXCODEC_IMAGE_JPG: - return JpegStartDecode(pDIBitmap); - case FXCODEC_IMAGE_PNG: - return PngStartDecode(pDIBitmap); - case FXCODEC_IMAGE_GIF: - return GifStartDecode(pDIBitmap); - case FXCODEC_IMAGE_BMP: - return BmpStartDecode(pDIBitmap); -#ifdef PDF_ENABLE_XFA_TIFF - case FXCODEC_IMAGE_TIFF: - m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - return m_status; -#endif // PDF_ENABLE_XFA_TIFF - default: - return FXCODEC_STATUS_ERROR; - } -} - -FXCODEC_STATUS CCodec_ProgressiveDecoder::JpegStartDecode( - const RetainPtr& pDIBitmap) { - int down_scale = 1; - GetDownScale(down_scale); - // Setting jump marker before calling StartScanLine, since a longjmp to - // the marker indicates a fatal error. - if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) { - m_pJpegContext.reset(); - m_status = FXCODEC_STATUS_ERROR; - return FXCODEC_STATUS_ERROR; - } - - CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); - bool startStatus = - pJpegModule->StartScanline(m_pJpegContext.get(), down_scale); - while (!startStatus) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; - if (!JpegReadMoreData(pJpegModule, error_status)) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = error_status; - return m_status; - } - - startStatus = pJpegModule->StartScanline(m_pJpegContext.get(), down_scale); - } - int scanline_size = (m_SrcWidth + down_scale - 1) / down_scale; - scanline_size = (scanline_size * m_SrcComponents + 3) / 4 * 4; - FX_Free(m_pDecodeBuf); - m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); - memset(m_pDecodeBuf, 0, scanline_size); - m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, - m_clipBox.Width()); - m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); - switch (m_SrcComponents) { - case 1: - m_SrcFormat = FXCodec_8bppGray; - break; - case 3: - m_SrcFormat = FXCodec_Rgb; - break; - case 4: - m_SrcFormat = FXCodec_Cmyk; - break; - } - GetTransMethod(pDIBitmap->GetFormat(), m_SrcFormat); - m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - return m_status; -} - -FXCODEC_STATUS CCodec_ProgressiveDecoder::PngStartDecode( - const RetainPtr& pDIBitmap) { - CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); - if (!pPngModule) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - m_pPngContext = pPngModule->Start(this); - if (!m_pPngContext) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; + dest_r += pWeight->m_Weights[0] * (*scan_src1++); + dest_a += pWeight->m_Weights[0] * (*scan_src1++); + dest_b += pWeight->m_Weights[1] * (*scan_src2++); + dest_g += pWeight->m_Weights[1] * (*scan_src2++); + dest_r += pWeight->m_Weights[1] * (*scan_src2++); + dest_a += pWeight->m_Weights[1] * (*scan_src2++); + *scan_des++ = (uint8_t)((dest_b) >> 16); + *scan_des++ = (uint8_t)((dest_g) >> 16); + *scan_des++ = (uint8_t)((dest_r) >> 16); + *scan_des++ = (uint8_t)((dest_a) >> 16); + } break; + default: + return; + } + } } - m_offSet = 0; - switch (m_pDeviceBitmap->GetFormat()) { - case FXDIB_8bppMask: - case FXDIB_8bppRgb: - m_SrcComponents = 1; - m_SrcFormat = FXCodec_8bppGray; - break; - case FXDIB_Rgb: - m_SrcComponents = 3; - m_SrcFormat = FXCodec_Rgb; - break; - case FXDIB_Rgb32: - case FXDIB_Argb: - m_SrcComponents = 4; - m_SrcFormat = FXCodec_Argb; - break; - default: { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_PARAMS; - return m_status; + int dest_bottom = dest_top + m_sizeY; + if (dest_row + (int)scale_y >= dest_bottom - 1) { + uint8_t* scan_src = + (uint8_t*)pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet; + while (++dest_row < dest_bottom) { + uint8_t* scan_des = + (uint8_t*)pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet; + uint32_t size = m_sizeX * dest_Bpp; + memmove(scan_des, scan_src, size); } } - GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); - int scanline_size = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; - FX_Free(m_pDecodeBuf); - m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); - memset(m_pDecodeBuf, 0, scanline_size); - m_WeightHorzOO.Calc(m_sizeX, m_clipBox.Width()); - m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); - m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - return m_status; } -FXCODEC_STATUS CCodec_ProgressiveDecoder::GifStartDecode( - const RetainPtr& pDIBitmap) { - CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); - if (!pGifModule) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; +void CCodec_ProgressiveDecoder::Resample( + const RetainPtr& pDeviceBitmap, + int32_t src_line, + uint8_t* src_scan, + FXCodec_Format src_format) { + int src_top = m_clipBox.top; + int dest_top = m_startY; + int src_height = m_clipBox.Height(); + int dest_height = m_sizeY; + if (src_line >= src_top) { + double scale_y = static_cast(dest_height) / src_height; + int src_row = src_line - src_top; + int dest_row = (int)(src_row * scale_y) + dest_top; + if (dest_row >= dest_top + dest_height) { + return; + } + ReSampleScanline(pDeviceBitmap, dest_row, m_pDecodeBuf, src_format); + if (scale_y > 1.0) { + ResampleVert(pDeviceBitmap, scale_y, dest_row); + } } - m_SrcFormat = FXCodec_8bppRgb; - GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); - int scanline_size = (m_SrcWidth + 3) / 4 * 4; - FX_Free(m_pDecodeBuf); - m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); - memset(m_pDecodeBuf, 0, scanline_size); - m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, - m_clipBox.Width()); - m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); - m_FrameCur = 0; - m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - return m_status; } -FXCODEC_STATUS CCodec_ProgressiveDecoder::BmpStartDecode( - const RetainPtr& pDIBitmap) { - CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); - if (!pBmpModule) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; +std::pair CCodec_ProgressiveDecoder::GetFrames() { + if (!(m_status == FXCODEC_STATUS_FRAME_READY || + m_status == FXCODEC_STATUS_FRAME_TOBECONTINUE)) { + return {FXCODEC_STATUS_ERROR, 0}; } - GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); - m_ScanlineSize = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; - FX_Free(m_pDecodeBuf); - m_pDecodeBuf = FX_Alloc(uint8_t, m_ScanlineSize); - memset(m_pDecodeBuf, 0, m_ScanlineSize); - m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, - m_clipBox.Width()); - m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); - m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - return m_status; -} - -FXCODEC_STATUS CCodec_ProgressiveDecoder::ContinueDecode() { - if (m_status != FXCODEC_STATUS_DECODE_TOBECONTINUE) - return FXCODEC_STATUS_ERROR; switch (m_imagType) { case FXCODEC_IMAGE_JPG: - return JpegContinueDecode(); - case FXCODEC_IMAGE_PNG: - return PngContinueDecode(); - case FXCODEC_IMAGE_GIF: - return GifContinueDecode(); case FXCODEC_IMAGE_BMP: - return BmpContinueDecode(); +#ifdef PDF_ENABLE_XFA_PNG + case FXCODEC_IMAGE_PNG: +#endif // PDF_ENABLE_XFA_PNG #ifdef PDF_ENABLE_XFA_TIFF case FXCODEC_IMAGE_TIFF: - return TiffContinueDecode(); #endif // PDF_ENABLE_XFA_TIFF - default: - return FXCODEC_STATUS_ERROR; - } -} - -FXCODEC_STATUS CCodec_ProgressiveDecoder::JpegContinueDecode() { - CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); - // Setting jump marker before calling ReadScanLine, since a longjmp to - // the marker indicates a fatal error. - if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) { - m_pJpegContext.reset(); - m_status = FXCODEC_STATUS_ERROR; - return FXCODEC_STATUS_ERROR; - } - - while (true) { - bool readRes = - pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf); - while (!readRes) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; - if (!JpegReadMoreData(pJpegModule, error_status)) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = error_status; - return m_status; + m_FrameNumber = 1; + m_status = FXCODEC_STATUS_DECODE_READY; + return {m_status, 1}; + case FXCODEC_IMAGE_GIF: { + CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); + if (!pGifModule) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return {m_status, 0}; } - readRes = pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf); - } - if (m_SrcFormat == FXCodec_Rgb) { - int src_Bpp = (m_SrcFormat & 0xff) >> 3; - RGB2BGR(m_pDecodeBuf + m_clipBox.left * src_Bpp, m_clipBox.Width()); - } - if (m_SrcRow >= m_clipBox.bottom) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_DECODE_FINISH; - return m_status; - } - Resample(m_pDeviceBitmap, m_SrcRow, m_pDecodeBuf, m_SrcFormat); - m_SrcRow++; - } -} - -FXCODEC_STATUS CCodec_ProgressiveDecoder::PngContinueDecode() { - CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); - if (!pPngModule) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - while (true) { - uint32_t remain_size = (uint32_t)m_pFile->GetSize() - m_offSet; - uint32_t input_size = - remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size; - if (input_size == 0) { - m_pPngContext.reset(); - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_DECODE_FINISH; - return m_status; - } - if (m_pSrcBuf && input_size > m_SrcSize) { - FX_Free(m_pSrcBuf); - m_pSrcBuf = FX_Alloc(uint8_t, input_size); - memset(m_pSrcBuf, 0, input_size); - m_SrcSize = input_size; - } - bool bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size); - if (!bResult) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_READ; - return m_status; - } - m_offSet += input_size; - bResult = - pPngModule->Input(m_pPngContext.get(), m_pSrcBuf, input_size, nullptr); - if (!bResult) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERROR; - return m_status; - } - } -} - -FXCODEC_STATUS CCodec_ProgressiveDecoder::GifContinueDecode() { - CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); - if (!pGifModule) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } + while (true) { + CFX_GifDecodeStatus readResult; + std::tie(readResult, m_FrameNumber) = + pGifModule->LoadFrameInfo(m_pGifContext.get()); + while (readResult == CFX_GifDecodeStatus::Unfinished) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_READ; + if (!GifReadMoreData(pGifModule, error_status)) + return {error_status, 0}; - CFX_GifDecodeStatus readRes = - pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr); - while (readRes == CFX_GifDecodeStatus::Unfinished) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; - if (!GifReadMoreData(pGifModule, error_status)) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = error_status; - return m_status; + std::tie(readResult, m_FrameNumber) = + pGifModule->LoadFrameInfo(m_pGifContext.get()); + } + if (readResult == CFX_GifDecodeStatus::Success) { + m_status = FXCODEC_STATUS_DECODE_READY; + return {m_status, m_FrameNumber}; + } + m_pGifContext = nullptr; + m_status = FXCODEC_STATUS_ERROR; + return {m_status, 0}; + } } - readRes = pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr); + default: + return {FXCODEC_STATUS_ERROR, 0}; } +} - if (readRes == CFX_GifDecodeStatus::Success) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_DECODE_FINISH; - return m_status; - } +FXCODEC_STATUS CCodec_ProgressiveDecoder::StartDecode( + const RetainPtr& pDIBitmap, + int start_x, + int start_y, + int size_x, + int size_y) { + if (m_status != FXCODEC_STATUS_DECODE_READY) + return FXCODEC_STATUS_ERROR; - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERROR; - return m_status; -} + if (!pDIBitmap || pDIBitmap->GetBPP() < 8 || m_FrameNumber == 0) + return FXCODEC_STATUS_ERR_PARAMS; -FXCODEC_STATUS CCodec_ProgressiveDecoder::BmpContinueDecode() { - CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); - if (!pBmpModule) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - while (true) { - int32_t readRes = pBmpModule->LoadImage(m_pBmpContext.get()); - while (readRes == 2) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; - if (!BmpReadMoreData(pBmpModule, error_status)) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = error_status; - return m_status; - } - readRes = pBmpModule->LoadImage(m_pBmpContext.get()); + m_pDeviceBitmap = pDIBitmap; + if (m_clipBox.IsEmpty()) + return FXCODEC_STATUS_ERR_PARAMS; + if (size_x <= 0 || size_x > 65535 || size_y <= 0 || size_y > 65535) + return FXCODEC_STATUS_ERR_PARAMS; + + FX_RECT device_rc = + FX_RECT(start_x, start_y, start_x + size_x, start_y + size_y); + int32_t out_range_x = device_rc.right - pDIBitmap->GetWidth(); + int32_t out_range_y = device_rc.bottom - pDIBitmap->GetHeight(); + device_rc.Intersect( + FX_RECT(0, 0, pDIBitmap->GetWidth(), pDIBitmap->GetHeight())); + if (device_rc.IsEmpty()) + return FXCODEC_STATUS_ERR_PARAMS; + + m_startX = device_rc.left; + m_startY = device_rc.top; + m_sizeX = device_rc.Width(); + m_sizeY = device_rc.Height(); + m_FrameCur = 0; + if (start_x < 0 || out_range_x > 0) { + float scaleX = (float)m_clipBox.Width() / (float)size_x; + if (start_x < 0) { + m_clipBox.left -= (int32_t)ceil((float)start_x * scaleX); } - if (readRes == 1) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_DECODE_FINISH; - return m_status; + if (out_range_x > 0) { + m_clipBox.right -= (int32_t)floor((float)out_range_x * scaleX); } - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERROR; - return m_status; - } -} - -#ifdef PDF_ENABLE_XFA_TIFF -FXCODEC_STATUS CCodec_ProgressiveDecoder::TiffContinueDecode() { - CCodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule(); - if (!pTiffModule) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; } - bool ret = false; - if (m_pDeviceBitmap->GetBPP() == 32 && - m_pDeviceBitmap->GetWidth() == m_SrcWidth && m_SrcWidth == m_sizeX && - m_pDeviceBitmap->GetHeight() == m_SrcHeight && m_SrcHeight == m_sizeY && - m_startX == 0 && m_startY == 0 && m_clipBox.left == 0 && - m_clipBox.top == 0 && m_clipBox.right == m_SrcWidth && - m_clipBox.bottom == m_SrcHeight) { - ret = pTiffModule->Decode(m_pTiffContext.get(), m_pDeviceBitmap); - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - if (!ret) { - m_status = FXCODEC_STATUS_ERROR; - return m_status; + if (start_y < 0 || out_range_y > 0) { + float scaleY = (float)m_clipBox.Height() / (float)size_y; + if (start_y < 0) { + m_clipBox.top -= (int32_t)ceil((float)start_y * scaleY); + } + if (out_range_y > 0) { + m_clipBox.bottom -= (int32_t)floor((float)out_range_y * scaleY); } - m_status = FXCODEC_STATUS_DECODE_FINISH; - return m_status; - } - - auto pDIBitmap = pdfium::MakeRetain(); - pDIBitmap->Create(m_SrcWidth, m_SrcHeight, FXDIB_Argb); - if (!pDIBitmap->GetBuffer()) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - ret = pTiffModule->Decode(m_pTiffContext.get(), pDIBitmap); - if (!ret) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERROR; - return m_status; } - RetainPtr pClipBitmap = - (m_clipBox.left == 0 && m_clipBox.top == 0 && - m_clipBox.right == m_SrcWidth && m_clipBox.bottom == m_SrcHeight) - ? pDIBitmap - : pDIBitmap->Clone(&m_clipBox); - if (!pClipBitmap) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; + if (m_clipBox.IsEmpty()) { + return FXCODEC_STATUS_ERR_PARAMS; } - RetainPtr pFormatBitmap; - switch (m_pDeviceBitmap->GetFormat()) { - case FXDIB_8bppRgb: - pFormatBitmap = pdfium::MakeRetain(); - pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), - FXDIB_8bppRgb); - break; - case FXDIB_8bppMask: - pFormatBitmap = pdfium::MakeRetain(); - pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), - FXDIB_8bppMask); - break; - case FXDIB_Rgb: - pFormatBitmap = pdfium::MakeRetain(); - pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), - FXDIB_Rgb); - break; - case FXDIB_Rgb32: - pFormatBitmap = pdfium::MakeRetain(); - pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), - FXDIB_Rgb32); - break; - case FXDIB_Argb: - pFormatBitmap = pClipBitmap; - break; + switch (m_imagType) { + case FXCODEC_IMAGE_JPG: + return JpegStartDecode(pDIBitmap); +#ifdef PDF_ENABLE_XFA_PNG + case FXCODEC_IMAGE_PNG: + return PngStartDecode(pDIBitmap); +#endif // PDF_ENABLE_XFA_PNG + case FXCODEC_IMAGE_GIF: + return GifStartDecode(pDIBitmap); + case FXCODEC_IMAGE_BMP: + return BmpStartDecode(pDIBitmap); +#ifdef PDF_ENABLE_XFA_TIFF + case FXCODEC_IMAGE_TIFF: + m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + return m_status; +#endif // PDF_ENABLE_XFA_TIFF default: - break; + return FXCODEC_STATUS_ERROR; } - switch (m_pDeviceBitmap->GetFormat()) { - case FXDIB_8bppRgb: - case FXDIB_8bppMask: { - for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { - uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); - uint8_t* dest_line = (uint8_t*)pFormatBitmap->GetScanline(row); - for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { - uint8_t _a = 255 - src_line[3]; - uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; - uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; - uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255; - *dest_line++ = FXRGB2GRAY(r, g, b); - src_line += 4; - } - } - } break; - case FXDIB_Rgb: - case FXDIB_Rgb32: { - int32_t desBpp = (m_pDeviceBitmap->GetFormat() == FXDIB_Rgb) ? 3 : 4; - for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { - uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); - uint8_t* dest_line = (uint8_t*)pFormatBitmap->GetScanline(row); - for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { - uint8_t _a = 255 - src_line[3]; - uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; - uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; - uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255; - *dest_line++ = b; - *dest_line++ = g; - *dest_line++ = r; - dest_line += desBpp - 3; - src_line += 4; - } - } - } break; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::ContinueDecode() { + if (m_status != FXCODEC_STATUS_DECODE_TOBECONTINUE) + return FXCODEC_STATUS_ERROR; + + switch (m_imagType) { + case FXCODEC_IMAGE_JPG: + return JpegContinueDecode(); +#ifdef PDF_ENABLE_XFA_PNG + case FXCODEC_IMAGE_PNG: + return PngContinueDecode(); +#endif // PDF_ENABLE_XFA_PNG + case FXCODEC_IMAGE_GIF: + return GifContinueDecode(); + case FXCODEC_IMAGE_BMP: + return BmpContinueDecode(); +#ifdef PDF_ENABLE_XFA_TIFF + case FXCODEC_IMAGE_TIFF: + return TiffContinueDecode(); +#endif // PDF_ENABLE_XFA_TIFF default: - break; - } - if (!pFormatBitmap) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - RetainPtr pStrechBitmap = - pFormatBitmap->StretchTo(m_sizeX, m_sizeY, FXDIB_INTERPOL, nullptr); - pFormatBitmap = nullptr; - if (!pStrechBitmap) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; + return FXCODEC_STATUS_ERROR; } - m_pDeviceBitmap->TransferBitmap(m_startX, m_startY, m_sizeX, m_sizeY, - pStrechBitmap, 0, 0); - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_DECODE_FINISH; - return m_status; } -#endif // PDF_ENABLE_XFA_TIFF std::unique_ptr CCodec_ModuleMgr::CreateProgressiveDecoder() { diff --git a/core/fxcodec/fx_codec_def.h b/core/fxcodec/fx_codec_def.h index e4ac0437eb..b7944ee1c1 100644 --- a/core/fxcodec/fx_codec_def.h +++ b/core/fxcodec/fx_codec_def.h @@ -28,13 +28,16 @@ enum FXCODEC_IMAGE_TYPE { FXCODEC_IMAGE_UNKNOWN = 0, FXCODEC_IMAGE_BMP, FXCODEC_IMAGE_JPG, +#ifdef PDF_ENABLE_XFA_PNG FXCODEC_IMAGE_PNG, +#endif // PDF_ENABLE_XFA_PNG FXCODEC_IMAGE_GIF, #ifdef PDF_ENABLE_XFA_TIFF FXCODEC_IMAGE_TIFF, #endif // PDF_ENABLE_XFA_TIFF FXCODEC_IMAGE_MAX }; + enum FXCODEC_RESUNIT { FXCODEC_RESUNIT_NONE = 0, FXCODEC_RESUNIT_INCH, -- cgit v1.2.3