22#include "rawspeedconfig.h"
49void init_source(j_decompress_ptr ) {
53boolean fill_input_buffer(j_decompress_ptr cinfo) {
54 return cinfo->src->bytes_in_buffer != 0;
58void skip_input_data(j_decompress_ptr cinfo,
long num_bytes) {
59 auto* src = cinfo->src;
61 if (num_bytes >
static_cast<int>(src->bytes_in_buffer))
64#pragma GCC diagnostic push
65#pragma GCC diagnostic ignored "-Wpragmas"
66#pragma GCC diagnostic ignored "-Wunknown-warning-option"
67#pragma GCC diagnostic ignored "-Wunsafe-buffer-usage"
68 src->next_input_byte +=
static_cast<size_t>(num_bytes);
69#pragma GCC diagnostic pop
70 src->bytes_in_buffer -=
static_cast<size_t>(num_bytes);
74void term_source(j_decompress_ptr ) {
79jpeg_mem_src_int(j_decompress_ptr cinfo,
const unsigned char* buffer,
83 if (cinfo->src ==
nullptr) {
85 cinfo->mem->alloc_small(
reinterpret_cast<j_common_ptr
>(cinfo),
86 JPOOL_PERMANENT,
sizeof(jpeg_source_mgr));
87 cinfo->src =
static_cast<jpeg_source_mgr*
>(
buf);
91 src->init_source = init_source;
92 src->fill_input_buffer = fill_input_buffer;
93 src->skip_input_data = skip_input_data;
94 src->resync_to_restart = jpeg_resync_to_restart;
95 src->term_source = term_source;
96 src->bytes_in_buffer = nbytes;
97 src->next_input_byte = buffer;
101[[noreturn]] METHODDEF(
void) my_error_throw(j_common_ptr cinfo) {
102 std::array<char, JMSG_LENGTH_MAX>
buf;
104 cinfo->err->format_message(cinfo,
buf.data());
110struct JpegDecompressor::JpegDecompressStruct final : jpeg_decompress_struct {
111 struct jpeg_error_mgr jerr;
113 JpegDecompressStruct(
const JpegDecompressStruct&) =
delete;
114 JpegDecompressStruct(JpegDecompressStruct&&) noexcept = delete;
115 JpegDecompressStruct&
116 operator=(const JpegDecompressStruct&) noexcept = delete;
117 JpegDecompressStruct& operator=(JpegDecompressStruct&&) noexcept = delete;
119 JpegDecompressStruct() {
120 jpeg_create_decompress(
this);
122 err = jpeg_std_error(&jerr);
123 jerr.error_exit = &my_error_throw;
125 ~JpegDecompressStruct() { jpeg_destroy_decompress(
this); }
128void JpegDecompressor::decode(uint32_t offX,
130 JpegDecompressStruct dinfo;
132#ifdef HAVE_JPEG_MEM_SRC
134 jpeg_mem_src(&dinfo,
const_cast<uint8_t*
>(input.begin()), input.getSize());
136 jpeg_mem_src_int(&dinfo, input.begin(), input.getSize());
139 if (JPEG_HEADER_OK != jpeg_read_header(&dinfo,
static_cast<boolean>(
true)))
140 ThrowRDE(
"Unable to read JPEG header");
142 jpeg_start_decompress(&dinfo);
143 if (dinfo.output_components !=
static_cast<int>(mRaw->getCpp()))
144 ThrowRDE(
"Component count doesn't match");
145 int row_stride = dinfo.output_width * dinfo.output_components;
147 std::vector<uint8_t, AlignedAllocator<uint8_t, 16>> complete_buffer;
148 complete_buffer.resize(dinfo.output_height * row_stride);
151 dinfo.output_components * dinfo.output_width,
152 dinfo.output_height, row_stride);
154 while (dinfo.output_scanline < dinfo.output_height) {
155 JSAMPROW rowOut = &tmp(dinfo.output_scanline, 0);
156 if (0 == jpeg_read_scanlines(&dinfo, &rowOut, 1))
157 ThrowRDE(
"JPEG Error while decompressing image.");
159 jpeg_finish_decompress(&dinfo);
162 int copy_w = min(mRaw->dim.x - offX, dinfo.output_width);
163 int copy_h = min(mRaw->dim.y - offY, dinfo.output_height);
166 for (
int row = 0; row < copy_h; row++) {
167 for (
int col = 0; col < dinfo.output_components * copy_w; col++)
168 out(row + offY, (dinfo.output_components * offX) + col) = tmp(row, col);
177 "JPEG is not present! Lossy JPEG compression will not be supported!"
void RAWSPEED_UNLIKELY_FUNCTION RAWSPEED_NOINLINE static char buf[bufSize]