This source file includes following definitions.
- php_jpeg_emit_message
- fatal_jpeg_error
- gdJpegGetVersionInt
- gdJpegGetVersionString
- gdImageJpeg
- gdImageJpegPtr
- gdImageJpegCtx
- gdImageCreateFromJpeg
- gdImageCreateFromJpegEx
- gdImageCreateFromJpegPtr
- gdImageCreateFromJpegPtrEx
- gdImageCreateFromJpegCtx
- gdImageCreateFromJpegCtxEx
- CMYKToRGB
- init_source
- fill_input_buffer
- skip_input_data
- term_source
- jpeg_gdIOCtx_src
- init_destination
- empty_output_buffer
- term_destination
- jpeg_gdIOCtx_dest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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
32
33 #ifdef HAVE_LIBJPEG
34 #include "gdhelpers.h"
35 #undef HAVE_STDLIB_H
36
37
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
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
64 if (level < 0) {
65
66
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
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
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
105 int gdJpegGetVersionInt()
106 {
107 return JPEG_LIB_VERSION;
108 }
109
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 case 90:
126 return "9 compatible";
127 break;
128
129 default:
130 return "unknown";
131 }
132 }
133
134
135
136
137
138
139
140
141
142
143
144 void gdImageJpeg (gdImagePtr im, FILE * outFile, int quality)
145 {
146 gdIOCtx *out = gdNewFileCtx (outFile);
147 gdImageJpegCtx (im, out, quality);
148 out->gd_free (out);
149 }
150
151 void *gdImageJpegPtr (gdImagePtr im, int *size, int quality)
152 {
153 void *rv;
154 gdIOCtx *out = gdNewDynamicCtx (2048, NULL);
155 gdImageJpegCtx (im, out, quality);
156 rv = gdDPExtractData (out, size);
157 out->gd_free (out);
158
159 return rv;
160 }
161
162 void jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile);
163
164 void gdImageJpegCtx (gdImagePtr im, gdIOCtx * outfile, int quality)
165 {
166 struct jpeg_compress_struct cinfo;
167 struct jpeg_error_mgr jerr;
168 int i, j, jidx;
169
170 volatile JSAMPROW row = 0;
171 JSAMPROW rowptr[1];
172 jmpbuf_wrapper jmpbufw;
173 JDIMENSION nlines;
174 char comment[255];
175
176 memset (&cinfo, 0, sizeof (cinfo));
177 memset (&jerr, 0, sizeof (jerr));
178
179 cinfo.err = jpeg_std_error (&jerr);
180 cinfo.client_data = &jmpbufw;
181 if (setjmp (jmpbufw.jmpbuf) != 0) {
182
183 if (row) {
184 gdFree (row);
185 }
186 return;
187 }
188
189 cinfo.err->error_exit = fatal_jpeg_error;
190
191 jpeg_create_compress (&cinfo);
192
193 cinfo.image_width = im->sx;
194 cinfo.image_height = im->sy;
195 cinfo.input_components = 3;
196 cinfo.in_color_space = JCS_RGB;
197 jpeg_set_defaults (&cinfo);
198 if (quality >= 0) {
199 jpeg_set_quality (&cinfo, quality, TRUE);
200 }
201
202
203 if (gdImageGetInterlaced (im)) {
204 jpeg_simple_progression (&cinfo);
205 }
206
207 jpeg_gdIOCtx_dest (&cinfo, outfile);
208
209 row = (JSAMPROW) safe_emalloc(cinfo.image_width * cinfo.input_components, sizeof(JSAMPLE), 0);
210 memset(row, 0, cinfo.image_width * cinfo.input_components * sizeof(JSAMPLE));
211 rowptr[0] = row;
212
213 jpeg_start_compress (&cinfo, TRUE);
214
215 if (quality >= 0) {
216 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);
217 } else {
218 snprintf(comment, sizeof(comment)-1, "CREATOR: gd-jpeg v%s (using IJG JPEG v%d), default quality\n", GD_JPEG_VERSION, JPEG_LIB_VERSION);
219 }
220 jpeg_write_marker (&cinfo, JPEG_COM, (unsigned char *) comment, (unsigned int) strlen (comment));
221 if (im->trueColor) {
222
223 #if BITS_IN_JSAMPLE == 12
224 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");
225 goto error;
226 #endif
227
228 for (i = 0; i < im->sy; i++) {
229 for (jidx = 0, j = 0; j < im->sx; j++) {
230 int val = im->tpixels[i][j];
231
232 row[jidx++] = gdTrueColorGetRed (val);
233 row[jidx++] = gdTrueColorGetGreen (val);
234 row[jidx++] = gdTrueColorGetBlue (val);
235 }
236
237 nlines = jpeg_write_scanlines (&cinfo, rowptr, 1);
238 if (nlines != 1) {
239 php_gd_error_ex(E_WARNING, "gd_jpeg: warning: jpeg_write_scanlines returns %u -- expected 1", nlines);
240 }
241 }
242 } else {
243 for (i = 0; i < im->sy; i++) {
244 for (jidx = 0, j = 0; j < im->sx; j++) {
245 int idx = im->pixels[i][j];
246
247
248
249
250
251 #if BITS_IN_JSAMPLE == 8
252 row[jidx++] = im->red[idx];
253 row[jidx++] = im->green[idx];
254 row[jidx++] = im->blue[idx];
255 #elif BITS_IN_JSAMPLE == 12
256 row[jidx++] = im->red[idx] << 4;
257 row[jidx++] = im->green[idx] << 4;
258 row[jidx++] = im->blue[idx] << 4;
259 #else
260 #error IJG JPEG library BITS_IN_JSAMPLE value must be 8 or 12
261 #endif
262 }
263
264 nlines = jpeg_write_scanlines (&cinfo, rowptr, 1);
265 if (nlines != 1) {
266 php_gd_error_ex(E_WARNING, "gd_jpeg: warning: jpeg_write_scanlines returns %u -- expected 1", nlines);
267 }
268 }
269 }
270
271 jpeg_finish_compress (&cinfo);
272 jpeg_destroy_compress (&cinfo);
273 gdFree (row);
274 }
275
276 gdImagePtr gdImageCreateFromJpeg (FILE * inFile)
277 {
278 return gdImageCreateFromJpegEx(inFile, 1);
279 }
280
281 gdImagePtr gdImageCreateFromJpegEx (FILE * inFile, int ignore_warning)
282 {
283 gdImagePtr im;
284 gdIOCtx *in = gdNewFileCtx(inFile);
285 im = gdImageCreateFromJpegCtxEx(in, ignore_warning);
286 in->gd_free (in);
287
288 return im;
289 }
290
291 gdImagePtr gdImageCreateFromJpegPtr (int size, void *data)
292 {
293 return gdImageCreateFromJpegPtrEx(size, data, 1);
294 }
295
296 gdImagePtr gdImageCreateFromJpegPtrEx (int size, void *data, int ignore_warning)
297 {
298 gdImagePtr im;
299 gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
300 im = gdImageCreateFromJpegCtxEx(in, ignore_warning);
301 in->gd_free(in);
302
303 return im;
304 }
305
306 void jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile);
307
308 static int CMYKToRGB(int c, int m, int y, int k, int inverted);
309
310
311
312
313
314
315 gdImagePtr gdImageCreateFromJpegCtx (gdIOCtx * infile)
316 {
317 return gdImageCreateFromJpegCtxEx(infile, 1);
318 }
319
320 gdImagePtr gdImageCreateFromJpegCtxEx (gdIOCtx * infile, int ignore_warning)
321 {
322 struct jpeg_decompress_struct cinfo;
323 struct jpeg_error_mgr jerr;
324 jmpbuf_wrapper jmpbufw;
325
326 volatile JSAMPROW row = 0;
327 volatile gdImagePtr im = 0;
328 JSAMPROW rowptr[1];
329 unsigned int i, j;
330 int retval;
331 JDIMENSION nrows;
332 int channels = 3;
333 int inverted = 0;
334
335 memset (&cinfo, 0, sizeof (cinfo));
336 memset (&jerr, 0, sizeof (jerr));
337
338 jmpbufw.ignore_warning = ignore_warning;
339
340 cinfo.err = jpeg_std_error (&jerr);
341 cinfo.client_data = &jmpbufw;
342
343 cinfo.err->emit_message = (void (*)(j_common_ptr,int)) php_jpeg_emit_message;
344
345 if (setjmp (jmpbufw.jmpbuf) != 0) {
346
347 if (row) {
348 gdFree (row);
349 }
350 if (im) {
351 gdImageDestroy (im);
352 }
353 return 0;
354 }
355
356 cinfo.err->error_exit = fatal_jpeg_error;
357
358 jpeg_create_decompress (&cinfo);
359
360 jpeg_gdIOCtx_src (&cinfo, infile);
361
362
363 jpeg_save_markers(&cinfo, JPEG_APP0 + 14, 256);
364
365 retval = jpeg_read_header (&cinfo, TRUE);
366 if (retval != JPEG_HEADER_OK) {
367 php_gd_error_ex(E_WARNING, "gd-jpeg: warning: jpeg_read_header returned %d, expected %d", retval, JPEG_HEADER_OK);
368 }
369
370 if (cinfo.image_height > INT_MAX) {
371 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);
372 }
373
374 if (cinfo.image_width > INT_MAX) {
375 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);
376 }
377
378 im = gdImageCreateTrueColor ((int) cinfo.image_width, (int) cinfo.image_height);
379 if (im == 0) {
380 php_gd_error("gd-jpeg error: cannot allocate gdImage struct");
381 goto error;
382 }
383
384
385
386
387 if ((cinfo.jpeg_color_space == JCS_CMYK) || (cinfo.jpeg_color_space == JCS_YCCK)) {
388 cinfo.out_color_space = JCS_CMYK;
389 } else {
390 cinfo.out_color_space = JCS_RGB;
391 }
392
393 if (jpeg_start_decompress (&cinfo) != TRUE) {
394 php_gd_error("gd-jpeg: warning: jpeg_start_decompress reports suspended data source");
395 }
396
397
398
399
400
401
402
403
404
405
406 #if 0
407 gdImageInterlace (im, cinfo.progressive_mode != 0);
408 #endif
409
410 if (cinfo.out_color_space == JCS_RGB) {
411 if (cinfo.output_components != 3) {
412 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);
413 goto error;
414 }
415 channels = 3;
416 } else if (cinfo.out_color_space == JCS_CMYK) {
417 jpeg_saved_marker_ptr marker;
418 if (cinfo.output_components != 4) {
419 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);
420 goto error;
421 }
422 channels = 4;
423 marker = cinfo.marker_list;
424 while (marker) {
425 if ((marker->marker == (JPEG_APP0 + 14)) && (marker->data_length >= 12) && (!strncmp((const char *) marker->data, "Adobe", 5))) {
426 inverted = 1;
427 break;
428 }
429 marker = marker->next;
430 }
431 } else {
432 php_gd_error_ex(E_WARNING, "gd-jpeg: error: unexpected colorspace.");
433 goto error;
434 }
435
436 #if BITS_IN_JSAMPLE == 12
437 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.");
438 goto error;
439 #endif
440
441 row = safe_emalloc(cinfo.output_width * channels, sizeof(JSAMPLE), 0);
442 memset(row, 0, cinfo.output_width * channels * sizeof(JSAMPLE));
443 rowptr[0] = row;
444
445 if (cinfo.out_color_space == JCS_CMYK) {
446 for (i = 0; i < cinfo.output_height; i++) {
447 register JSAMPROW currow = row;
448 register int *tpix = im->tpixels[i];
449 nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
450 if (nrows != 1) {
451 php_gd_error_ex(E_WARNING, "gd-jpeg: error: jpeg_read_scanlines returns %u, expected 1", nrows);
452 goto error;
453 }
454 for (j = 0; j < cinfo.output_width; j++, currow += 4, tpix++) {
455 *tpix = CMYKToRGB (currow[0], currow[1], currow[2], currow[3], inverted);
456 }
457 }
458 } else {
459 for (i = 0; i < cinfo.output_height; i++) {
460 register JSAMPROW currow = row;
461 register int *tpix = im->tpixels[i];
462 nrows = jpeg_read_scanlines (&cinfo, rowptr, 1);
463 if (nrows != 1) {
464 php_gd_error_ex(E_WARNING, "gd-jpeg: error: jpeg_read_scanlines returns %u, expected 1", nrows);
465 goto error;
466 }
467 for (j = 0; j < cinfo.output_width; j++, currow += 3, tpix++) {
468 *tpix = gdTrueColor (currow[0], currow[1], currow[2]);
469 }
470 }
471 }
472
473 if (jpeg_finish_decompress (&cinfo) != TRUE) {
474 php_gd_error("gd-jpeg: warning: jpeg_finish_decompress reports suspended data source");
475 }
476 if (!ignore_warning) {
477 if (cinfo.err->num_warnings > 0) {
478 goto error;
479 }
480 }
481
482 jpeg_destroy_decompress (&cinfo);
483 gdFree (row);
484
485 return im;
486
487 error:
488 jpeg_destroy_decompress (&cinfo);
489 if (row) {
490 gdFree (row);
491 }
492 if (im) {
493 gdImageDestroy (im);
494 }
495 return 0;
496 }
497
498
499 static int CMYKToRGB(int c, int m, int y, int k, int inverted)
500 {
501 if (inverted) {
502 c = 255 - c;
503 m = 255 - m;
504 y = 255 - y;
505 k = 255 - k;
506 }
507 return gdTrueColor((255 - c) * (255 - k) / 255, (255 - m) * (255 - k) / 255, (255 - y) * (255 - k) / 255);
508 }
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523 #ifdef HAVE_BOOLEAN
524 typedef boolean safeboolean;
525 #else
526 typedef int safeboolean;
527 #endif
528
529
530
531 typedef struct
532 {
533 struct jpeg_source_mgr pub;
534
535 gdIOCtx *infile;
536 unsigned char *buffer;
537 safeboolean start_of_file;
538 } my_source_mgr;
539
540 typedef my_source_mgr *my_src_ptr;
541
542 #define INPUT_BUF_SIZE 4096
543
544
545
546
547
548
549 void init_source (j_decompress_ptr cinfo)
550 {
551 my_src_ptr src = (my_src_ptr) cinfo->src;
552
553
554
555
556
557 src->start_of_file = TRUE;
558 }
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594 #define END_JPEG_SEQUENCE "\r\n[*]--:END JPEG:--[*]\r\n"
595
596 safeboolean fill_input_buffer (j_decompress_ptr cinfo)
597 {
598 my_src_ptr src = (my_src_ptr) cinfo->src;
599
600 ssize_t nbytes = 0;
601
602
603
604 memset(src->buffer, 0, INPUT_BUF_SIZE);
605
606 while (nbytes < INPUT_BUF_SIZE) {
607 int got = gdGetBuf(src->buffer + nbytes, INPUT_BUF_SIZE - nbytes, src->infile);
608
609 if (got == EOF || got == 0) {
610
611 if (!nbytes) {
612 nbytes = -1;
613 }
614 break;
615 }
616 nbytes += got;
617 }
618
619 if (nbytes <= 0) {
620 if (src->start_of_file) {
621 ERREXIT (cinfo, JERR_INPUT_EMPTY);
622 }
623 WARNMS (cinfo, JWRN_JPEG_EOF);
624
625 src->buffer[0] = (unsigned char) 0xFF;
626 src->buffer[1] = (unsigned char) JPEG_EOI;
627 nbytes = 2;
628 }
629
630 src->pub.next_input_byte = src->buffer;
631 src->pub.bytes_in_buffer = nbytes;
632 src->start_of_file = FALSE;
633
634 return TRUE;
635 }
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650 void skip_input_data (j_decompress_ptr cinfo, long num_bytes)
651 {
652 my_src_ptr src = (my_src_ptr) cinfo->src;
653
654
655
656
657 if (num_bytes > 0) {
658 while (num_bytes > (long) src->pub.bytes_in_buffer) {
659 num_bytes -= (long) src->pub.bytes_in_buffer;
660 (void) fill_input_buffer (cinfo);
661
662
663
664 }
665 src->pub.next_input_byte += (size_t) num_bytes;
666 src->pub.bytes_in_buffer -= (size_t) num_bytes;
667 }
668 }
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689 void term_source (j_decompress_ptr cinfo)
690 {
691 #if 0
692 * never used */
693 my_src_ptr src = (my_src_ptr) cinfo->src;
694 #endif
695 }
696
697
698
699
700
701
702
703
704 void jpeg_gdIOCtx_src (j_decompress_ptr cinfo, gdIOCtx * infile)
705 {
706 my_src_ptr src;
707
708
709
710
711
712
713
714
715 if (cinfo->src == NULL) {
716 cinfo->src = (struct jpeg_source_mgr *)
717 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof (my_source_mgr));
718 src = (my_src_ptr) cinfo->src;
719 src->buffer = (unsigned char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * sizeof (unsigned char));
720
721 }
722
723 src = (my_src_ptr) cinfo->src;
724 src->pub.init_source = init_source;
725 src->pub.fill_input_buffer = fill_input_buffer;
726 src->pub.skip_input_data = skip_input_data;
727 src->pub.resync_to_restart = jpeg_resync_to_restart;
728 src->pub.term_source = term_source;
729 src->infile = infile;
730 src->pub.bytes_in_buffer = 0;
731 src->pub.next_input_byte = NULL;
732 }
733
734
735
736 typedef struct
737 {
738 struct jpeg_destination_mgr pub;
739 gdIOCtx *outfile;
740 unsigned char *buffer;
741 } my_destination_mgr;
742
743 typedef my_destination_mgr *my_dest_ptr;
744
745 #define OUTPUT_BUF_SIZE 4096
746
747
748
749
750
751
752 void init_destination (j_compress_ptr cinfo)
753 {
754 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
755
756
757 dest->buffer = (unsigned char *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, OUTPUT_BUF_SIZE * sizeof (unsigned char));
758
759 dest->pub.next_output_byte = dest->buffer;
760 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
761 }
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787 safeboolean empty_output_buffer (j_compress_ptr cinfo)
788 {
789 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
790
791 if (gdPutBuf (dest->buffer, OUTPUT_BUF_SIZE, dest->outfile) != (size_t) OUTPUT_BUF_SIZE) {
792 ERREXIT (cinfo, JERR_FILE_WRITE);
793 }
794
795 dest->pub.next_output_byte = dest->buffer;
796 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
797
798 return TRUE;
799 }
800
801
802
803
804
805
806
807
808
809
810
811 void term_destination (j_compress_ptr cinfo)
812 {
813 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
814 size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
815
816
817 if (datacount > 0 && ((size_t)gdPutBuf (dest->buffer, datacount, dest->outfile) != datacount)) {
818 ERREXIT (cinfo, JERR_FILE_WRITE);
819 }
820 }
821
822
823
824
825
826
827
828
829 void jpeg_gdIOCtx_dest (j_compress_ptr cinfo, gdIOCtx * outfile)
830 {
831 my_dest_ptr dest;
832
833
834
835
836
837
838
839 if (cinfo->dest == NULL) {
840 cinfo->dest = (struct jpeg_destination_mgr *) (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof (my_destination_mgr));
841 }
842
843 dest = (my_dest_ptr) cinfo->dest;
844 dest->pub.init_destination = init_destination;
845 dest->pub.empty_output_buffer = empty_output_buffer;
846 dest->pub.term_destination = term_destination;
847 dest->outfile = outfile;
848 }
849
850 #endif