]> git.ipfire.org Git - thirdparty/cups.git/blob - filter/image-photocd.c
28ca201ee79c7f4ed5694941a00e884672eb3836
[thirdparty/cups.git] / filter / image-photocd.c
1 /*
2 * "$Id$"
3 *
4 * PhotoCD routines for the Common UNIX Printing System (CUPS).
5 *
6 * PhotoCD support is currently limited to the 768x512 base image, which
7 * is only YCC encoded. Support for the higher resolution images will
8 * require a lot of extra code...
9 *
10 * Copyright 1993-2006 by Easy Software Products.
11 *
12 * These coded instructions, statements, and computer programs are the
13 * property of Easy Software Products and are protected by Federal
14 * copyright law. Distribution and use rights are outlined in the file
15 * "LICENSE.txt" which should have been included with this file. If this
16 * file is missing or damaged please contact Easy Software Products
17 * at:
18 *
19 * Attn: CUPS Licensing Information
20 * Easy Software Products
21 * 44141 Airport View Drive, Suite 204
22 * Hollywood, Maryland 20636 USA
23 *
24 * Voice: (301) 373-9600
25 * EMail: cups-info@cups.org
26 * WWW: http://www.cups.org
27 *
28 * This file is subject to the Apple OS-Developed Software exception.
29 *
30 * Contents:
31 *
32 * _cupsImageReadPhotoCD() - Read a PhotoCD image file.
33 */
34
35 /*
36 * Include necessary headers...
37 */
38
39 #include "image-private.h"
40
41
42 /*
43 * '_cupsImageReadPhotoCD()' - Read a PhotoCD image file.
44 */
45
46 int /* O - Read status */
47 _cupsImageReadPhotoCD(
48 cups_image_t *img, /* IO - cupsImage */
49 FILE *fp, /* I - cupsImage file */
50 cups_icspace_t primary, /* I - Primary choice for colorspace */
51 cups_icspace_t secondary, /* I - Secondary choice for colorspace */
52 int saturation, /* I - Color saturation (%) */
53 int hue, /* I - Color hue (degrees) */
54 const cups_ib_t *lut) /* I - Lookup table for gamma/brightness */
55 {
56 int x, y; /* Looping vars */
57 int xdir, /* X direction */
58 xstart; /* X starting point */
59 int bpp; /* Bytes per pixel */
60 int pass; /* Pass number */
61 int rotation; /* 0 for 768x512, 1 for 512x768 */
62 int temp, /* Adjusted luminance */
63 temp2, /* Red, green, and blue values */
64 cb, cr; /* Adjusted chroma values */
65 cups_ib_t *in, /* Input (YCC) pixels */
66 *iy, /* Luminance */
67 *icb, /* Blue chroma */
68 *icr, /* Red chroma */
69 *rgb, /* RGB */
70 *rgbptr, /* Pointer into RGB data */
71 *out; /* Output pixels */
72
73
74 (void)secondary;
75
76 /*
77 * Get the image orientation...
78 */
79
80 fseek(fp, 72, SEEK_SET);
81 rotation = (getc(fp) & 63) != 8;
82
83 /*
84 * Seek to the start of the base image...
85 */
86
87 fseek(fp, 0x30000, SEEK_SET);
88
89 /*
90 * Allocate and initialize...
91 */
92
93 img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB : primary;
94 img->xppi = 128;
95 img->yppi = 128;
96
97 if (rotation)
98 {
99 img->xsize = 512;
100 img->ysize = 768;
101 }
102 else
103 {
104 img->xsize = 768;
105 img->ysize = 512;
106 }
107
108 cupsImageSetMaxTiles(img, 0);
109
110 bpp = cupsImageGetDepth(img);
111 in = malloc(768 * 3);
112 out = malloc(768 * bpp);
113
114 if (bpp > 1)
115 rgb = malloc(768 * 3);
116 else
117 rgb = NULL;
118
119 if (rotation)
120 {
121 xstart = 767 * bpp;
122 xdir = -2 * bpp;
123 }
124 else
125 {
126 xstart = 0;
127 xdir = 0;
128 }
129
130 /*
131 * Read the image file...
132 */
133
134 for (y = 0; y < 512; y += 2)
135 {
136 /*
137 * Grab the next two scanlines:
138 *
139 * YYYYYYYYYYYYYYY...
140 * YYYYYYYYYYYYYYY...
141 * CbCbCb...CrCrCr...
142 */
143
144 if (fread(in, 1, 768 * 3, fp) < (768 * 3))
145 {
146 /*
147 * Couldn't read a row of data - return an error!
148 */
149
150 free(in);
151 free(out);
152
153 return (-1);
154 }
155
156 /*
157 * Process the two scanlines...
158 */
159
160 for (pass = 0, iy = in; pass < 2; pass ++)
161 {
162 if (bpp == 1)
163 {
164 /*
165 * Just extract the luminance channel from the line and put it
166 * in the image...
167 */
168
169 if (primary == CUPS_IMAGE_BLACK)
170 {
171 if (rotation)
172 {
173 for (rgbptr = out + xstart, x = 0; x < 768; x ++)
174 *rgbptr-- = 255 - *iy++;
175
176 if (lut)
177 cupsImageLut(out, 768, lut);
178
179 _cupsImagePutCol(img, 511 - y - pass, 0, 768, out);
180 }
181 else
182 {
183 cupsImageWhiteToBlack(iy, out, 768);
184
185 if (lut)
186 cupsImageLut(out, 768, lut);
187
188 _cupsImagePutRow(img, 0, y + pass, 768, out);
189 iy += 768;
190 }
191 }
192 else if (rotation)
193 {
194 for (rgbptr = out + xstart, x = 0; x < 768; x ++)
195 *rgbptr-- = 255 - *iy++;
196
197 if (lut)
198 cupsImageLut(out, 768, lut);
199
200 _cupsImagePutCol(img, 511 - y - pass, 0, 768, out);
201 }
202 else
203 {
204 if (lut)
205 cupsImageLut(iy, 768, lut);
206
207 _cupsImagePutRow(img, 0, y + pass, 768, iy);
208 iy += 768;
209 }
210 }
211 else
212 {
213 /*
214 * Convert YCbCr to RGB... While every pixel gets a luminance
215 * value, adjacent pixels share chroma information.
216 */
217
218 cb = cr = 0.0f;
219
220 for (x = 0, rgbptr = rgb + xstart, icb = in + 1536, icr = in + 1920;
221 x < 768;
222 x ++, iy ++, rgbptr += xdir)
223 {
224 if (!(x & 1))
225 {
226 cb = (float)(*icb - 156);
227 cr = (float)(*icr - 137);
228 }
229
230 temp = 92241 * (*iy);
231
232 temp2 = (temp + 86706 * cr) / 65536;
233 if (temp2 < 0)
234 *rgbptr++ = 0;
235 else if (temp2 > 255)
236 *rgbptr++ = 255;
237 else
238 *rgbptr++ = temp2;
239
240 temp2 = (temp - 25914 * cb - 44166 * cr) / 65536;
241 if (temp2 < 0)
242 *rgbptr++ = 0;
243 else if (temp2 > 255)
244 *rgbptr++ = 255;
245 else
246 *rgbptr++ = temp2;
247
248 temp2 = (temp + 133434 * cb) / 65536;
249 if (temp2 < 0)
250 *rgbptr++ = 0;
251 else if (temp2 > 255)
252 *rgbptr++ = 255;
253 else
254 *rgbptr++ = temp2;
255
256 if (x & 1)
257 {
258 icb ++;
259 icr ++;
260 }
261 }
262
263 /*
264 * Adjust the hue and saturation if needed...
265 */
266
267 if (saturation != 100 || hue != 0)
268 cupsImageRGBAdjust(rgb, 768, saturation, hue);
269
270 /*
271 * Then convert the RGB data to the appropriate colorspace and
272 * put it in the image...
273 */
274
275 switch (img->colorspace)
276 {
277 default :
278 break;
279
280 case CUPS_IMAGE_RGB :
281 cupsImageRGBToRGB(rgb, out, 768);
282 break;
283 case CUPS_IMAGE_CMY :
284 cupsImageRGBToCMY(rgb, out, 768);
285 break;
286 case CUPS_IMAGE_CMYK :
287 cupsImageRGBToCMYK(rgb, out, 768);
288 break;
289 }
290
291 if (lut)
292 cupsImageLut(out, 768 * bpp, lut);
293
294 if (rotation)
295 _cupsImagePutCol(img, 511 - y - pass, 0, 768, out);
296 else
297 _cupsImagePutRow(img, 0, y + pass, 768, out);
298 }
299 }
300 }
301
302 /*
303 * Free memory and return...
304 */
305
306 free(in);
307 free(out);
308 if (bpp > 1)
309 free(rgb);
310
311 return (0);
312 }
313
314
315 /*
316 * End of "$Id$".
317 */