36 #include <libopenraw/debug.h> 38 #include "bitmapdata.hpp" 39 #include "io/stream.hpp" 40 #include "io/streamclone.hpp" 42 #include "jfifcontainer.hpp" 43 #include "ifdfilecontainer.hpp" 47 using namespace Debug;
54 void j_init_source(::j_decompress_ptr cinfo);
55 ::boolean j_fill_input_buffer(::j_decompress_ptr cinfo);
56 void j_skip_input_data(::j_decompress_ptr cinfo,
58 void j_term_source(::j_decompress_ptr cinfo);
59 void j_error_exit(::j_common_ptr cinfo);
68 struct jpeg_source_mgr pub;
74 JfifContainer::JfifContainer(
const IO::Stream::Ptr &_file, off_t _offset)
79 setEndian(ENDIAN_BIG);
84 m_cinfo.err = jpeg_std_error(&m_jerr);
85 m_jerr.error_exit = &j_error_exit;
86 jpeg_create_decompress(&m_cinfo);
91 (*m_cinfo.mem->alloc_small)((j_common_ptr)&m_cinfo,
94 m_cinfo.src = (jpeg_source_mgr*)src;
95 src->
pub.init_source = j_init_source;
96 src->
pub.fill_input_buffer = j_fill_input_buffer;
97 src->
pub.skip_input_data = j_skip_input_data;
98 src->
pub.resync_to_restart = jpeg_resync_to_restart;
99 src->
pub.term_source = j_term_source;
101 src->
pub.bytes_in_buffer = 0;
102 src->
pub.next_input_byte =
nullptr;
103 src->buf = (JOCTET*)(*m_cinfo.mem->alloc_small)
104 ((j_common_ptr)&m_cinfo,
106 BUF_SIZE *
sizeof(JOCTET));
111 jpeg_destroy_decompress(&m_cinfo);
115 bool JfifContainer::getDimensions(uint32_t &x, uint32_t &y)
117 if(!m_headerLoaded) {
118 if (_loadHeader() == 0) {
119 LOGDBG1(
"load header failed\n");
123 x = m_cinfo.output_width;
124 y = m_cinfo.output_height;
129 bool JfifContainer::getDecompressedData(
BitmapData &data)
131 if(!m_headerLoaded) {
132 if (_loadHeader() == 0) {
133 LOGDBG1(
"load header failed\n");
137 if (::setjmp(m_jpegjmp) != 0) {
140 jpeg_start_decompress(&m_cinfo);
141 int row_size = m_cinfo.output_width * m_cinfo.output_components;
143 = (
char*)data.allocData(row_size * m_cinfo.output_height);
144 char *currentPtr = dataPtr;
146 = (*m_cinfo.mem->alloc_sarray)((j_common_ptr)&m_cinfo,
147 JPOOL_IMAGE, row_size,
149 while (m_cinfo.output_scanline < m_cinfo.output_height) {
150 jpeg_read_scanlines(&m_cinfo, buffer, 1);
151 memcpy(currentPtr, buffer, row_size);
152 currentPtr += row_size;
154 data.
setDimensions(m_cinfo.output_width, m_cinfo.output_height);
156 jpeg_finish_decompress(&m_cinfo);
161 int JfifContainer::_loadHeader()
164 m_file->seek(0, SEEK_SET);
166 if (::setjmp(m_jpegjmp) == 0) {
167 int ret = jpeg_read_header(&m_cinfo, TRUE);
169 jpeg_calc_output_dimensions(&m_cinfo);
170 m_headerLoaded = (ret == 1);
178 void j_error_exit(j_common_ptr cinfo)
180 (*cinfo->err->output_message) (cinfo);
182 ::longjmp(
self->jpegjmp(), 1);
185 void j_init_source(j_decompress_ptr)
190 boolean j_fill_input_buffer(j_decompress_ptr cinfo)
194 int n =
self->file()->read(src->buf, BUF_SIZE *
sizeof(*src->buf));
196 src->
pub.next_input_byte = src->buf;
197 src->
pub.bytes_in_buffer = n;
200 src->
pub.next_input_byte =
nullptr;
201 src->
pub.bytes_in_buffer = 0;
207 void j_skip_input_data(j_decompress_ptr cinfo,
212 while ((
size_t)num_bytes > src->
pub.bytes_in_buffer) {
213 num_bytes -= src->
pub.bytes_in_buffer;
214 j_fill_input_buffer(cinfo);
216 src->
pub.next_input_byte += (size_t) num_bytes;
217 src->
pub.bytes_in_buffer -= (size_t) num_bytes;
222 void j_term_source(j_decompress_ptr)
231 m_file->seek(0, SEEK_SET);
234 auto result = readUInt16(m_file);
235 result = readUInt16(m_file);
236 result = readUInt16(m_file);
240 m_file->read(delim, 6);
241 if(memcmp(delim,
"Exif\0\0", 6) == 0) {
242 size_t exif_offset = m_file->seek(0, SEEK_CUR);
245 std::make_shared<IO::StreamClone>(m_file, exif_offset)), 0));
254 return m_ifd->setDirectory(0);
256 return IfdDir::Ref();
262 return m_ifd->setDirectory(idx);
264 return IfdDir::Ref();
270 IfdDir::Ref main = mainIfd();
271 return main->getExifIFD();
CIFF is the container for CRW files. It is an attempt from Canon to make this a standard. I guess it failed.
std::unique_ptr< IfdFileContainer > & ifdContainer()
IfdDir::Ref getIfdDirAt(int idx)
struct jpeg_source_mgr pub
virtual void setDimensions(uint32_t x, uint32_t y)