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