38 #include <libopenraw/debug.h> 40 #include "bitmapdata.hpp" 41 #include "io/stream.hpp" 42 #include "io/streamclone.hpp" 44 #include "jfifcontainer.hpp" 45 #include "ifdfilecontainer.hpp" 49 using namespace Debug;
58 struct JPEG::jpeg_source_mgr pub;
64 JfifContainer::JfifContainer(
const IO::Stream::Ptr &_file, off_t _offset)
67 m_headerLoaded(false),
70 setEndian(ENDIAN_BIG);
76 m_cinfo.err = JPEG::jpeg_std_error(&m_jerr);
77 m_jerr.error_exit = &j_error_exit;
78 JPEG::jpeg_create_decompress(&m_cinfo);
83 (*m_cinfo.mem->alloc_small)((JPEG::j_common_ptr)&m_cinfo,
86 m_cinfo.src = (JPEG::jpeg_source_mgr*)src;
87 src->
pub.init_source = j_init_source;
88 src->
pub.fill_input_buffer = j_fill_input_buffer;
89 src->
pub.skip_input_data = j_skip_input_data;
90 src->
pub.resync_to_restart = JPEG::jpeg_resync_to_restart;
91 src->
pub.term_source = j_term_source;
93 src->
pub.bytes_in_buffer = 0;
94 src->
pub.next_input_byte =
nullptr;
95 src->buf = (JPEG::JOCTET*)(*m_cinfo.mem->alloc_small)
96 ((JPEG::j_common_ptr)&m_cinfo,
98 BUF_SIZE *
sizeof(JPEG::JOCTET));
103 JPEG::jpeg_destroy_decompress(&m_cinfo);
108 bool JfifContainer::getDimensions(uint32_t &x, uint32_t &y)
110 if(!m_headerLoaded) {
111 if (_loadHeader() == 0) {
112 Trace(DEBUG1) <<
"load header failed\n";
116 x = m_cinfo.output_width;
117 y = m_cinfo.output_height;
122 bool JfifContainer::getDecompressedData(
BitmapData &data)
124 if(!m_headerLoaded) {
125 if (_loadHeader() == 0) {
126 Trace(DEBUG1) <<
"load header failed\n";
130 if (::setjmp(m_jpegjmp) != 0) {
133 JPEG::jpeg_start_decompress(&m_cinfo);
134 int row_size = m_cinfo.output_width * m_cinfo.output_components;
136 = (
char*)data.allocData(row_size * m_cinfo.output_height);
137 char *currentPtr = dataPtr;
138 JPEG::JSAMPARRAY buffer
139 = (*m_cinfo.mem->alloc_sarray)((JPEG::j_common_ptr)&m_cinfo,
140 JPOOL_IMAGE, row_size,
142 while (m_cinfo.output_scanline < m_cinfo.output_height) {
143 jpeg_read_scanlines(&m_cinfo, buffer, 1);
144 memcpy(currentPtr, buffer, row_size);
145 currentPtr += row_size;
147 data.
setDimensions(m_cinfo.output_width, m_cinfo.output_height);
149 JPEG::jpeg_finish_decompress(&m_cinfo);
154 int JfifContainer::_loadHeader()
157 m_file->seek(0, SEEK_SET);
159 if (::setjmp(m_jpegjmp) == 0) {
160 int ret = JPEG::jpeg_read_header(&m_cinfo, TRUE);
163 JPEG::jpeg_calc_output_dimensions(&m_cinfo);
164 m_headerLoaded = (ret == 1);
171 void JfifContainer::j_error_exit(JPEG::j_common_ptr cinfo)
173 (*cinfo->err->output_message) (cinfo);
175 ::longjmp(
self->m_jpegjmp, 1);
178 void JfifContainer::j_init_source(JPEG::j_decompress_ptr)
184 JfifContainer::j_fill_input_buffer(JPEG::j_decompress_ptr cinfo)
188 int n =
self->file()->read(src->buf, BUF_SIZE *
sizeof(*src->buf));
190 src->
pub.next_input_byte = src->buf;
191 src->
pub.bytes_in_buffer = n;
194 src->
pub.next_input_byte =
nullptr;
195 src->
pub.bytes_in_buffer = 0;
201 void JfifContainer::j_skip_input_data(JPEG::j_decompress_ptr cinfo,
206 while ((
size_t)num_bytes > src->
pub.bytes_in_buffer) {
207 num_bytes -= src->
pub.bytes_in_buffer;
208 j_fill_input_buffer(cinfo);
210 src->
pub.next_input_byte += (size_t) num_bytes;
211 src->
pub.bytes_in_buffer -= (size_t) num_bytes;
216 void JfifContainer::j_term_source(JPEG::j_decompress_ptr)
223 m_file->seek(0, SEEK_SET);
226 readUInt16(m_file, marker);
227 readUInt16(m_file, marker);
228 readUInt16(m_file, marker);
232 m_file->read(delim, 6);
233 if(memcmp(delim,
"Exif\0\0", 6) == 0) {
234 size_t exif_offset = m_file->seek(0, SEEK_CUR);
237 std::make_shared<IO::StreamClone>(m_file, exif_offset)), 0);
246 return m_ifd->setDirectory(0);
248 return IfdDir::Ref();
254 return m_ifd->setDirectory(idx);
256 return IfdDir::Ref();
262 IfdDir::Ref main = mainIfd();
263 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.
IfdDir::Ref getIfdDirAt(int idx)
struct JPEG::jpeg_source_mgr pub
virtual void setDimensions(uint32_t x, uint32_t y)
IfdFileContainer * ifdContainer()