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