]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/image-jpeg.c
Import CUPS 1.4svn-r7356.
[thirdparty/cups.git] / filter / image-jpeg.c
CommitLineData
ef416fc2 1/*
bc44d920 2 * "$Id: image-jpeg.c 6649 2007-07-11 21:46:42Z mike $"
ef416fc2 3 *
4 * JPEG image routines for the Common UNIX Printing System (CUPS).
5 *
bc44d920 6 * Copyright 2007 by Apple Inc.
c0e1af83 7 * Copyright 1993-2007 by Easy Software Products.
ef416fc2 8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 14 *
15 * This file is subject to the Apple OS-Developed Software exception.
16 *
17 * Contents:
18 *
19 * _cupsImageReadJPEG() - Read a JPEG image file.
20 */
21
22/*
23 * Include necessary headers...
24 */
25
26#include "image-private.h"
27
28#ifdef HAVE_LIBJPEG
29# include <jpeglib.h> /* JPEG/JFIF image definitions */
30
31
32/*
33 * '_cupsImageReadJPEG()' - Read a JPEG image file.
34 */
35
36int /* O - Read status */
37_cupsImageReadJPEG(
38 cups_image_t *img, /* IO - cupsImage */
39 FILE *fp, /* I - cupsImage file */
40 cups_icspace_t primary, /* I - Primary choice for colorspace */
41 cups_icspace_t secondary, /* I - Secondary choice for colorspace */
42 int saturation, /* I - Color saturation (%) */
43 int hue, /* I - Color hue (degrees) */
44 const cups_ib_t *lut) /* I - Lookup table for gamma/brightness */
45{
46 struct jpeg_decompress_struct cinfo; /* Decompressor info */
47 struct jpeg_error_mgr jerr; /* Error handler info */
48 cups_ib_t *in, /* Input pixels */
49 *out; /* Output pixels */
568fa3fa
MS
50 jpeg_saved_marker_ptr marker; /* Pointer to marker data */
51 int psjpeg = 0; /* Non-zero if Photoshop CMYK JPEG */
ef416fc2 52 static const char *cspaces[] =
53 { /* JPEG colorspaces... */
54 "JCS_UNKNOWN",
55 "JCS_GRAYSCALE",
56 "JCS_RGB",
57 "JCS_YCbCr",
58 "JCS_CMYK",
59 "JCS_YCCK"
60 };
61
62
ef416fc2 63 /*
64 * Read the JPEG header...
65 */
66
67 cinfo.err = jpeg_std_error(&jerr);
68 jpeg_create_decompress(&cinfo);
568fa3fa 69 jpeg_save_markers(&cinfo, JPEG_APP0 + 14, 0xffff); /* Adobe JPEG */
ef416fc2 70 jpeg_stdio_src(&cinfo, fp);
71 jpeg_read_header(&cinfo, 1);
72
568fa3fa
MS
73 /*
74 * Parse any Adobe APPE data embedded in the JPEG file. Since Adobe doesn't
75 * bother following standards, we have to invert the CMYK JPEG data written by
76 * Adobe apps...
77 */
78
79 for (marker = cinfo.marker_list; marker; marker = marker->next)
80 if (marker->marker == (JPEG_APP0 + 14) && marker->data_length >= 12 &&
81 !memcmp(marker->data, "Adobe", 5) && marker->data[11] == 2)
82 {
83 fputs("DEBUG: Adobe CMYK JPEG detected (inverting color values)\n",
84 stderr);
85 psjpeg = 1;
86 }
87
ef416fc2 88 cinfo.quantize_colors = 0;
89
90 fprintf(stderr, "DEBUG: num_components = %d\n", cinfo.num_components);
91 fprintf(stderr, "DEBUG: jpeg_color_space = %s\n",
92 cspaces[cinfo.jpeg_color_space]);
93
94 if (cinfo.num_components == 1)
95 {
96 fputs("DEBUG: Converting image to grayscale...\n", stderr);
97
98 cinfo.out_color_space = JCS_GRAYSCALE;
99 cinfo.out_color_components = 1;
100 cinfo.output_components = 1;
101
102 img->colorspace = secondary;
103 }
104 else if (cinfo.num_components == 4)
105 {
106 fputs("DEBUG: Converting image to CMYK...\n", stderr);
107
108 cinfo.out_color_space = JCS_CMYK;
109 cinfo.out_color_components = 4;
110 cinfo.output_components = 4;
111
112 img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_CMYK : primary;
113 }
114 else
115 {
116 fputs("DEBUG: Converting image to RGB...\n", stderr);
117
118 cinfo.out_color_space = JCS_RGB;
119 cinfo.out_color_components = 3;
120 cinfo.output_components = 3;
121
122 img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB : primary;
123 }
124
125 jpeg_calc_output_dimensions(&cinfo);
126
127 if (cinfo.output_width <= 0 || cinfo.output_width > CUPS_IMAGE_MAX_WIDTH ||
128 cinfo.output_height <= 0 || cinfo.output_height > CUPS_IMAGE_MAX_HEIGHT)
129 {
c0e1af83 130 fprintf(stderr, "DEBUG: Bad JPEG dimensions %dx%d!\n",
ef416fc2 131 cinfo.output_width, cinfo.output_height);
132
133 jpeg_destroy_decompress(&cinfo);
134
135 fclose(fp);
136 return (1);
137 }
138
139 img->xsize = cinfo.output_width;
140 img->ysize = cinfo.output_height;
141
142 if (cinfo.X_density > 0 && cinfo.Y_density > 0 && cinfo.density_unit > 0)
143 {
144 if (cinfo.density_unit == 1)
145 {
146 img->xppi = cinfo.X_density;
147 img->yppi = cinfo.Y_density;
148 }
149 else
150 {
151 img->xppi = (int)((float)cinfo.X_density * 2.54);
152 img->yppi = (int)((float)cinfo.Y_density * 2.54);
153 }
154
155 if (img->xppi == 0 || img->yppi == 0)
156 {
c0e1af83 157 fprintf(stderr, "DEBUG: Bad JPEG image resolution %dx%d PPI.\n",
ef416fc2 158 img->xppi, img->yppi);
159 img->xppi = img->yppi = 128;
160 }
161 }
162
163 fprintf(stderr, "DEBUG: JPEG image %dx%dx%d, %dx%d PPI\n",
164 img->xsize, img->ysize, cinfo.output_components,
165 img->xppi, img->yppi);
166
167 cupsImageSetMaxTiles(img, 0);
168
169 in = malloc(img->xsize * cinfo.output_components);
170 out = malloc(img->xsize * cupsImageGetDepth(img));
171
172 jpeg_start_decompress(&cinfo);
173
174 while (cinfo.output_scanline < cinfo.output_height)
175 {
176 jpeg_read_scanlines(&cinfo, (JSAMPROW *)&in, (JDIMENSION)1);
177
178 if (psjpeg && cinfo.output_components == 4)
179 {
180 /*
181 * Invert CMYK data from Photoshop...
182 */
183
184 cups_ib_t *ptr; /* Pointer into buffer */
185 int i; /* Looping var */
186
187
188 for (ptr = in, i = img->xsize * 4; i > 0; i --, ptr ++)
189 *ptr = 255 - *ptr;
190 }
191
192 if ((saturation != 100 || hue != 0) && cinfo.output_components == 3)
193 cupsImageRGBAdjust(in, img->xsize, saturation, hue);
194
195 if ((img->colorspace == CUPS_IMAGE_WHITE && cinfo.out_color_space == JCS_GRAYSCALE) ||
ef416fc2 196 (img->colorspace == CUPS_IMAGE_CMYK && cinfo.out_color_space == JCS_CMYK))
197 {
198#ifdef DEBUG
199 int i, j;
200 cups_ib_t *ptr;
201
202
203 fputs("DEBUG: Direct Data...\n", stderr);
204
205 fputs("DEBUG:", stderr);
206
207 for (i = 0, ptr = in; i < img->xsize; i ++)
208 {
209 putc(' ', stderr);
210 for (j = 0; j < cinfo.output_components; j ++, ptr ++)
211 fprintf(stderr, "%02X", *ptr & 255);
212 }
213
214 putc('\n', stderr);
215#endif /* DEBUG */
216
217 if (lut)
218 cupsImageLut(in, img->xsize * cupsImageGetDepth(img), lut);
219
220 _cupsImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, in);
221 }
222 else if (cinfo.out_color_space == JCS_GRAYSCALE)
223 {
224 switch (img->colorspace)
225 {
226 default :
227 break;
228
229 case CUPS_IMAGE_BLACK :
230 cupsImageWhiteToBlack(in, out, img->xsize);
231 break;
232 case CUPS_IMAGE_RGB :
233 cupsImageWhiteToRGB(in, out, img->xsize);
234 break;
235 case CUPS_IMAGE_CMY :
236 cupsImageWhiteToCMY(in, out, img->xsize);
237 break;
238 case CUPS_IMAGE_CMYK :
239 cupsImageWhiteToCMYK(in, out, img->xsize);
240 break;
241 }
242
243 if (lut)
244 cupsImageLut(out, img->xsize * cupsImageGetDepth(img), lut);
245
246 _cupsImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, out);
247 }
248 else if (cinfo.out_color_space == JCS_RGB)
249 {
250 switch (img->colorspace)
251 {
252 default :
253 break;
254
f301802f 255 case CUPS_IMAGE_RGB :
256 cupsImageRGBToRGB(in, out, img->xsize);
257 break;
ef416fc2 258 case CUPS_IMAGE_WHITE :
259 cupsImageRGBToWhite(in, out, img->xsize);
260 break;
261 case CUPS_IMAGE_BLACK :
262 cupsImageRGBToBlack(in, out, img->xsize);
263 break;
264 case CUPS_IMAGE_CMY :
265 cupsImageRGBToCMY(in, out, img->xsize);
266 break;
267 case CUPS_IMAGE_CMYK :
268 cupsImageRGBToCMYK(in, out, img->xsize);
269 break;
270 }
271
272 if (lut)
273 cupsImageLut(out, img->xsize * cupsImageGetDepth(img), lut);
274
275 _cupsImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, out);
276 }
277 else /* JCS_CMYK */
278 {
279 fputs("DEBUG: JCS_CMYK\n", stderr);
280
281 switch (img->colorspace)
282 {
283 default :
284 break;
285
286 case CUPS_IMAGE_WHITE :
287 cupsImageCMYKToWhite(in, out, img->xsize);
288 break;
289 case CUPS_IMAGE_BLACK :
290 cupsImageCMYKToBlack(in, out, img->xsize);
291 break;
292 case CUPS_IMAGE_CMY :
293 cupsImageCMYKToCMY(in, out, img->xsize);
294 break;
295 case CUPS_IMAGE_RGB :
296 cupsImageCMYKToRGB(in, out, img->xsize);
297 break;
298 }
299
300 if (lut)
301 cupsImageLut(out, img->xsize * cupsImageGetDepth(img), lut);
302
303 _cupsImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, out);
304 }
305 }
306
307 free(in);
308 free(out);
309
310 jpeg_finish_decompress(&cinfo);
311 jpeg_destroy_decompress(&cinfo);
312
313 fclose(fp);
314
315 return (0);
316}
317#endif /* HAVE_LIBJPEG */
318
319
320/*
bc44d920 321 * End of "$Id: image-jpeg.c 6649 2007-07-11 21:46:42Z mike $".
ef416fc2 322 */