themes: Workaround for bug where a background color of RGB 0,0,0 in Black color schem...
[ntk.git] / src / Fl_JPEG_Image.cxx
blob38ad20b0c20e38e1b78db54d6b387829036cca02
1 //
2 // "$Id: Fl_JPEG_Image.cxx 8462 2011-02-22 09:41:26Z manolo $"
3 //
4 // Fl_JPEG_Image routines.
5 //
6 // Copyright 1997-2011 by Easy Software Products.
7 // Image support by Matthias Melcher, Copyright 2000-2009.
8 //
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
22 // USA.
24 // Please report all bugs and problems on the following page:
26 // http://www.fltk.org/str.php
28 // Contents:
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>
40 #include <config.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <setjmp.h>
44 #include <stdint.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__)
51 # define XMD_H
52 #endif // WIN32 && __CYGWIN__
55 extern "C"
57 #ifdef HAVE_LIBJPEG
58 # include <jpeglib.h>
59 #endif // HAVE_LIBJPEG
64 // Custom JPEG error handling structure...
67 #ifdef HAVE_LIBJPEG
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...
79 #ifdef HAVE_LIBJPEG
80 extern "C" {
81 static void
82 fl_jpeg_error_handler(j_common_ptr dinfo) { // I - Decompressor info
83 longjmp(((fl_jpeg_error_mgr *)(dinfo->err))->errhand_, 1);
86 static void
87 fl_jpeg_output_handler(j_common_ptr) { // I - Decompressor info (not used)
90 #endif // HAVE_LIBJPEG
93 /**
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
97 by the image.
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) {
106 #ifdef HAVE_LIBJPEG
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
111 uint32_t *row;
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
118 // Clear data...
119 alloc_array = 0;
120 array = (uchar *)0;
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);
146 fclose(fp);
148 w(0);
149 h(0);
150 d(0);
152 if (array) {
153 delete[] (uchar *)array;
154 array = 0;
155 alloc_array = 0;
158 free(max_destroy_decompress_err);
159 free(max_finish_decompress_err);
161 return;
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 )];
182 alloc_array = 1;
184 jpeg_start_decompress(&dinfo);
186 while (dinfo.output_scanline < dinfo.output_height) {
187 row = (uint32_t*)
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 ) |
196 ( line[ i + 2 ] );
200 d(4);
202 delete[] line;
204 jpeg_finish_decompress(&dinfo);
205 jpeg_destroy_decompress(&dinfo);
207 free(max_destroy_decompress_err);
208 free(max_finish_decompress_err);
210 fclose(fp);
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 */
224 #ifdef HAVE_LIBJPEG
225 typedef struct {
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? */
230 } my_source_mgr;
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;
237 src->s = src->data;
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;
245 src->s += nbytes;
246 return TRUE;
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;
255 if (num_bytes > 0) {
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)
267 my_src_ptr src;
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 */
277 src->data = data;
278 src->s = data;
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
292 by the image.
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) {
302 #ifdef HAVE_LIBJPEG
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
312 // Clear data...
313 alloc_array = 0;
314 array = (uchar *)0;
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);
337 w(0);
338 h(0);
339 d(0);
341 if (array) {
342 delete[] (uchar *)array;
343 array = 0;
344 alloc_array = 0;
347 free(max_destroy_decompress_err);
348 free(max_finish_decompress_err);
350 return;
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()];
369 alloc_array = 1;
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);
388 si->add();
390 #endif // HAVE_LIBJPEG
394 // End of "$Id: Fl_JPEG_Image.cxx 8462 2011-02-22 09:41:26Z manolo $".