7#include "core/fxcodec/progressive_decoder.h"
14#include "build/build_config.h"
15#include "core/fxcodec/cfx_codec_memory.h"
16#include "core/fxcodec/jpeg/jpeg_progressive_decoder.h"
17#include "core/fxcrt/fx_safe_types.h"
18#include "core/fxcrt/fx_stream.h"
19#include "core/fxcrt/fx_system.h"
20#include "core/fxcrt/span_util.h"
21#include "core/fxge/dib/cfx_cmyk_to_srgb.h"
22#include "core/fxge/dib/cfx_dibitmap.h"
23#include "core/fxge/dib/fx_dib.h"
24#include "third_party/base/check.h"
25#include "third_party/base/check_op.h"
26#include "third_party/base/notreached.h"
27#include "third_party/base/numerics/safe_conversions.h"
29#ifdef PDF_ENABLE_XFA_BMP
30#include "core/fxcodec/bmp/bmp_progressive_decoder.h"
33#ifdef PDF_ENABLE_XFA_GIF
34#include "core/fxcodec/gif/gif_progressive_decoder.h"
37#ifdef PDF_ENABLE_XFA_TIFF
38#include "core/fxcodec/tiff/tiff_decoder.h"
45constexpr size_t kBlockSize = 4096;
47#ifdef PDF_ENABLE_XFA_PNG
48#if BUILDFLAG(IS_APPLE)
49const double kPngGamma = 1.7;
51const double kPngGamma = 2.2;
55void RGB2BGR(uint8_t* buffer,
int width = 1) {
56 if (buffer && width > 0) {
60 for (; i < width; i++, j += 3) {
62 buffer[j] = buffer[j + 2];
70ProgressiveDecoder::HorzTable::HorzTable() =
default;
72ProgressiveDecoder::HorzTable::~HorzTable() =
default;
74void ProgressiveDecoder::HorzTable::CalculateWeights(
int dest_len,
76 CHECK_GE(dest_len, 0);
78 pdfium::base::checked_cast<
int>(PixelWeight::TotalBytesForWeightCount(2));
79 FX_SAFE_SIZE_T safe_size = m_ItemSize;
80 safe_size *= dest_len;
81 m_pWeightTables.resize(safe_size.ValueOrDie(), 0);
82 double scale = (
double)dest_len / (
double)src_len;
85 for (
int src_col = 0; src_col < src_len; src_col++) {
86 double dest_col_f = src_col * scale;
88 PixelWeight* pWeight = GetPixelWeight(dest_col);
92 if (src_col == src_len - 1 && dest_col < dest_len - 1) {
93 for (
int dest_col_index = pre_dest_col + 1; dest_col_index < dest_len;
95 pWeight = GetPixelWeight(dest_col_index);
102 int dest_col_len = dest_col - pre_dest_col;
103 for (
int dest_col_index = pre_dest_col + 1; dest_col_index < dest_col;
105 pWeight = GetPixelWeight(dest_col_index);
109 ((
float)dest_col - (
float)dest_col_index) / (
float)dest_col_len
);
113 pre_dest_col = dest_col;
117 for (
int dest_col = 0; dest_col < dest_len; dest_col++) {
118 double src_col_f = dest_col / scale;
120 PixelWeight* pWeight = GetPixelWeight(dest_col);
127ProgressiveDecoder::VertTable::VertTable() =
default;
129ProgressiveDecoder::VertTable::~VertTable() =
default;
131void ProgressiveDecoder::VertTable::CalculateWeights(
int dest_len,
133 CHECK_GE(dest_len, 0);
135 pdfium::base::checked_cast<
int>(PixelWeight::TotalBytesForWeightCount(2));
136 FX_SAFE_SIZE_T safe_size = m_ItemSize;
137 safe_size *= dest_len;
138 m_pWeightTables.resize(safe_size.ValueOrDie(), 0);
139 double scale = (
double)dest_len / (
double)src_len;
141 for (
int dest_row = 0; dest_row < dest_len; dest_row++) {
142 PixelWeight* pWeight = GetPixelWeight(dest_row);
153 while (step < (
double)dest_len) {
154 int start_step = (
int)step;
155 step = scale * (++src_row);
156 int end_step = (
int)step;
157 if (end_step >= dest_len) {
159 for (
int dest_row = start_step; dest_row < end_step; dest_row++) {
160 PixelWeight* pWeight = GetPixelWeight(dest_row);
168 int length = end_step - start_step;
170 PixelWeight* pWeight = GetPixelWeight(start_step);
176 for (
int dest_row = start_step + 1; dest_row < end_step; dest_row++) {
177 PixelWeight* pWeight = GetPixelWeight(dest_row);
181 (
float)(end_step - dest_row) / (
float)length
);
192#ifdef PDF_ENABLE_XFA_PNG
356#ifdef PDF_ENABLE_XFA_GIF
510#ifdef PDF_ENABLE_XFA_BMP
758#ifdef PDF_ENABLE_XFA_GIF
919bool ProgressiveDecoder::JpegReadMoreData(
FXCODEC_STATUS* err_status) {
920 return ReadMoreData(JpegProgressiveDecoder::GetInstance(),
921 m_pJpegContext.get(), err_status);
924bool ProgressiveDecoder::JpegDetectImageTypeInBuffer(
925 CFX_DIBAttribute* pAttribute) {
926 m_pJpegContext = JpegProgressiveDecoder::Start();
927 if (!m_pJpegContext) {
931 JpegProgressiveDecoder::GetInstance()->Input(m_pJpegContext.get(),
936 if (setjmp(JpegProgressiveDecoder::GetJumpMark(m_pJpegContext.get())) == -1) {
937 m_pJpegContext.reset();
942 int32_t readResult = JpegProgressiveDecoder::ReadHeader(
943 m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight, &m_SrcComponents,
945 while (readResult == 2) {
947 if (!JpegReadMoreData(&error_status)) {
948 m_status = error_status;
951 readResult = JpegProgressiveDecoder::ReadHeader(
952 m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight, &m_SrcComponents,
960 m_pJpegContext.reset();
966 int down_scale = GetDownScale();
969 if (setjmp(JpegProgressiveDecoder::GetJumpMark(m_pJpegContext.get())) == -1) {
970 m_pJpegContext.reset();
976 JpegProgressiveDecoder::StartScanline(m_pJpegContext.get(), down_scale);
977 while (!startStatus) {
979 if (!JpegReadMoreData(&error_status)) {
980 m_pDeviceBitmap =
nullptr;
982 m_status = error_status;
987 JpegProgressiveDecoder::StartScanline(m_pJpegContext.get(), down_scale);
989 int scanline_size = (m_SrcWidth + down_scale - 1) / down_scale;
990 scanline_size = FxAlignToBoundary<4>(scanline_size * m_SrcComponents);
991 m_DecodeBuf.resize(scanline_size);
994 m_WeightHorz.CalculateWeights(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0,
995 m_clipBox.Width(), options);
996 m_WeightVert.CalculateWeights(m_sizeY, m_clipBox.Height());
997 switch (m_SrcComponents) {
1008 GetTransMethod(format, m_SrcFormat);
1017 if (setjmp(JpegProgressiveDecoder::GetJumpMark(m_pJpegContext.get())) == -1) {
1018 m_pJpegContext.reset();
1024 bool readRes = JpegProgressiveDecoder::ReadScanline(m_pJpegContext.get(),
1025 m_DecodeBuf.data());
1028 if (!JpegReadMoreData(&error_status)) {
1029 m_pDeviceBitmap =
nullptr;
1031 m_status = error_status;
1034 readRes = JpegProgressiveDecoder::ReadScanline(m_pJpegContext.get(),
1035 m_DecodeBuf.data());
1038 int src_Bpp = (m_SrcFormat & 0xff) >> 3;
1039 RGB2BGR(m_DecodeBuf.data() + m_clipBox.left * src_Bpp, m_clipBox.Width());
1041 if (m_SrcRow >= m_clipBox
.bottom) {
1042 m_pDeviceBitmap =
nullptr;
1047 Resample(m_pDeviceBitmap, m_SrcRow, m_DecodeBuf.data(), m_SrcFormat);
1052#ifdef PDF_ENABLE_XFA_PNG
1234#ifdef PDF_ENABLE_XFA_TIFF
1401bool ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType,
1402 CFX_DIBAttribute* pAttribute) {
1403#ifdef PDF_ENABLE_XFA_TIFF
1404 if (imageType == FXCODEC_IMAGE_TIFF)
1405 return TiffDetectImageTypeFromFile(pAttribute);
1408 size_t size = pdfium::base::checked_cast<size_t>(
1409 std::min<
FX_FILESIZE>(m_pFile->GetSize(), kBlockSize));
1410 m_pCodecMemory = pdfium::MakeRetain<CFX_CodecMemory>(size);
1412 if (!m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBufferSpan().first(size),
1419 if (imageType == FXCODEC_IMAGE_JPG)
1420 return JpegDetectImageTypeInBuffer(pAttribute);
1422#ifdef PDF_ENABLE_XFA_BMP
1423 if (imageType == FXCODEC_IMAGE_BMP)
1424 return BmpDetectImageTypeInBuffer(pAttribute);
1427#ifdef PDF_ENABLE_XFA_GIF
1428 if (imageType == FXCODEC_IMAGE_GIF)
1429 return GifDetectImageTypeInBuffer();
1432#ifdef PDF_ENABLE_XFA_PNG
1433 if (imageType == FXCODEC_IMAGE_PNG)
1434 return PngDetectImageTypeInBuffer(pAttribute);
1441bool ProgressiveDecoder::ReadMoreData(
1446 if (m_offSet >=
static_cast<uint32_t>(m_pFile->GetSize()))
1450 uint32_t dwBytesToFetchFromFile =
1451 pdfium::base::checked_cast<uint32_t>(m_pFile->GetSize() - m_offSet);
1454 size_t dwUnconsumed;
1455 FX_SAFE_SIZE_T avail_input = pModule->GetAvailInput(pContext);
1456 if (!avail_input.AssignIfValid(&dwUnconsumed))
1459 if (dwUnconsumed == m_pCodecMemory->GetSize()) {
1463 dwBytesToFetchFromFile =
1464 std::min<uint32_t>(dwBytesToFetchFromFile, kBlockSize);
1465 size_t dwNewSize = m_pCodecMemory->GetSize() + dwBytesToFetchFromFile;
1466 if (!m_pCodecMemory->TryResize(dwNewSize)) {
1474 size_t dwConsumable = m_pCodecMemory->GetSize() - dwUnconsumed;
1475 dwBytesToFetchFromFile = pdfium::base::checked_cast<uint32_t>(
1476 std::min<size_t>(dwBytesToFetchFromFile, dwConsumable));
1477 m_pCodecMemory->Consume(dwBytesToFetchFromFile);
1478 m_pCodecMemory->Seek(dwConsumable - dwBytesToFetchFromFile);
1479 dwUnconsumed += m_pCodecMemory->GetPosition();
1483 if (!m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBufferSpan().subspan(
1484 dwUnconsumed, dwBytesToFetchFromFile),
1489 m_offSet += dwBytesToFetchFromFile;
1490 return pModule->Input(pContext, m_pCodecMemory);
1495 FXCODEC_IMAGE_TYPE imageType,
1496 CFX_DIBAttribute* pAttribute,
1497 bool bSkipImageTypeCheck) {
1509 m_pFile = std::move(pFile);
1515 m_SrcWidth = m_SrcHeight = 0;
1516 m_SrcComponents = m_SrcBPC = 0;
1518 m_startX = m_startY = 0;
1519 m_sizeX = m_sizeY = 0;
1520 m_SrcPassNumber = 0;
1521 if (imageType != FXCODEC_IMAGE_UNKNOWN &&
1522 DetectImageType(imageType, pAttribute)) {
1523 m_imageType = imageType;
1530 if (bSkipImageTypeCheck)
1533 for (
int type = FXCODEC_IMAGE_UNKNOWN + 1; type < FXCODEC_IMAGE_MAX; type++) {
1534 if (DetectImageType(
static_cast<FXCODEC_IMAGE_TYPE>(type), pAttribute)) {
1535 m_imageType =
static_cast<FXCODEC_IMAGE_TYPE>(type);
1564int ProgressiveDecoder::GetDownScale() {
1566 int ratio_w = m_clipBox
.Width() / m_sizeX;
1567 int ratio_h = m_clipBox
.Height() / m_sizeY;
1568 int ratio =
std::min(ratio_w, ratio_h);
1571 else if (ratio >= 4)
1573 else if (ratio >= 2)
1576 m_clipBox
.left /= down_scale;
1577 m_clipBox
.right /= down_scale;
1578 m_clipBox
.top /= down_scale;
1579 m_clipBox
.bottom /= down_scale;
1587void ProgressiveDecoder::GetTransMethod(
FXDIB_Format dest_format,
1589 switch (dest_format) {
1592 switch (src_format) {
1602 switch (src_format) {
1626 switch (src_format) {
1651 switch (src_format) {
1685void ProgressiveDecoder::ResampleScanline(
1686 const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1688 pdfium::span<uint8_t> src_span,
1690 uint8_t* src_scan = src_span.data();
1691 int src_left = m_clipBox
.left;
1692 int dest_left = m_startX;
1693 uint8_t* dest_scan = pDeviceBitmap->GetWritableScanline(dest_line).data();
1694 int src_bytes_per_pixel = (src_format & 0xff) / 8;
1695 int dest_bytes_per_pixel = pDeviceBitmap->GetBPP() / 8;
1696 src_scan += src_left * src_bytes_per_pixel;
1697 dest_scan += dest_left * dest_bytes_per_pixel;
1698 for (
int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1699 PixelWeight* pPixelWeights = m_WeightHorz.GetPixelWeight(dest_col);
1700 switch (m_TransMethod) {
1708 uint32_t dest_g = 0;
1711 uint32_t pixel_weight =
1713 dest_g += pixel_weight * src_scan[j];
1718 uint32_t dest_r = 0;
1719 uint32_t dest_g = 0;
1720 uint32_t dest_b = 0;
1723 uint32_t pixel_weight =
1725 uint32_t argb = m_SrcPalette[src_scan[j]];
1726 dest_r += pixel_weight *
FXARGB_R(argb);
1727 dest_g += pixel_weight *
FXARGB_G(argb);
1728 dest_b += pixel_weight *
FXARGB_B(argb);
1730 *dest_scan++ =
static_cast<uint8_t>(
1736 uint32_t dest_b = 0;
1737 uint32_t dest_g = 0;
1738 uint32_t dest_r = 0;
1741 uint32_t pixel_weight =
1743 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1744 dest_b += pixel_weight * (*src_pixel++);
1745 dest_g += pixel_weight * (*src_pixel++);
1746 dest_r += pixel_weight * (*src_pixel);
1748 *dest_scan++ =
static_cast<uint8_t>(
1754 uint32_t dest_b = 0;
1755 uint32_t dest_g = 0;
1756 uint32_t dest_r = 0;
1759 uint32_t pixel_weight =
1761 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1765 std::tie(src_r, src_g, src_b) =
1766 AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1],
1767 255 - src_pixel[2], 255 - src_pixel[3]);
1768 dest_b += pixel_weight * src_b;
1769 dest_g += pixel_weight * src_g;
1770 dest_r += pixel_weight * src_r;
1772 *dest_scan++ =
static_cast<uint8_t>(
1780 uint32_t dest_g = 0;
1783 uint32_t pixel_weight =
1785 dest_g += pixel_weight * src_scan[j];
1788 dest_scan += dest_bytes_per_pixel;
1791 uint32_t dest_r = 0;
1792 uint32_t dest_g = 0;
1793 uint32_t dest_b = 0;
1796 uint32_t pixel_weight =
1798 uint32_t argb = m_SrcPalette[src_scan[j]];
1799 dest_r += pixel_weight *
FXARGB_R(argb);
1800 dest_g += pixel_weight *
FXARGB_G(argb);
1801 dest_b += pixel_weight *
FXARGB_B(argb);
1806 dest_scan += dest_bytes_per_pixel - 3;
1809#ifdef PDF_ENABLE_XFA_BMP
1810 if (m_pBmpContext) {
1811 uint32_t dest_r = 0;
1812 uint32_t dest_g = 0;
1813 uint32_t dest_b = 0;
1814 for (
int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
1816 uint32_t pixel_weight =
1817 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1818 uint32_t argb = m_SrcPalette[src_scan[j]];
1819 dest_r += pixel_weight * FXARGB_R(argb);
1820 dest_g += pixel_weight * FXARGB_G(argb);
1821 dest_b += pixel_weight * FXARGB_B(argb);
1823 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1824 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1825 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1826 *dest_scan++ = 0xFF;
1830 uint32_t dest_a = 0;
1831 uint32_t dest_r = 0;
1832 uint32_t dest_g = 0;
1833 uint32_t dest_b = 0;
1836 uint32_t pixel_weight =
1838 unsigned long argb = m_SrcPalette[src_scan[j]];
1839 dest_a += pixel_weight *
FXARGB_A(argb);
1840 dest_r += pixel_weight *
FXARGB_R(argb);
1841 dest_g += pixel_weight *
FXARGB_G(argb);
1842 dest_b += pixel_weight *
FXARGB_B(argb);
1850 uint32_t dest_b = 0;
1851 uint32_t dest_g = 0;
1852 uint32_t dest_r = 0;
1855 uint32_t pixel_weight =
1857 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1858 dest_b += pixel_weight * (*src_pixel++);
1859 dest_g += pixel_weight * (*src_pixel++);
1860 dest_r += pixel_weight * (*src_pixel);
1865 dest_scan += dest_bytes_per_pixel - 3;
1868 uint32_t dest_b = 0;
1869 uint32_t dest_g = 0;
1870 uint32_t dest_r = 0;
1873 uint32_t pixel_weight =
1875 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1879 std::tie(src_r, src_g, src_b) =
1880 AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1],
1881 255 - src_pixel[2], 255 - src_pixel[3]);
1882 dest_b += pixel_weight * src_b;
1883 dest_g += pixel_weight * src_g;
1884 dest_r += pixel_weight * src_r;
1889 dest_scan += dest_bytes_per_pixel - 3;
1892 uint32_t dest_alpha = 0;
1893 uint32_t dest_r = 0;
1894 uint32_t dest_g = 0;
1895 uint32_t dest_b = 0;
1898 uint32_t pixel_weight =
1900 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1901 pixel_weight = pixel_weight * src_pixel[3] / 255;
1902 dest_b += pixel_weight * (*src_pixel++);
1903 dest_g += pixel_weight * (*src_pixel++);
1904 dest_r += pixel_weight * (*src_pixel);
1905 dest_alpha += pixel_weight;
1918void ProgressiveDecoder::ResampleVert(
1919 const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1922 int dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
1923 uint32_t dest_ScanOffset = m_startX * dest_Bpp;
1924 int dest_top = m_startY;
1925 FX_SAFE_INT32 check_dest_row_1 = dest_row;
1926 check_dest_row_1 -= pdfium::base::checked_cast<
int>(scale_y);
1927 int dest_row_1 = check_dest_row_1.ValueOrDie();
1928 if (dest_row_1 < dest_top) {
1929 int dest_bottom = dest_top + m_sizeY;
1930 if (dest_row + (
int)scale_y >= dest_bottom - 1) {
1931 pdfium::span<
const uint8_t> scan_src =
1932 pDeviceBitmap->GetScanline(dest_row).subspan(dest_ScanOffset,
1933 m_sizeX * dest_Bpp);
1934 while (++dest_row < dest_bottom) {
1935 fxcrt::spanmove(pDeviceBitmap->GetWritableScanline(dest_row).subspan(
1942 for (; dest_row_1 < dest_row; dest_row_1++) {
1943 uint8_t* scan_des = pDeviceBitmap->GetWritableScanline(dest_row_1)
1944 .subspan(dest_ScanOffset)
1946 PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top);
1947 const uint8_t* scan_src1 =
1948 pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top)
1949 .subspan(dest_ScanOffset)
1951 const uint8_t* scan_src2 =
1952 pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + dest_top)
1953 .subspan(dest_ScanOffset)
1955 switch (pDeviceBitmap->GetFormat()) {
1956 case FXDIB_Format::kInvalid:
1957 case FXDIB_Format::k1bppMask:
1958 case FXDIB_Format::k1bppRgb:
1960 case FXDIB_Format::k8bppMask:
1961 case FXDIB_Format::k8bppRgb:
1962 if (pDeviceBitmap->HasPalette())
1964 for (
int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1965 uint32_t dest_g = 0;
1971 case FXDIB_Format::kRgb:
1972 case FXDIB_Format::kRgb32:
1973 for (
int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1974 uint32_t dest_b = pWeight
->m_Weights[0] * (*scan_src1++);
1975 uint32_t dest_g = pWeight
->m_Weights[0] * (*scan_src1++);
1976 uint32_t dest_r = pWeight
->m_Weights[0] * (*scan_src1++);
1977 scan_src1 += dest_Bpp - 3;
1981 scan_src2 += dest_Bpp - 3;
1985 scan_des += dest_Bpp - 3;
1988 case FXDIB_Format::kArgb:
1989 for (
int dest_col = 0; dest_col < m_sizeX; dest_col++) {
1990 uint32_t dest_b = pWeight
->m_Weights[0] * (*scan_src1++);
1991 uint32_t dest_g = pWeight
->m_Weights[0] * (*scan_src1++);
1992 uint32_t dest_r = pWeight
->m_Weights[0] * (*scan_src1++);
1993 uint32_t dest_a = pWeight
->m_Weights[0] * (*scan_src1++);
2006 int dest_bottom = dest_top + m_sizeY;
2007 if (dest_row + (
int)scale_y >= dest_bottom - 1) {
2008 pdfium::span<
const uint8_t> scan_src =
2009 pDeviceBitmap->GetScanline(dest_row).subspan(dest_ScanOffset,
2010 m_sizeX * dest_Bpp);
2011 while (++dest_row < dest_bottom) {
2013 pDeviceBitmap->GetWritableScanline(dest_row).subspan(dest_ScanOffset),
2019void ProgressiveDecoder::Resample(
const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
2023 int src_top = m_clipBox
.top;
2024 int dest_top = m_startY;
2026 int dest_height = m_sizeY;
2027 if (src_line >= src_top) {
2028 double scale_y =
static_cast<
double>(dest_height) / src_height;
2029 int src_row = src_line - src_top;
2030 int dest_row = (
int)(src_row * scale_y) + dest_top;
2031 if (dest_row >= dest_top + dest_height)
2034 ResampleScanline(pDeviceBitmap, dest_row, m_DecodeBuf, src_format);
2036 ResampleVert(pDeviceBitmap, scale_y, dest_row);
2046 switch (m_imageType) {
2047#ifdef PDF_ENABLE_XFA_BMP
2048 case FXCODEC_IMAGE_BMP:
2050 case FXCODEC_IMAGE_JPG:
2051#ifdef PDF_ENABLE_XFA_PNG
2052 case FXCODEC_IMAGE_PNG:
2054#ifdef PDF_ENABLE_XFA_TIFF
2055 case FXCODEC_IMAGE_TIFF:
2059 return {m_status, 1};
2060#ifdef PDF_ENABLE_XFA_GIF
2061 case FXCODEC_IMAGE_GIF: {
2063 GifDecoder::Status readResult;
2064 std::tie(readResult, m_FrameNumber) =
2065 GifDecoder::LoadFrameInfo(m_pGifContext.get());
2066 while (readResult == GifDecoder::Status::kUnfinished) {
2067 FXCODEC_STATUS error_status = FXCODEC_STATUS::kError;
2068 if (!GifReadMoreData(&error_status))
2069 return {error_status, 0};
2071 std::tie(readResult, m_FrameNumber) =
2072 GifDecoder::LoadFrameInfo(m_pGifContext.get());
2074 if (readResult == GifDecoder::Status::kSuccess) {
2075 m_status = FXCODEC_STATUS::kDecodeReady;
2076 return {m_status, m_FrameNumber};
2078 m_pGifContext =
nullptr;
2079 m_status = FXCODEC_STATUS::kError;
2080 return {m_status, 0};
2090 const RetainPtr<CFX_DIBitmap>& pDIBitmap,
2098 if (!pDIBitmap || pDIBitmap->GetBPP() < 8 || m_FrameNumber == 0)
2101 m_pDeviceBitmap = pDIBitmap;
2104 if (size_x <= 0 || size_x > 65535 || size_y <= 0 || size_y > 65535)
2108 FX_RECT(start_x
, start_y
, start_x + size_x
, start_y + size_y
);
2109 int32_t out_range_x = device_rc.right - pDIBitmap->GetWidth();
2110 int32_t out_range_y = device_rc.bottom - pDIBitmap->GetHeight();
2111 device_rc.Intersect(
2112 FX_RECT(0, 0, pDIBitmap->GetWidth(), pDIBitmap->GetHeight()));
2116 m_startX = device_rc
.left;
2117 m_startY = device_rc
.top;
2121 if (start_x < 0 || out_range_x > 0) {
2122 float scaleX = (
float)m_clipBox
.Width() / (
float)size_x;
2124 m_clipBox
.left -=
static_cast<int32_t>(ceil((
float)start_x * scaleX));
2126 if (out_range_x > 0) {
2128 static_cast<int32_t>(floor((
float)out_range_x * scaleX));
2131 if (start_y < 0 || out_range_y > 0) {
2132 float scaleY = (
float)m_clipBox
.Height() / (
float)size_y;
2134 m_clipBox
.top -=
static_cast<int32_t>(ceil((
float)start_y * scaleY));
2136 if (out_range_y > 0) {
2138 static_cast<int32_t>(floor((
float)out_range_y * scaleY));
2144 switch (m_imageType) {
2145#ifdef PDF_ENABLE_XFA_BMP
2146 case FXCODEC_IMAGE_BMP:
2147 return BmpStartDecode();
2149#ifdef PDF_ENABLE_XFA_GIF
2150 case FXCODEC_IMAGE_GIF:
2151 return GifStartDecode();
2153 case FXCODEC_IMAGE_JPG:
2154 return JpegStartDecode(pDIBitmap->GetFormat());
2155#ifdef PDF_ENABLE_XFA_PNG
2156 case FXCODEC_IMAGE_PNG:
2157 return PngStartDecode();
2159#ifdef PDF_ENABLE_XFA_TIFF
2160 case FXCODEC_IMAGE_TIFF:
2161 m_status = FXCODEC_STATUS::kDecodeToBeContinued;
2173 switch (m_imageType) {
2174 case FXCODEC_IMAGE_JPG:
2175 return JpegContinueDecode();
2176#ifdef PDF_ENABLE_XFA_BMP
2177 case FXCODEC_IMAGE_BMP:
2178 return BmpContinueDecode();
2180#ifdef PDF_ENABLE_XFA_GIF
2181 case FXCODEC_IMAGE_GIF:
2182 return GifContinueDecode();
2184#ifdef PDF_ENABLE_XFA_PNG
2185 case FXCODEC_IMAGE_PNG:
2186 return PngContinueDecode();
2188#ifdef PDF_ENABLE_XFA_TIFF
2189 case FXCODEC_IMAGE_TIFF:
2190 return TiffContinueDecode();
static uint32_t FixedFromFloat(float f)
static uint8_t PixelFromFixed(uint32_t fixed)
static constexpr uint32_t kFixedPointOne
FXCODEC_STATUS ContinueDecode()
void SetClipBox(FX_RECT *clip)
virtual ~ProgressiveDecoder()
std::pair< FXCODEC_STATUS, size_t > GetFrames()
FXCODEC_STATUS LoadImageInfo(RetainPtr< IFX_SeekableReadStream > pFile, FXCODEC_IMAGE_TYPE imageType, CFX_DIBAttribute *pAttribute, bool bSkipImageTypeCheck)
FXCODEC_STATUS StartDecode(const RetainPtr< CFX_DIBitmap > &pDIBitmap, int start_x, int start_y, int size_x, int size_y)
#define FXRGB2GRAY(r, g, b)
int FXSYS_roundf(float f)
bool bInterpolateBilinear
FX_RECT & operator=(const FX_RECT &that)=default
constexpr FX_RECT()=default
constexpr FX_RECT(int l, int t, int r, int b)