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