Updates to Tomato RAF including NGINX && PHP
[tomato.git] / release / src / router / php / ext / gd / libgd / gd_jpeg.c
blob175c5b85fd783bc0748afaaa63be632e256bf9c2
1 /*
2 * gd_jpeg.c: Read and write JPEG (JFIF) format image files using the
3 * gd graphics library (http://www.boutell.com/gd/).
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/.
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.
14 * Copyright 2000 Doug Becker, mailto:thebeckers@home.com
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
20 * 2.0.10: more efficient gdImageCreateFromJpegCtx, thanks to
21 * Christian Aberger
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <setjmp.h>
27 #include <limits.h>
28 #include <string.h>
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
37 /* 1.8.1: remove dependency on jinclude.h */
38 #include "jpeglib.h"
39 #include "jerror.h"
41 static const char *const GD_JPEG_VERSION = "1.0";
43 typedef struct _jmpbuf_wrapper
45 jmp_buf jmpbuf;
46 int ignore_warning;
47 } jmpbuf_wrapper;
49 static long php_jpeg_emit_message(j_common_ptr jpeg_info, int level)
51 char message[JMSG_LENGTH_MAX];
52 jmpbuf_wrapper *jmpbufw;
53 int ignore_warning = 0;
55 jmpbufw = (jmpbuf_wrapper *) jpeg_info->client_data;
57 if (jmpbufw != 0) {
58 ignore_warning = jmpbufw->ignore_warning;
61 (jpeg_info->err->format_message)(jpeg_info,message);
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
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);
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);
79 return 1;
84 /* Called by the IJG JPEG library upon encountering a fatal error */
85 static void fatal_jpeg_error (j_common_ptr cinfo)
87 jmpbuf_wrapper *jmpbufw;
89 php_gd_error("gd-jpeg: JPEG library reports unrecoverable error: ");
90 (*cinfo->err->output_message) (cinfo);
92 jmpbufw = (jmpbuf_wrapper *) cinfo->client_data;
93 jpeg_destroy (cinfo);
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");
102 exit (99);
105 int gdJpegGetVersionInt()
107 return JPEG_LIB_VERSION;
110 const char * gdJpegGetVersionString()
112 switch(JPEG_LIB_VERSION) {
113 case 62:
114 return "6b";
115 break;
117 case 70:
118 return "7";
119 break;
121 case 80:
122 return "8";
123 break;
125 default:
126 return "unknown";
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.
140 void gdImageJpeg (gdImagePtr im, FILE * outFile, int quality)
142 gdIOCtx *out = gdNewFileCtx (outFile);
143 gdImageJpegCtx (im, out, quality);
144 out->gd_free (out);
147 void *gdImageJpegPtr (gdImagePtr im, int *size, int quality)
149 void *rv;
150 gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
151 gdImageJpegCtx (im, out, quality);
152 rv = gdDPExtractData (out, size);
153 out->gd_free (out);
155 return rv;
158 void jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile);
160 void gdImageJpegCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
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];
172 memset (&cinfo, 0, sizeof (cinfo));
173 memset (&jerr, 0, sizeof (jerr));
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);
182 return;
185 cinfo.err->error_exit = fatal_jpeg_error;
187 jpeg_create_compress (&cinfo);
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);
198 /* If user requests interlace, translate that to progressive JPEG */
199 if (gdImageGetInterlaced (im)) {
200 jpeg_simple_progression (&cinfo);
203 jpeg_gdIOCtx_dest (&cinfo, outfile);
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;
209 jpeg_start_compress (&cinfo, TRUE);
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);
216 jpeg_write_marker (&cinfo, JPEG_COM, (unsigned char *) comment, (unsigned int) strlen (comment));
217 if (im->trueColor) {
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 */
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];
228 row[jidx++] = gdTrueColorGetRed (val);
229 row[jidx++] = gdTrueColorGetGreen (val);
230 row[jidx++] = gdTrueColorGetBlue (val);
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);
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];
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)
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
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);
267 jpeg_finish_compress (&cinfo);
268 jpeg_destroy_compress (&cinfo);
269 gdFree (row);
272 gdImagePtr gdImageCreateFromJpeg (FILE * inFile, int ignore_warning)
274 gdImagePtr im;
275 gdIOCtx *in = gdNewFileCtx(inFile);
276 im = gdImageCreateFromJpegCtx(in, ignore_warning);
277 in->gd_free (in);
279 return im;
282 gdImagePtr gdImageCreateFromJpegPtr (int size, void *data, int ignore_warning)
284 gdImagePtr im;
285 gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
286 im = gdImageCreateFromJpegCtx(in, ignore_warning);
287 in->gd_free(in);
289 return im;
292 void jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile);
294 static int CMYKToRGB(int c, int m, int y, int k, int inverted);
298 * Create a gd-format image from the JPEG-format INFILE. Returns the
299 * image, or NULL upon error.
301 gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile, int ignore_warning)
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;
316 memset (&cinfo, 0, sizeof (cinfo));
317 memset (&jerr, 0, sizeof (jerr));
319 jmpbufw.ignore_warning = ignore_warning;
321 cinfo.err = jpeg_std_error (&jerr);
322 cinfo.client_data = &jmpbufw;
324 cinfo.err->emit_message = (void (*)(j_common_ptr,int)) php_jpeg_emit_message;
326 if (setjmp (jmpbufw.jmpbuf) != 0) {
327 /* we're here courtesy of longjmp */
328 if (row) {
329 gdFree (row);
331 if (im) {
332 gdImageDestroy (im);
334 return 0;
337 cinfo.err->error_exit = fatal_jpeg_error;
339 jpeg_create_decompress (&cinfo);
341 jpeg_gdIOCtx_src (&cinfo, infile);
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);
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);
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);
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);
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;
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;
374 if (jpeg_start_decompress (&cinfo) != TRUE) {
375 php_gd_error("gd-jpeg: warning: jpeg_start_decompress reports suspended data source");
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?
387 #if 0
388 gdImageInterlace (im, cinfo.progressive_mode != 0);
389 #endif
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;
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;
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;
410 marker = marker->next;
412 } else {
413 php_gd_error_ex(E_WARNING, "gd-jpeg: error: unexpected colorspace.");
414 goto error;
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 */
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;
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;
435 for (j = 0; j < cinfo.output_width; j++, currow += 4, tpix++) {
436 *tpix = CMYKToRGB (currow[0], currow[1], currow[2], currow[3], inverted);
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;
448 for (j = 0; j < cinfo.output_width; j++, currow += 3, tpix++) {
449 *tpix = gdTrueColor (currow[0], currow[1], currow[2]);
454 if (jpeg_finish_decompress (&cinfo) != TRUE) {
455 php_gd_error("gd-jpeg: warning: jpeg_finish_decompress reports suspended data source");
457 if (!ignore_warning) {
458 if (cinfo.err->num_warnings > 0) {
459 goto error;
463 jpeg_destroy_decompress (&cinfo);
464 gdFree (row);
466 return im;
468 error:
469 jpeg_destroy_decompress (&cinfo);
470 if (row) {
471 gdFree (row);
473 if (im) {
474 gdImageDestroy (im);
476 return 0;
479 /* A very basic conversion approach, TBB */
480 static int CMYKToRGB(int c, int m, int y, int k, int inverted)
482 if (inverted) {
483 c = 255 - c;
484 m = 255 - m;
485 y = 255 - y;
486 k = 255 - k;
488 return gdTrueColor((255 - c) * (255 - k) / 255, (255 - m) * (255 - k) / 255, (255 - y) * (255 - k) / 255);
492 * gdIOCtx JPEG data sources and sinks, T. Boutell
493 * almost a simple global replace from T. Lane's stdio versions.
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 */
504 #ifdef HAVE_BOOLEAN
505 typedef boolean safeboolean;
506 #else
507 typedef int safeboolean;
508 #endif /* HAVE_BOOLEAN */
510 /* Expanded data source object for gdIOCtx input */
512 typedef struct
514 struct jpeg_source_mgr pub; /* public fields */
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;
521 typedef my_source_mgr *my_src_ptr;
523 #define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
526 * Initialize source --- called by jpeg_read_header
527 * before any data is actually read.
530 void init_source (j_decompress_ptr cinfo)
532 my_src_ptr src = (my_src_ptr) cinfo->src;
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.
538 src->start_of_file = TRUE;
543 * Fill the input buffer --- called whenever buffer is emptied.
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.
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.
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.
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.
575 #define END_JPEG_SEQUENCE "\r\n[*]--:END JPEG:--[*]\r\n"
577 safeboolean fill_input_buffer (j_decompress_ptr cinfo)
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;
583 /* ssize_t got; */
584 /* char *s; */
585 memset(src->buffer, 0, INPUT_BUF_SIZE);
587 while (nbytes < INPUT_BUF_SIZE) {
588 int got = gdGetBuf(src->buffer + nbytes, INPUT_BUF_SIZE - nbytes, src->infile);
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;
595 break;
597 nbytes += got;
600 if (nbytes <= 0) {
601 if (src->start_of_file) { /* Treat empty input file as fatal error */
602 ERREXIT (cinfo, JERR_INPUT_EMPTY);
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;
611 src->pub.next_input_byte = src->buffer;
612 src->pub.bytes_in_buffer = nbytes;
613 src->start_of_file = FALSE;
615 return TRUE;
620 * Skip data --- used to skip over a potentially large amount of
621 * uninteresting data (such as an APPn marker).
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.
631 void skip_input_data (j_decompress_ptr cinfo, long num_bytes)
633 my_src_ptr src = (my_src_ptr) cinfo->src;
635 /* Just a dumb implementation for now. Not clear that being smart is worth
636 * any trouble anyway --- large skips are infrequent.
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.
646 src->pub.next_input_byte += (size_t) num_bytes;
647 src->pub.bytes_in_buffer -= (size_t) num_bytes;
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.
662 * Terminate source --- called by jpeg_finish_decompress
663 * after all data has been read. Often a no-op.
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.
670 void term_source (j_decompress_ptr cinfo)
672 #if 0
673 * never used */
674 my_src_ptr src = (my_src_ptr) cinfo->src;
675 #endif
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.
685 void jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile)
687 my_src_ptr src;
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.
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));
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 */
715 /* Expanded data destination object for stdio output */
717 typedef struct
719 struct jpeg_destination_mgr pub; /* public fields */
720 gdIOCtx *outfile; /* target stream */
721 unsigned char *buffer; /* start of buffer */
722 } my_destination_mgr;
724 typedef my_destination_mgr *my_dest_ptr;
726 #define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
729 * Initialize destination --- called by jpeg_start_compress
730 * before any data is actually written.
733 void init_destination (j_compress_ptr cinfo)
735 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
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));
740 dest->pub.next_output_byte = dest->buffer;
741 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
746 * Empty the output buffer --- called whenever buffer fills up.
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.
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.
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.
768 safeboolean empty_output_buffer (j_compress_ptr cinfo)
770 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
772 if (gdPutBuf (dest->buffer, OUTPUT_BUF_SIZE, dest->outfile) != (size_t) OUTPUT_BUF_SIZE) {
773 ERREXIT (cinfo, JERR_FILE_WRITE);
776 dest->pub.next_output_byte = dest->buffer;
777 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
779 return TRUE;
784 * Terminate destination --- called by jpeg_finish_compress
785 * after all data has been written. Usually needs to flush buffer.
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.
792 void term_destination (j_compress_ptr cinfo)
794 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
795 size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
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);
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.
810 void jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile)
812 my_dest_ptr dest;
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.
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));
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;
831 #endif /* HAVE_JPEG */