JpegParser.C
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #ifndef RASTER_JPEGPARSER_C_DEFINED
00039 #define RASTER_JPEGPARSER_C_DEFINED
00040
00041 #include "Raster/JpegParser.H"
00042
00043 #include "Raster/GenericFrame.H"
00044 #include "rutz/error.h"
00045 #include "rutz/sfmt.h"
00046 #include "rutz/trace.h"
00047
00048 #include <csetjmp>
00049 #include <cstdio>
00050
00051 #ifdef INVT_HAVE_LIBJPEG
00052
00053
00054
00055
00056
00057
00058
00059
00060 #include <stdlib.h>
00061 #include <stdio.h>
00062 #undef HAVE_STDLIB_H
00063 extern "C"
00064 {
00065 #include <jpeglib.h>
00066 }
00067
00068 namespace
00069 {
00070 struct jpeg_aux
00071 {
00072 FILE* infile;
00073 jmp_buf* jmp_state;
00074 };
00075
00076 void cleanup(jpeg_decompress_struct* cinfo)
00077 {
00078 jpeg_aux* aux = static_cast<jpeg_aux*>(cinfo->client_data);
00079 if (aux->infile != 0)
00080 fclose(aux->infile);
00081 jpeg_destroy_decompress(cinfo);
00082 }
00083
00084 void jpeg_error_exit(j_common_ptr cinfo)
00085 {
00086
00087
00088
00089 cinfo->err->output_message(cinfo);
00090
00091 jpeg_aux* aux = static_cast<jpeg_aux*>(cinfo->client_data);
00092 longjmp(*(aux->jmp_state), 1);
00093 }
00094 }
00095
00096 #define SETJMP_TRY(statement) \
00097 do { \
00098 if (setjmp(state) == 0) \
00099 { \
00100 statement; \
00101 } \
00102 else \
00103 { \
00104 LFATAL("%s failed for file %s", #statement, filename); \
00105 } \
00106 } while (0)
00107
00108 #endif
00109
00110 struct JpegParser::Impl
00111 {
00112 Impl(const char* fname);
00113
00114 Image<PixRGB<byte> > rgb;
00115 Image<byte> gray;
00116 };
00117
00118
00119
00120 JpegParser::Impl::Impl(const char* filename)
00121 {
00122 #ifndef INVT_HAVE_LIBJPEG
00123 LFATAL("jpeg support is disabled since libjpeg was not found at configure time");
00124 #else
00125 GVX_TRACE(__PRETTY_FUNCTION__);
00126
00127 if (BITS_IN_JSAMPLE != 8)
00128 {
00129 throw rutz::error("jpeg library must be built for 8 bits-per-sample",
00130 SRC_POS);
00131 }
00132
00133 jmp_buf state;
00134
00135
00136 jpeg_decompress_struct cinfo;
00137 jpeg_error_mgr jerr;
00138
00139 jpeg_aux aux;
00140 aux.infile = 0;
00141 aux.jmp_state = &state;
00142 cinfo.client_data = static_cast<void*>(&aux);
00143
00144 cinfo.err = jpeg_std_error(&jerr);
00145 cinfo.err->error_exit = &jpeg_error_exit;
00146
00147 SETJMP_TRY(jpeg_create_decompress(&cinfo));
00148
00149
00150 aux.infile = fopen(filename, "rb");
00151
00152 if (aux.infile == 0)
00153 {
00154 throw rutz::error(rutz::sfmt("couldn't open '%s' for reading",
00155 filename), SRC_POS);
00156 }
00157
00158
00159 SETJMP_TRY(jpeg_stdio_src(&cinfo, aux.infile));
00160
00161
00162 SETJMP_TRY(jpeg_read_header(&cinfo, TRUE));
00163
00164
00165
00166
00167 SETJMP_TRY(jpeg_start_decompress(&cinfo));
00168
00169
00170
00171
00172
00173
00174
00175
00176 switch (cinfo.output_components)
00177 {
00178 case 1:
00179 {
00180 this->gray = Image<byte>(cinfo.output_width,
00181 cinfo.output_height,
00182 NO_INIT);
00183
00184 while (cinfo.output_scanline < cinfo.output_height)
00185 {
00186 JSAMPLE* dest =
00187 this->gray.getArrayPtr()
00188 + cinfo.output_scanline * this->gray.getWidth();
00189
00190 SETJMP_TRY(jpeg_read_scanlines(&cinfo,
00191 &dest,
00192 1));
00193 }
00194 }
00195 break;
00196 case 3:
00197 {
00198 this->rgb = Image<PixRGB<byte> >(cinfo.output_width,
00199 cinfo.output_height,
00200 NO_INIT);
00201
00202 while (cinfo.output_scanline < cinfo.output_height)
00203 {
00204 JSAMPLE* dest =
00205 reinterpret_cast<JSAMPLE*>
00206 (this->rgb.getArrayPtr()
00207 + cinfo.output_scanline * this->rgb.getWidth());
00208
00209 SETJMP_TRY(jpeg_read_scanlines(&cinfo,
00210 &dest,
00211 1));
00212 }
00213 }
00214 break;
00215 default:
00216 LFATAL("invalid number of jpeg components (%d)",
00217 cinfo.output_components);
00218 break;
00219 }
00220
00221
00222 SETJMP_TRY(jpeg_finish_decompress(&cinfo));
00223
00224
00225 cleanup(&cinfo);
00226 #endif
00227 }
00228
00229
00230
00231 JpegParser::JpegParser(const char* fname)
00232 :
00233 rep(new Impl(fname))
00234 {
00235 ASSERT(rep->rgb.initialized() || rep->gray.initialized());
00236 }
00237
00238
00239
00240 JpegParser::~JpegParser()
00241 {
00242 delete rep;
00243 }
00244
00245 GenericFrameSpec JpegParser::getFrameSpec() const
00246 {
00247 GenericFrameSpec result;
00248
00249 if (rep->rgb.initialized())
00250 {
00251 result.nativeType = GenericFrame::RGB_U8;
00252 result.dims = rep->rgb.getDims();
00253 }
00254 else if (rep->gray.initialized())
00255 {
00256 result.nativeType = GenericFrame::GRAY_U8;
00257 result.dims = rep->gray.getDims();
00258 }
00259 else
00260 ASSERT(0);
00261
00262 result.videoFormat = VIDFMT_AUTO;
00263 result.videoByteSwap = false;
00264 result.floatFlags = 0;
00265
00266 return result;
00267 }
00268
00269
00270
00271 std::string JpegParser::getComments() const
00272 {
00273 return std::string();
00274 }
00275
00276
00277
00278 uint JpegParser::getTagCount() const
00279 {
00280 return 0;
00281 }
00282
00283
00284
00285 bool JpegParser::getTag(uint tag, std::string &name, std::string &value) const
00286 {
00287 return false;
00288 }
00289
00290
00291
00292 GenericFrame JpegParser::getFrame()
00293 {
00294 if (rep->rgb.initialized())
00295 return GenericFrame(rep->rgb);
00296
00297
00298 ASSERT(rep->gray.initialized());
00299 return GenericFrame(rep->gray);
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309 #endif // RASTER_JPEGPARSER_C_DEFINED