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