fltk  1.3.5-source
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X.
  Fossies Dox: fltk-1.3.5-source.tar.bz2  ("inofficial" and yet experimental doxygen-generated source code documentation)  

Fl_JPEG_Image.cxx
Go to the documentation of this file.
1 //
2 // "$Id$"
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. Distribution and use rights are outlined in
10 // the file "COPYING" which should have been included with this file. If this
11 // file is missing or damaged, see the license at:
12 //
13 // http://www.fltk.org/COPYING.php
14 //
15 // Please report all bugs and problems on the following page:
16 //
17 // http://www.fltk.org/str.php
18 //
19 // Contents:
20 //
21 // Fl_JPEG_Image::Fl_JPEG_Image() - Load a JPEG image file.
22 //
23 
24 //
25 // Include necessary header files...
26 //
27 
28 #include <FL/Fl_JPEG_Image.H>
29 #include <FL/Fl_Shared_Image.H>
30 #include <FL/fl_utf8.h>
31 #include <FL/Fl.H>
32 #include <config.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <setjmp.h>
36 
37 
38 // Some releases of the Cygwin JPEG libraries don't have a correctly
39 // updated header file for the INT32 data type; the following define
40 // from Shane Hill seems to be a usable workaround...
41 
42 #if defined(WIN32) && defined(__CYGWIN__)
43 # define XMD_H
44 #endif // WIN32 && __CYGWIN__
45 
46 
47 extern "C"
48 {
49 #ifdef HAVE_LIBJPEG
50 # include <jpeglib.h>
51 #endif // HAVE_LIBJPEG
52 }
53 
54 
55 //
56 // Custom JPEG error handling structure...
57 //
58 
59 #ifdef HAVE_LIBJPEG
60 struct fl_jpeg_error_mgr {
61  jpeg_error_mgr pub_; // Destination manager...
62  jmp_buf errhand_; // Error handler
63 };
64 #endif // HAVE_LIBJPEG
65 
66 
67 //
68 // Error handler for JPEG files...
69 //
70 
71 #ifdef HAVE_LIBJPEG
72 extern "C" {
73  static void
74  fl_jpeg_error_handler(j_common_ptr dinfo) { // I - Decompressor info
75  longjmp(((fl_jpeg_error_mgr *)(dinfo->err))->errhand_, 1);
76  }
77 
78  static void
79  fl_jpeg_output_handler(j_common_ptr) { // I - Decompressor info (not used)
80  }
81 }
82 #endif // HAVE_LIBJPEG
83 
84 
99 Fl_JPEG_Image::Fl_JPEG_Image(const char *filename) // I - File to load
100 : Fl_RGB_Image(0,0,0) {
101 #ifdef HAVE_LIBJPEG
102  FILE *fp; // File pointer
103  jpeg_decompress_struct dinfo; // Decompressor info
104  fl_jpeg_error_mgr jerr; // Error handler info
105  JSAMPROW row; // Sample row pointer
106 
107  // the following variables are pointers allocating some private space that
108  // is not reset by 'setjmp()'
109  char* max_finish_decompress_err; // count errors and give up afer a while
110  char* max_destroy_decompress_err; // to avoid recusion and deadlock
111 
112  // Clear data...
113  alloc_array = 0;
114  array = (uchar *)0;
115 
116  // Open the image file...
117  if ((fp = fl_fopen(filename, "rb")) == NULL) {
119  return;
120  }
121 
122  // Setup the decompressor info and read the header...
123  dinfo.err = jpeg_std_error((jpeg_error_mgr *)&jerr);
124  jerr.pub_.error_exit = fl_jpeg_error_handler;
125  jerr.pub_.output_message = fl_jpeg_output_handler;
126 
127  // Setup error loop variables
128  max_finish_decompress_err = (char*)malloc(1); // allocate space on the frame for error counters
129  max_destroy_decompress_err = (char*)malloc(1); // otherwise, the variables are reset on the longjmp
130  *max_finish_decompress_err=10;
131  *max_destroy_decompress_err=10;
132 
133  if (setjmp(jerr.errhand_))
134  {
135  // JPEG error handling...
136  Fl::warning("JPEG file \"%s\" is too large or contains errors!\n", filename);
137  // if any of the cleanup routines hits another error, we would end up
138  // in a loop. So instead, we decrement max_err for some upper cleanup limit.
139  if ( ((*max_finish_decompress_err)-- > 0) && array)
140  jpeg_finish_decompress(&dinfo);
141  if ( (*max_destroy_decompress_err)-- > 0)
142  jpeg_destroy_decompress(&dinfo);
143 
144  fclose(fp);
145 
146  w(0);
147  h(0);
148  d(0);
149 
150  if (array) {
151  delete[] (uchar *)array;
152  array = 0;
153  alloc_array = 0;
154  }
155 
156  free(max_destroy_decompress_err);
157  free(max_finish_decompress_err);
158 
159  ld(ERR_FORMAT);
160  return;
161  }
162 
163  jpeg_create_decompress(&dinfo);
164  jpeg_stdio_src(&dinfo, fp);
165  jpeg_read_header(&dinfo, TRUE);
166 
167  dinfo.quantize_colors = (boolean)FALSE;
168  dinfo.out_color_space = JCS_RGB;
169  dinfo.out_color_components = 3;
170  dinfo.output_components = 3;
171 
173 
174  w(dinfo.output_width);
175  h(dinfo.output_height);
176  d(dinfo.output_components);
177 
178  if (((size_t)w()) * h() * d() > max_size() ) longjmp(jerr.errhand_, 1);
179  array = new uchar[w() * h() * d()];
180  alloc_array = 1;
181 
182  jpeg_start_decompress(&dinfo);
183 
184  while (dinfo.output_scanline < dinfo.output_height) {
185  row = (JSAMPROW)(array +
186  dinfo.output_scanline * dinfo.output_width *
187  dinfo.output_components);
188  jpeg_read_scanlines(&dinfo, &row, (JDIMENSION)1);
189  }
190 
191  jpeg_finish_decompress(&dinfo);
192  jpeg_destroy_decompress(&dinfo);
193 
194  free(max_destroy_decompress_err);
195  free(max_finish_decompress_err);
196 
197  fclose(fp);
198 #endif // HAVE_LIBJPEG
199 }
200 
201 
202 // data source manager for reading jpegs from memory
203 // init_source (j_decompress_ptr cinfo)
204 // fill_input_buffer (j_decompress_ptr cinfo)
205 // skip_input_data (j_decompress_ptr cinfo, long num_bytes)
206 // resync_to_restart (j_decompress_ptr cinfo, int desired)
207 // term_source (j_decompress_ptr cinfo)
208 // JOCTET * next_output_byte; /* => next byte to write in buffer */
209 // size_t free_in_buffer; /* # of byte spaces remaining in buffer */
210 
211 #ifdef HAVE_LIBJPEG
212 typedef struct {
213  struct jpeg_source_mgr pub;
214  const unsigned char *data, *s;
215  // JOCTET * buffer; /* start of buffer */
216  // boolean start_of_file; /* have we gotten any data yet? */
217 } my_source_mgr;
218 
219 typedef my_source_mgr *my_src_ptr;
220 
221 
222 extern "C" {
223 
224  static void init_source(j_decompress_ptr cinfo) {
225  my_src_ptr src = (my_src_ptr)cinfo->src;
226  src->s = src->data;
227  }
228 
229  static boolean fill_input_buffer(j_decompress_ptr cinfo) {
230  my_src_ptr src = (my_src_ptr)cinfo->src;
231  size_t nbytes = 4096;
232  src->pub.next_input_byte = src->s;
233  src->pub.bytes_in_buffer = nbytes;
234  src->s += nbytes;
235  return TRUE;
236  }
237 
238  static void term_source(j_decompress_ptr cinfo)
239  {
240  }
241 
242  static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) {
243  my_src_ptr src = (my_src_ptr)cinfo->src;
244  if (num_bytes > 0) {
245  while (num_bytes > (long)src->pub.bytes_in_buffer) {
246  num_bytes -= (long)src->pub.bytes_in_buffer;
247  fill_input_buffer(cinfo);
248  }
249  src->pub.next_input_byte += (size_t) num_bytes;
250  src->pub.bytes_in_buffer -= (size_t) num_bytes;
251  }
252  }
253 
254 } // extern "C"
255 
256 static void jpeg_mem_src(j_decompress_ptr cinfo, const unsigned char *data)
257 {
258  my_src_ptr src;
259  cinfo->src = (struct jpeg_source_mgr *)malloc(sizeof(my_source_mgr));
260  src = (my_src_ptr)cinfo->src;
261  src->pub.init_source = init_source;
265  src->pub.term_source = term_source;
266  src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
267  src->pub.next_input_byte = NULL; /* until buffer loaded */
268  src->data = data;
269  src->s = data;
270 }
271 #endif // HAVE_LIBJPEG
272 
273 
294 Fl_JPEG_Image::Fl_JPEG_Image(const char *name, const unsigned char *data)
295 : Fl_RGB_Image(0,0,0) {
296 #ifdef HAVE_LIBJPEG
297  jpeg_decompress_struct dinfo; // Decompressor info
298  fl_jpeg_error_mgr jerr; // Error handler info
299  JSAMPROW row; // Sample row pointer
300 
301  // the following variables are pointers allocating some private space that
302  // is not reset by 'setjmp()'
303  char* max_finish_decompress_err; // count errors and give up afer a while
304  char* max_destroy_decompress_err; // to avoid recusion and deadlock
305 
306  // Clear data...
307  alloc_array = 0;
308  array = (uchar *)0;
309 
310  // Setup the decompressor info and read the header...
311  dinfo.err = jpeg_std_error((jpeg_error_mgr *)&jerr);
312  jerr.pub_.error_exit = fl_jpeg_error_handler;
313  jerr.pub_.output_message = fl_jpeg_output_handler;
314 
315  // Setup error loop variables
316  max_finish_decompress_err = (char*)malloc(1); // allocate space on the frame for error counters
317  max_destroy_decompress_err = (char*)malloc(1); // otherwise, the variables are reset on the longjmp
318  *max_finish_decompress_err=10;
319  *max_destroy_decompress_err=10;
320 
321  if (setjmp(jerr.errhand_))
322  {
323  // JPEG error handling...
324  Fl::warning("JPEG data is too large or contains errors!\n");
325  // if any of the cleanup routines hits another error, we would end up
326  // in a loop. So instead, we decrement max_err for some upper cleanup limit.
327  if ( ((*max_finish_decompress_err)-- > 0) && array)
328  jpeg_finish_decompress(&dinfo);
329  if ( (*max_destroy_decompress_err)-- > 0)
330  jpeg_destroy_decompress(&dinfo);
331 
332  w(0);
333  h(0);
334  d(0);
335 
336  if (array) {
337  delete[] (uchar *)array;
338  array = 0;
339  alloc_array = 0;
340  }
341 
342  free(max_destroy_decompress_err);
343  free(max_finish_decompress_err);
344 
345  return;
346  }
347 
348  jpeg_create_decompress(&dinfo);
349  jpeg_mem_src(&dinfo, data);
350  jpeg_read_header(&dinfo, TRUE);
351 
352  dinfo.quantize_colors = (boolean)FALSE;
353  dinfo.out_color_space = JCS_RGB;
354  dinfo.out_color_components = 3;
355  dinfo.output_components = 3;
356 
358 
359  w(dinfo.output_width);
360  h(dinfo.output_height);
361  d(dinfo.output_components);
362 
363  if (((size_t)w()) * h() * d() > max_size() ) longjmp(jerr.errhand_, 1);
364  array = new uchar[w() * h() * d()];
365  alloc_array = 1;
366 
367  jpeg_start_decompress(&dinfo);
368 
369  while (dinfo.output_scanline < dinfo.output_height) {
370  row = (JSAMPROW)(array +
371  dinfo.output_scanline * dinfo.output_width *
372  dinfo.output_components);
373  jpeg_read_scanlines(&dinfo, &row, (JDIMENSION)1);
374  }
375 
376  jpeg_finish_decompress(&dinfo);
377  jpeg_destroy_decompress(&dinfo);
378 
379  free(max_destroy_decompress_err);
380  free(max_finish_decompress_err);
381 
382  if (w() && h() && name) {
383  Fl_Shared_Image *si = new Fl_Shared_Image(name, this);
384  si->add();
385  }
386 #endif // HAVE_LIBJPEG
387 }
388 
389 //
390 // End of "$Id$".
391 //
Fl.H
skip_input_data
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
Definition: jdatasrc.c:156
jpeglib.h
init_source
static void init_source(j_decompress_ptr cinfo)
Definition: jdatasrc.c:45
jpeg_decompress_struct::output_scanline
JDIMENSION output_scanline
Definition: jpeglib.h:537
Fl_Image::data
const char *const * data() const
Definition: Fl_Image.H:138
jpeg_destroy_decompress
void jpeg_destroy_decompress(j_decompress_ptr cinfo)
Definition: jdapimin.c:92
JCS_RGB
Definition: jpeglib.h:223
jpeg_error_mgr::output_message
void(* output_message)()
Definition: jpeglib.h:708
Fl_Image::d
int d() const
Definition: Fl_Image.H:121
my_source_mgr
Definition: jdatasrc.c:26
jpeg_source_mgr::next_input_byte
const JOCTET * next_input_byte
Definition: jpeglib.h:785
jpeg_decompress_struct::src
struct jpeg_source_mgr * src
Definition: jpeglib.h:463
free
void free()
jpeg_read_scanlines
JDIMENSION jpeg_read_scanlines(j_decompress_ptr cinfo, JSAMPARRAY scanlines, JDIMENSION max_lines)
Definition: jdapistd.c:153
jpeg_decompress_struct::output_width
JDIMENSION output_width
Definition: jpeglib.h:507
jpeg_error_mgr
Definition: jpeglib.h:702
NULL
#define NULL
Definition: forms.H:34
jpeg_finish_decompress
boolean jpeg_finish_decompress(j_decompress_ptr cinfo)
Definition: jdapimin.c:373
jpeg_create_decompress
#define jpeg_create_decompress(cinfo)
Definition: jpeglib.h:961
Fl_JPEG_Image.H
fl_fopen
FILE * fl_fopen(const char *f, const char *mode)
Definition: fl_utf8.cxx:498
jpeg_source_mgr::term_source
void(* term_source)()
Definition: jpeglib.h:792
term_source
static void term_source(j_decompress_ptr cinfo)
Definition: jdatasrc.c:197
jpeg_source_mgr::skip_input_data
void(* skip_input_data)()
Definition: jpeglib.h:790
Fl_Image::ld
int ld() const
Definition: Fl_Image.H:126
jpeg_decompress_struct::output_height
JDIMENSION output_height
Definition: jpeglib.h:508
jpeg_source_mgr::resync_to_restart
boolean(* resync_to_restart)()
Definition: jpeglib.h:791
jpeg_resync_to_restart
boolean jpeg_resync_to_restart(j_decompress_ptr cinfo, int desired)
Definition: jdmarker.c:1343
JSAMPROW
JSAMPLE * JSAMPROW
Definition: jpeglib.h:75
jpeg_decompress_struct::err
struct jpeg_error_mgr * err
Definition: jpeglib.h:460
my_src_ptr
my_source_mgr * my_src_ptr
Definition: jdatasrc.c:34
jpeg_common_struct
Definition: jpeglib.h:276
Fl_JPEG_Image::Fl_JPEG_Image
Fl_JPEG_Image(const char *filename)
The constructor loads the JPEG image from the given jpeg filename.
Definition: Fl_JPEG_Image.cxx:99
jpeg_source_mgr::bytes_in_buffer
size_t bytes_in_buffer
Definition: jpeglib.h:786
TRUE
Definition: jmorecfg.h:317
Fl_RGB_Image::alloc_array
int alloc_array
Definition: Fl_Image.H:215
fl_utf8.h
header for Unicode and UTF-8 character handling
jpeg_decompress_struct::output_components
int output_components
Definition: jpeglib.h:510
jpeg_calc_output_dimensions
void jpeg_calc_output_dimensions(j_decompress_ptr cinfo)
Definition: jdmaster.c:89
jpeg_start_decompress
boolean jpeg_start_decompress(j_decompress_ptr cinfo)
Definition: jdapistd.c:39
filename
static const char * filename
Definition: fluid.cxx:119
Fl_Image::ERR_FORMAT
static const int ERR_FORMAT
Definition: Fl_Image.H:60
JDIMENSION
unsigned int JDIMENSION
Definition: jmorecfg.h:229
Fl_Shared_Image::add
void add()
Definition: Fl_Shared_Image.cxx:167
Fl_Image::h
int h() const
Definition: Fl_Image.H:115
jpeg_decompress_struct::quantize_colors
boolean quantize_colors
Definition: jpeglib.h:491
Fl_RGB_Image::array
const uchar * array
Definition: Fl_Image.H:212
Fl_Shared_Image.H
jpeg_error_mgr::error_exit
noreturn_t(* error_exit)()
Definition: jpeglib.h:704
jpeg_decompress_struct::out_color_space
J_COLOR_SPACE out_color_space
Definition: jpeglib.h:478
jpeg_common_struct::err
struct jpeg_error_mgr * err
Definition: jpeglib.h:277
jpeg_std_error
struct jpeg_error_mgr * jpeg_std_error(struct jpeg_error_mgr *err)
Definition: jerror.c:232
FALSE
Definition: jmorecfg.h:317
jpeg_decompress_struct::out_color_components
int out_color_components
Definition: jpeglib.h:509
Fl_RGB_Image::max_size
static size_t max_size()
Definition: Fl_Image.H:255
Fl_Image::w
int w() const
Definition: Fl_Image.H:111
boolean
boolean
Definition: jmorecfg.h:317
malloc
voidp malloc()
Fl::warning
static void(* warning)(const char *,...)
Definition: Fl.H:498
jpeg_stdio_src
void jpeg_stdio_src(j_decompress_ptr cinfo, FILE *infile)
Definition: jdatasrc.c:210
Fl_Image::ERR_FILE_ACCESS
static const int ERR_FILE_ACCESS
Definition: Fl_Image.H:59
jpeg_source_mgr::init_source
void(* init_source)()
Definition: jpeglib.h:788
jpeg_read_header
int jpeg_read_header(j_decompress_ptr cinfo, boolean require_image)
Definition: jdapimin.c:245
uchar
unsigned char uchar
Definition: fl_types.h:30
jpeg_mem_src
void jpeg_mem_src(j_decompress_ptr cinfo, unsigned char *inbuffer, unsigned long insize)
Definition: jdatasrc.c:249
name
static const char * name
Definition: Fl_arg.cxx:53
my_source_mgr::pub
struct jpeg_source_mgr pub
Definition: jdatasrc.c:27
Fl_RGB_Image
Definition: Fl_Image.H:202
Fl_Shared_Image
Definition: Fl_Shared_Image.H:50
jpeg_source_mgr
Definition: jpeglib.h:784
jpeg_decompress_struct
Definition: jpeglib.h:459
fill_input_buffer
static boolean fill_input_buffer(j_decompress_ptr cinfo)
Definition: jdatasrc.c:97
jpeg_source_mgr::fill_input_buffer
boolean(* fill_input_buffer)()
Definition: jpeglib.h:789