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