]> git.ipfire.org Git - thirdparty/cups.git/blob - filter/image-jpeg.c
Load cups into easysw/current.
[thirdparty/cups.git] / filter / image-jpeg.c
1 /*
2 * "$Id: image-jpeg.c 6649 2007-07-11 21:46:42Z mike $"
3 *
4 * JPEG image routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 2007 by Apple Inc.
7 * Copyright 1993-2007 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
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/".
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
36 int /* 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 */
50 char header[16]; /* Photoshop JPEG header */
51 int psjpeg; /* Non-zero if Photoshop JPEG */
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
63 /*
64 * Read the first 16 bytes to determine if this is a Photoshop JPEG file...
65 */
66
67 fread(header, sizeof(header), 1, fp);
68 rewind(fp);
69
70 psjpeg = memcmp(header + 6, "Photoshop ", 10) == 0;
71
72 /*
73 * Read the JPEG header...
74 */
75
76 cinfo.err = jpeg_std_error(&jerr);
77 jpeg_create_decompress(&cinfo);
78 jpeg_stdio_src(&cinfo, fp);
79 jpeg_read_header(&cinfo, 1);
80
81 cinfo.quantize_colors = 0;
82
83 fprintf(stderr, "DEBUG: num_components = %d\n", cinfo.num_components);
84 fprintf(stderr, "DEBUG: jpeg_color_space = %s\n",
85 cspaces[cinfo.jpeg_color_space]);
86
87 if (cinfo.num_components == 1)
88 {
89 fputs("DEBUG: Converting image to grayscale...\n", stderr);
90
91 cinfo.out_color_space = JCS_GRAYSCALE;
92 cinfo.out_color_components = 1;
93 cinfo.output_components = 1;
94
95 img->colorspace = secondary;
96 }
97 else if (cinfo.num_components == 4)
98 {
99 fputs("DEBUG: Converting image to CMYK...\n", stderr);
100
101 cinfo.out_color_space = JCS_CMYK;
102 cinfo.out_color_components = 4;
103 cinfo.output_components = 4;
104
105 img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_CMYK : primary;
106 }
107 else
108 {
109 fputs("DEBUG: Converting image to RGB...\n", stderr);
110
111 cinfo.out_color_space = JCS_RGB;
112 cinfo.out_color_components = 3;
113 cinfo.output_components = 3;
114
115 img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB : primary;
116 }
117
118 jpeg_calc_output_dimensions(&cinfo);
119
120 if (cinfo.output_width <= 0 || cinfo.output_width > CUPS_IMAGE_MAX_WIDTH ||
121 cinfo.output_height <= 0 || cinfo.output_height > CUPS_IMAGE_MAX_HEIGHT)
122 {
123 fprintf(stderr, "DEBUG: Bad JPEG dimensions %dx%d!\n",
124 cinfo.output_width, cinfo.output_height);
125
126 jpeg_destroy_decompress(&cinfo);
127
128 fclose(fp);
129 return (1);
130 }
131
132 img->xsize = cinfo.output_width;
133 img->ysize = cinfo.output_height;
134
135 if (cinfo.X_density > 0 && cinfo.Y_density > 0 && cinfo.density_unit > 0)
136 {
137 if (cinfo.density_unit == 1)
138 {
139 img->xppi = cinfo.X_density;
140 img->yppi = cinfo.Y_density;
141 }
142 else
143 {
144 img->xppi = (int)((float)cinfo.X_density * 2.54);
145 img->yppi = (int)((float)cinfo.Y_density * 2.54);
146 }
147
148 if (img->xppi == 0 || img->yppi == 0)
149 {
150 fprintf(stderr, "DEBUG: Bad JPEG image resolution %dx%d PPI.\n",
151 img->xppi, img->yppi);
152 img->xppi = img->yppi = 128;
153 }
154 }
155
156 fprintf(stderr, "DEBUG: JPEG image %dx%dx%d, %dx%d PPI\n",
157 img->xsize, img->ysize, cinfo.output_components,
158 img->xppi, img->yppi);
159
160 cupsImageSetMaxTiles(img, 0);
161
162 in = malloc(img->xsize * cinfo.output_components);
163 out = malloc(img->xsize * cupsImageGetDepth(img));
164
165 jpeg_start_decompress(&cinfo);
166
167 while (cinfo.output_scanline < cinfo.output_height)
168 {
169 jpeg_read_scanlines(&cinfo, (JSAMPROW *)&in, (JDIMENSION)1);
170
171 if (psjpeg && cinfo.output_components == 4)
172 {
173 /*
174 * Invert CMYK data from Photoshop...
175 */
176
177 cups_ib_t *ptr; /* Pointer into buffer */
178 int i; /* Looping var */
179
180
181 for (ptr = in, i = img->xsize * 4; i > 0; i --, ptr ++)
182 *ptr = 255 - *ptr;
183 }
184
185 if ((saturation != 100 || hue != 0) && cinfo.output_components == 3)
186 cupsImageRGBAdjust(in, img->xsize, saturation, hue);
187
188 if ((img->colorspace == CUPS_IMAGE_WHITE && cinfo.out_color_space == JCS_GRAYSCALE) ||
189 (img->colorspace == CUPS_IMAGE_CMYK && cinfo.out_color_space == JCS_CMYK))
190 {
191 #ifdef DEBUG
192 int i, j;
193 cups_ib_t *ptr;
194
195
196 fputs("DEBUG: Direct Data...\n", stderr);
197
198 fputs("DEBUG:", stderr);
199
200 for (i = 0, ptr = in; i < img->xsize; i ++)
201 {
202 putc(' ', stderr);
203 for (j = 0; j < cinfo.output_components; j ++, ptr ++)
204 fprintf(stderr, "%02X", *ptr & 255);
205 }
206
207 putc('\n', stderr);
208 #endif /* DEBUG */
209
210 if (lut)
211 cupsImageLut(in, img->xsize * cupsImageGetDepth(img), lut);
212
213 _cupsImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, in);
214 }
215 else if (cinfo.out_color_space == JCS_GRAYSCALE)
216 {
217 switch (img->colorspace)
218 {
219 default :
220 break;
221
222 case CUPS_IMAGE_BLACK :
223 cupsImageWhiteToBlack(in, out, img->xsize);
224 break;
225 case CUPS_IMAGE_RGB :
226 cupsImageWhiteToRGB(in, out, img->xsize);
227 break;
228 case CUPS_IMAGE_CMY :
229 cupsImageWhiteToCMY(in, out, img->xsize);
230 break;
231 case CUPS_IMAGE_CMYK :
232 cupsImageWhiteToCMYK(in, out, img->xsize);
233 break;
234 }
235
236 if (lut)
237 cupsImageLut(out, img->xsize * cupsImageGetDepth(img), lut);
238
239 _cupsImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, out);
240 }
241 else if (cinfo.out_color_space == JCS_RGB)
242 {
243 switch (img->colorspace)
244 {
245 default :
246 break;
247
248 case CUPS_IMAGE_RGB :
249 cupsImageRGBToRGB(in, out, img->xsize);
250 break;
251 case CUPS_IMAGE_WHITE :
252 cupsImageRGBToWhite(in, out, img->xsize);
253 break;
254 case CUPS_IMAGE_BLACK :
255 cupsImageRGBToBlack(in, out, img->xsize);
256 break;
257 case CUPS_IMAGE_CMY :
258 cupsImageRGBToCMY(in, out, img->xsize);
259 break;
260 case CUPS_IMAGE_CMYK :
261 cupsImageRGBToCMYK(in, out, img->xsize);
262 break;
263 }
264
265 if (lut)
266 cupsImageLut(out, img->xsize * cupsImageGetDepth(img), lut);
267
268 _cupsImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, out);
269 }
270 else /* JCS_CMYK */
271 {
272 fputs("DEBUG: JCS_CMYK\n", stderr);
273
274 switch (img->colorspace)
275 {
276 default :
277 break;
278
279 case CUPS_IMAGE_WHITE :
280 cupsImageCMYKToWhite(in, out, img->xsize);
281 break;
282 case CUPS_IMAGE_BLACK :
283 cupsImageCMYKToBlack(in, out, img->xsize);
284 break;
285 case CUPS_IMAGE_CMY :
286 cupsImageCMYKToCMY(in, out, img->xsize);
287 break;
288 case CUPS_IMAGE_RGB :
289 cupsImageCMYKToRGB(in, out, img->xsize);
290 break;
291 }
292
293 if (lut)
294 cupsImageLut(out, img->xsize * cupsImageGetDepth(img), lut);
295
296 _cupsImagePutRow(img, 0, cinfo.output_scanline - 1, img->xsize, out);
297 }
298 }
299
300 free(in);
301 free(out);
302
303 jpeg_finish_decompress(&cinfo);
304 jpeg_destroy_decompress(&cinfo);
305
306 fclose(fp);
307
308 return (0);
309 }
310 #endif /* HAVE_LIBJPEG */
311
312
313 /*
314 * End of "$Id: image-jpeg.c 6649 2007-07-11 21:46:42Z mike $".
315 */