2 // "$Id: Fl_JPEG_Image.cxx 8462 2011-02-22 09:41:26Z manolo $"
4 // Fl_JPEG_Image routines.
6 // Copyright 1997-2011 by Easy Software Products.
7 // Image support by Matthias Melcher, Copyright 2000-2009.
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Library General Public
11 // License as published by the Free Software Foundation; either
12 // version 2 of the License, or (at your option) any later version.
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Library General Public License for more details.
19 // You should have received a copy of the GNU Library General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
24 // Please report all bugs and problems on the following page:
26 // http://www.fltk.org/str.php
30 // Fl_JPEG_Image::Fl_JPEG_Image() - Load a JPEG image file.
34 // Include necessary header files...
37 #include <FL/Fl_JPEG_Image.H>
38 #include <FL/Fl_Shared_Image.H>
39 #include <FL/fl_utf8.h>
46 // Some releases of the Cygwin JPEG libraries don't have a correctly
47 // updated header file for the INT32 data type; the following define
48 // from Shane Hill seems to be a usable workaround...
50 #if defined(WIN32) && defined(__CYGWIN__)
52 #endif // WIN32 && __CYGWIN__
59 #endif // HAVE_LIBJPEG
64 // Custom JPEG error handling structure...
68 struct fl_jpeg_error_mgr
{
69 jpeg_error_mgr pub_
; // Destination manager...
70 jmp_buf errhand_
; // Error handler
72 #endif // HAVE_LIBJPEG
76 // Error handler for JPEG files...
82 fl_jpeg_error_handler(j_common_ptr dinfo
) { // I - Decompressor info
83 longjmp(((fl_jpeg_error_mgr
*)(dinfo
->err
))->errhand_
, 1);
87 fl_jpeg_output_handler(j_common_ptr
) { // I - Decompressor info (not used)
90 #endif // HAVE_LIBJPEG
94 \brief The constructor loads the JPEG image from the given jpeg filename.
96 The inherited destructor frees all memory and server resources that are used
99 There is no error function in this class. If the image has loaded correctly,
100 w(), h(), and d() should return values greater zero.
102 \param[in] filename a full path and name pointing to a valid jpeg file.
104 Fl_JPEG_Image::Fl_JPEG_Image(const char *filename
) // I - File to load
105 : Fl_RGB_Image(0,0,0) {
107 FILE *fp
; // File pointer
108 jpeg_decompress_struct dinfo
; // Decompressor info
109 fl_jpeg_error_mgr jerr
; // Error handler info
110 // JSAMPROW row; // Sample row pointer
113 // the following variables are pointers allocating some private space that
114 // is not reset by 'setjmp()'
115 char* max_finish_decompress_err
; // count errors and give up afer a while
116 char* max_destroy_decompress_err
; // to avoid recusion and deadlock
122 // Open the image file...
123 if ((fp
= fl_fopen(filename
, "rb")) == NULL
) return;
125 // Setup the decompressor info and read the header...
126 dinfo
.err
= jpeg_std_error((jpeg_error_mgr
*)&jerr
);
127 jerr
.pub_
.error_exit
= fl_jpeg_error_handler
;
128 jerr
.pub_
.output_message
= fl_jpeg_output_handler
;
130 // Setup error loop variables
131 max_finish_decompress_err
= (char*)malloc(1); // allocate space on the frame for error counters
132 max_destroy_decompress_err
= (char*)malloc(1); // otherwise, the variables are reset on the longjmp
133 *max_finish_decompress_err
=10;
134 *max_destroy_decompress_err
=10;
136 if (setjmp(jerr
.errhand_
))
138 // JPEG error handling...
139 // if any of the cleanup routines hits another error, we would end up
140 // in a loop. So instead, we decrement max_err for some upper cleanup limit.
141 if ( ((*max_finish_decompress_err
)-- > 0) && array
)
142 jpeg_finish_decompress(&dinfo
);
143 if ( (*max_destroy_decompress_err
)-- > 0)
144 jpeg_destroy_decompress(&dinfo
);
153 delete[] (uchar
*)array
;
158 free(max_destroy_decompress_err
);
159 free(max_finish_decompress_err
);
164 jpeg_create_decompress(&dinfo
);
165 jpeg_stdio_src(&dinfo
, fp
);
166 jpeg_read_header(&dinfo
, 1);
168 dinfo
.quantize_colors
= (boolean
)FALSE
;
169 dinfo
.out_color_space
= JCS_RGB
;
170 dinfo
.out_color_components
= 3;
171 dinfo
.output_components
= 3;
173 jpeg_calc_output_dimensions(&dinfo
);
175 w(dinfo
.output_width
);
176 h(dinfo
.output_height
);
177 d(dinfo
.output_components
);
179 uchar
*line
= new uchar
[ w() * d() ];
181 array
= new uchar
[w() * h() * ( d() + 1 )];
184 jpeg_start_decompress(&dinfo
);
186 while (dinfo
.output_scanline
< dinfo
.output_height
) {
188 (array
+ dinfo
.output_scanline
* dinfo
.output_width
* ( dinfo
.output_components
+ 1 ));
190 jpeg_read_scanlines(&dinfo
, &line
, (JDIMENSION
)1);
192 for ( int i
= 0, j
= 0; i
< w() * d(); i
+= 3, j
++ )
194 row
[ j
] = ( line
[ i
] << 16 ) |
195 ( line
[ i
+ 1 ] << 8 ) |
204 jpeg_finish_decompress(&dinfo
);
205 jpeg_destroy_decompress(&dinfo
);
207 free(max_destroy_decompress_err
);
208 free(max_finish_decompress_err
);
211 #endif // HAVE_LIBJPEG
215 // data source manager for reading jpegs from memory
216 // init_source (j_decompress_ptr cinfo)
217 // fill_input_buffer (j_decompress_ptr cinfo)
218 // skip_input_data (j_decompress_ptr cinfo, long num_bytes)
219 // resync_to_restart (j_decompress_ptr cinfo, int desired)
220 // term_source (j_decompress_ptr cinfo)
221 // JOCTET * next_output_byte; /* => next byte to write in buffer */
222 // size_t free_in_buffer; /* # of byte spaces remaining in buffer */
226 struct jpeg_source_mgr pub
;
227 const unsigned char *data
, *s
;
228 // JOCTET * buffer; /* start of buffer */
229 // boolean start_of_file; /* have we gotten any data yet? */
232 typedef my_source_mgr
*my_src_ptr
;
235 void init_source (j_decompress_ptr cinfo
) {
236 my_src_ptr src
= (my_src_ptr
)cinfo
->src
;
240 boolean
fill_input_buffer(j_decompress_ptr cinfo
) {
241 my_src_ptr src
= (my_src_ptr
)cinfo
->src
;
242 size_t nbytes
= 4096;
243 src
->pub
.next_input_byte
= src
->s
;
244 src
->pub
.bytes_in_buffer
= nbytes
;
249 void term_source(j_decompress_ptr cinfo
)
253 void skip_input_data(j_decompress_ptr cinfo
, long num_bytes
) {
254 my_src_ptr src
= (my_src_ptr
)cinfo
->src
;
256 while (num_bytes
> (long)src
->pub
.bytes_in_buffer
) {
257 num_bytes
-= (long)src
->pub
.bytes_in_buffer
;
258 fill_input_buffer(cinfo
);
260 src
->pub
.next_input_byte
+= (size_t) num_bytes
;
261 src
->pub
.bytes_in_buffer
-= (size_t) num_bytes
;
265 static void jpeg_mem_src(j_decompress_ptr cinfo
, const unsigned char *data
)
268 cinfo
->src
= (struct jpeg_source_mgr
*)malloc(sizeof(my_source_mgr
));
269 src
= (my_src_ptr
)cinfo
->src
;
270 src
->pub
.init_source
= init_source
;
271 src
->pub
.fill_input_buffer
= fill_input_buffer
;
272 src
->pub
.skip_input_data
= skip_input_data
;
273 src
->pub
.resync_to_restart
= jpeg_resync_to_restart
;
274 src
->pub
.term_source
= term_source
;
275 src
->pub
.bytes_in_buffer
= 0; /* forces fill_input_buffer on first read */
276 src
->pub
.next_input_byte
= NULL
; /* until buffer loaded */
280 #endif // HAVE_LIBJPEG
284 \brief The constructor loads the JPEG image from memory.
286 Construct an image from a block of memory inside the application. Fluid offers
287 "binary Data" chunks as a great way to add image data into the C++ source code.
288 name_png can be NULL. If a name is given, the image is added to the list of
289 shared images (see: Fl_Shared_Image) and will be available by that name.
291 The inherited destructor frees all memory and server resources that are used
294 There is no error function in this class. If the image has loaded correctly,
295 w(), h(), and d() should return values greater zero.
297 \param name A unique name or NULL
298 \param data A pointer to the memory location of the JPEG image
300 Fl_JPEG_Image::Fl_JPEG_Image(const char *name
, const unsigned char *data
)
301 : Fl_RGB_Image(0,0,0) {
303 jpeg_decompress_struct dinfo
; // Decompressor info
304 fl_jpeg_error_mgr jerr
; // Error handler info
305 JSAMPROW row
; // Sample row pointer
307 // the following variables are pointers allocating some private space that
308 // is not reset by 'setjmp()'
309 char* max_finish_decompress_err
; // count errors and give up afer a while
310 char* max_destroy_decompress_err
; // to avoid recusion and deadlock
316 // Setup the decompressor info and read the header...
317 dinfo
.err
= jpeg_std_error((jpeg_error_mgr
*)&jerr
);
318 jerr
.pub_
.error_exit
= fl_jpeg_error_handler
;
319 jerr
.pub_
.output_message
= fl_jpeg_output_handler
;
321 // Setup error loop variables
322 max_finish_decompress_err
= (char*)malloc(1); // allocate space on the frame for error counters
323 max_destroy_decompress_err
= (char*)malloc(1); // otherwise, the variables are reset on the longjmp
324 *max_finish_decompress_err
=10;
325 *max_destroy_decompress_err
=10;
327 if (setjmp(jerr
.errhand_
))
329 // JPEG error handling...
330 // if any of the cleanup routines hits another error, we would end up
331 // in a loop. So instead, we decrement max_err for some upper cleanup limit.
332 if ( ((*max_finish_decompress_err
)-- > 0) && array
)
333 jpeg_finish_decompress(&dinfo
);
334 if ( (*max_destroy_decompress_err
)-- > 0)
335 jpeg_destroy_decompress(&dinfo
);
342 delete[] (uchar
*)array
;
347 free(max_destroy_decompress_err
);
348 free(max_finish_decompress_err
);
353 jpeg_create_decompress(&dinfo
);
354 jpeg_mem_src(&dinfo
, data
);
355 jpeg_read_header(&dinfo
, 1);
357 dinfo
.quantize_colors
= (boolean
)FALSE
;
358 dinfo
.out_color_space
= JCS_RGB
;
359 dinfo
.out_color_components
= 3;
360 dinfo
.output_components
= 3;
362 jpeg_calc_output_dimensions(&dinfo
);
364 w(dinfo
.output_width
);
365 h(dinfo
.output_height
);
366 d(dinfo
.output_components
);
368 array
= new uchar
[w() * h() * d()];
371 jpeg_start_decompress(&dinfo
);
373 while (dinfo
.output_scanline
< dinfo
.output_height
) {
374 row
= (JSAMPROW
)(array
+
375 dinfo
.output_scanline
* dinfo
.output_width
*
376 dinfo
.output_components
);
377 jpeg_read_scanlines(&dinfo
, &row
, (JDIMENSION
)1);
380 jpeg_finish_decompress(&dinfo
);
381 jpeg_destroy_decompress(&dinfo
);
383 free(max_destroy_decompress_err
);
384 free(max_finish_decompress_err
);
386 if (w() && h() && name
) {
387 Fl_Shared_Image
*si
= new Fl_Shared_Image(name
, this);
390 #endif // HAVE_LIBJPEG
394 // End of "$Id: Fl_JPEG_Image.cxx 8462 2011-02-22 09:41:26Z manolo $".