00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <setjmp.h>
00023 #include <cstdio>
00024
00025 namespace JPEG {
00026
00027
00028
00029
00030 extern "C" {
00031 #include <jpeglib.h>
00032 }
00033 }
00034
00035 #include "io/stream.h"
00036 #include "debug.h"
00037 #include "jfifcontainer.h"
00038
00039 namespace OpenRaw {
00040
00041 using namespace Debug;
00042
00043 namespace Internals {
00044
00047 #define BUF_SIZE 1024
00048
00049 typedef struct {
00050 struct JPEG::jpeg_source_mgr pub;
00051 JFIFContainer * self;
00052 off_t offset;
00053 JPEG::JOCTET* buf;
00054 } jpeg_src_t;
00055
00056 JFIFContainer::JFIFContainer(IO::Stream *file, off_t offset)
00057 : RawContainer(file, offset),
00058 m_cinfo(), m_jerr(),
00059 m_headerLoaded(false)
00060 {
00061
00062
00063
00064 using namespace JPEG;
00065
00066 m_cinfo.err = JPEG::jpeg_std_error(&m_jerr);
00067 m_jerr.error_exit = &j_error_exit;
00068 JPEG::jpeg_create_decompress(&m_cinfo);
00069
00070
00071
00072 jpeg_src_t *src = (jpeg_src_t *)
00073 (*m_cinfo.mem->alloc_small)((JPEG::j_common_ptr)&m_cinfo,
00074 JPOOL_PERMANENT,
00075 sizeof(jpeg_src_t));
00076 m_cinfo.src = (JPEG::jpeg_source_mgr*)src;
00077 src->pub.init_source = j_init_source;
00078 src->pub.fill_input_buffer = j_fill_input_buffer;
00079 src->pub.skip_input_data = j_skip_input_data;
00080 src->pub.resync_to_restart = JPEG::jpeg_resync_to_restart;
00081 src->pub.term_source = j_term_source;
00082 src->self = this;
00083 src->pub.bytes_in_buffer = 0;
00084 src->pub.next_input_byte = NULL;
00085 src->buf = (JPEG::JOCTET*)(*m_cinfo.mem->alloc_small)
00086 ((JPEG::j_common_ptr)&m_cinfo,
00087 JPOOL_PERMANENT,
00088 BUF_SIZE * sizeof(JPEG::JOCTET));
00089 }
00090
00091 JFIFContainer::~JFIFContainer()
00092 {
00093 JPEG::jpeg_destroy_decompress(&m_cinfo);
00094 }
00095
00096
00097 bool JFIFContainer::getDimensions(uint32_t &x, uint32_t &y)
00098 {
00099 if(!m_headerLoaded) {
00100 if (_loadHeader() == 0) {
00101 Trace(DEBUG1) << "load error failed\n";
00102 return false;
00103 }
00104 }
00105 x = m_cinfo.output_width;
00106 y = m_cinfo.output_height;
00107 return true;
00108 }
00109
00110 int JFIFContainer::_loadHeader()
00111 {
00112 int ret = 0;
00113 if (::setjmp(m_jpegjmp) == 0) {
00114 ret = JPEG::jpeg_read_header(&m_cinfo, TRUE);
00115
00116
00117 JPEG::jpeg_calc_output_dimensions(&m_cinfo);
00118 }
00119 m_headerLoaded = (ret == 1);
00120 return ret;
00121 }
00122
00123
00124 void JFIFContainer::j_error_exit(JPEG::j_common_ptr cinfo)
00125 {
00126 (*cinfo->err->output_message) (cinfo);
00127 JFIFContainer *self = ((jpeg_src_t *)(((JPEG::j_decompress_ptr)cinfo)->src))->self;
00128 ::longjmp(self->m_jpegjmp, 1);
00129 }
00130
00131 void JFIFContainer::j_init_source(JPEG::j_decompress_ptr)
00132 {
00133 }
00134
00135
00136 JPEG::boolean
00137 JFIFContainer::j_fill_input_buffer(JPEG::j_decompress_ptr cinfo)
00138 {
00139 jpeg_src_t *src = (jpeg_src_t*)cinfo->src;
00140 JFIFContainer *self = src->self;
00141 size_t n = self->file()->read(src->buf, BUF_SIZE * sizeof(*src->buf));
00142 if (n >= 0) {
00143 src->pub.next_input_byte = src->buf;
00144 src->pub.bytes_in_buffer = n;
00145 }
00146 else {
00147 src->pub.next_input_byte = NULL;
00148 src->pub.bytes_in_buffer = 0;
00149 }
00150 return TRUE;
00151 }
00152
00153
00154 void JFIFContainer::j_skip_input_data(JPEG::j_decompress_ptr cinfo,
00155 long num_bytes)
00156 {
00157 jpeg_src_t *src = (jpeg_src_t*)cinfo->src;
00158 if (num_bytes > 0) {
00159 while ((size_t)num_bytes > src->pub.bytes_in_buffer) {
00160 num_bytes -= src->pub.bytes_in_buffer;
00161 j_fill_input_buffer(cinfo);
00162 }
00163 src->pub.next_input_byte += (size_t) num_bytes;
00164 src->pub.bytes_in_buffer -= (size_t) num_bytes;
00165 }
00166 }
00167
00168
00169 void JFIFContainer::j_term_source(JPEG::j_decompress_ptr)
00170 {
00171 }
00172
00173
00174 }
00175 }