4
* gd_jpeg.c: Read and write JPEG (JFIF) format image files using the
5
* gd graphics library (http://www.boutell.com/gd/).
7
* This software is based in part on the work of the Independent JPEG
8
* Group. For more information on the IJG JPEG software (and JPEG
9
* documentation, etc.), see ftp://ftp.uu.net/graphics/jpeg/.
11
* NOTE: IJG 12-bit JSAMPLE (BITS_IN_JSAMPLE == 12) mode is not
12
* supported at all on read in gd 2.0, and is not supported on write
13
* except for palette images, which is sort of pointless (TBB). Even that
14
* has never been tested according to DB.
16
* Copyright 2000 Doug Becker, mailto:thebeckers@home.com
18
* Modification 4/18/00 TBB: JPEG_DEBUG rather than just DEBUG,
19
* so VC++ builds don't spew to standard output, causing
20
* major CGI brain damage
31
/* TBB: move this up so include files are not brought in */
32
/* JCE: HAVE_LIBJPEG is set by gvconfig.h in gd.h */
35
#include "gdhelpers.h"
36
/* 1.8.1: remove dependency on jinclude.h */
40
static const char *const GD_JPEG_VERSION = "1.0";
42
typedef struct _jmpbuf_wrapper
48
/* Called by the IJG JPEG library upon encountering a fatal error */
50
fatal_jpeg_error (j_common_ptr cinfo)
52
jmpbuf_wrapper *jmpbufw;
54
fprintf (stderr, "gd-jpeg: JPEG library reports unrecoverable error: ");
55
(*cinfo->err->output_message) (cinfo);
58
jmpbufw = (jmpbuf_wrapper *) cinfo->client_data;
63
longjmp (jmpbufw->jmpbuf, 1);
64
fprintf (stderr, "gd-jpeg: EXTREMELY fatal error: longjmp"
65
" returned control; terminating\n");
69
fprintf (stderr, "gd-jpeg: EXTREMELY fatal error: jmpbuf"
70
" unrecoverable; terminating\n");
78
* Write IM to OUTFILE as a JFIF-formatted JPEG image, using quality
79
* QUALITY. If QUALITY is in the range 0-100, increasing values
80
* represent higher quality but also larger image size. If QUALITY is
81
* negative, the IJG JPEG library's default quality is used (which
82
* should be near optimal for many applications). See the IJG JPEG
83
* library documentation for more details. */
86
gdImageJpeg (gdImagePtr im, FILE * outFile, int quality)
88
gdIOCtx *out = gdNewFileCtx (outFile);
89
gdImageJpegCtx (im, out, quality);
94
gdImageJpegPtr (gdImagePtr im, int *size, int quality)
97
gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
98
gdImageJpegCtx (im, out, quality);
99
rv = gdDPExtractData (out, size);
104
void jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile);
107
gdImageJpegCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
109
struct jpeg_compress_struct cinfo;
110
struct jpeg_error_mgr jerr;
112
/* volatile so we can gdFree it on return from longjmp */
113
volatile JSAMPROW row = 0;
115
jmpbuf_wrapper jmpbufw;
120
printf ("gd-jpeg: gd JPEG version %s\n", GD_JPEG_VERSION);
121
printf ("gd-jpeg: JPEG library version %d, %d-bit sample values\n",
122
JPEG_LIB_VERSION, BITS_IN_JSAMPLE);
125
for (i = 0; i < im->colorsTotal; i++)
128
printf ("gd-jpeg: gd colormap index %d: (%d, %d, %d)\n", i,
129
im->red[i], im->green[i], im->blue[i]);
132
#endif /* JPEG_DEBUG */
134
memset (&cinfo, 0, sizeof (cinfo));
135
memset (&jerr, 0, sizeof (jerr));
137
cinfo.err = jpeg_std_error (&jerr);
138
cinfo.client_data = &jmpbufw;
139
if (setjmp (jmpbufw.jmpbuf) != 0)
141
/* we're here courtesy of longjmp */
147
cinfo.err->error_exit = fatal_jpeg_error;
149
jpeg_create_compress (&cinfo);
151
cinfo.image_width = im->sx;
152
cinfo.image_height = im->sy;
153
cinfo.input_components = 3; /* # of color components per pixel */
154
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
155
jpeg_set_defaults (&cinfo);
157
jpeg_set_quality (&cinfo, quality, TRUE);
159
/* If user requests interlace, translate that to progressive JPEG */
160
if (gdImageGetInterlaced (im))
163
printf ("gd-jpeg: interlace set, outputting progressive"
166
jpeg_simple_progression (&cinfo);
169
jpeg_gdIOCtx_dest (&cinfo, outfile);
171
row = (JSAMPROW) gdCalloc (1, cinfo.image_width * cinfo.input_components
175
fprintf (stderr, "gd-jpeg: error: unable to allocate JPEG row "
176
"structure: gdCalloc returns NULL\n");
177
jpeg_destroy_compress (&cinfo);
183
jpeg_start_compress (&cinfo, TRUE);
185
sprintf (comment, "CREATOR: gd-jpeg v%s (using IJG JPEG v%d),",
186
GD_JPEG_VERSION, JPEG_LIB_VERSION);
188
sprintf (comment + strlen (comment), " quality = %d\n",
191
strcat (comment + strlen (comment), " default quality\n");
192
jpeg_write_marker (&cinfo, JPEG_COM, (unsigned char *) comment,
193
(unsigned int) strlen (comment));
196
#if BITS_IN_JSAMPLE == 12
197
fprintf (stderr, "gd-jpeg: error: jpeg library was compiled for 12-bit\n"
198
"precision. This is mostly useless, because JPEGs on the web are\n"
199
"8-bit and such versions of the jpeg library won't read or write\n"
200
"them. GD doesn't support these unusual images. Edit your\n"
201
"jmorecfg.h file to specify the correct precision and completely\n"
202
"'make clean' and 'make install' libjpeg again. Sorry.\n");
204
#endif /* BITS_IN_JSAMPLE == 12 */
205
for (i = 0; i < im->sy; i++)
207
for (jidx = 0, j = 0; j < im->sx; j++)
209
int val = im->tpixels[i][j];
210
row[jidx++] = gdTrueColorGetRed (val);
211
row[jidx++] = gdTrueColorGetGreen (val);
212
row[jidx++] = gdTrueColorGetBlue (val);
215
nlines = jpeg_write_scanlines (&cinfo, rowptr, 1);
217
fprintf (stderr, "gd_jpeg: warning: jpeg_write_scanlines"
218
" returns %u -- expected 1\n", nlines);
223
for (i = 0; i < im->sy; i++)
225
for (jidx = 0, j = 0; j < im->sx; j++)
227
int idx = im->pixels[i][j];
230
* NB: Although gd RGB values are ints, their max value is
231
* 255 (see the documentation for gdImageColorAllocate())
232
* -- perfect for 8-bit JPEG encoding (which is the norm)
234
#if BITS_IN_JSAMPLE == 8
235
row[jidx++] = im->red[idx];
236
row[jidx++] = im->green[idx];
237
row[jidx++] = im->blue[idx];
238
#elif BITS_IN_JSAMPLE == 12
239
row[jidx++] = im->red[idx] << 4;
240
row[jidx++] = im->green[idx] << 4;
241
row[jidx++] = im->blue[idx] << 4;
243
#error IJG JPEG library BITS_IN_JSAMPLE value must be 8 or 12
247
nlines = jpeg_write_scanlines (&cinfo, rowptr, 1);
249
fprintf (stderr, "gd_jpeg: warning: jpeg_write_scanlines"
250
" returns %u -- expected 1\n", nlines);
253
jpeg_finish_compress (&cinfo);
255
jpeg_destroy_compress (&cinfo);
260
gdImageCreateFromJpeg (FILE * inFile)
263
gdIOCtx *in = gdNewFileCtx (inFile);
264
im = gdImageCreateFromJpegCtx (in);
270
jpeg_gdIOCtx_src (j_decompress_ptr cinfo,
274
* Create a gd-format image from the JPEG-format INFILE. Returns the
275
* image, or NULL upon error.
278
gdImageCreateFromJpegCtx (gdIOCtx * infile)
280
struct jpeg_decompress_struct cinfo;
281
struct jpeg_error_mgr jerr;
282
jmpbuf_wrapper jmpbufw;
283
/* volatile so we can gdFree them after longjmp */
284
volatile JSAMPROW row = 0;
285
volatile gdImagePtr im = 0;
291
printf ("gd-jpeg: gd JPEG version %s\n", GD_JPEG_VERSION);
292
printf ("gd-jpeg: JPEG library version %d, %d-bit sample values\n",
293
JPEG_LIB_VERSION, BITS_IN_JSAMPLE);
296
memset (&cinfo, 0, sizeof (cinfo));
297
memset (&jerr, 0, sizeof (jerr));
299
cinfo.err = jpeg_std_error (&jerr);
300
cinfo.client_data = &jmpbufw;
301
if (setjmp (jmpbufw.jmpbuf) != 0)
303
/* we're here courtesy of longjmp */
311
cinfo.err->error_exit = fatal_jpeg_error;
313
jpeg_create_decompress (&cinfo);
315
jpeg_gdIOCtx_src (&cinfo, infile);
317
retval = jpeg_read_header (&cinfo, TRUE);
318
if (retval != JPEG_HEADER_OK)
319
fprintf (stderr, "gd-jpeg: warning: jpeg_read_header returns"
320
" %d, expected %d\n", retval, JPEG_HEADER_OK);
322
if (cinfo.image_height > INT_MAX)
323
fprintf (stderr, "gd-jpeg: warning: JPEG image height (%u) is"
324
" greater than INT_MAX (%d) (and thus greater than"
325
" gd can handle)", cinfo.image_height,
328
if (cinfo.image_width > INT_MAX)
329
fprintf (stderr, "gd-jpeg: warning: JPEG image width (%u) is"
330
" greater than INT_MAX (%d) (and thus greater than"
331
" gd can handle)\n", cinfo.image_width, INT_MAX);
333
im = gdImageCreateTrueColor ((int) cinfo.image_width,
334
(int) cinfo.image_height);
337
fprintf (stderr, "gd-jpeg error: cannot allocate gdImage"
343
* Force the image into RGB colorspace, but don't
344
* reduce the number of colors anymore (GD 2.0)
346
cinfo.out_color_space = JCS_RGB;
348
if (jpeg_start_decompress (&cinfo) != TRUE)
349
fprintf (stderr, "gd-jpeg: warning: jpeg_start_decompress"
350
" reports suspended data source\n");
353
printf ("gd-jpeg: JPEG image information:");
354
if (cinfo.saw_JFIF_marker)
355
printf (" JFIF version %d.%.2d",
356
(int) cinfo.JFIF_major_version,
357
(int) cinfo.JFIF_minor_version);
358
else if (cinfo.saw_Adobe_marker)
359
printf (" Adobe format");
361
printf (" UNKNOWN format");
363
printf (" %ux%u (raw) / %ux%u (scaled) %d-bit", cinfo.image_width,
364
cinfo.image_height, cinfo.output_width,
365
cinfo.output_height, cinfo.data_precision);
366
printf (" %s", (cinfo.progressive_mode ? "progressive" :
368
printf (" image, %d quantized colors, ",
369
cinfo.actual_number_of_colors);
371
switch (cinfo.jpeg_color_space)
374
printf ("grayscale");
382
printf ("YCbCr (a.k.a. YUV)");
394
printf ("UNKNOWN (value: %d)", (int) cinfo.jpeg_color_space);
397
printf (" colorspace\n");
399
#endif /* JPEG_DEBUG */
401
/* REMOVED by TBB 2/12/01. This field of the structure is
402
documented as private, and sure enough it's gone in the
403
latest libjpeg, replaced by something else. Unfortunately
404
there is still no right way to find out if the file was
405
progressive or not; just declare your intent before you
406
write one by calling gdImageInterlace(im, 1) yourself.
407
After all, we're not really supposed to rework JPEGs and
408
write them out again anyway. Lossy compression, remember? */
410
gdImageInterlace (im, cinfo.progressive_mode != 0);
412
if (cinfo.output_components != 3)
414
fprintf (stderr, "gd-jpeg: error: JPEG color quantization"
415
" request resulted in output_components == %d"
416
" (expected 3)\n", cinfo.output_components);
420
#if BITS_IN_JSAMPLE == 12
421
fprintf (stderr, "gd-jpeg: error: jpeg library was compiled for 12-bit\n"
422
"precision. This is mostly useless, because JPEGs on the web are\n"
423
"8-bit and such versions of the jpeg library won't read or write\n"
424
"them. GD doesn't support these unusual images. Edit your\n"
425
"jmorecfg.h file to specify the correct precision and completely\n"
426
"'make clean' and 'make install' libjpeg again. Sorry.\n");
428
#endif /* BITS_IN_JSAMPLE == 12 */
430
row = gdCalloc (cinfo.output_width * 3, sizeof (JSAMPLE));
433
fprintf (stderr, "gd-jpeg: error: unable to allocate row for"
434
" JPEG scanline: gdCalloc returns NULL\n");
439
for (i = 0; i < cinfo.output_height; i++)
441
nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
444
fprintf (stderr, "gd-jpeg: error: jpeg_read_scanlines"
445
" returns %u, expected 1\n", nrows);
449
for (j = 0; j < cinfo.output_width; j++)
450
im->tpixels[i][j] = gdTrueColor (row[j * 3], row[j * 3 + 1],
454
if (jpeg_finish_decompress (&cinfo) != TRUE)
455
fprintf (stderr, "gd-jpeg: warning: jpeg_finish_decompress"
456
" reports suspended data source\n");
459
jpeg_destroy_decompress (&cinfo);
464
jpeg_destroy_decompress (&cinfo);
474
* gdIOCtx JPEG data sources and sinks, T. Boutell
475
* almost a simple global replace from T. Lane's stdio versions.
479
/* Different versions of libjpeg use either 'jboolean' or 'boolean', and
480
some platforms define 'boolean', and so forth. Deal with this
481
madness by typedeffing 'safeboolean' to 'boolean' if HAVE_BOOLEAN
482
is already set, because this is the test that libjpeg uses.
483
Otherwise, typedef it to int, because that's what libjpeg does
484
if HAVE_BOOLEAN is not defined. -TBB */
487
typedef boolean safeboolean;
489
typedef int safeboolean;
490
#endif /* HAVE_BOOLEAN */
492
/* Expanded data source object for gdIOCtx input */
496
struct jpeg_source_mgr pub; /* public fields */
498
gdIOCtx *infile; /* source stream */
499
unsigned char *buffer; /* start of buffer */
500
safeboolean start_of_file; /* have we gotten any data yet? */
505
typedef my_source_mgr *my_src_ptr;
507
#define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
510
* Initialize source --- called by jpeg_read_header
511
* before any data is actually read.
515
init_source (j_decompress_ptr cinfo)
517
my_src_ptr src = (my_src_ptr) cinfo->src;
519
/* We reset the empty-input-file flag for each image,
520
* but we don't clear the input buffer.
521
* This is correct behavior for reading a series of images from one source.
523
src->start_of_file = TRUE;
528
* Fill the input buffer --- called whenever buffer is emptied.
530
* In typical applications, this should read fresh data into the buffer
531
* (ignoring the current state of next_input_byte & bytes_in_buffer),
532
* reset the pointer & count to the start of the buffer, and return TRUE
533
* indicating that the buffer has been reloaded. It is not necessary to
534
* fill the buffer entirely, only to obtain at least one more byte.
536
* There is no such thing as an EOF return. If the end of the file has been
537
* reached, the routine has a choice of ERREXIT() or inserting fake data into
538
* the buffer. In most cases, generating a warning message and inserting a
539
* fake EOI marker is the best course of action --- this will allow the
540
* decompressor to output however much of the image is there. However,
541
* the resulting error message is misleading if the real problem is an empty
542
* input file, so we handle that case specially.
544
* In applications that need to be able to suspend compression due to input
545
* not being available yet, a FALSE return indicates that no more data can be
546
* obtained right now, but more may be forthcoming later. In this situation,
547
* the decompressor will return to its caller (with an indication of the
548
* number of scanlines it has read, if any). The application should resume
549
* decompression after it has loaded more data into the input buffer. Note
550
* that there are substantial restrictions on the use of suspension --- see
553
* When suspending, the decompressor will back up to a convenient restart point
554
* (typically the start of the current MCU). next_input_byte & bytes_in_buffer
555
* indicate where the restart point will be if the current call returns FALSE.
556
* Data beyond this point must be rescanned after resumption, so move it to
557
* the front of the buffer rather than discarding it.
560
#define END_JPEG_SEQUENCE "\r\n[*]--:END JPEG:--[*]\r\n"
563
fill_input_buffer (j_decompress_ptr cinfo)
565
my_src_ptr src = (my_src_ptr) cinfo->src;
570
memset (src->buffer, 0, INPUT_BUF_SIZE);
572
while (nbytes < INPUT_BUF_SIZE)
575
int got = gdGetBuf (src->buffer + nbytes,
576
INPUT_BUF_SIZE - nbytes,
579
if ((got == EOF) || (got == 0))
582
/* EOF or error. If we got any data, don't worry about it.
583
If we didn't, then this is unexpected. */
601
if (src->start_of_file) /* Treat empty input file as fatal error */
602
ERREXIT (cinfo, JERR_INPUT_EMPTY);
603
WARNMS (cinfo, JWRN_JPEG_EOF);
604
/* Insert a fake EOI marker */
605
src->buffer[0] = (unsigned char) 0xFF;
606
src->buffer[1] = (unsigned char) JPEG_EOI;
610
src->pub.next_input_byte = src->buffer;
611
src->pub.bytes_in_buffer = nbytes;
612
src->start_of_file = FALSE;
619
* Skip data --- used to skip over a potentially large amount of
620
* uninteresting data (such as an APPn marker).
622
* Writers of suspendable-input applications must note that skip_input_data
623
* is not granted the right to give a suspension return. If the skip extends
624
* beyond the data currently in the buffer, the buffer can be marked empty so
625
* that the next read will cause a fill_input_buffer call that can suspend.
626
* Arranging for additional bytes to be discarded before reloading the input
627
* buffer is the application writer's problem.
631
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.
640
while (num_bytes > (long) src->pub.bytes_in_buffer)
642
num_bytes -= (long) src->pub.bytes_in_buffer;
643
(void) fill_input_buffer (cinfo);
644
/* note we assume that fill_input_buffer will never return FALSE,
645
* so suspension need not be handled.
648
src->pub.next_input_byte += (size_t) num_bytes;
649
src->pub.bytes_in_buffer -= (size_t) num_bytes;
655
* An additional method that can be provided by data source modules is the
656
* resync_to_restart method for error recovery in the presence of RST markers.
657
* For the moment, this source module just uses the default resync method
658
* provided by the JPEG library. That method assumes that no backtracking
664
* Terminate source --- called by jpeg_finish_decompress
665
* after all data has been read. Often a no-op.
667
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
668
* application must deal with any cleanup that should happen even
673
term_source (j_decompress_ptr cinfo)
678
my_src_ptr src = (my_src_ptr) cinfo->src;
685
* Prepare for input from a gdIOCtx stream.
686
* The caller must have already opened the stream, and is responsible
687
* for closing it after finishing decompression.
691
jpeg_gdIOCtx_src (j_decompress_ptr cinfo,
696
/* The source object and input buffer are made permanent so that a series
697
* of JPEG images can be read from the same file by calling jpeg_gdIOCtx_src
698
* only before the first one. (If we discarded the buffer at the end of
699
* one image, we'd likely lose the start of the next one.)
700
* This makes it unsafe to use this manager and a different source
701
* manager serially with the same JPEG object. Caveat programmer.
703
if (cinfo->src == NULL)
704
{ /* first time for this JPEG object? */
705
cinfo->src = (struct jpeg_source_mgr *)
706
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
707
sizeof (my_source_mgr));
708
src = (my_src_ptr) cinfo->src;
709
src->buffer = (unsigned char *)
710
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
711
INPUT_BUF_SIZE * sizeof (unsigned char));
715
src = (my_src_ptr) cinfo->src;
716
src->pub.init_source = init_source;
717
src->pub.fill_input_buffer = fill_input_buffer;
718
src->pub.skip_input_data = skip_input_data;
719
src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
720
src->pub.term_source = term_source;
721
src->infile = infile;
722
src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
723
src->pub.next_input_byte = NULL; /* until buffer loaded */
726
/* Expanded data destination object for stdio output */
730
struct jpeg_destination_mgr pub; /* public fields */
731
gdIOCtx *outfile; /* target stream */
732
unsigned char *buffer; /* start of buffer */
736
typedef my_destination_mgr *my_dest_ptr;
738
#define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
741
* Initialize destination --- called by jpeg_start_compress
742
* before any data is actually written.
746
init_destination (j_compress_ptr cinfo)
748
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
750
/* Allocate the output buffer --- it will be released when done with image */
751
dest->buffer = (unsigned char *)
752
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
753
OUTPUT_BUF_SIZE * sizeof (unsigned char));
755
dest->pub.next_output_byte = dest->buffer;
756
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
761
* Empty the output buffer --- called whenever buffer fills up.
763
* In typical applications, this should write the entire output buffer
764
* (ignoring the current state of next_output_byte & free_in_buffer),
765
* reset the pointer & count to the start of the buffer, and return TRUE
766
* indicating that the buffer has been dumped.
768
* In applications that need to be able to suspend compression due to output
769
* overrun, a FALSE return indicates that the buffer cannot be emptied now.
770
* In this situation, the compressor will return to its caller (possibly with
771
* an indication that it has not accepted all the supplied scanlines). The
772
* application should resume compression after it has made more room in the
773
* output buffer. Note that there are substantial restrictions on the use of
774
* suspension --- see the documentation.
776
* When suspending, the compressor will back up to a convenient restart point
777
* (typically the start of the current MCU). next_output_byte & free_in_buffer
778
* indicate where the restart point will be if the current call returns FALSE.
779
* Data beyond this point will be regenerated after resumption, so do not
780
* write it out when emptying the buffer externally.
784
empty_output_buffer (j_compress_ptr cinfo)
786
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
788
if (gdPutBuf (dest->buffer, OUTPUT_BUF_SIZE, dest->outfile) !=
789
(size_t) OUTPUT_BUF_SIZE)
790
ERREXIT (cinfo, JERR_FILE_WRITE);
792
dest->pub.next_output_byte = dest->buffer;
793
dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
800
* Terminate destination --- called by jpeg_finish_compress
801
* after all data has been written. Usually needs to flush buffer.
803
* NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
804
* application must deal with any cleanup that should happen even
809
term_destination (j_compress_ptr cinfo)
811
my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
812
size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
814
/* Write any data remaining in the buffer */
817
if (gdPutBuf (dest->buffer, datacount, dest->outfile) != datacount)
818
ERREXIT (cinfo, JERR_FILE_WRITE);
824
* Prepare for output to a stdio stream.
825
* The caller must have already opened the stream, and is responsible
826
* for closing it after finishing compression.
830
jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile)
834
/* The destination object is made permanent so that multiple JPEG images
835
* can be written to the same file without re-executing jpeg_stdio_dest.
836
* This makes it dangerous to use this manager and a different destination
837
* manager serially with the same JPEG object, because their private object
838
* sizes may be different. Caveat programmer.
840
if (cinfo->dest == NULL)
841
{ /* first time for this JPEG object? */
842
cinfo->dest = (struct jpeg_destination_mgr *)
843
(*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT,
844
sizeof (my_destination_mgr));
847
dest = (my_dest_ptr) cinfo->dest;
848
dest->pub.init_destination = init_destination;
849
dest->pub.empty_output_buffer = empty_output_buffer;
850
dest->pub.term_destination = term_destination;
851
dest->outfile = outfile;
854
#endif /* HAVE_JPEG */