|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 // 00002 // "$Id: Fl_JPEG_Image.cxx 7903 2010-11-28 21:06:39Z matt $" 00003 // 00004 // Fl_JPEG_Image routines. 00005 // 00006 // Copyright 1997-2010 by Easy Software Products. 00007 // Image support by Matthias Melcher, Copyright 2000-2009. 00008 // 00009 // This library is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU Library General Public 00011 // License as published by the Free Software Foundation; either 00012 // version 2 of the License, or (at your option) any later version. 00013 // 00014 // This library is distributed in the hope that it will be useful, 00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 // Library General Public License for more details. 00018 // 00019 // You should have received a copy of the GNU Library General Public 00020 // License along with this library; if not, write to the Free Software 00021 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00022 // USA. 00023 // 00024 // Please report all bugs and problems on the following page: 00025 // 00026 // http://www.fltk.org/str.php 00027 // 00028 // Contents: 00029 // 00030 // Fl_JPEG_Image::Fl_JPEG_Image() - Load a JPEG image file. 00031 // 00032 00033 // 00034 // Include necessary header files... 00035 // 00036 00037 #include <FL/Fl_JPEG_Image.H> 00038 #include <FL/fl_utf8.h> 00039 #include <config.h> 00040 #include <stdio.h> 00041 #include <stdlib.h> 00042 #include <setjmp.h> 00043 00044 00045 // Some releases of the Cygwin JPEG libraries don't have a correctly 00046 // updated header file for the INT32 data type; the following define 00047 // from Shane Hill seems to be a usable workaround... 00048 00049 #if defined(WIN32) && defined(__CYGWIN__) 00050 # define XMD_H 00051 #endif // WIN32 && __CYGWIN__ 00052 00053 00054 extern "C" 00055 { 00056 #ifdef HAVE_LIBJPEG 00057 # include <jpeglib.h> 00058 #endif // HAVE_LIBJPEG 00059 } 00060 00061 00062 // 00063 // Custom JPEG error handling structure... 00064 // 00065 00066 #ifdef HAVE_LIBJPEG 00067 struct fl_jpeg_error_mgr { 00068 jpeg_error_mgr pub_; // Destination manager... 00069 jmp_buf errhand_; // Error handler 00070 }; 00071 #endif // HAVE_LIBJPEG 00072 00073 00074 // 00075 // Error handler for JPEG files... 00076 // 00077 00078 #ifdef HAVE_LIBJPEG 00079 extern "C" { 00080 static void 00081 fl_jpeg_error_handler(j_common_ptr dinfo) { // I - Decompressor info 00082 longjmp(((fl_jpeg_error_mgr *)(dinfo->err))->errhand_, 1); 00083 } 00084 00085 static void 00086 fl_jpeg_output_handler(j_common_ptr) { // I - Decompressor info (not used) 00087 } 00088 } 00089 #endif // HAVE_LIBJPEG 00090 00091 00103 Fl_JPEG_Image::Fl_JPEG_Image(const char *filename) // I - File to load 00104 : Fl_RGB_Image(0,0,0) { 00105 #ifdef HAVE_LIBJPEG 00106 FILE *fp; // File pointer 00107 jpeg_decompress_struct dinfo; // Decompressor info 00108 fl_jpeg_error_mgr jerr; // Error handler info 00109 JSAMPROW row; // Sample row pointer 00110 00111 // the following variables are pointers allocating some private space that 00112 // is not reset by 'setjmp()' 00113 char* max_finish_decompress_err; // count errors and give up afer a while 00114 char* max_destroy_decompress_err; // to avoid recusion and deadlock 00115 00116 // Clear data... 00117 alloc_array = 0; 00118 array = (uchar *)0; 00119 00120 // Open the image file... 00121 if ((fp = fl_fopen(filename, "rb")) == NULL) return; 00122 00123 // Setup the decompressor info and read the header... 00124 dinfo.err = jpeg_std_error((jpeg_error_mgr *)&jerr); 00125 jerr.pub_.error_exit = fl_jpeg_error_handler; 00126 jerr.pub_.output_message = fl_jpeg_output_handler; 00127 00128 // Setup error loop variables 00129 max_finish_decompress_err = (char*)malloc(1); // allocate space on the frame for error counters 00130 max_destroy_decompress_err = (char*)malloc(1); // otherwise, the variables are reset on the longjmp 00131 *max_finish_decompress_err=10; 00132 *max_destroy_decompress_err=10; 00133 00134 if (setjmp(jerr.errhand_)) 00135 { 00136 // JPEG error handling... 00137 // if any of the cleanup routines hits another error, we would end up 00138 // in a loop. So instead, we decrement max_err for some upper cleanup limit. 00139 if ( ((*max_finish_decompress_err)-- > 0) && array) 00140 jpeg_finish_decompress(&dinfo); 00141 if ( (*max_destroy_decompress_err)-- > 0) 00142 jpeg_destroy_decompress(&dinfo); 00143 00144 fclose(fp); 00145 00146 w(0); 00147 h(0); 00148 d(0); 00149 00150 if (array) { 00151 delete[] (uchar *)array; 00152 array = 0; 00153 alloc_array = 0; 00154 } 00155 00156 free(max_destroy_decompress_err); 00157 free(max_finish_decompress_err); 00158 00159 return; 00160 } 00161 00162 jpeg_create_decompress(&dinfo); 00163 jpeg_stdio_src(&dinfo, fp); 00164 jpeg_read_header(&dinfo, 1); 00165 00166 dinfo.quantize_colors = (boolean)FALSE; 00167 dinfo.out_color_space = JCS_RGB; 00168 dinfo.out_color_components = 3; 00169 dinfo.output_components = 3; 00170 00171 jpeg_calc_output_dimensions(&dinfo); 00172 00173 w(dinfo.output_width); 00174 h(dinfo.output_height); 00175 d(dinfo.output_components); 00176 00177 array = new uchar[w() * h() * d()]; 00178 alloc_array = 1; 00179 00180 jpeg_start_decompress(&dinfo); 00181 00182 while (dinfo.output_scanline < dinfo.output_height) { 00183 row = (JSAMPROW)(array + 00184 dinfo.output_scanline * dinfo.output_width * 00185 dinfo.output_components); 00186 jpeg_read_scanlines(&dinfo, &row, (JDIMENSION)1); 00187 } 00188 00189 jpeg_finish_decompress(&dinfo); 00190 jpeg_destroy_decompress(&dinfo); 00191 00192 free(max_destroy_decompress_err); 00193 free(max_finish_decompress_err); 00194 00195 fclose(fp); 00196 #endif // HAVE_LIBJPEG 00197 } 00198 00199 00200 // data source manager for reading jpegs from memory 00201 // init_source (j_decompress_ptr cinfo) 00202 // fill_input_buffer (j_decompress_ptr cinfo) 00203 // skip_input_data (j_decompress_ptr cinfo, long num_bytes) 00204 // resync_to_restart (j_decompress_ptr cinfo, int desired) 00205 // term_source (j_decompress_ptr cinfo) 00206 // JOCTET * next_output_byte; /* => next byte to write in buffer */ 00207 // size_t free_in_buffer; /* # of byte spaces remaining in buffer */ 00208 00209 #ifdef HAVE_LIBJPEG 00210 typedef struct { 00211 struct jpeg_source_mgr pub; 00212 const unsigned char *data, *s; 00213 // JOCTET * buffer; /* start of buffer */ 00214 // boolean start_of_file; /* have we gotten any data yet? */ 00215 } my_source_mgr; 00216 00217 typedef my_source_mgr *my_src_ptr; 00218 00219 00220 void init_source (j_decompress_ptr cinfo) { 00221 my_src_ptr src = (my_src_ptr)cinfo->src; 00222 src->s = src->data; 00223 } 00224 00225 boolean fill_input_buffer(j_decompress_ptr cinfo) { 00226 my_src_ptr src = (my_src_ptr)cinfo->src; 00227 size_t nbytes = 4096; 00228 src->pub.next_input_byte = src->s; 00229 src->pub.bytes_in_buffer = nbytes; 00230 src->s += nbytes; 00231 return TRUE; 00232 } 00233 00234 void term_source(j_decompress_ptr cinfo) 00235 { 00236 } 00237 00238 void skip_input_data(j_decompress_ptr cinfo, long num_bytes) { 00239 my_src_ptr src = (my_src_ptr)cinfo->src; 00240 if (num_bytes > 0) { 00241 while (num_bytes > (long)src->pub.bytes_in_buffer) { 00242 num_bytes -= (long)src->pub.bytes_in_buffer; 00243 fill_input_buffer(cinfo); 00244 } 00245 src->pub.next_input_byte += (size_t) num_bytes; 00246 src->pub.bytes_in_buffer -= (size_t) num_bytes; 00247 } 00248 } 00249 00250 static void jpeg_mem_src(j_decompress_ptr cinfo, const unsigned char *data) 00251 { 00252 my_src_ptr src; 00253 cinfo->src = (struct jpeg_source_mgr *)malloc(sizeof(my_source_mgr)); 00254 src = (my_src_ptr)cinfo->src; 00255 src->pub.init_source = init_source; 00256 src->pub.fill_input_buffer = fill_input_buffer; 00257 src->pub.skip_input_data = skip_input_data; 00258 src->pub.resync_to_restart = jpeg_resync_to_restart; 00259 src->pub.term_source = term_source; 00260 src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */ 00261 src->pub.next_input_byte = NULL; /* until buffer loaded */ 00262 src->data = data; 00263 src->s = data; 00264 } 00265 #endif // HAVE_LIBJPEG 00266 00267 00280 Fl_JPEG_Image::Fl_JPEG_Image(const char *name, const unsigned char *data) 00281 : Fl_RGB_Image(0,0,0) { 00282 #ifdef HAVE_LIBJPEG 00283 jpeg_decompress_struct dinfo; // Decompressor info 00284 fl_jpeg_error_mgr jerr; // Error handler info 00285 JSAMPROW row; // Sample row pointer 00286 00287 // the following variables are pointers allocating some private space that 00288 // is not reset by 'setjmp()' 00289 char* max_finish_decompress_err; // count errors and give up afer a while 00290 char* max_destroy_decompress_err; // to avoid recusion and deadlock 00291 00292 // Clear data... 00293 alloc_array = 0; 00294 array = (uchar *)0; 00295 00296 // Setup the decompressor info and read the header... 00297 dinfo.err = jpeg_std_error((jpeg_error_mgr *)&jerr); 00298 jerr.pub_.error_exit = fl_jpeg_error_handler; 00299 jerr.pub_.output_message = fl_jpeg_output_handler; 00300 00301 // Setup error loop variables 00302 max_finish_decompress_err = (char*)malloc(1); // allocate space on the frame for error counters 00303 max_destroy_decompress_err = (char*)malloc(1); // otherwise, the variables are reset on the longjmp 00304 *max_finish_decompress_err=10; 00305 *max_destroy_decompress_err=10; 00306 00307 if (setjmp(jerr.errhand_)) 00308 { 00309 // JPEG error handling... 00310 // if any of the cleanup routines hits another error, we would end up 00311 // in a loop. So instead, we decrement max_err for some upper cleanup limit. 00312 if ( ((*max_finish_decompress_err)-- > 0) && array) 00313 jpeg_finish_decompress(&dinfo); 00314 if ( (*max_destroy_decompress_err)-- > 0) 00315 jpeg_destroy_decompress(&dinfo); 00316 00317 w(0); 00318 h(0); 00319 d(0); 00320 00321 if (array) { 00322 delete[] (uchar *)array; 00323 array = 0; 00324 alloc_array = 0; 00325 } 00326 00327 free(max_destroy_decompress_err); 00328 free(max_finish_decompress_err); 00329 00330 return; 00331 } 00332 00333 jpeg_create_decompress(&dinfo); 00334 jpeg_mem_src(&dinfo, data); 00335 jpeg_read_header(&dinfo, 1); 00336 00337 dinfo.quantize_colors = (boolean)FALSE; 00338 dinfo.out_color_space = JCS_RGB; 00339 dinfo.out_color_components = 3; 00340 dinfo.output_components = 3; 00341 00342 jpeg_calc_output_dimensions(&dinfo); 00343 00344 w(dinfo.output_width); 00345 h(dinfo.output_height); 00346 d(dinfo.output_components); 00347 00348 array = new uchar[w() * h() * d()]; 00349 alloc_array = 1; 00350 00351 jpeg_start_decompress(&dinfo); 00352 00353 while (dinfo.output_scanline < dinfo.output_height) { 00354 row = (JSAMPROW)(array + 00355 dinfo.output_scanline * dinfo.output_width * 00356 dinfo.output_components); 00357 jpeg_read_scanlines(&dinfo, &row, (JDIMENSION)1); 00358 } 00359 00360 jpeg_finish_decompress(&dinfo); 00361 jpeg_destroy_decompress(&dinfo); 00362 00363 free(max_destroy_decompress_err); 00364 free(max_finish_decompress_err); 00365 #endif // HAVE_LIBJPEG 00366 } 00367 00368 // 00369 // End of "$Id: Fl_JPEG_Image.cxx 7903 2010-11-28 21:06:39Z matt $". 00370 //