xref: /PHP-5.5/ext/gd/libgd/gd_jpeg.c (revision 3f049bcf)
1 /*
2  * gd_jpeg.c: Read and write JPEG (JFIF) format image files using the
3  * gd graphics library (http://www.boutell.com/gd/).
4  *
5  * This software is based in part on the work of the Independent JPEG
6  * Group.  For more information on the IJG JPEG software (and JPEG
7  * documentation, etc.), see ftp://ftp.uu.net/graphics/jpeg/.
8  *
9  * NOTE: IJG 12-bit JSAMPLE (BITS_IN_JSAMPLE == 12) mode is not
10  * supported at all on read in gd 2.0, and is not supported on write
11  * except for palette images, which is sort of pointless (TBB). Even that
12  * has never been tested according to DB.
13  *
14  * Copyright 2000 Doug Becker, mailto:thebeckers@home.com
15  *
16  * Modification 4/18/00 TBB: JPEG_DEBUG rather than just DEBUG,
17  * so VC++ builds don't spew to standard output, causing
18  * major CGI brain damage
19  *
20  * 2.0.10: more efficient gdImageCreateFromJpegCtx, thanks to
21  * Christian Aberger
22  */
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <setjmp.h>
27 #include <limits.h>
28 #include <string.h>
29 
30 #include "gd.h"
31 /* TBB: move this up so include files are not brought in */
32 /* JCE: arrange HAVE_LIBJPEG so that it can be set in gd.h */
33 #ifdef HAVE_LIBJPEG
34 #include "gdhelpers.h"
35 #undef HAVE_STDLIB_H
36 
37 /* 1.8.1: remove dependency on jinclude.h */
38 #include "jpeglib.h"
39 #include "jerror.h"
40 
41 static const char *const GD_JPEG_VERSION = "1.0";
42 
43 typedef struct _jmpbuf_wrapper
44 {
45 	jmp_buf jmpbuf;
46 	int ignore_warning;
47 } jmpbuf_wrapper;
48 
php_jpeg_emit_message(j_common_ptr jpeg_info,int level)49 static long php_jpeg_emit_message(j_common_ptr jpeg_info, int level)
50 {
51 	char message[JMSG_LENGTH_MAX];
52 	jmpbuf_wrapper *jmpbufw;
53 	int ignore_warning = 0;
54 
55 	jmpbufw = (jmpbuf_wrapper *) jpeg_info->client_data;
56 
57 	if (jmpbufw != 0) {
58 		ignore_warning = jmpbufw->ignore_warning;
59 	}
60 
61 	(jpeg_info->err->format_message)(jpeg_info,message);
62 
63 	/* It is a warning message */
64 	if (level < 0) {
65 		/* display only the 1st warning, as would do a default libjpeg
66 		 * unless strace_level >= 3
67 		 */
68 		if ((jpeg_info->err->num_warnings == 0) || (jpeg_info->err->trace_level >= 3)) {
69 			php_gd_error_ex(ignore_warning ? E_NOTICE : E_WARNING, "gd-jpeg, libjpeg: recoverable error: %s\n", message);
70 		}
71 
72 		jpeg_info->err->num_warnings++;
73 	} else {
74 		/* strace msg, Show it if trace_level >= level. */
75 		if (jpeg_info->err->trace_level >= level) {
76 			php_gd_error_ex(E_NOTICE, "gd-jpeg, libjpeg: strace message: %s\n", message);
77 		}
78 	}
79 	return 1;
80 }
81 
82 
83 
84 /* Called by the IJG JPEG library upon encountering a fatal error */
fatal_jpeg_error(j_common_ptr cinfo)85 static void fatal_jpeg_error (j_common_ptr cinfo)
86 {
87 	jmpbuf_wrapper *jmpbufw;
88 
89 	php_gd_error("gd-jpeg: JPEG library reports unrecoverable error: ");
90 	(*cinfo->err->output_message) (cinfo);
91 
92 	jmpbufw = (jmpbuf_wrapper *) cinfo->client_data;
93 	jpeg_destroy (cinfo);
94 
95 	if (jmpbufw != 0) {
96 		longjmp (jmpbufw->jmpbuf, 1);
97 		php_gd_error_ex(E_ERROR, "gd-jpeg: EXTREMELY fatal error: longjmp returned control; terminating");
98 	} else {
99 		php_gd_error_ex(E_ERROR, "gd-jpeg: EXTREMELY fatal error: jmpbuf unrecoverable; terminating");
100 	}
101 
102 	exit (99);
103 }
104 
gdJpegGetVersionInt()105 int gdJpegGetVersionInt()
106 {
107 	return JPEG_LIB_VERSION;
108 }
109 
gdJpegGetVersionString()110 const char * gdJpegGetVersionString()
111 {
112 	switch(JPEG_LIB_VERSION) {
113 		case 62:
114 			return "6b";
115 			break;
116 
117 		case 70:
118 			return "7";
119 			break;
120 
121 		case 80:
122 			return "8";
123 			break;
124 
125 		case 90:
126 			return "9 compatible";
127 			break;
128 
129 		default:
130 			return "unknown";
131 	}
132 }
133 
134 
135 /*
136  * Write IM to OUTFILE as a JFIF-formatted JPEG image, using quality
137  * QUALITY.  If QUALITY is in the range 0-100, increasing values
138  * represent higher quality but also larger image size.  If QUALITY is
139  * negative, the IJG JPEG library's default quality is used (which
140  * should be near optimal for many applications).  See the IJG JPEG
141  * library documentation for more details.
142  */
143 
gdImageJpeg(gdImagePtr im,FILE * outFile,int quality)144 void gdImageJpeg (gdImagePtr im, FILE * outFile, int quality)
145 {
146 	gdIOCtx *out = gdNewFileCtx (outFile);
147 	gdImageJpegCtx (im, out, quality);
148 	out->gd_free (out);
149 }
150 
gdImageJpegPtr(gdImagePtr im,int * size,int quality)151 void *gdImageJpegPtr (gdImagePtr im, int *size, int quality)
152 {
153 	void *rv;
154 	gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
155 	gdImageJpegCtx (im, out, quality);
156 	rv = gdDPExtractData (out, size);
157 	out->gd_free (out);
158 
159 	return rv;
160 }
161 
162 void jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile);
163 
gdImageJpegCtx(gdImagePtr im,gdIOCtx * outfile,int quality)164 void gdImageJpegCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
165 {
166 	struct jpeg_compress_struct cinfo;
167 	struct jpeg_error_mgr jerr;
168 	int i, j, jidx;
169 	/* volatile so we can gdFree it on return from longjmp */
170 	volatile JSAMPROW row = 0;
171 	JSAMPROW rowptr[1];
172 	jmpbuf_wrapper jmpbufw;
173 	JDIMENSION nlines;
174 	char comment[255];
175 
176 	memset (&cinfo, 0, sizeof (cinfo));
177 	memset (&jerr, 0, sizeof (jerr));
178 
179 	cinfo.err = jpeg_std_error (&jerr);
180 	cinfo.client_data = &jmpbufw;
181 	if (setjmp (jmpbufw.jmpbuf) != 0) {
182 		/* we're here courtesy of longjmp */
183 		if (row) {
184 			gdFree (row);
185 		}
186 		return;
187 	}
188 
189 	cinfo.err->error_exit = fatal_jpeg_error;
190 
191 	jpeg_create_compress (&cinfo);
192 
193 	cinfo.image_width = im->sx;
194 	cinfo.image_height = im->sy;
195 	cinfo.input_components = 3;	/* # of color components per pixel */
196 	cinfo.in_color_space = JCS_RGB;	/* colorspace of input image */
197 	jpeg_set_defaults (&cinfo);
198 	if (quality >= 0) {
199 		jpeg_set_quality (&cinfo, quality, TRUE);
200 	}
201 
202 	/* If user requests interlace, translate that to progressive JPEG */
203 	if (gdImageGetInterlaced (im)) {
204 		jpeg_simple_progression (&cinfo);
205 	}
206 
207 	jpeg_gdIOCtx_dest (&cinfo, outfile);
208 
209 	row = (JSAMPROW) safe_emalloc(cinfo.image_width * cinfo.input_components, sizeof(JSAMPLE), 0);
210 	memset(row, 0, cinfo.image_width * cinfo.input_components * sizeof(JSAMPLE));
211 	rowptr[0] = row;
212 
213 	jpeg_start_compress (&cinfo, TRUE);
214 
215 	if (quality >= 0) {
216 		snprintf(comment, sizeof(comment)-1, "CREATOR: gd-jpeg v%s (using IJG JPEG v%d), quality = %d\n", GD_JPEG_VERSION, JPEG_LIB_VERSION, quality);
217 	} else {
218 		snprintf(comment, sizeof(comment)-1, "CREATOR: gd-jpeg v%s (using IJG JPEG v%d), default quality\n", GD_JPEG_VERSION, JPEG_LIB_VERSION);
219 	}
220 	jpeg_write_marker (&cinfo, JPEG_COM, (unsigned char *) comment, (unsigned int) strlen (comment));
221 	if (im->trueColor) {
222 
223 #if BITS_IN_JSAMPLE == 12
224 		php_gd_error("gd-jpeg: error: jpeg library was compiled for 12-bit precision. This is mostly useless, because JPEGs on the web are 8-bit and such versions of the jpeg library won't read or write them. GD doesn't support these unusual images. Edit your jmorecfg.h file to specify the correct precision and completely 'make clean' and 'make install' libjpeg again. Sorry");
225 		goto error;
226 #endif /* BITS_IN_JSAMPLE == 12 */
227 
228 		for (i = 0; i < im->sy; i++) {
229 			for (jidx = 0, j = 0; j < im->sx; j++) {
230 				int val = im->tpixels[i][j];
231 
232 				row[jidx++] = gdTrueColorGetRed (val);
233 				row[jidx++] = gdTrueColorGetGreen (val);
234 				row[jidx++] = gdTrueColorGetBlue (val);
235 			}
236 
237 			nlines = jpeg_write_scanlines (&cinfo, rowptr, 1);
238 			if (nlines != 1) {
239 				php_gd_error_ex(E_WARNING, "gd_jpeg: warning: jpeg_write_scanlines returns %u -- expected 1", nlines);
240 			}
241 		}
242 	} else {
243 		for (i = 0; i < im->sy; i++) {
244 			for (jidx = 0, j = 0; j < im->sx; j++) {
245 				int idx = im->pixels[i][j];
246 
247 				/* NB: Although gd RGB values are ints, their max value is
248 				 * 255 (see the documentation for gdImageColorAllocate())
249 				 * -- perfect for 8-bit JPEG encoding (which is the norm)
250 				 */
251 #if BITS_IN_JSAMPLE == 8
252 				row[jidx++] = im->red[idx];
253 				row[jidx++] = im->green[idx];
254 				row[jidx++] = im->blue[idx];
255 #elif BITS_IN_JSAMPLE == 12
256 				row[jidx++] = im->red[idx] << 4;
257 				row[jidx++] = im->green[idx] << 4;
258 				row[jidx++] = im->blue[idx] << 4;
259 #else
260 #error IJG JPEG library BITS_IN_JSAMPLE value must be 8 or 12
261 #endif
262 			}
263 
264 			nlines = jpeg_write_scanlines (&cinfo, rowptr, 1);
265 			if (nlines != 1) {
266 				php_gd_error_ex(E_WARNING, "gd_jpeg: warning: jpeg_write_scanlines returns %u -- expected 1", nlines);
267 			}
268 		}
269 	}
270 
271 	jpeg_finish_compress (&cinfo);
272 	jpeg_destroy_compress (&cinfo);
273 	gdFree (row);
274 }
275 
gdImageCreateFromJpeg(FILE * inFile)276 gdImagePtr gdImageCreateFromJpeg (FILE * inFile)
277 {
278 	return gdImageCreateFromJpegEx(inFile, 1);
279 }
280 
gdImageCreateFromJpegEx(FILE * inFile,int ignore_warning)281 gdImagePtr gdImageCreateFromJpegEx (FILE * inFile, int ignore_warning)
282 {
283 	gdImagePtr im;
284 	gdIOCtx *in = gdNewFileCtx(inFile);
285 	im = gdImageCreateFromJpegCtxEx(in, ignore_warning);
286 	in->gd_free (in);
287 
288 	return im;
289 }
290 
gdImageCreateFromJpegPtr(int size,void * data)291 gdImagePtr gdImageCreateFromJpegPtr (int size, void *data)
292 {
293 	return gdImageCreateFromJpegPtrEx(size, data, 1);
294 }
295 
gdImageCreateFromJpegPtrEx(int size,void * data,int ignore_warning)296 gdImagePtr gdImageCreateFromJpegPtrEx (int size, void *data, int ignore_warning)
297 {
298 	gdImagePtr im;
299 	gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
300 	im = gdImageCreateFromJpegCtxEx(in, ignore_warning);
301 	in->gd_free(in);
302 
303 	return im;
304 }
305 
306 void jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile);
307 
308 static int CMYKToRGB(int c, int m, int y, int k, int inverted);
309 
310 
311 /*
312  * Create a gd-format image from the JPEG-format INFILE.  Returns the
313  * image, or NULL upon error.
314  */
gdImageCreateFromJpegCtx(gdIOCtx * infile)315 gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile)
316 {
317 	return gdImageCreateFromJpegCtxEx(infile, 1);
318 }
319 
gdImageCreateFromJpegCtxEx(gdIOCtx * infile,int ignore_warning)320 gdImagePtr gdImageCreateFromJpegCtxEx (gdIOCtx * infile, int ignore_warning)
321 {
322 	struct jpeg_decompress_struct cinfo;
323 	struct jpeg_error_mgr jerr;
324 	jmpbuf_wrapper jmpbufw;
325 	/* volatile so we can gdFree them after longjmp */
326 	volatile JSAMPROW row = 0;
327 	volatile gdImagePtr im = 0;
328 	JSAMPROW rowptr[1];
329 	unsigned int i, j;
330 	int retval;
331 	JDIMENSION nrows;
332 	int channels = 3;
333 	int inverted = 0;
334 
335 	memset (&cinfo, 0, sizeof (cinfo));
336 	memset (&jerr, 0, sizeof (jerr));
337 
338 	jmpbufw.ignore_warning = ignore_warning;
339 
340 	cinfo.err = jpeg_std_error (&jerr);
341 	cinfo.client_data = &jmpbufw;
342 
343 	cinfo.err->emit_message = (void (*)(j_common_ptr,int)) php_jpeg_emit_message;
344 
345 	if (setjmp (jmpbufw.jmpbuf) != 0) {
346 		/* we're here courtesy of longjmp */
347 		if (row) {
348 			gdFree (row);
349 		}
350 		if (im) {
351 			gdImageDestroy (im);
352 		}
353 		return 0;
354 	}
355 
356 	cinfo.err->error_exit = fatal_jpeg_error;
357 
358 	jpeg_create_decompress (&cinfo);
359 
360 	jpeg_gdIOCtx_src (&cinfo, infile);
361 
362 	/* 2.0.22: save the APP14 marker to check for Adobe Photoshop CMYK files with inverted components. */
363 	jpeg_save_markers(&cinfo, JPEG_APP0 + 14, 256);
364 
365 	retval = jpeg_read_header (&cinfo, TRUE);
366 	if (retval != JPEG_HEADER_OK) {
367 		php_gd_error_ex(E_WARNING, "gd-jpeg: warning: jpeg_read_header returned %d, expected %d", retval, JPEG_HEADER_OK);
368 	}
369 
370 	if (cinfo.image_height > INT_MAX) {
371 		php_gd_error_ex(E_WARNING, "gd-jpeg: warning: JPEG image height (%u) is greater than INT_MAX (%d) (and thus greater than gd can handle)", cinfo.image_height, INT_MAX);
372 	}
373 
374 	if (cinfo.image_width > INT_MAX) {
375 		php_gd_error_ex(E_WARNING, "gd-jpeg: warning: JPEG image width (%u) is greater than INT_MAX (%d) (and thus greater than gd can handle)", cinfo.image_width, INT_MAX);
376 	}
377 
378 	im = gdImageCreateTrueColor ((int) cinfo.image_width, (int) cinfo.image_height);
379 	if (im == 0) {
380 		php_gd_error("gd-jpeg error: cannot allocate gdImage struct");
381 		goto error;
382 	}
383 
384 	/* 2.0.22: very basic support for reading CMYK colorspace files. Nice for
385 	 * thumbnails but there's no support for fussy adjustment of the
386 	 * assumed properties of inks and paper. */
387 	if ((cinfo.jpeg_color_space == JCS_CMYK) || (cinfo.jpeg_color_space == JCS_YCCK)) {
388 		cinfo.out_color_space = JCS_CMYK;
389 	} else {
390 		cinfo.out_color_space = JCS_RGB;
391 	}
392 
393 	if (jpeg_start_decompress (&cinfo) != TRUE) {
394 		php_gd_error("gd-jpeg: warning: jpeg_start_decompress reports suspended data source");
395 	}
396 
397 	/* REMOVED by TBB 2/12/01. This field of the structure is
398 	 * documented as private, and sure enough it's gone in the
399 	 * latest libjpeg, replaced by something else. Unfortunately
400 	 * there is still no right way to find out if the file was
401 	 * progressive or not; just declare your intent before you
402 	 * write one by calling gdImageInterlace(im, 1) yourself.
403 	 * After all, we're not really supposed to rework JPEGs and
404 	 * write them out again anyway. Lossy compression, remember?
405 	 */
406 #if 0
407   gdImageInterlace (im, cinfo.progressive_mode != 0);
408 #endif
409 
410 	if (cinfo.out_color_space == JCS_RGB) {
411 		if (cinfo.output_components != 3) {
412 			php_gd_error_ex(E_WARNING, "gd-jpeg: error: JPEG color quantization request resulted in output_components == %d (expected 3 for RGB)", cinfo.output_components);
413 			goto error;
414 		}
415 		channels = 3;
416 	} else if (cinfo.out_color_space == JCS_CMYK) {
417 		jpeg_saved_marker_ptr marker;
418 		if (cinfo.output_components != 4)  {
419 			php_gd_error_ex(E_WARNING, "gd-jpeg: error: JPEG color quantization request resulted in output_components == %d (expected 4 for CMYK)", cinfo.output_components);
420 			goto error;
421 		}
422 		channels = 4;
423 		marker = cinfo.marker_list;
424 		while (marker) {
425 			if ((marker->marker == (JPEG_APP0 + 14)) && (marker->data_length >= 12) && (!strncmp((const char *) marker->data, "Adobe", 5))) {
426 				inverted = 1;
427 				break;
428 			}
429 			marker = marker->next;
430 		}
431 	} else {
432 		php_gd_error_ex(E_WARNING, "gd-jpeg: error: unexpected colorspace.");
433 		goto error;
434 	}
435 
436 #if BITS_IN_JSAMPLE == 12
437 	php_gd_error("gd-jpeg: error: jpeg library was compiled for 12-bit precision. This is mostly useless, because JPEGs on the web are 8-bit and such versions of the jpeg library won't read or write them. GD doesn't support these unusual images. Edit your jmorecfg.h file to specify the correct precision and completely 'make clean' and 'make install' libjpeg again. Sorry.");
438 	goto error;
439 #endif /* BITS_IN_JSAMPLE == 12 */
440 
441 	row = safe_emalloc(cinfo.output_width * channels, sizeof(JSAMPLE), 0);
442 	memset(row, 0, cinfo.output_width * channels * sizeof(JSAMPLE));
443 	rowptr[0] = row;
444 
445 	if (cinfo.out_color_space == JCS_CMYK) {
446 		for (i = 0; i < cinfo.output_height; i++) {
447 			register JSAMPROW currow = row;
448 			register int *tpix = im->tpixels[i];
449 			nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
450 			if (nrows != 1) {
451 				php_gd_error_ex(E_WARNING, "gd-jpeg: error: jpeg_read_scanlines returns %u, expected 1", nrows);
452 				goto error;
453 			}
454 			for (j = 0; j < cinfo.output_width; j++, currow += 4, tpix++) {
455 				*tpix = CMYKToRGB (currow[0], currow[1], currow[2], currow[3], inverted);
456 			}
457 		}
458 	} else {
459 		for (i = 0; i < cinfo.output_height; i++) {
460 			register JSAMPROW currow = row;
461 			register int *tpix = im->tpixels[i];
462 			nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
463 			if (nrows != 1) {
464 				php_gd_error_ex(E_WARNING, "gd-jpeg: error: jpeg_read_scanlines returns %u, expected 1", nrows);
465 				goto error;
466 			}
467 			for (j = 0; j < cinfo.output_width; j++, currow += 3, tpix++) {
468 				*tpix = gdTrueColor (currow[0], currow[1], currow[2]);
469 			}
470 		}
471 	}
472 
473 	if (jpeg_finish_decompress (&cinfo) != TRUE) {
474 		php_gd_error("gd-jpeg: warning: jpeg_finish_decompress reports suspended data source");
475 	}
476 	if (!ignore_warning) {
477 		if (cinfo.err->num_warnings > 0) {
478 			goto error;
479 		}
480 	}
481 
482 	jpeg_destroy_decompress (&cinfo);
483 	gdFree (row);
484 
485 	return im;
486 
487 error:
488 	jpeg_destroy_decompress (&cinfo);
489 	if (row) {
490 		gdFree (row);
491 	}
492 	if (im) {
493 		gdImageDestroy (im);
494 	}
495 	return 0;
496 }
497 
498 /* A very basic conversion approach, TBB */
CMYKToRGB(int c,int m,int y,int k,int inverted)499 static int CMYKToRGB(int c, int m, int y, int k, int inverted)
500 {
501 	if (inverted) {
502 		c = 255 - c;
503 		m = 255 - m;
504 		y = 255 - y;
505 		k = 255 - k;
506 	}
507 	return gdTrueColor((255 - c) * (255 - k) / 255, (255 - m) * (255 - k) / 255, (255 - y) * (255 - k) / 255);
508 }
509 
510 /*
511  * gdIOCtx JPEG data sources and sinks, T. Boutell
512  * almost a simple global replace from T. Lane's stdio versions.
513  *
514  */
515 
516 /* Different versions of libjpeg use either 'jboolean' or 'boolean', and
517    some platforms define 'boolean', and so forth. Deal with this
518    madness by typedeffing 'safeboolean' to 'boolean' if HAVE_BOOLEAN
519    is already set, because this is the test that libjpeg uses.
520    Otherwise, typedef it to int, because that's what libjpeg does
521    if HAVE_BOOLEAN is not defined. -TBB */
522 
523 #ifdef HAVE_BOOLEAN
524 typedef boolean safeboolean;
525 #else
526 typedef int safeboolean;
527 #endif /* HAVE_BOOLEAN */
528 
529 /* Expanded data source object for gdIOCtx input */
530 
531 typedef struct
532 {
533 	struct jpeg_source_mgr pub;	/* public fields */
534 
535 	gdIOCtx *infile;		/* source stream */
536 	unsigned char *buffer;	/* start of buffer */
537 	safeboolean start_of_file;	/* have we gotten any data yet? */
538 } my_source_mgr;
539 
540 typedef my_source_mgr *my_src_ptr;
541 
542 #define INPUT_BUF_SIZE  4096	/* choose an efficiently fread'able size */
543 
544 /*
545  * Initialize source --- called by jpeg_read_header
546  * before any data is actually read.
547  */
548 
init_source(j_decompress_ptr cinfo)549 void init_source (j_decompress_ptr cinfo)
550 {
551 	my_src_ptr src = (my_src_ptr) cinfo->src;
552 
553 	/* We reset the empty-input-file flag for each image,
554 	 * but we don't clear the input buffer.
555 	 * This is correct behavior for reading a series of images from one source.
556 	 */
557 	src->start_of_file = TRUE;
558 }
559 
560 
561 /*
562  * Fill the input buffer --- called whenever buffer is emptied.
563  *
564  * In typical applications, this should read fresh data into the buffer
565  * (ignoring the current state of next_input_byte & bytes_in_buffer),
566  * reset the pointer & count to the start of the buffer, and return TRUE
567  * indicating that the buffer has been reloaded.  It is not necessary to
568  * fill the buffer entirely, only to obtain at least one more byte.
569  *
570  * There is no such thing as an EOF return.  If the end of the file has been
571  * reached, the routine has a choice of ERREXIT() or inserting fake data into
572  * the buffer.  In most cases, generating a warning message and inserting a
573  * fake EOI marker is the best course of action --- this will allow the
574  * decompressor to output however much of the image is there.  However,
575  * the resulting error message is misleading if the real problem is an empty
576  * input file, so we handle that case specially.
577  *
578  * In applications that need to be able to suspend compression due to input
579  * not being available yet, a FALSE return indicates that no more data can be
580  * obtained right now, but more may be forthcoming later.  In this situation,
581  * the decompressor will return to its caller (with an indication of the
582  * number of scanlines it has read, if any).  The application should resume
583  * decompression after it has loaded more data into the input buffer.  Note
584  * that there are substantial restrictions on the use of suspension --- see
585  * the documentation.
586  *
587  * When suspending, the decompressor will back up to a convenient restart point
588  * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
589  * indicate where the restart point will be if the current call returns FALSE.
590  * Data beyond this point must be rescanned after resumption, so move it to
591  * the front of the buffer rather than discarding it.
592  */
593 
594 #define END_JPEG_SEQUENCE "\r\n[*]--:END JPEG:--[*]\r\n"
595 
fill_input_buffer(j_decompress_ptr cinfo)596 safeboolean fill_input_buffer (j_decompress_ptr cinfo)
597 {
598 	my_src_ptr src = (my_src_ptr) cinfo->src;
599 	/* 2.0.12: signed size. Thanks to Geert Jansen */
600 	ssize_t nbytes = 0;
601 
602 	/* ssize_t got; */
603 	/* char *s; */
604 	memset(src->buffer, 0, INPUT_BUF_SIZE);
605 
606 	while (nbytes < INPUT_BUF_SIZE) {
607 		int got = gdGetBuf(src->buffer + nbytes, INPUT_BUF_SIZE - nbytes, src->infile);
608 
609 		if (got == EOF || got == 0) {
610 			/* EOF or error. If we got any data, don't worry about it. If we didn't, then this is unexpected. */
611 			if (!nbytes) {
612 				nbytes = -1;
613 			}
614 			break;
615 		}
616 		nbytes += got;
617 	}
618 
619 	if (nbytes <= 0) {
620 		if (src->start_of_file)	{ /* Treat empty input file as fatal error */
621 			ERREXIT (cinfo, JERR_INPUT_EMPTY);
622 		}
623 		WARNMS (cinfo, JWRN_JPEG_EOF);
624 		/* Insert a fake EOI marker */
625 		src->buffer[0] = (unsigned char) 0xFF;
626 		src->buffer[1] = (unsigned char) JPEG_EOI;
627 		nbytes = 2;
628 	}
629 
630 	src->pub.next_input_byte = src->buffer;
631 	src->pub.bytes_in_buffer = nbytes;
632 	src->start_of_file = FALSE;
633 
634 	return TRUE;
635 }
636 
637 
638 /*
639  * Skip data --- used to skip over a potentially large amount of
640  * uninteresting data (such as an APPn marker).
641  *
642  * Writers of suspendable-input applications must note that skip_input_data
643  * is not granted the right to give a suspension return.  If the skip extends
644  * beyond the data currently in the buffer, the buffer can be marked empty so
645  * that the next read will cause a fill_input_buffer call that can suspend.
646  * Arranging for additional bytes to be discarded before reloading the input
647  * buffer is the application writer's problem.
648  */
649 
skip_input_data(j_decompress_ptr cinfo,long num_bytes)650 void skip_input_data (j_decompress_ptr cinfo, long num_bytes)
651 {
652 	my_src_ptr src = (my_src_ptr) cinfo->src;
653 
654 	/* Just a dumb implementation for now. Not clear that being smart is worth
655 	 * any trouble anyway --- large skips are infrequent.
656 	 */
657 	if (num_bytes > 0) {
658 		while (num_bytes > (long) src->pub.bytes_in_buffer) {
659 			num_bytes -= (long) src->pub.bytes_in_buffer;
660 			(void) fill_input_buffer (cinfo);
661 			/* note we assume that fill_input_buffer will never return FALSE,
662 			 * so suspension need not be handled.
663 			 */
664 		}
665 		src->pub.next_input_byte += (size_t) num_bytes;
666 		src->pub.bytes_in_buffer -= (size_t) num_bytes;
667 	}
668 }
669 
670 
671 /*
672  * An additional method that can be provided by data source modules is the
673  * resync_to_restart method for error recovery in the presence of RST markers.
674  * For the moment, this source module just uses the default resync method
675  * provided by the JPEG library.  That method assumes that no backtracking
676  * is possible.
677  */
678 
679 
680 /*
681  * Terminate source --- called by jpeg_finish_decompress
682  * after all data has been read.  Often a no-op.
683  *
684  * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
685  * application must deal with any cleanup that should happen even
686  * for error exit.
687  */
688 
term_source(j_decompress_ptr cinfo)689 void term_source (j_decompress_ptr cinfo)
690 {
691 #if 0
692 	* never used */
693 	my_src_ptr src = (my_src_ptr) cinfo->src;
694 #endif
695 }
696 
697 
698 /*
699  * Prepare for input from a gdIOCtx stream.
700  * The caller must have already opened the stream, and is responsible
701  * for closing it after finishing decompression.
702  */
703 
jpeg_gdIOCtx_src(j_decompress_ptr cinfo,gdIOCtx * infile)704 void jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile)
705 {
706 	my_src_ptr src;
707 
708 	/* The source object and input buffer are made permanent so that a series
709 	 * of JPEG images can be read from the same file by calling jpeg_gdIOCtx_src
710 	 * only before the first one.  (If we discarded the buffer at the end of
711 	 * one image, we'd likely lose the start of the next one.)
712 	 * This makes it unsafe to use this manager and a different source
713 	 * manager serially with the same JPEG object.  Caveat programmer.
714 	 */
715 	if (cinfo->src == NULL) { /* first time for this JPEG object? */
716 		cinfo->src = (struct jpeg_source_mgr *)
717 		(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof (my_source_mgr));
718 		src = (my_src_ptr) cinfo->src;
719 		src->buffer = (unsigned char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * sizeof (unsigned char));
720 
721 	}
722 
723 	src = (my_src_ptr) cinfo->src;
724 	src->pub.init_source = init_source;
725 	src->pub.fill_input_buffer = fill_input_buffer;
726 	src->pub.skip_input_data = skip_input_data;
727 	src->pub.resync_to_restart = jpeg_resync_to_restart;	/* use default method */
728 	src->pub.term_source = term_source;
729 	src->infile = infile;
730 	src->pub.bytes_in_buffer = 0;	/* forces fill_input_buffer on first read */
731 	src->pub.next_input_byte = NULL;	/* until buffer loaded */
732 }
733 
734 /* Expanded data destination object for stdio output */
735 
736 typedef struct
737 {
738 	struct jpeg_destination_mgr pub; /* public fields */
739 	gdIOCtx *outfile;		 /* target stream */
740 	unsigned char *buffer;		 /* start of buffer */
741 } my_destination_mgr;
742 
743 typedef my_destination_mgr *my_dest_ptr;
744 
745 #define OUTPUT_BUF_SIZE  4096	/* choose an efficiently fwrite'able size */
746 
747 /*
748  * Initialize destination --- called by jpeg_start_compress
749  * before any data is actually written.
750  */
751 
init_destination(j_compress_ptr cinfo)752 void init_destination (j_compress_ptr cinfo)
753 {
754 	my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
755 
756 	/* Allocate the output buffer --- it will be released when done with image */
757 	dest->buffer = (unsigned char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * sizeof (unsigned char));
758 
759 	dest->pub.next_output_byte = dest->buffer;
760 	dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
761 }
762 
763 
764 /*
765  * Empty the output buffer --- called whenever buffer fills up.
766  *
767  * In typical applications, this should write the entire output buffer
768  * (ignoring the current state of next_output_byte & free_in_buffer),
769  * reset the pointer & count to the start of the buffer, and return TRUE
770  * indicating that the buffer has been dumped.
771  *
772  * In applications that need to be able to suspend compression due to output
773  * overrun, a FALSE return indicates that the buffer cannot be emptied now.
774  * In this situation, the compressor will return to its caller (possibly with
775  * an indication that it has not accepted all the supplied scanlines).  The
776  * application should resume compression after it has made more room in the
777  * output buffer.  Note that there are substantial restrictions on the use of
778  * suspension --- see the documentation.
779  *
780  * When suspending, the compressor will back up to a convenient restart point
781  * (typically the start of the current MCU). next_output_byte & free_in_buffer
782  * indicate where the restart point will be if the current call returns FALSE.
783  * Data beyond this point will be regenerated after resumption, so do not
784  * write it out when emptying the buffer externally.
785  */
786 
empty_output_buffer(j_compress_ptr cinfo)787 safeboolean empty_output_buffer (j_compress_ptr cinfo)
788 {
789 	my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
790 
791 	if (gdPutBuf (dest->buffer, OUTPUT_BUF_SIZE, dest->outfile) != (size_t) OUTPUT_BUF_SIZE) {
792 		ERREXIT (cinfo, JERR_FILE_WRITE);
793 	}
794 
795 	dest->pub.next_output_byte = dest->buffer;
796 	dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
797 
798 	return TRUE;
799 }
800 
801 
802 /*
803  * Terminate destination --- called by jpeg_finish_compress
804  * after all data has been written.  Usually needs to flush buffer.
805  *
806  * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
807  * application must deal with any cleanup that should happen even
808  * for error exit.
809  */
810 
term_destination(j_compress_ptr cinfo)811 void term_destination (j_compress_ptr cinfo)
812 {
813 	my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
814 	size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
815 
816 	/* Write any data remaining in the buffer */
817 	if (datacount > 0 && ((size_t)gdPutBuf (dest->buffer, datacount, dest->outfile) != datacount)) {
818 		ERREXIT (cinfo, JERR_FILE_WRITE);
819 	}
820 }
821 
822 
823 /*
824  * Prepare for output to a stdio stream.
825  * The caller must have already opened the stream, and is responsible
826  * for closing it after finishing compression.
827  */
828 
jpeg_gdIOCtx_dest(j_compress_ptr cinfo,gdIOCtx * outfile)829 void jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile)
830 {
831 	my_dest_ptr dest;
832 
833 	/* The destination object is made permanent so that multiple JPEG images
834 	 * can be written to the same file without re-executing jpeg_stdio_dest.
835 	 * This makes it dangerous to use this manager and a different destination
836 	 * manager serially with the same JPEG object, because their private object
837 	 * sizes may be different.  Caveat programmer.
838 	 */
839 	if (cinfo->dest == NULL) { /* first time for this JPEG object? */
840 		cinfo->dest = (struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof (my_destination_mgr));
841 	}
842 
843 	dest = (my_dest_ptr) cinfo->dest;
844 	dest->pub.init_destination = init_destination;
845 	dest->pub.empty_output_buffer = empty_output_buffer;
846 	dest->pub.term_destination = term_destination;
847 	dest->outfile = outfile;
848 }
849 
850 #endif /* HAVE_JPEG */
851