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