Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
jpeg_progressive_decoder.cpp
Go to the documentation of this file.
1// Copyright 2020 The PDFium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "core/fxcodec/jpeg/jpeg_progressive_decoder.h"
8
9#include <utility>
10
11#include "core/fxcodec/cfx_codec_memory.h"
12#include "core/fxcodec/fx_codec.h"
13#include "core/fxcodec/jpeg/jpeg_common.h"
14#include "core/fxcodec/scanlinedecoder.h"
15#include "core/fxcrt/fx_safe_types.h"
16#include "core/fxge/dib/cfx_dibbase.h"
17#include "core/fxge/dib/fx_dib.h"
18#include "third_party/abseil-cpp/absl/types/optional.h"
19#include "third_party/base/check.h"
20#include "third_party/base/memory/ptr_util.h"
21
22class CJpegContext final : public ProgressiveDecoderIface::Context {
23 public:
25 ~CJpegContext() override;
26
27 jmp_buf& GetJumpMark() { return m_JumpMark; }
28
29 jmp_buf m_JumpMark;
33 unsigned int m_SkipSize = 0;
34};
35
36extern "C" {
37
38static void error_fatal(j_common_ptr cinfo) {
39 auto* pContext = reinterpret_cast<CJpegContext*>(cinfo->client_data);
40 longjmp(pContext->m_JumpMark, -1);
41}
42
43static void src_skip_data(jpeg_decompress_struct* cinfo, long num) {
44 if (cinfo->src->bytes_in_buffer < static_cast<size_t>(num)) {
45 auto* pContext = reinterpret_cast<CJpegContext*>(cinfo->client_data);
46 pContext->m_SkipSize = (unsigned int)(num - cinfo->src->bytes_in_buffer);
47 cinfo->src->bytes_in_buffer = 0;
48 } else {
49 cinfo->src->next_input_byte += num;
50 cinfo->src->bytes_in_buffer -= num;
51 }
52}
53
54} // extern "C"
55
56static void JpegLoadAttribute(const jpeg_decompress_struct& info,
57 CFX_DIBAttribute* pAttribute) {
58 pAttribute->m_nXDPI = info.X_density;
59 pAttribute->m_nYDPI = info.Y_density;
60 pAttribute->m_wDPIUnit =
61 static_cast<CFX_DIBAttribute::ResUnit>(info.density_unit);
62}
63
64CJpegContext::CJpegContext() {
65 m_Info.client_data = this;
66 m_Info.err = &m_ErrMgr;
67
68 m_ErrMgr.error_exit = error_fatal;
69 m_ErrMgr.emit_message = error_do_nothing_int;
70 m_ErrMgr.output_message = error_do_nothing;
71 m_ErrMgr.format_message = error_do_nothing_char;
72 m_ErrMgr.reset_error_mgr = error_do_nothing;
73
74 m_SrcMgr.init_source = src_do_nothing;
75 m_SrcMgr.term_source = src_do_nothing;
76 m_SrcMgr.skip_input_data = src_skip_data;
77 m_SrcMgr.fill_input_buffer = src_fill_buffer;
78 m_SrcMgr.resync_to_restart = src_resync;
79}
80
81CJpegContext::~CJpegContext() {
82 jpeg_destroy_decompress(&m_Info);
83}
84
85namespace fxcodec {
86
87namespace {
88
89JpegProgressiveDecoder* g_jpeg_decoder = nullptr;
90
91} // namespace
92
93// static
94void JpegProgressiveDecoder::InitializeGlobals() {
95 CHECK(!g_jpeg_decoder);
96 g_jpeg_decoder = new JpegProgressiveDecoder();
97}
98
99// static
100void JpegProgressiveDecoder::DestroyGlobals() {
101 delete g_jpeg_decoder;
102 g_jpeg_decoder = nullptr;
103}
104
105// static
106JpegProgressiveDecoder* JpegProgressiveDecoder::GetInstance() {
107 return g_jpeg_decoder;
108}
109
110// static
111std::unique_ptr<ProgressiveDecoderIface::Context>
112JpegProgressiveDecoder::Start() {
113 // Use ordinary pointer until past the possibility of a longjump.
114 auto* pContext = new CJpegContext();
115 if (setjmp(pContext->m_JumpMark) == -1) {
116 delete pContext;
117 return nullptr;
118 }
119
120 jpeg_create_decompress(&pContext->m_Info);
121 pContext->m_Info.src = &pContext->m_SrcMgr;
122 pContext->m_SkipSize = 0;
123 return pdfium::WrapUnique(pContext);
124}
125
126// static
127jmp_buf& JpegProgressiveDecoder::GetJumpMark(Context* pContext) {
128 return static_cast<CJpegContext*>(pContext)->GetJumpMark();
129}
130
131// static
132int JpegProgressiveDecoder::ReadHeader(Context* pContext,
133 int* width,
134 int* height,
135 int* nComps,
136 CFX_DIBAttribute* pAttribute) {
137 DCHECK(pAttribute);
138
139 auto* ctx = static_cast<CJpegContext*>(pContext);
140 int ret = jpeg_read_header(&ctx->m_Info, TRUE);
141 if (ret == JPEG_SUSPENDED)
142 return 2;
143 if (ret != JPEG_HEADER_OK)
144 return 1;
145
146 *width = ctx->m_Info.image_width;
147 *height = ctx->m_Info.image_height;
148 *nComps = ctx->m_Info.num_components;
149 JpegLoadAttribute(ctx->m_Info, pAttribute);
150 return 0;
151}
152
153// static
154bool JpegProgressiveDecoder::StartScanline(Context* pContext, int down_scale) {
155 auto* ctx = static_cast<CJpegContext*>(pContext);
156 ctx->m_Info.scale_denom = static_cast<unsigned int>(down_scale);
157 return !!jpeg_start_decompress(&ctx->m_Info);
158}
159
160// static
161bool JpegProgressiveDecoder::ReadScanline(Context* pContext,
162 unsigned char* dest_buf) {
163 auto* ctx = static_cast<CJpegContext*>(pContext);
164 unsigned int nlines = jpeg_read_scanlines(&ctx->m_Info, &dest_buf, 1);
165 return nlines == 1;
166}
167
168FX_FILESIZE JpegProgressiveDecoder::GetAvailInput(Context* pContext) const {
169 auto* ctx = static_cast<CJpegContext*>(pContext);
170 return static_cast<FX_FILESIZE>(ctx->m_SrcMgr.bytes_in_buffer);
171}
172
173bool JpegProgressiveDecoder::Input(Context* pContext,
174 RetainPtr<CFX_CodecMemory> codec_memory) {
175 pdfium::span<uint8_t> src_buf = codec_memory->GetUnconsumedSpan();
176 auto* ctx = static_cast<CJpegContext*>(pContext);
177 if (ctx->m_SkipSize) {
178 if (ctx->m_SkipSize > src_buf.size()) {
179 ctx->m_SrcMgr.bytes_in_buffer = 0;
180 ctx->m_SkipSize -= src_buf.size();
181 return true;
182 }
183 src_buf = src_buf.subspan(ctx->m_SkipSize);
184 ctx->m_SkipSize = 0;
185 }
186 ctx->m_SrcMgr.next_input_byte = src_buf.data();
187 ctx->m_SrcMgr.bytes_in_buffer = src_buf.size();
188 return true;
189}
190
191JpegProgressiveDecoder::JpegProgressiveDecoder() = default;
192
193JpegProgressiveDecoder::~JpegProgressiveDecoder() = default;
194
195} // namespace fxcodec
jpeg_decompress_struct m_Info
static bool ReadScanline(Context *pContext, uint8_t *dest_buf)
static jmp_buf & GetJumpMark(Context *pContext)
static int ReadHeader(Context *pContext, int *width, int *height, int *nComps, CFX_DIBAttribute *pAttribute)
static JpegProgressiveDecoder * GetInstance()
FX_FILESIZE GetAvailInput(Context *pContext) const override
bool Input(Context *pContext, RetainPtr< CFX_CodecMemory > codec_memory) override
static bool StartScanline(Context *pContext, int down_scale)
#define FX_FILESIZE
Definition fx_types.h:19
static void JpegLoadAttribute(const jpeg_decompress_struct &info, CFX_DIBAttribute *pAttribute)
static void src_skip_data(jpeg_decompress_struct *cinfo, long num)
static void error_fatal(j_common_ptr cinfo)
#define CHECK(cvref)