7#include "core/fxcodec/progressive_decoder.h"
13#include "build/build_config.h"
14#include "core/fxcodec/cfx_codec_memory.h"
15#include "core/fxcodec/jpeg/jpeg_progressive_decoder.h"
16#include "core/fxcrt/check.h"
17#include "core/fxcrt/check_op.h"
18#include "core/fxcrt/compiler_specific.h"
19#include "core/fxcrt/fx_2d_size.h"
20#include "core/fxcrt/fx_memcpy_wrappers.h"
21#include "core/fxcrt/fx_safe_types.h"
22#include "core/fxcrt/fx_stream.h"
23#include "core/fxcrt/fx_system.h"
24#include "core/fxcrt/notreached.h"
25#include "core/fxcrt/numerics/safe_conversions.h"
26#include "core/fxcrt/span_util.h"
27#include "core/fxcrt/stl_util.h"
28#include "core/fxge/dib/cfx_cmyk_to_srgb.h"
29#include "core/fxge/dib/cfx_dibitmap.h"
30#include "core/fxge/dib/fx_dib.h"
32#ifdef PDF_ENABLE_XFA_BMP
33#include "core/fxcodec/bmp/bmp_progressive_decoder.h"
36#ifdef PDF_ENABLE_XFA_GIF
37#include "core/fxcodec/gif/gif_progressive_decoder.h"
40#ifdef PDF_ENABLE_XFA_TIFF
41#include "core/fxcodec/tiff/tiff_decoder.h"
48constexpr size_t kBlockSize = 4096;
50#ifdef PDF_ENABLE_XFA_PNG
51#if BUILDFLAG(IS_APPLE)
52const double kPngGamma = 1.7;
54const double kPngGamma = 2.2;
58void RGB2BGR(uint8_t* buffer,
int width = 1) {
59 if (buffer && width > 0) {
64 for (; i < width; i++, j += 3) {
66 buffer[j] = buffer[j + 2];
79#ifdef PDF_ENABLE_XFA_PNG
125#if defined(PDF_USE_SKIA)
163#ifdef PDF_ENABLE_XFA_GIF
282#ifdef PDF_ENABLE_XFA_BMP
418#ifdef PDF_ENABLE_XFA_GIF
493bool ProgressiveDecoder::JpegReadMoreData(
FXCODEC_STATUS* err_status) {
494 return ReadMoreData(JpegProgressiveDecoder::GetInstance(),
495 m_pJpegContext.get(), err_status);
498bool ProgressiveDecoder::JpegDetectImageTypeInBuffer(
499 CFX_DIBAttribute* pAttribute) {
500 m_pJpegContext = JpegProgressiveDecoder::Start();
501 if (!m_pJpegContext) {
505 JpegProgressiveDecoder::GetInstance()->Input(m_pJpegContext.get(),
510 if (setjmp(JpegProgressiveDecoder::GetJumpMark(m_pJpegContext.get())) == -1) {
511 m_pJpegContext.reset();
516 int32_t readResult = JpegProgressiveDecoder::ReadHeader(
517 m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight, &m_SrcComponents,
519 while (readResult == 2) {
521 if (!JpegReadMoreData(&error_status)) {
522 m_status = error_status;
525 readResult = JpegProgressiveDecoder::ReadHeader(
526 m_pJpegContext.get(), &m_SrcWidth, &m_SrcHeight, &m_SrcComponents,
533 m_pJpegContext.reset();
541 if (setjmp(JpegProgressiveDecoder::GetJumpMark(m_pJpegContext.get())) == -1) {
542 m_pJpegContext.reset();
548 JpegProgressiveDecoder::StartScanline(m_pJpegContext.get());
549 while (!start_status) {
551 if (!JpegReadMoreData(&error_status)) {
552 m_pDeviceBitmap =
nullptr;
554 m_status = error_status;
558 start_status = JpegProgressiveDecoder::StartScanline(m_pJpegContext.get());
560 m_DecodeBuf.resize(FxAlignToBoundary<4>(m_SrcWidth * m_SrcComponents));
563 m_WeightHorz.CalculateWeights(m_SrcWidth, 0, m_SrcWidth, m_SrcWidth, 0,
564 m_SrcWidth, options);
565 switch (m_SrcComponents) {
585 if (setjmp(JpegProgressiveDecoder::GetJumpMark(m_pJpegContext.get())) == -1) {
586 m_pJpegContext.reset();
592 bool readRes = JpegProgressiveDecoder::ReadScanline(m_pJpegContext.get(),
596 if (!JpegReadMoreData(&error_status)) {
597 m_pDeviceBitmap =
nullptr;
599 m_status = error_status;
602 readRes = JpegProgressiveDecoder::ReadScanline(m_pJpegContext.get(),
606 RGB2BGR(
UNSAFE_TODO(m_DecodeBuf.data()), m_SrcWidth);
608 if (m_SrcRow >= m_SrcHeight) {
609 m_pDeviceBitmap =
nullptr;
614 Resample(m_pDeviceBitmap, m_SrcRow, m_DecodeBuf.data(), m_SrcFormat);
619#ifdef PDF_ENABLE_XFA_PNG
708#ifdef PDF_ENABLE_XFA_TIFF
742bool ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType,
743 CFX_DIBAttribute* pAttribute) {
744#ifdef PDF_ENABLE_XFA_TIFF
745 if (imageType == FXCODEC_IMAGE_TIFF)
746 return TiffDetectImageTypeFromFile(pAttribute);
749 size_t size = pdfium::checked_cast<size_t>(
750 std::min<
FX_FILESIZE>(m_pFile->GetSize(), kBlockSize));
751 m_pCodecMemory = pdfium::MakeRetain<CFX_CodecMemory>(size);
753 if (!m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBufferSpan().first(size),
760 if (imageType == FXCODEC_IMAGE_JPG)
761 return JpegDetectImageTypeInBuffer(pAttribute);
763#ifdef PDF_ENABLE_XFA_BMP
764 if (imageType == FXCODEC_IMAGE_BMP)
765 return BmpDetectImageTypeInBuffer(pAttribute);
768#ifdef PDF_ENABLE_XFA_GIF
769 if (imageType == FXCODEC_IMAGE_GIF)
770 return GifDetectImageTypeInBuffer();
773#ifdef PDF_ENABLE_XFA_PNG
774 if (imageType == FXCODEC_IMAGE_PNG)
775 return PngDetectImageTypeInBuffer(pAttribute);
782bool ProgressiveDecoder::ReadMoreData(
787 if (m_offSet >=
static_cast<uint32_t>(m_pFile->GetSize()))
791 uint32_t dwBytesToFetchFromFile =
792 pdfium::checked_cast<uint32_t>(m_pFile->GetSize() - m_offSet);
797 if (!avail_input.AssignIfValid(&dwUnconsumed))
800 if (dwUnconsumed == m_pCodecMemory->GetSize()) {
804 dwBytesToFetchFromFile =
805 std::min<uint32_t>(dwBytesToFetchFromFile, kBlockSize);
806 size_t dwNewSize = m_pCodecMemory->GetSize() + dwBytesToFetchFromFile;
807 if (!m_pCodecMemory->TryResize(dwNewSize)) {
815 size_t dwConsumable = m_pCodecMemory->GetSize() - dwUnconsumed;
816 dwBytesToFetchFromFile = pdfium::checked_cast<uint32_t>(
817 std::min<size_t>(dwBytesToFetchFromFile, dwConsumable));
818 m_pCodecMemory->Consume(dwBytesToFetchFromFile);
819 m_pCodecMemory->Seek(dwConsumable - dwBytesToFetchFromFile);
820 dwUnconsumed += m_pCodecMemory->GetPosition();
824 if (!m_pFile->ReadBlockAtOffset(m_pCodecMemory->GetBufferSpan().subspan(
825 dwUnconsumed, dwBytesToFetchFromFile),
830 m_offSet += dwBytesToFetchFromFile;
831 return pModule->Input(pContext, m_pCodecMemory);
836 FXCODEC_IMAGE_TYPE imageType,
837 CFX_DIBAttribute* pAttribute,
838 bool bSkipImageTypeCheck) {
851 m_pFile = std::move(pFile);
862 if (imageType != FXCODEC_IMAGE_UNKNOWN &&
863 DetectImageType(imageType, pAttribute)) {
864 m_imageType = imageType;
871 if (bSkipImageTypeCheck)
874 for (
int type = FXCODEC_IMAGE_UNKNOWN + 1; type < FXCODEC_IMAGE_MAX; type++) {
875 if (DetectImageType(
static_cast<FXCODEC_IMAGE_TYPE>(type), pAttribute)) {
876 m_imageType =
static_cast<FXCODEC_IMAGE_TYPE>(type);
886void ProgressiveDecoder::SetTransMethod() {
887 switch (m_pDeviceBitmap->GetFormat()) {
888 case FXDIB_Format::kInvalid:
889 case FXDIB_Format::k1bppMask:
890 case FXDIB_Format::k1bppRgb:
891 case FXDIB_Format::k8bppMask:
892 case FXDIB_Format::k8bppRgb:
894 case FXDIB_Format::kBgr: {
895 switch (m_SrcFormat) {
897 m_TransMethod = TransformMethod::kInvalid;
900 m_TransMethod = TransformMethod::k8BppGrayToRgbMaybeAlpha;
903 m_TransMethod = TransformMethod::k8BppRgbToRgbNoAlpha;
908 m_TransMethod = TransformMethod::kRgbMaybeAlphaToRgbMaybeAlpha;
911 m_TransMethod = TransformMethod::kCmykToRgbMaybeAlpha;
916 case FXDIB_Format::kBgrx:
917 case FXDIB_Format::kBgra: {
918 switch (m_SrcFormat) {
920 m_TransMethod = TransformMethod::kInvalid;
923 m_TransMethod = TransformMethod::k8BppGrayToRgbMaybeAlpha;
926 if (m_pDeviceBitmap->GetFormat() == FXDIB_Format::kBgra) {
927 m_TransMethod = TransformMethod::k8BppRgbToArgb;
929 m_TransMethod = TransformMethod::k8BppRgbToRgbNoAlpha;
934 m_TransMethod = TransformMethod::kRgbMaybeAlphaToRgbMaybeAlpha;
937 m_TransMethod = TransformMethod::kCmykToRgbMaybeAlpha;
940 m_TransMethod = TransformMethod::kArgbToArgb;
945#if defined(PDF_USE_SKIA)
946 case FXDIB_Format::kBgraPremul:
949 NOTREACHED_NORETURN();
954void ProgressiveDecoder::ResampleScanline(
955 const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
957 pdfium::span<uint8_t> src_span,
959 uint8_t* src_scan = src_span.data();
960 uint8_t* dest_scan = pDeviceBitmap->GetWritableScanline(dest_line).data();
961 const int src_bytes_per_pixel = (src_format & 0xff) / 8;
962 const int dest_bytes_per_pixel = pDeviceBitmap->GetBPP() / 8;
963 for (
int dest_col = 0; dest_col < m_SrcWidth; dest_col++) {
965 m_WeightHorz.GetPixelWeight(dest_col);
966 switch (m_TransMethod) {
967 case TransformMethod::kInvalid:
969 case TransformMethod::k8BppGrayToRgbMaybeAlpha: {
974 uint32_t pixel_weight =
976 dest_g += pixel_weight * src_scan[j];
979 dest_scan += dest_bytes_per_pixel;
983 case TransformMethod::k8BppRgbToRgbNoAlpha: {
990 uint32_t pixel_weight =
992 uint32_t argb = m_SrcPalette[src_scan[j]];
993 dest_r += pixel_weight *
FXARGB_R(argb);
994 dest_g += pixel_weight *
FXARGB_G(argb);
995 dest_b += pixel_weight *
FXARGB_B(argb);
1000 dest_scan += dest_bytes_per_pixel - 3;
1004 case TransformMethod::k8BppRgbToArgb: {
1005#ifdef PDF_ENABLE_XFA_BMP
1006 if (m_pBmpContext) {
1008 uint32_t dest_r = 0;
1009 uint32_t dest_g = 0;
1010 uint32_t dest_b = 0;
1011 for (
int j = pPixelWeights->m_SrcStart;
1012 j <= pPixelWeights->m_SrcEnd; j++) {
1013 uint32_t pixel_weight =
1014 pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
1015 uint32_t argb = m_SrcPalette[src_scan[j]];
1016 dest_r += pixel_weight * FXARGB_R(argb);
1017 dest_g += pixel_weight * FXARGB_G(argb);
1018 dest_b += pixel_weight * FXARGB_B(argb);
1020 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
1021 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
1022 *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
1023 *dest_scan++ = 0xFF;
1029 uint32_t dest_a = 0;
1030 uint32_t dest_r = 0;
1031 uint32_t dest_g = 0;
1032 uint32_t dest_b = 0;
1035 uint32_t pixel_weight =
1037 FX_ARGB argb = m_SrcPalette[src_scan[j]];
1038 dest_a += pixel_weight *
FXARGB_A(argb);
1039 dest_r += pixel_weight *
FXARGB_R(argb);
1040 dest_g += pixel_weight *
FXARGB_G(argb);
1041 dest_b += pixel_weight *
FXARGB_B(argb);
1050 case TransformMethod::kRgbMaybeAlphaToRgbMaybeAlpha: {
1052 uint32_t dest_b = 0;
1053 uint32_t dest_g = 0;
1054 uint32_t dest_r = 0;
1057 uint32_t pixel_weight =
1059 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1060 dest_b += pixel_weight * (*src_pixel++);
1061 dest_g += pixel_weight * (*src_pixel++);
1062 dest_r += pixel_weight * (*src_pixel);
1067 dest_scan += dest_bytes_per_pixel - 3;
1071 case TransformMethod::kCmykToRgbMaybeAlpha: {
1073 uint32_t dest_b = 0;
1074 uint32_t dest_g = 0;
1075 uint32_t dest_r = 0;
1078 uint32_t pixel_weight =
1080 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1082 AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1],
1083 255 - src_pixel[2], 255 - src_pixel[3]);
1084 dest_b += pixel_weight * src_rgb.blue;
1085 dest_g += pixel_weight * src_rgb.green;
1086 dest_r += pixel_weight * src_rgb.red;
1091 dest_scan += dest_bytes_per_pixel - 3;
1095 case TransformMethod::kArgbToArgb: {
1097 uint32_t dest_alpha = 0;
1098 uint32_t dest_r = 0;
1099 uint32_t dest_g = 0;
1100 uint32_t dest_b = 0;
1103 uint32_t pixel_weight =
1105 const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
1106 pixel_weight = pixel_weight * src_pixel[3] / 255;
1107 dest_b += pixel_weight * (*src_pixel++);
1108 dest_g += pixel_weight * (*src_pixel++);
1109 dest_r += pixel_weight * (*src_pixel);
1110 dest_alpha += pixel_weight;
1123void ProgressiveDecoder::Resample(
const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
1127 if (src_line < 0 || src_line >= m_SrcHeight) {
1131 ResampleScanline(pDeviceBitmap, src_line, m_DecodeBuf, src_format);
1135 switch (m_imageType) {
1136 case FXCODEC_IMAGE_JPG:
1137#ifdef PDF_ENABLE_XFA_BMP
1138 case FXCODEC_IMAGE_BMP:
1141#ifdef PDF_ENABLE_XFA_PNG
1142 case FXCODEC_IMAGE_PNG:
1144#ifdef PDF_ENABLE_XFA_TIFF
1145 case FXCODEC_IMAGE_TIFF:
1160 switch (m_imageType) {
1161#ifdef PDF_ENABLE_XFA_BMP
1162 case FXCODEC_IMAGE_BMP:
1164 case FXCODEC_IMAGE_JPG:
1165#ifdef PDF_ENABLE_XFA_PNG
1166 case FXCODEC_IMAGE_PNG:
1168#ifdef PDF_ENABLE_XFA_TIFF
1169 case FXCODEC_IMAGE_TIFF:
1173 return {m_status, 1};
1174#ifdef PDF_ENABLE_XFA_GIF
1175 case FXCODEC_IMAGE_GIF: {
1177 GifDecoder::Status readResult;
1178 std::tie(readResult, m_FrameNumber) =
1179 GifDecoder::LoadFrameInfo(m_pGifContext.get());
1180 while (readResult == GifDecoder::Status::kUnfinished) {
1181 FXCODEC_STATUS error_status = FXCODEC_STATUS::kError;
1182 if (!GifReadMoreData(&error_status))
1183 return {error_status, 0};
1185 std::tie(readResult, m_FrameNumber) =
1186 GifDecoder::LoadFrameInfo(m_pGifContext.get());
1188 if (readResult == GifDecoder::Status::kSuccess) {
1189 m_status = FXCODEC_STATUS::kDecodeReady;
1190 return {m_status, m_FrameNumber};
1192 m_pGifContext =
nullptr;
1193 m_status = FXCODEC_STATUS::kError;
1194 return {m_status, 0};
1205 CHECK_EQ(bitmap->GetWidth(), m_SrcWidth);
1206 CHECK_EQ(bitmap->GetHeight(), m_SrcHeight);
1218 if (m_FrameNumber == 0) {
1222 if (bitmap->GetWidth() > 65535 || bitmap->GetHeight() > 65535) {
1227 m_pDeviceBitmap = std::move(bitmap);
1228 switch (m_imageType) {
1229#ifdef PDF_ENABLE_XFA_BMP
1230 case FXCODEC_IMAGE_BMP:
1231 return BmpStartDecode();
1233#ifdef PDF_ENABLE_XFA_GIF
1234 case FXCODEC_IMAGE_GIF:
1235 return GifStartDecode();
1237 case FXCODEC_IMAGE_JPG:
1238 return JpegStartDecode();
1239#ifdef PDF_ENABLE_XFA_PNG
1240 case FXCODEC_IMAGE_PNG:
1241 return PngStartDecode();
1243#ifdef PDF_ENABLE_XFA_TIFF
1244 case FXCODEC_IMAGE_TIFF:
1245 m_status = FXCODEC_STATUS::kDecodeToBeContinued;
1257 switch (m_imageType) {
1258 case FXCODEC_IMAGE_JPG:
1259 return JpegContinueDecode();
1260#ifdef PDF_ENABLE_XFA_BMP
1261 case FXCODEC_IMAGE_BMP:
1262 return BmpContinueDecode();
1264#ifdef PDF_ENABLE_XFA_GIF
1265 case FXCODEC_IMAGE_GIF:
1266 return GifContinueDecode();
1268#ifdef PDF_ENABLE_XFA_PNG
1269 case FXCODEC_IMAGE_PNG:
1270 return PngContinueDecode();
1272#ifdef PDF_ENABLE_XFA_TIFF
1273 case FXCODEC_IMAGE_TIFF:
1274 return TiffContinueDecode();
static uint8_t PixelFromFixed(uint32_t fixed)
virtual FX_FILESIZE GetAvailInput(Context *pContext) const =0
FXCODEC_STATUS ContinueDecode()
FXCODEC_STATUS StartDecode(RetainPtr< CFX_DIBitmap > bitmap)
FXDIB_Format GetBitmapFormat() const
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)
UNSAFE_BUFFER_USAGE void * FXSYS_memset(void *ptr1, int val, size_t len)
#define NOTREACHED_NORETURN()
bool bInterpolateBilinear