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