1 /*
2 * gd_jpeg.c: Read and write JPEG (JFIF) format image files using the
3 * gd graphics library (http://www.libgd.org).
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 /**
25 * File: JPEG IO
26 *
27 * Read and write JPEG images.
28 */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <stdlib.h>
35 #include <setjmp.h>
36 #include <limits.h>
37 #include <string.h>
38
39 #include "gd.h"
40 #include "gd_errors.h"
41 /* TBB: move this up so include files are not brought in */
42 /* JCE: arrange HAVE_LIBJPEG so that it can be set in gd.h */
43 #ifdef HAVE_LIBJPEG
44 #include "gdhelpers.h"
45
46 #if defined(_WIN32) && defined(__MINGW32__)
47 # define HAVE_BOOLEAN
48 #endif
49
50 /* 1.8.1: remove dependency on jinclude.h */
51 #include "jpeglib.h"
52 #include "jerror.h"
53
54 static const char *const GD_JPEG_VERSION = "1.0";
55
56 typedef struct _jmpbuf_wrapper {
57 jmp_buf jmpbuf;
58 int ignore_warning;
59 }
60 jmpbuf_wrapper;
61
jpeg_emit_message(j_common_ptr jpeg_info,int level)62 static void jpeg_emit_message(j_common_ptr jpeg_info, int level)
63 {
64 char message[JMSG_LENGTH_MAX];
65 jmpbuf_wrapper *jmpbufw;
66 int ignore_warning = 0;
67
68 jmpbufw = (jmpbuf_wrapper *) jpeg_info->client_data;
69
70 if (jmpbufw != 0) {
71 ignore_warning = jmpbufw->ignore_warning;
72 }
73
74 (jpeg_info->err->format_message)(jpeg_info,message);
75
76 /* It is a warning message */
77 if (level < 0) {
78 /* display only the 1st warning, as would do a default libjpeg
79 * unless strace_level >= 3
80 */
81 if ((jpeg_info->err->num_warnings == 0) || (jpeg_info->err->trace_level >= 3)) {
82 if (!ignore_warning) {
83 gd_error("gd-jpeg, libjpeg: recoverable error: %s\n", message);
84 }
85 }
86
87 jpeg_info->err->num_warnings++;
88 } else {
89 /* strace msg, Show it if trace_level >= level. */
90 if (jpeg_info->err->trace_level >= level) {
91 if (!ignore_warning) {
92 gd_error("gd-jpeg, libjpeg: strace message: %s\n", message);
93 }
94 }
95 }
96 }
97
98 /* Called by the IJG JPEG library upon encountering a fatal error */
fatal_jpeg_error(j_common_ptr cinfo)99 static void fatal_jpeg_error(j_common_ptr cinfo)
100 {
101 jmpbuf_wrapper *jmpbufw;
102 char buffer[JMSG_LENGTH_MAX];
103
104 (*cinfo->err->format_message)(cinfo, buffer);
105 gd_error_ex(GD_WARNING, "gd-jpeg: JPEG library reports unrecoverable error: %s", buffer);
106
107 jmpbufw = (jmpbuf_wrapper *)cinfo->client_data;
108 jpeg_destroy(cinfo);
109
110 if(jmpbufw != 0) {
111 longjmp(jmpbufw->jmpbuf, 1);
112 gd_error_ex(GD_ERROR, "gd-jpeg: EXTREMELY fatal error: longjmp returned control; terminating\n");
113 } else {
114 gd_error_ex(GD_ERROR, "gd-jpeg: EXTREMELY fatal error: jmpbuf unrecoverable; terminating\n");
115 }
116
117 exit(99);
118 }
119
120 static int _gdImageJpegCtx(gdImagePtr im, gdIOCtx *outfile, int quality);
121
122 /*
123 * Write IM to OUTFILE as a JFIF-formatted JPEG image, using quality
124 * QUALITY. If QUALITY is in the range 0-100, increasing values
125 * represent higher quality but also larger image size. If QUALITY is
126 * negative, the IJG JPEG library's default quality is used (which
127 * should be near optimal for many applications). See the IJG JPEG
128 * library documentation for more details.
129 */
130
131
132 /*
133 Function: gdImageJpeg
134
135 <gdImageJpeg> outputs the specified image to the specified file in
136 JPEG format. The file must be open for writing. Under MSDOS and
137 all versions of Windows, it is important to use "wb" as opposed to
138 simply "w" as the mode when opening the file, and under Unix there
139 is no penalty for doing so. <gdImageJpeg> does not close the file;
140 your code must do so.
141
142 If _quality_ is negative, the default IJG JPEG quality value (which
143 should yield a good general quality / size tradeoff for most
144 situations) is used. Otherwise, for practical purposes, _quality_
145 should be a value in the range 0-95, higher quality values usually
146 implying both higher quality and larger image sizes.
147
148 If you have set image interlacing using <gdImageInterlace>, this
149 function will interpret that to mean you wish to output a
150 progressive JPEG. Some programs (e.g., Web browsers) can display
151 progressive JPEGs incrementally; this can be useful when browsing
152 over a relatively slow communications link, for
153 example. Progressive JPEGs can also be slightly smaller than
154 sequential (non-progressive) JPEGs.
155
156 Variants:
157
158 <gdImageJpegCtx> stores the image using a <gdIOCtx> struct.
159
160 <gdImageJpegPtr> stores the image to RAM.
161
162 Parameters:
163
164 im - The image to save
165 outFile - The FILE pointer to write to.
166 quality - Compression quality (0-95, 0 means use the default).
167
168 Returns:
169
170 Nothing.
171
172 Example:
173 (start code)
174
175 gdImagePtr im;
176 int black, white;
177 FILE *out;
178 // Create the image
179 im = gdImageCreate(100, 100);
180 // Allocate background
181 white = gdImageColorAllocate(im, 255, 255, 255);
182 // Allocate drawing color
183 black = gdImageColorAllocate(im, 0, 0, 0);
184 // Draw rectangle
185 gdImageRectangle(im, 0, 0, 99, 99, black);
186 // Open output file in binary mode
187 out = fopen("rect.jpg", "wb");
188 // Write JPEG using default quality
189 gdImageJpeg(im, out, -1);
190 // Close file
191 fclose(out);
192 // Destroy image
193 gdImageDestroy(im);
194
195 (end code)
196 */
197
gdImageJpeg(gdImagePtr im,FILE * outFile,int quality)198 BGD_DECLARE(void) gdImageJpeg(gdImagePtr im, FILE *outFile, int quality)
199 {
200 gdIOCtx *out = gdNewFileCtx(outFile);
201 if (out == NULL) return;
202 gdImageJpegCtx(im, out, quality);
203 out->gd_free(out);
204 }
205
206 /*
207 Function: gdImageJpegPtr
208
209 Identical to <gdImageJpeg> except that it returns a pointer to a
210 memory area with the JPEG data. This memory must be freed by the
211 caller when it is no longer needed.
212
213 The caller *must* invoke <gdFree>, not free(). This is because it
214 is not guaranteed that libgd will use the same implementation of
215 malloc, free, etc. as your proggram.
216
217 The 'size' parameter receives the total size of the block of
218 memory.
219
220 Parameters:
221
222 im - The image to write
223 size - Output: the size of the resulting image.
224 quality - Compression quality.
225
226 Returns:
227
228 A pointer to the JPEG data or NULL if an error occurred.
229
230 */
gdImageJpegPtr(gdImagePtr im,int * size,int quality)231 BGD_DECLARE(void *) gdImageJpegPtr(gdImagePtr im, int *size, int quality)
232 {
233 void *rv;
234 gdIOCtx *out = gdNewDynamicCtx(2048, NULL);
235 if (out == NULL) return NULL;
236 if (!_gdImageJpegCtx(im, out, quality)) {
237 rv = gdDPExtractData(out, size);
238 } else {
239 rv = NULL;
240 }
241 out->gd_free(out);
242 return rv;
243 }
244
245 void jpeg_gdIOCtx_dest(j_compress_ptr cinfo, gdIOCtx *outfile);
246
247 /*
248 Function: gdImageJpegCtx
249
250 Write the image as JPEG data via a <gdIOCtx>. See <gdImageJpeg>
251 for more details.
252
253 Parameters:
254
255 im - The image to write.
256 outfile - The output sink.
257 quality - Image quality.
258
259 */
gdImageJpegCtx(gdImagePtr im,gdIOCtx * outfile,int quality)260 BGD_DECLARE(void) gdImageJpegCtx(gdImagePtr im, gdIOCtx *outfile, int quality)
261 {
262 _gdImageJpegCtx(im, outfile, quality);
263 }
264
265 /* returns 0 on success, 1 on failure */
_gdImageJpegCtx(gdImagePtr im,gdIOCtx * outfile,int quality)266 static int _gdImageJpegCtx(gdImagePtr im, gdIOCtx *outfile, int quality)
267 {
268 struct jpeg_compress_struct cinfo;
269 struct jpeg_error_mgr jerr;
270 int i, j, jidx;
271 /* volatile so we can gdFree it on return from longjmp */
272 volatile JSAMPROW row = 0;
273 JSAMPROW rowptr[1];
274 jmpbuf_wrapper jmpbufw;
275 JDIMENSION nlines;
276 char comment[255];
277
278 #ifdef JPEG_DEBUG
279 gd_error_ex(GD_DEBUG, "gd-jpeg: gd JPEG version %s\n", GD_JPEG_VERSION);
280 gd_error_ex(GD_DEBUG, "gd-jpeg: JPEG library version %d, %d-bit sample values\n", JPEG_LIB_VERSION, BITS_IN_JSAMPLE);
281 if (!im->trueColor) {
282 for(i = 0; i < im->colorsTotal; i++) {
283 if(!im->open[i]) {
284 gd_error_ex(GD_DEBUG, "gd-jpeg: gd colormap index %d: (%d, %d, %d)\n", i, im->red[i], im->green[i], im->blue[i]);
285 }
286 }
287 }
288 #endif /* JPEG_DEBUG */
289
290 memset(&cinfo, 0, sizeof(cinfo));
291 memset(&jerr, 0, sizeof(jerr));
292
293 cinfo.err = jpeg_std_error(&jerr);
294 cinfo.client_data = &jmpbufw;
295
296 if(setjmp(jmpbufw.jmpbuf) != 0) {
297 /* we're here courtesy of longjmp */
298 if(row) {
299 gdFree(row);
300 }
301 return 1;
302 }
303
304 cinfo.err->emit_message = jpeg_emit_message;
305 cinfo.err->error_exit = fatal_jpeg_error;
306
307 jpeg_create_compress(&cinfo);
308
309 cinfo.image_width = im->sx;
310 cinfo.image_height = im->sy;
311 cinfo.input_components = 3; /* # of color components per pixel */
312 cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
313
314 jpeg_set_defaults(&cinfo);
315
316 cinfo.density_unit = 1;
317 cinfo.X_density = im->res_x;
318 cinfo.Y_density = im->res_y;
319
320 if(quality >= 0) {
321 jpeg_set_quality(&cinfo, quality, TRUE);
322 if (quality >= 90) {
323 cinfo.comp_info[0].h_samp_factor = 1;
324 cinfo.comp_info[0].v_samp_factor = 1;
325 }
326 }
327
328 /* If user requests interlace, translate that to progressive JPEG */
329 if(gdImageGetInterlaced(im)) {
330 #ifdef JPEG_DEBUG
331 gd_error_ex(GD_DEBUG, "gd-jpeg: interlace set, outputting progressive JPEG image\n");
332 #endif
333 jpeg_simple_progression(&cinfo);
334 }
335
336 jpeg_gdIOCtx_dest(&cinfo, outfile);
337
338 row = (JSAMPROW)gdCalloc(1, cinfo.image_width * cinfo.input_components * sizeof(JSAMPLE));
339 if(row == 0) {
340 gd_error("gd-jpeg: error: unable to allocate JPEG row structure: gdCalloc returns NULL\n");
341 jpeg_destroy_compress(&cinfo);
342 return 1;
343 }
344
345 rowptr[0] = row;
346
347 jpeg_start_compress(&cinfo, TRUE);
348
349 sprintf(comment, "CREATOR: gd-jpeg v%s (using IJG JPEG v%d),", GD_JPEG_VERSION, JPEG_LIB_VERSION);
350
351 if(quality >= 0) {
352 sprintf (comment + strlen(comment), " quality = %d\n", quality);
353 } else {
354 strcat(comment + strlen(comment), " default quality\n");
355 }
356
357 jpeg_write_marker(&cinfo, JPEG_COM, (unsigned char *) comment, (unsigned int)strlen(comment));
358
359 if(im->trueColor) {
360 #if BITS_IN_JSAMPLE == 12
361 gd_error(
362 "gd-jpeg: error: jpeg library was compiled for 12-bit\n"
363 "precision. This is mostly useless, because JPEGs on the web are\n"
364 "8-bit and such versions of the jpeg library won't read or write\n"
365 "them. GD doesn't support these unusual images. Edit your\n"
366 "jmorecfg.h file to specify the correct precision and completely\n"
367 "'make clean' and 'make install' libjpeg again. Sorry.\n"
368 );
369 goto error;
370 #endif /* BITS_IN_JSAMPLE == 12 */
371 for(i = 0; i < im->sy; i++) {
372 for(jidx = 0, j = 0; j < im->sx; j++) {
373 int val = im->tpixels[i][j];
374 row[jidx++] = gdTrueColorGetRed(val);
375 row[jidx++] = gdTrueColorGetGreen(val);
376 row[jidx++] = gdTrueColorGetBlue(val);
377 }
378
379 nlines = jpeg_write_scanlines(&cinfo, rowptr, 1);
380
381 if(nlines != 1) {
382 gd_error("gd_jpeg: warning: jpeg_write_scanlines returns %u -- expected 1\n", nlines);
383 }
384 }
385 } else {
386 for(i = 0; i < im->sy; i++) {
387 for(jidx = 0, j = 0; j < im->sx; j++) {
388 int idx = im->pixels[i][j];
389
390 /*
391 * NB: Although gd RGB values are ints, their max value is
392 * 255 (see the documentation for gdImageColorAllocate())
393 * -- perfect for 8-bit JPEG encoding (which is the norm)
394 */
395 #if BITS_IN_JSAMPLE == 8
396 row[jidx++] = im->red[idx];
397 row[jidx++] = im->green[idx];
398 row[jidx++] = im->blue[idx];
399 #elif BITS_IN_JSAMPLE == 12
400 row[jidx++] = im->red[idx] << 4;
401 row[jidx++] = im->green[idx] << 4;
402 row[jidx++] = im->blue[idx] << 4;
403 #else
404 #error IJG JPEG library BITS_IN_JSAMPLE value must be 8 or 12
405 #endif
406 }
407
408 nlines = jpeg_write_scanlines(&cinfo, rowptr, 1);
409 if(nlines != 1) {
410 gd_error("gd_jpeg: warning: jpeg_write_scanlines"
411 " returns %u -- expected 1\n", nlines);
412 }
413 }
414 }
415
416 jpeg_finish_compress(&cinfo);
417 jpeg_destroy_compress(&cinfo);
418 gdFree(row);
419 return 0;
420 }
421
422
423
424
425 /*
426 Function: gdImageCreateFromJpeg
427
428 See <gdImageCreateFromJpegEx>.
429 */
gdImageCreateFromJpeg(FILE * inFile)430 BGD_DECLARE(gdImagePtr) gdImageCreateFromJpeg(FILE *inFile)
431 {
432 return gdImageCreateFromJpegEx(inFile, 1);
433 }
434
435
436 /*
437 Function: gdImageCreateFromJpegEx
438
439 <gdImageCreateFromJpegEx> is called to load truecolor images from
440 JPEG format files. Invoke <gdImageCreateFromJpegEx> with an
441 already opened pointer to a file containing the desired
442 image. <gdImageCreateFromJpegEx> returns a <gdImagePtr> to the new
443 truecolor image, or NULL if unable to load the image (most often
444 because the file is corrupt or does not contain a JPEG
445 image). <gdImageCreateFromJpegEx> does not close the file.
446
447 You can inspect the sx and sy members of the image to determine
448 its size. The image must eventually be destroyed using
449 <gdImageDestroy>.
450
451 *The returned image is always a truecolor image.*
452
453 Variants:
454
455 <gdImageCreateFromJpegPtrEx> creates an image from JPEG data
456 already in memory.
457
458 <gdImageCreateFromJpegCtxEx> reads its data via the function
459 pointers in a <gdIOCtx> structure.
460
461 <gdImageCreateFromJpeg>, <gdImageCreateFromJpegPtr> and
462 <gdImageCreateFromJpegCtx> are equivalent to calling their
463 _Ex_-named counterparts with an ignore_warning set to 1
464 (i.e. TRUE).
465
466 Parameters:
467
468 infile - The input FILE pointer.
469 ignore_warning - Flag. If true, ignores recoverable warnings.
470
471 Returns:
472
473 A pointer to the new *truecolor* image. This will need to be
474 destroyed with <gdImageDestroy> once it is no longer needed.
475
476 On error, returns NULL.
477
478 Example:
479 (start code)
480
481 gdImagePtr im;
482 FILE *in;
483 in = fopen("myjpeg.jpg", "rb");
484 im = gdImageCreateFromJpegEx(in, GD_TRUE);
485 fclose(in);
486 // ... Use the image ...
487 gdImageDestroy(im);
488
489 (end code)
490 */
gdImageCreateFromJpegEx(FILE * inFile,int ignore_warning)491 BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegEx(FILE *inFile, int ignore_warning)
492 {
493 gdImagePtr im;
494 gdIOCtx *in = gdNewFileCtx(inFile);
495 if (in == NULL) return NULL;
496 im = gdImageCreateFromJpegCtxEx(in, ignore_warning);
497 in->gd_free(in);
498 return im;
499 }
500
501 /*
502 Function: gdImageCreateFromJpegPtr
503
504 Parameters:
505
506 size - size of JPEG data in bytes.
507 data - pointer to JPEG data.
508
509 See <gdImageCreateFromJpegEx>.
510 */
gdImageCreateFromJpegPtr(int size,void * data)511 BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegPtr(int size, void *data)
512 {
513 return gdImageCreateFromJpegPtrEx(size, data, 1);
514 }
515
516 /*
517 Function: gdImageCreateFromJpegPtrEx
518
519 Parameters:
520
521 size - size of JPEG data in bytes.
522 data - pointer to JPEG data.
523 ignore_warning - if true, ignore recoverable warnings
524
525 See <gdImageCreateFromJpegEx>.
526 */
gdImageCreateFromJpegPtrEx(int size,void * data,int ignore_warning)527 BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegPtrEx(int size, void *data, int ignore_warning)
528 {
529 gdImagePtr im;
530 gdIOCtx *in = gdNewDynamicCtxEx(size, data, 0);
531 if(!in) {
532 return 0;
533 }
534 im = gdImageCreateFromJpegCtxEx(in, ignore_warning);
535 in->gd_free(in);
536 return im;
537 }
538
539 void jpeg_gdIOCtx_src(j_decompress_ptr cinfo, gdIOCtx *infile);
540
541 static int CMYKToRGB(int c, int m, int y, int k, int inverted);
542
543 /*
544 Function: gdImageCreateFromJpegCtx
545
546 See <gdImageCreateFromJpeg>.
547 */
gdImageCreateFromJpegCtx(gdIOCtx * infile)548 BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegCtx(gdIOCtx *infile)
549 {
550 return gdImageCreateFromJpegCtxEx(infile, 1);
551 }
552
553 /*
554 Function: gdImageCreateFromJpegCtxEx
555
556 See <gdImageCreateFromJpeg>.
557 */
gdImageCreateFromJpegCtxEx(gdIOCtx * infile,int ignore_warning)558 BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegCtxEx(gdIOCtx *infile, int ignore_warning)
559 {
560 struct jpeg_decompress_struct cinfo;
561 struct jpeg_error_mgr jerr;
562 jmpbuf_wrapper jmpbufw;
563 /* volatile so we can gdFree them after longjmp */
564 volatile JSAMPROW row = 0;
565 volatile gdImagePtr im = 0;
566 JSAMPROW rowptr[1];
567 JDIMENSION i, j;
568 int retval;
569 JDIMENSION nrows;
570 int channels = 3;
571 int inverted = 0;
572
573 #ifdef JPEG_DEBUG
574 gd_error_ex(GD_DEBUG, "gd-jpeg: gd JPEG version %s\n", GD_JPEG_VERSION);
575 gd_error_ex(GD_DEBUG, "gd-jpeg: JPEG library version %d, %d-bit sample values\n", JPEG_LIB_VERSION, BITS_IN_JSAMPLE);
576 gd_error_ex(GD_DEBUG, "sizeof: %d\n", sizeof(struct jpeg_decompress_struct));
577 #endif
578
579 memset(&cinfo, 0, sizeof(cinfo));
580 memset(&jerr, 0, sizeof(jerr));
581
582 jmpbufw.ignore_warning = ignore_warning;
583
584 cinfo.err = jpeg_std_error(&jerr);
585 cinfo.client_data = &jmpbufw;
586
587 cinfo.err->emit_message = jpeg_emit_message;
588
589 if(setjmp(jmpbufw.jmpbuf) != 0) {
590 /* we're here courtesy of longjmp */
591 if(row) {
592 gdFree(row);
593 }
594 if(im) {
595 gdImageDestroy(im);
596 }
597 return 0;
598 }
599
600 cinfo.err->error_exit = fatal_jpeg_error;
601
602 jpeg_create_decompress(&cinfo);
603
604 jpeg_gdIOCtx_src(&cinfo, infile);
605
606 /* 2.0.22: save the APP14 marker to check for Adobe Photoshop CMYK
607 * files with inverted components.
608 */
609 jpeg_save_markers(&cinfo, JPEG_APP0 + 14, 256);
610
611 retval = jpeg_read_header(&cinfo, TRUE);
612 if(retval != JPEG_HEADER_OK) {
613 gd_error("gd-jpeg: warning: jpeg_read_header returns"
614 " %d, expected %d\n", retval, JPEG_HEADER_OK);
615 }
616
617 if(cinfo.image_height > INT_MAX) {
618 gd_error("gd-jpeg: warning: JPEG image height (%u) is"
619 " greater than INT_MAX (%d) (and thus greater than"
620 " gd can handle)", cinfo.image_height, INT_MAX);
621 }
622
623 if(cinfo.image_width > INT_MAX) {
624 gd_error("gd-jpeg: warning: JPEG image width (%u) is"
625 " greater than INT_MAX (%d) (and thus greater than"
626 " gd can handle)\n", cinfo.image_width, INT_MAX);
627 }
628
629 im = gdImageCreateTrueColor((int)cinfo.image_width, (int)cinfo.image_height);
630 if(im == 0) {
631 gd_error("gd-jpeg error: cannot allocate gdImage struct\n");
632 goto error;
633 }
634
635 /* check if the resolution is specified */
636 switch (cinfo.density_unit) {
637 case 1:
638 im->res_x = cinfo.X_density;
639 im->res_y = cinfo.Y_density;
640 break;
641 case 2:
642 im->res_x = DPCM2DPI(cinfo.X_density);
643 im->res_y = DPCM2DPI(cinfo.Y_density);
644 break;
645 }
646
647 /* 2.0.22: very basic support for reading CMYK colorspace files. Nice for
648 * thumbnails but there's no support for fussy adjustment of the
649 * assumed properties of inks and paper.
650 */
651 if((cinfo.jpeg_color_space == JCS_CMYK) || (cinfo.jpeg_color_space == JCS_YCCK)) {
652 cinfo.out_color_space = JCS_CMYK;
653 } else {
654 cinfo.out_color_space = JCS_RGB;
655 }
656
657 if(jpeg_start_decompress(&cinfo) != TRUE) {
658 gd_error("gd-jpeg: warning: jpeg_start_decompress"
659 " reports suspended data source\n");
660 }
661
662 #ifdef JPEG_DEBUG
663 gd_error_ex(GD_DEBUG, "gd-jpeg: JPEG image information:");
664 if(cinfo.saw_JFIF_marker) {
665 gd_error_ex(GD_DEBUG, " JFIF version %d.%.2d", (int)cinfo.JFIF_major_version, (int)cinfo.JFIF_minor_version);
666 } else if(cinfo.saw_Adobe_marker) {
667 gd_error_ex(GD_DEBUG, " Adobe format");
668 } else {
669 gd_error_ex(GD_DEBUG, " UNKNOWN format");
670 }
671
672 gd_error_ex(GD_DEBUG, " %ux%u (raw) / %ux%u (scaled) %d-bit", cinfo.image_width,
673 cinfo.image_height, cinfo.output_width,
674 cinfo.output_height, cinfo.data_precision
675 );
676 gd_error_ex(GD_DEBUG, " %s", (cinfo.progressive_mode ? "progressive" : "baseline"));
677 gd_error_ex(GD_DEBUG, " image, %d quantized colors, ", cinfo.actual_number_of_colors);
678
679 switch(cinfo.jpeg_color_space) {
680 case JCS_GRAYSCALE:
681 gd_error_ex(GD_DEBUG, "grayscale");
682 break;
683
684 case JCS_RGB:
685 gd_error_ex(GD_DEBUG, "RGB");
686 break;
687
688 case JCS_YCbCr:
689 gd_error_ex(GD_DEBUG, "YCbCr (a.k.a. YUV)");
690 break;
691
692 case JCS_CMYK:
693 gd_error_ex(GD_DEBUG, "CMYK");
694 break;
695
696 case JCS_YCCK:
697 gd_error_ex(GD_DEBUG, "YCbCrK");
698 break;
699
700 default:
701 gd_error_ex(GD_DEBUG, "UNKNOWN (value: %d)", (int)cinfo.jpeg_color_space);
702 break;
703 }
704
705 gd_error_ex(GD_DEBUG, " colorspace\n");
706 fflush(stdout);
707 #endif /* JPEG_DEBUG */
708
709 /* REMOVED by TBB 2/12/01. This field of the structure is
710 * documented as private, and sure enough it's gone in the
711 * latest libjpeg, replaced by something else. Unfortunately
712 * there is still no right way to find out if the file was
713 * progressive or not; just declare your intent before you
714 * write one by calling gdImageInterlace(im, 1) yourself.
715 * After all, we're not really supposed to rework JPEGs and
716 * write them out again anyway. Lossy compression, remember? */
717 #if 0
718 gdImageInterlace (im, cinfo.progressive_mode != 0);
719 #endif
720 if(cinfo.out_color_space == JCS_RGB) {
721 if(cinfo.output_components != 3) {
722 gd_error("gd-jpeg: error: JPEG color quantization"
723 " request resulted in output_components == %d"
724 " (expected 3 for RGB)\n", cinfo.output_components);
725 goto error;
726 }
727 channels = 3;
728 } else if(cinfo.out_color_space == JCS_CMYK) {
729 jpeg_saved_marker_ptr marker;
730 if(cinfo.output_components != 4) {
731 gd_error("gd-jpeg: error: JPEG color quantization"
732 " request resulted in output_components == %d"
733 " (expected 4 for CMYK)\n", cinfo.output_components);
734 goto error;
735 }
736 channels = 4;
737
738 marker = cinfo.marker_list;
739 while(marker) {
740 if( (marker->marker == (JPEG_APP0 + 14)) &&
741 (marker->data_length >= 12) &&
742 (!strncmp((const char *)marker->data, "Adobe", 5))) {
743 inverted = 1;
744 break;
745 }
746 marker = marker->next;
747 }
748 } else {
749 gd_error("gd-jpeg: error: unexpected colorspace\n");
750 goto error;
751 }
752 #if BITS_IN_JSAMPLE == 12
753 gd_error_ex(GD_ERROR,
754 "gd-jpeg: error: jpeg library was compiled for 12-bit\n"
755 "precision. This is mostly useless, because JPEGs on the web are\n"
756 "8-bit and such versions of the jpeg library won't read or write\n"
757 "them. GD doesn't support these unusual images. Edit your\n"
758 "jmorecfg.h file to specify the correct precision and completely\n"
759 "'make clean' and 'make install' libjpeg again. Sorry.\n");
760 goto error;
761 #endif /* BITS_IN_JSAMPLE == 12 */
762
763 row = gdCalloc(cinfo.output_width *channels, sizeof(JSAMPLE));
764 if(row == 0) {
765 gd_error("gd-jpeg: error: unable to allocate row for"
766 " JPEG scanline: gdCalloc returns NULL\n");
767 goto error;
768 }
769 rowptr[0] = row;
770 if(cinfo.out_color_space == JCS_CMYK) {
771 for(i = 0; i < cinfo.output_height; i++) {
772 register JSAMPROW currow = row;
773 register int *tpix = im->tpixels[i];
774 nrows = jpeg_read_scanlines(&cinfo, rowptr, 1);
775 if(nrows != 1) {
776 gd_error("gd-jpeg: error: jpeg_read_scanlines"
777 " returns %u, expected 1\n", nrows);
778 goto error;
779 }
780 for(j = 0; j < cinfo.output_width; j++, currow += 4, tpix++) {
781 *tpix = CMYKToRGB(currow[0], currow[1], currow[2], currow[3], inverted);
782 }
783 }
784 } else {
785 for(i = 0; i < cinfo.output_height; i++) {
786 register JSAMPROW currow = row;
787 register int *tpix = im->tpixels[i];
788 nrows = jpeg_read_scanlines(&cinfo, rowptr, 1);
789 if(nrows != 1) {
790 gd_error("gd-jpeg: error: jpeg_read_scanlines"
791 " returns %u, expected 1\n", nrows);
792 goto error;
793 }
794 for(j = 0; j < cinfo.output_width; j++, currow += 3, tpix++) {
795 *tpix = gdTrueColor(currow[0], currow[1], currow[2]);
796 }
797 }
798 }
799
800 if(jpeg_finish_decompress (&cinfo) != TRUE) {
801 gd_error("gd-jpeg: warning: jpeg_finish_decompress"
802 " reports suspended data source\n");
803 }
804 /* TBB 2.0.29: we should do our best to read whatever we can read, and a
805 * warning is a warning. A fatal error on warnings doesn't make sense. */
806 #if 0
807 /* This was originally added by Truxton Fulton */
808 if (cinfo.err->num_warnings > 0)
809 goto error;
810 #endif
811
812 jpeg_destroy_decompress(&cinfo);
813 gdFree(row);
814 return im;
815
816 error:
817 jpeg_destroy_decompress(&cinfo);
818
819 if(row) {
820 gdFree(row);
821 }
822 if(im) {
823 gdImageDestroy(im);
824 }
825
826 return 0;
827 }
828
829 /* A very basic conversion approach, TBB */
830
CMYKToRGB(int c,int m,int y,int k,int inverted)831 static int CMYKToRGB(int c, int m, int y, int k, int inverted)
832 {
833 if(inverted) {
834 c = 255 - c;
835 m = 255 - m;
836 y = 255 - y;
837 k = 255 - k;
838 }
839
840 return gdTrueColor(
841 (255 - c) * (255 - k) / 255,
842 (255 - m) * (255 - k) / 255,
843 (255 - y) * (255 - k) / 255
844 );
845 #if 0
846 if (inverted) {
847 c = 255 - c;
848 m = 255 - m;
849 y = 255 - y;
850 k = 255 - k;
851 }
852 c = c * (255 - k) / 255 + k;
853 if (c > 255) {
854 c = 255;
855 }
856 if (c < 0) {
857 c = 0;
858 }
859 m = m * (255 - k) / 255 + k;
860 if (m > 255) {
861 m = 255;
862 }
863 if (m < 0) {
864 m = 0;
865 }
866 y = y * (255 - k) / 255 + k;
867 if (y > 255) {
868 y = 255;
869 }
870 if (y < 0) {
871 y = 0;
872 }
873 c = 255 - c;
874 m = 255 - m;
875 y = 255 - y;
876 return gdTrueColor (c, m, y);
877 #endif
878 }
879
880 /*
881 * gdIOCtx JPEG data sources and sinks, T. Boutell
882 * almost a simple global replace from T. Lane's stdio versions.
883 */
884
885 /* Expanded data source object for gdIOCtx input */
886 typedef struct {
887 struct jpeg_source_mgr pub; /* public fields */
888 gdIOCtx *infile; /* source stream */
889 unsigned char *buffer; /* start of buffer */
890 boolean start_of_file; /* have we gotten any data yet? */
891 }
892 my_source_mgr;
893
894 typedef my_source_mgr *my_src_ptr;
895
896 #define INPUT_BUF_SIZE 4096 /* choose an efficiently fread'able size */
897
898 /*
899 * Initialize source --- called by jpeg_read_header
900 * before any data is actually read.
901 */
902
init_source(j_decompress_ptr cinfo)903 void init_source(j_decompress_ptr cinfo)
904 {
905 my_src_ptr src = (my_src_ptr)cinfo->src;
906
907 /* We reset the empty-input-file flag for each image,
908 * but we don't clear the input buffer.
909 * This is correct behavior for reading a series of images from one source.
910 */
911 src->start_of_file = TRUE;
912 }
913
914
915 /*
916 * Fill the input buffer --- called whenever buffer is emptied.
917 *
918 * In typical applications, this should read fresh data into the buffer
919 * (ignoring the current state of next_input_byte & bytes_in_buffer),
920 * reset the pointer & count to the start of the buffer, and return TRUE
921 * indicating that the buffer has been reloaded. It is not necessary to
922 * fill the buffer entirely, only to obtain at least one more byte.
923 *
924 * There is no such thing as an EOF return. If the end of the file has been
925 * reached, the routine has a choice of ERREXIT() or inserting fake data into
926 * the buffer. In most cases, generating a warning message and inserting a
927 * fake EOI marker is the best course of action --- this will allow the
928 * decompressor to output however much of the image is there. However,
929 * the resulting error message is misleading if the real problem is an empty
930 * input file, so we handle that case specially.
931 *
932 * In applications that need to be able to suspend compression due to input
933 * not being available yet, a FALSE return indicates that no more data can be
934 * obtained right now, but more may be forthcoming later. In this situation,
935 * the decompressor will return to its caller (with an indication of the
936 * number of scanlines it has read, if any). The application should resume
937 * decompression after it has loaded more data into the input buffer. Note
938 * that there are substantial restrictions on the use of suspension --- see
939 * the documentation.
940 *
941 * When suspending, the decompressor will back up to a convenient restart point
942 * (typically the start of the current MCU). next_input_byte & bytes_in_buffer
943 * indicate where the restart point will be if the current call returns FALSE.
944 * Data beyond this point must be rescanned after resumption, so move it to
945 * the front of the buffer rather than discarding it.
946 */
947
948 #define END_JPEG_SEQUENCE "\r\n[*]--:END JPEG:--[*]\r\n"
949
fill_input_buffer(j_decompress_ptr cinfo)950 boolean fill_input_buffer(j_decompress_ptr cinfo)
951 {
952 my_src_ptr src = (my_src_ptr)cinfo->src;
953 /* 2.0.12: signed size. Thanks to Geert Jansen */
954 /* 2.0.14: some platforms (mingw-msys) don't have ssize_t. Call
955 * an int an int.
956 */
957 int nbytes = 0;
958 memset(src->buffer, 0, INPUT_BUF_SIZE);
959
960 while(nbytes < INPUT_BUF_SIZE) {
961 int got = gdGetBuf(src->buffer + nbytes, INPUT_BUF_SIZE - nbytes, src->infile);
962
963 if((got == EOF) || (got == 0)) {
964 /* EOF or error. If we got any data, don't worry about it.
965 * If we didn't, then this is unexpected. */
966 if(!nbytes) {
967 nbytes = -1;
968 }
969 break;
970 }
971 nbytes += got;
972 }
973
974 if(nbytes <= 0) {
975 if(src->start_of_file) {
976 /* Treat empty input file as fatal error */
977 ERREXIT(cinfo, JERR_INPUT_EMPTY);
978 }
979 WARNMS(cinfo, JWRN_JPEG_EOF);
980 /* Insert a fake EOI marker */
981 src->buffer[0] = (unsigned char)0xFF;
982 src->buffer[1] = (unsigned char)JPEG_EOI;
983 nbytes = 2;
984 }
985
986 src->pub.next_input_byte = src->buffer;
987 src->pub.bytes_in_buffer = nbytes;
988 src->start_of_file = FALSE;
989
990 return TRUE;
991 }
992
993 /*
994 * Skip data --- used to skip over a potentially large amount of
995 * uninteresting data (such as an APPn marker).
996 *
997 * Writers of suspendable-input applications must note that skip_input_data
998 * is not granted the right to give a suspension return. If the skip extends
999 * beyond the data currently in the buffer, the buffer can be marked empty so
1000 * that the next read will cause a fill_input_buffer call that can suspend.
1001 * Arranging for additional bytes to be discarded before reloading the input
1002 * buffer is the application writer's problem.
1003 */
1004
skip_input_data(j_decompress_ptr cinfo,long num_bytes)1005 void skip_input_data(j_decompress_ptr cinfo, long num_bytes)
1006 {
1007 my_src_ptr src = (my_src_ptr)cinfo->src;
1008
1009 /* Just a dumb implementation for now. Not clear that being smart is worth
1010 * any trouble anyway --- large skips are infrequent.
1011 */
1012 if(num_bytes > 0) {
1013 while(num_bytes > (long)src->pub.bytes_in_buffer) {
1014 num_bytes -= (long)src->pub.bytes_in_buffer;
1015 (void)fill_input_buffer(cinfo);
1016 /* note we assume that fill_input_buffer will never return FALSE,
1017 * so suspension need not be handled.
1018 */
1019 }
1020 src->pub.next_input_byte += (size_t)num_bytes;
1021 src->pub.bytes_in_buffer -= (size_t)num_bytes;
1022 }
1023 }
1024
1025 /*
1026 * An additional method that can be provided by data source modules is the
1027 * resync_to_restart method for error recovery in the presence of RST markers.
1028 * For the moment, this source module just uses the default resync method
1029 * provided by the JPEG library. That method assumes that no backtracking
1030 * is possible.
1031 */
1032
1033 /*
1034 * Terminate source --- called by jpeg_finish_decompress
1035 * after all data has been read. Often a no-op.
1036 *
1037 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
1038 * application must deal with any cleanup that should happen even
1039 * for error exit.
1040 */
term_source(j_decompress_ptr cinfo)1041 void term_source(j_decompress_ptr cinfo)
1042 {
1043 (void)cinfo;
1044 }
1045
1046
1047 /*
1048 * Prepare for input from a gdIOCtx stream.
1049 * The caller must have already opened the stream, and is responsible
1050 * for closing it after finishing decompression.
1051 */
1052
jpeg_gdIOCtx_src(j_decompress_ptr cinfo,gdIOCtx * infile)1053 void jpeg_gdIOCtx_src(j_decompress_ptr cinfo, gdIOCtx *infile)
1054 {
1055 my_src_ptr src;
1056
1057 /* The source object and input buffer are made permanent so that a series
1058 * of JPEG images can be read from the same file by calling jpeg_gdIOCtx_src
1059 * only before the first one. (If we discarded the buffer at the end of
1060 * one image, we'd likely lose the start of the next one.)
1061 * This makes it unsafe to use this manager and a different source
1062 * manager serially with the same JPEG object. Caveat programmer.
1063 */
1064 if(cinfo->src == NULL) {
1065 /* first time for this JPEG object? */
1066 cinfo->src = (struct jpeg_source_mgr *)
1067 (*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_PERMANENT,
1068 sizeof(my_source_mgr));
1069 src = (my_src_ptr)cinfo->src;
1070 src->buffer = (unsigned char *)
1071 (*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_PERMANENT,
1072 INPUT_BUF_SIZE * sizeof(unsigned char));
1073 }
1074
1075 src = (my_src_ptr)cinfo->src;
1076 src->pub.init_source = init_source;
1077 src->pub.fill_input_buffer = fill_input_buffer;
1078 src->pub.skip_input_data = skip_input_data;
1079 src->pub.resync_to_restart = jpeg_resync_to_restart; /* use default method */
1080 src->pub.term_source = term_source;
1081 src->infile = infile;
1082 src->pub.bytes_in_buffer = 0; /* forces fill_input_buffer on first read */
1083 src->pub.next_input_byte = NULL; /* until buffer loaded */
1084 }
1085
1086 /* Expanded data destination object for stdio output */
1087 typedef struct {
1088 struct jpeg_destination_mgr pub; /* public fields */
1089 gdIOCtx *outfile; /* target stream */
1090 unsigned char *buffer; /* start of buffer */
1091 }
1092 my_destination_mgr;
1093
1094 typedef my_destination_mgr *my_dest_ptr;
1095
1096 #define OUTPUT_BUF_SIZE 4096 /* choose an efficiently fwrite'able size */
1097
1098 /*
1099 * Initialize destination --- called by jpeg_start_compress
1100 * before any data is actually written.
1101 */
1102
init_destination(j_compress_ptr cinfo)1103 void init_destination(j_compress_ptr cinfo)
1104 {
1105 my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
1106
1107 /* Allocate the output buffer --- it will be released when done with image */
1108 dest->buffer = (unsigned char *)
1109 (*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_IMAGE,
1110 OUTPUT_BUF_SIZE * sizeof(unsigned char));
1111
1112 dest->pub.next_output_byte = dest->buffer;
1113 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
1114 }
1115
1116
1117 /*
1118 * Empty the output buffer --- called whenever buffer fills up.
1119 *
1120 * In typical applications, this should write the entire output buffer
1121 * (ignoring the current state of next_output_byte & free_in_buffer),
1122 * reset the pointer & count to the start of the buffer, and return TRUE
1123 * indicating that the buffer has been dumped.
1124 *
1125 * In applications that need to be able to suspend compression due to output
1126 * overrun, a FALSE return indicates that the buffer cannot be emptied now.
1127 * In this situation, the compressor will return to its caller (possibly with
1128 * an indication that it has not accepted all the supplied scanlines). The
1129 * application should resume compression after it has made more room in the
1130 * output buffer. Note that there are substantial restrictions on the use of
1131 * suspension --- see the documentation.
1132 *
1133 * When suspending, the compressor will back up to a convenient restart point
1134 * (typically the start of the current MCU). next_output_byte & free_in_buffer
1135 * indicate where the restart point will be if the current call returns FALSE.
1136 * Data beyond this point will be regenerated after resumption, so do not
1137 * write it out when emptying the buffer externally.
1138 */
1139
empty_output_buffer(j_compress_ptr cinfo)1140 boolean empty_output_buffer(j_compress_ptr cinfo)
1141 {
1142 my_dest_ptr dest = (my_dest_ptr)cinfo->dest;
1143
1144 if(gdPutBuf(dest->buffer, OUTPUT_BUF_SIZE, dest->outfile) != (size_t)OUTPUT_BUF_SIZE) {
1145 ERREXIT(cinfo, JERR_FILE_WRITE);
1146 }
1147
1148 dest->pub.next_output_byte = dest->buffer;
1149 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
1150
1151 return TRUE;
1152 }
1153
1154
1155 /*
1156 * Terminate destination --- called by jpeg_finish_compress
1157 * after all data has been written. Usually needs to flush buffer.
1158 *
1159 * NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
1160 * application must deal with any cleanup that should happen even
1161 * for error exit.
1162 */
1163
term_destination(j_compress_ptr cinfo)1164 void term_destination(j_compress_ptr cinfo)
1165 {
1166 my_dest_ptr dest = (my_dest_ptr) cinfo->dest;
1167 int datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
1168
1169 /* Write any data remaining in the buffer */
1170 if(datacount > 0) {
1171 if(gdPutBuf(dest->buffer, datacount, dest->outfile) != datacount) {
1172 ERREXIT(cinfo, JERR_FILE_WRITE);
1173 }
1174 }
1175 }
1176
1177 /*
1178 * Prepare for output to a stdio stream.
1179 * The caller must have already opened the stream, and is responsible
1180 * for closing it after finishing compression.
1181 */
1182
jpeg_gdIOCtx_dest(j_compress_ptr cinfo,gdIOCtx * outfile)1183 void jpeg_gdIOCtx_dest(j_compress_ptr cinfo, gdIOCtx *outfile)
1184 {
1185 my_dest_ptr dest;
1186
1187 /* The destination object is made permanent so that multiple JPEG images
1188 * can be written to the same file without re-executing jpeg_stdio_dest.
1189 * This makes it dangerous to use this manager and a different destination
1190 * manager serially with the same JPEG object, because their private object
1191 * sizes may be different. Caveat programmer.
1192 */
1193 if(cinfo->dest == NULL) {
1194 /* first time for this JPEG object? */
1195 cinfo->dest = (struct jpeg_destination_mgr *)
1196 (*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_PERMANENT,
1197 sizeof(my_destination_mgr));
1198 }
1199
1200 dest = (my_dest_ptr)cinfo->dest;
1201 dest->pub.init_destination = init_destination;
1202 dest->pub.empty_output_buffer = empty_output_buffer;
1203 dest->pub.term_destination = term_destination;
1204 dest->outfile = outfile;
1205 }
1206
1207 #else /* !HAVE_LIBJPEG */
1208
_noJpegError(void)1209 static void _noJpegError(void)
1210 {
1211 gd_error("JPEG image support has been disabled\n");
1212 }
1213
gdImageJpeg(gdImagePtr im,FILE * outFile,int quality)1214 BGD_DECLARE(void) gdImageJpeg(gdImagePtr im, FILE *outFile, int quality)
1215 {
1216 _noJpegError();
1217 }
1218
gdImageJpegPtr(gdImagePtr im,int * size,int quality)1219 BGD_DECLARE(void *) gdImageJpegPtr(gdImagePtr im, int *size, int quality)
1220 {
1221 _noJpegError();
1222 return NULL;
1223 }
1224
gdImageJpegCtx(gdImagePtr im,gdIOCtx * outfile,int quality)1225 BGD_DECLARE(void) gdImageJpegCtx(gdImagePtr im, gdIOCtx *outfile, int quality)
1226 {
1227 _noJpegError();
1228 }
1229
gdImageCreateFromJpeg(FILE * inFile)1230 BGD_DECLARE(gdImagePtr) gdImageCreateFromJpeg(FILE *inFile)
1231 {
1232 _noJpegError();
1233 return NULL;
1234 }
1235
gdImageCreateFromJpegEx(FILE * inFile,int ignore_warning)1236 BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegEx(FILE *inFile, int ignore_warning)
1237 {
1238 _noJpegError();
1239 return NULL;
1240 }
1241
gdImageCreateFromJpegPtr(int size,void * data)1242 BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegPtr(int size, void *data)
1243 {
1244 _noJpegError();
1245 return NULL;
1246 }
1247
gdImageCreateFromJpegPtrEx(int size,void * data,int ignore_warning)1248 BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegPtrEx(int size, void *data, int ignore_warning)
1249 {
1250 _noJpegError();
1251 return NULL;
1252 }
1253
gdImageCreateFromJpegCtx(gdIOCtx * infile)1254 BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegCtx(gdIOCtx *infile)
1255 {
1256 _noJpegError();
1257 return NULL;
1258 }
1259
gdImageCreateFromJpegCtxEx(gdIOCtx * infile,int ignore_warning)1260 BGD_DECLARE(gdImagePtr) gdImageCreateFromJpegCtxEx(gdIOCtx *infile, int ignore_warning)
1261 {
1262 _noJpegError();
1263 return NULL;
1264 }
1265
1266 #endif /* HAVE_LIBJPEG */
1267