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