kviewshell
JPEGDecoder.cpp
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
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #ifdef HAVE_CONFIG_H
00058 # include "config.h"
00059 #endif
00060 #if NEED_GNUG_PRAGMAS
00061 # pragma implementation
00062 #endif
00063
00064 #ifdef NEED_JPEG_DECODER
00065
00066 #include "JPEGDecoder.h"
00067
00068 #ifdef __cplusplus
00069 extern "C" {
00070 #endif
00071 #undef HAVE_STDLIB_H
00072 #undef HAVE_STDDEF_H
00073 #include <stdio.h>
00074 #include <jconfig.h>
00075 #include <jpeglib.h>
00076 #include <jerror.h>
00077 #ifdef __cplusplus
00078 }
00079 #endif
00080
00081 #include "ByteStream.h"
00082 #include "GPixmap.h"
00083 #ifdef LIBJPEGNAME
00084 #include "DjVuDynamic.h"
00085 #include "GString.h"
00086 #endif // LIBJPEGNAME
00087
00088
00089
00090 #ifdef HAVE_NAMESPACES
00091 namespace DJVU {
00092 # ifdef NOT_DEFINED // Just to fool emacs c++ mode
00093 }
00094 #endif
00095 #endif
00096
00097
00098 class JPEGDecoder::Impl : public JPEGDecoder
00099 {
00100 public:
00101 static void jpeg_byte_stream_src(j_decompress_ptr, ByteStream &);
00102 };
00103
00104 extern "C"
00105 {
00106
00107 struct djvu_error_mgr
00108 {
00109 struct jpeg_error_mgr pub;
00110
00111 jmp_buf setjmp_buffer;
00112 };
00113
00114 typedef struct djvu_error_mgr * djvu_error_ptr;
00115
00116 METHODDEF(void)
00117 djvu_error_exit (j_common_ptr cinfo)
00118 {
00119
00120 djvu_error_ptr djvuerr = (djvu_error_ptr) cinfo->err;
00121
00122
00123
00124 (*cinfo->err->output_message) (cinfo);
00125
00126
00127 longjmp(djvuerr->setjmp_buffer, 1);
00128 }
00129
00130 }
00131
00132 GP<GPixmap>
00133 JPEGDecoder::decode(ByteStream & bs )
00134 {
00135 GP<GPixmap> retval=GPixmap::create();
00136 G_TRY
00137 {
00138 decode(bs,*retval);
00139 } G_CATCH_ALL
00140 {
00141 retval=0;
00142 }
00143 G_ENDCATCH;
00144 return retval;
00145 }
00146
00147 void
00148 JPEGDecoder::decode(ByteStream & bs,GPixmap &pix)
00149 {
00150 struct jpeg_decompress_struct cinfo;
00151
00152
00153 struct djvu_error_mgr jerr;
00154
00155 JSAMPARRAY buffer;
00156 int row_stride;
00157 int full_buf_size;
00158 int isGrey,i;
00159
00160 cinfo.err = jpeg_std_error(&jerr.pub);
00161
00162 jerr.pub.error_exit = djvu_error_exit;
00163
00164 if (setjmp(jerr.setjmp_buffer))
00165 {
00166
00167 jpeg_destroy_decompress(&cinfo);
00168 G_THROW( ERR_MSG("GPixmap.unk_PPM") );
00169 }
00170
00171 jpeg_create_decompress(&cinfo);
00172
00173 Impl::jpeg_byte_stream_src(&cinfo, bs);
00174
00175 (void) jpeg_read_header(&cinfo, TRUE);
00176
00177 jpeg_start_decompress(&cinfo);
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187 row_stride = cinfo.output_width * cinfo.output_components;
00188 full_buf_size = row_stride * cinfo.output_height;
00189
00190
00191 buffer = (*cinfo.mem->alloc_sarray)
00192 ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
00193
00194 GP<ByteStream> goutputBlock=ByteStream::create();
00195 ByteStream &outputBlock=*goutputBlock;
00196 outputBlock.format("P6\n%d %d\n%d\n",cinfo.output_width,
00197 cinfo.output_height,255);
00198
00199 isGrey = ( cinfo.out_color_space == JCS_GRAYSCALE) ? 1 : 0;
00200
00201 while (cinfo.output_scanline < cinfo.output_height)
00202 {
00203 (void) jpeg_read_scanlines(&cinfo, buffer, 1);
00204
00205 if ( isGrey == 1 )
00206 {
00207 for (i=0; i<row_stride; i++)
00208 {
00209 outputBlock.write8((char)buffer[0][i]);
00210 outputBlock.write8((char)buffer[0][i]);
00211 outputBlock.write8((char)buffer[0][i]);
00212 }
00213 }else
00214 {
00215 for (i=0; i<row_stride; i++)
00216 outputBlock.write8((char)buffer[0][i]);
00217 }
00218 }
00219
00220 (void) jpeg_finish_decompress(&cinfo);
00221
00222 jpeg_destroy_decompress(&cinfo);
00223
00224 outputBlock.seek(0,SEEK_SET);
00225
00226 pix.init(outputBlock);
00227 }
00228
00229
00230
00231
00232 extern "C"
00233 {
00234
00235 typedef struct
00236 {
00237 struct jpeg_source_mgr pub;
00238
00239 ByteStream * byteStream;
00240 JOCTET * buffer;
00241 boolean start_of_stream;
00242 } byte_stream_src_mgr;
00243
00244
00245 typedef byte_stream_src_mgr * byte_stream_src_ptr;
00246
00247 #define INPUT_BUF_SIZE 4096
00248
00249 METHODDEF(void)
00250 init_source (j_decompress_ptr cinfo)
00251 {
00252 byte_stream_src_ptr src = (byte_stream_src_ptr) cinfo->src;
00253
00254 src->start_of_stream = TRUE;
00255 }
00256
00257 METHODDEF(boolean)
00258 fill_input_buffer (j_decompress_ptr cinfo)
00259 {
00260 byte_stream_src_ptr src = (byte_stream_src_ptr) cinfo->src;
00261 size_t nbytes;
00262
00263 nbytes = src->byteStream->readall(src->buffer, INPUT_BUF_SIZE);
00264
00265 if (nbytes <= 0)
00266 {
00267 if (src->start_of_stream)
00268 ERREXIT(cinfo, JERR_INPUT_EMPTY);
00269 WARNMS(cinfo, JWRN_JPEG_EOF);
00270
00271 src->buffer[0] = (JOCTET) 0xFF;
00272 src->buffer[1] = (JOCTET) JPEG_EOI;
00273 nbytes = 2;
00274 }
00275
00276 src->pub.next_input_byte = src->buffer;
00277 src->pub.bytes_in_buffer = nbytes;
00278 src->start_of_stream = FALSE;
00279
00280 return TRUE;
00281 }
00282
00283
00284 METHODDEF(void)
00285 skip_input_data (j_decompress_ptr cinfo, long num_bytes)
00286 {
00287 byte_stream_src_ptr src = (byte_stream_src_ptr) cinfo->src;
00288
00289 if (num_bytes > (long) src->pub.bytes_in_buffer)
00290 {
00291 src->byteStream->seek((num_bytes - src->pub.bytes_in_buffer), SEEK_CUR);
00292 (void) fill_input_buffer(cinfo);
00293 }else
00294 {
00295 src->pub.bytes_in_buffer -= num_bytes;
00296 src->pub.next_input_byte += num_bytes;
00297 }
00298 }
00299
00300 METHODDEF(void)
00301 term_source (j_decompress_ptr cinfo)
00302 {
00303
00304 }
00305
00306 }
00307
00308 void
00309 JPEGDecoder::Impl::jpeg_byte_stream_src(j_decompress_ptr cinfo,ByteStream &bs)
00310 {
00311 byte_stream_src_ptr src;
00312
00313 if (cinfo->src == NULL)
00314 {
00315 cinfo->src = (struct jpeg_source_mgr *)
00316 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
00317 sizeof(byte_stream_src_mgr));
00318 src = (byte_stream_src_ptr) cinfo->src;
00319 src->buffer = (JOCTET *)
00320 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
00321 INPUT_BUF_SIZE * sizeof(JOCTET));
00322 }
00323
00324 src = (byte_stream_src_ptr) cinfo->src;
00325 src->pub.init_source = init_source;
00326 src->pub.fill_input_buffer = fill_input_buffer;
00327 src->pub.skip_input_data = skip_input_data;
00328 src->pub.resync_to_restart = jpeg_resync_to_restart;
00329 src->pub.term_source = term_source;
00330 src->byteStream = &bs;
00331 src->pub.bytes_in_buffer = 0;
00332 src->pub.next_input_byte = NULL;
00333 }
00334
00335 #ifdef LIBJPEGNAME
00336 void *
00337 JPEGDecoder::jpeg_lookup(const GUTF8String &name)
00338 {
00339 static DjVuDynamic lib(GUTF8String(LIBJPEGNAME));
00340 void *sym=lib.lookup(name);
00341 if(!sym)
00342 G_THROW(ERR_MSG("DjVuFile.JPEG_bg2"));
00343 return sym;
00344 }
00345
00346 jpeg_error_mgr *
00347 JPEGDecoder::jpeg_std_error(jpeg_error_mgr *x)
00348 {
00349 static void *sym=jpeg_lookup("jpeg_std_error");
00350 return ((jpeg_error_mgr *(*)(jpeg_error_mgr *))sym)(x);
00351 }
00352
00353 void
00354 JPEGDecoder::jpeg_CreateDecompress(jpeg_decompress_struct *x,int v, size_t s)
00355 {
00356 static void *sym=jpeg_lookup("jpeg_CreateDecompress");
00357 ((void (*)(jpeg_decompress_struct *,int,size_t))sym)(x,v,s);
00358 }
00359
00360 void
00361 JPEGDecoder::jpeg_destroy_decompress(j_decompress_ptr x)
00362 {
00363 static void *sym=jpeg_lookup("jpeg_destroy_decompress");
00364 ((void (*)(j_decompress_ptr))sym)(x);
00365 }
00366
00367 int
00368 JPEGDecoder::jpeg_read_header(j_decompress_ptr x,boolean y)
00369 {
00370 static void *sym=jpeg_lookup("jpeg_read_header");
00371 return ((int (*)(j_decompress_ptr,boolean))sym)(x,y);
00372 }
00373
00374 JDIMENSION
00375 JPEGDecoder::jpeg_read_scanlines(j_decompress_ptr x,JSAMPARRAY y,JDIMENSION z)
00376 {
00377 static void *sym=jpeg_lookup("jpeg_read_scanlines");
00378 return ((JDIMENSION (*)(j_decompress_ptr,JSAMPARRAY,JDIMENSION))sym)(x,y,z);
00379 }
00380
00381 boolean
00382 JPEGDecoder::jpeg_finish_decompress(j_decompress_ptr x)
00383 {
00384 static void *sym=jpeg_lookup("jpeg_finish_decompress");
00385 return ((boolean (*)(j_decompress_ptr))sym)(x);
00386 }
00387
00388 boolean
00389 JPEGDecoder::jpeg_resync_to_restart(jpeg_decompress_struct *x,int d)
00390 {
00391 static void *sym=jpeg_lookup("jpeg_resync_to_restart");
00392 return ((boolean (*)(jpeg_decompress_struct *,int))sym)(x,d);
00393 }
00394
00395 boolean
00396 JPEGDecoder::jpeg_start_decompress(j_decompress_ptr x)
00397 {
00398 static void *sym=jpeg_lookup("jpeg_start_decompress");
00399 return ((boolean (*)(j_decompress_ptr))sym)(x);
00400 }
00401
00402 #endif // LIBJPEGNAME
00403
00404
00405 #ifdef HAVE_NAMESPACES
00406 }
00407 # ifndef NOT_USING_DJVU_NAMESPACE
00408 using namespace DJVU;
00409 # endif
00410 #endif
00411
00412 #endif
00413