• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *   Sun Raster image file routines for CUPS.
3  *
4  *   Copyright 2007-2011 by Apple Inc.
5  *   Copyright 1993-2007 by Easy Software Products.
6  *
7  *   These coded instructions, statements, and computer programs are the
8  *   property of Apple Inc. and are protected by Federal copyright
9  *   law.  Distribution and use rights are outlined in the file "COPYING"
10  *   which should have been included with this file.
11  *
12  * Contents:
13  *
14  *   _cupsImageReadSunRaster() - Read a SunRaster image file.
15  *   read_unsigned()      - Read a 32-bit unsigned integer.
16  */
17 
18 /*
19  * Include necessary headers...
20  */
21 
22 #include "image-private.h"
23 
24 
25 #define	RAS_MAGIC	0x59a66a95
26 
27 	/* Sun supported ras_type's */
28 #define RT_OLD		0		/* Raw pixrect image in 68000 byte order */
29 #define RT_STANDARD	1		/* Raw pixrect image in 68000 byte order */
30 #define RT_BYTE_ENCODED	2		/* Run-length compression of bytes */
31 #define RT_FORMAT_RGB	3		/* XRGB or RGB instead of XBGR or BGR */
32 #define RT_EXPERIMENTAL	0xffff		/* Reserved for testing */
33 
34 	/* Sun registered ras_maptype's */
35 #define RMT_RAW		2
36 	/* Sun supported ras_maptype's */
37 #define RMT_NONE	0		/* ras_maplength is expected to be 0 */
38 #define RMT_EQUAL_RGB	1		/* red[ras_maplength/3],green[],blue[] */
39 
40 #define RAS_RLE 0x80
41 
42 /*
43  * NOTES:
44  * 	Each line of the image is rounded out to a multiple of 16 bits.
45  *   This corresponds to the rounding convention used by the memory pixrect
46  *   package (/usr/include/pixrect/memvar.h) of the SunWindows system.
47  *	The ras_encoding field (always set to 0 by Sun's supported software)
48  *   was renamed to ras_length in release 2.0.  As a result, rasterfiles
49  *   of type 0 generated by the old software claim to have 0 length; for
50  *   compatibility, code reading rasterfiles must be prepared to compute the
51  *   true length from the width, height, and depth fields.
52  */
53 
54 /*
55  * Local functions...
56  */
57 
58 static unsigned	read_unsigned(FILE *fp);
59 
60 
61 /*
62  * '_cupsImageReadSunRaster()' - Read a SunRaster image file.
63  */
64 
65 int					/* O - Read status */
_cupsImageReadSunRaster(cups_image_t * img,FILE * fp,cups_icspace_t primary,cups_icspace_t secondary,int saturation,int hue,const cups_ib_t * lut)66 _cupsImageReadSunRaster(
67     cups_image_t    *img,		/* IO - cupsImage */
68     FILE            *fp,		/* I - cupsImage file */
69     cups_icspace_t  primary,		/* I - Primary choice for colorspace */
70     cups_icspace_t  secondary,		/* I - Secondary choice for colorspace */
71     int             saturation,		/* I - Color saturation (%) */
72     int             hue,		/* I - Color hue (degrees) */
73     const cups_ib_t *lut)		/* I - Lookup table for gamma/brightness */
74 {
75   int		i, x, y,
76 		bpp,			/* Bytes per pixel */
77 		scanwidth,
78 		run_count,
79 		run_value;
80   cups_ib_t	*in,
81 		*out,
82 		*scanline,
83 		*scanptr,
84 		*p,
85 		bit;
86   unsigned	ras_depth,		/* depth (1, 8, or 24 bits) of pixel */
87 		ras_type,		/* type of file; see RT_* below */
88 		ras_maplength;		/* length (bytes) of following map */
89   unsigned char	cmap[3][256];		/* colormap */
90 
91 
92  /*
93   * Read the header; we already know that this is a raster file (cupsImageOpen
94   * checks this) so we don't need to check the magic number again.
95   */
96 
97   fputs("DEBUG: Reading Sun Raster image...\n", stderr);
98 
99   read_unsigned(fp); /* Skip magic */
100   img->xsize    = read_unsigned(fp);
101   img->ysize    = read_unsigned(fp);
102   ras_depth     = read_unsigned(fp);
103   /* ras_length */read_unsigned(fp);
104   ras_type      = read_unsigned(fp);
105   /* ras_maptype*/read_unsigned(fp);
106   ras_maplength = read_unsigned(fp);
107 
108   fprintf(stderr, "DEBUG: ras_width=%d, ras_height=%d, ras_depth=%d, ras_type=%d, ras_maplength=%d\n",
109           img->xsize, img->ysize, ras_depth, ras_type, ras_maplength);
110 
111   if (ras_maplength > 768 ||
112       img->xsize == 0 || img->xsize > CUPS_IMAGE_MAX_WIDTH ||
113       img->ysize == 0 || img->ysize > CUPS_IMAGE_MAX_HEIGHT ||
114       ras_depth == 0 || ras_depth > 32)
115   {
116     fputs("DEBUG: Raster image cannot be loaded!\n", stderr);
117     fclose(fp);
118     return (1);
119   }
120 
121   if (ras_maplength > 0)
122   {
123     memset(cmap[0], 255, sizeof(cmap[0]));
124     memset(cmap[1], 0, sizeof(cmap[1]));
125     memset(cmap[2], 0, sizeof(cmap[2]));
126 
127     if (fread(cmap[0], 1, ras_maplength / 3, fp) == 0 && ferror(fp))
128       DEBUG_printf(("Error reading file!"));
129     if (fread(cmap[1], 1, ras_maplength / 3, fp) == 0 && ferror(fp))
130       DEBUG_printf(("Error reading file!"));
131     if (fread(cmap[2], 1, ras_maplength / 3, fp) == 0 && ferror(fp))
132       DEBUG_printf(("Error reading file!"));
133   }
134 
135  /*
136   * Compute the width of each line and allocate memory as needed...
137   */
138 
139   scanwidth = (img->xsize * ras_depth + 7) / 8;
140   if (scanwidth & 1)
141     scanwidth ++;
142 
143   if (ras_depth < 24 && ras_maplength == 0)
144   {
145     img->colorspace = secondary;
146     in = malloc(img->xsize + 1);
147   }
148   else
149   {
150     img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB : primary;
151     in = malloc(img->xsize * 3 + 1);
152   }
153 
154   if (!in)
155   {
156     fputs("DEBUG: Unable to allocate memory!\n", stderr);
157     fclose(fp);
158     return (1);
159   }
160 
161   bpp = cupsImageGetDepth(img);
162 
163   if ((out = malloc(img->xsize * bpp)) == NULL)
164   {
165     fputs("DEBUG: Unable to allocate memory!\n", stderr);
166     fclose(fp);
167     free(in);
168     return (1);
169   }
170 
171   if ((scanline = malloc(scanwidth)) == NULL)
172   {
173     fputs("DEBUG: Unable to allocate memory!\n", stderr);
174     fclose(fp);
175     free(in);
176     free(out);
177     return (1);
178   }
179 
180   run_count = 0;
181   run_value = 0;
182 
183   fprintf(stderr, "DEBUG: bpp=%d, scanwidth=%d\n", bpp, scanwidth);
184 
185   for (y = 0; y < img->ysize; y ++)
186   {
187     if ((ras_depth != 8 && ras_depth != 24) || ras_maplength > 0)
188       p = scanline;
189     else
190       p = in;
191 
192     if (ras_type != RT_BYTE_ENCODED)
193     {
194       if (fread(p, scanwidth, 1, fp) == 0 && ferror(fp))
195 	DEBUG_printf(("Error reading file!"));
196     }
197     else
198     {
199       for (i = scanwidth; i > 0; i --, p ++)
200       {
201         if (run_count > 0)
202         {
203           *p = run_value;
204           run_count --;
205         }
206         else
207         {
208           run_value = getc(fp);
209 
210           if (run_value == RAS_RLE)
211           {
212             run_count = getc(fp);
213             if (run_count == 0)
214               *p = RAS_RLE;
215             else
216               run_value = *p = getc(fp);
217           }
218           else
219             *p = run_value;
220         }
221       }
222     }
223 
224     if (ras_depth == 1 && ras_maplength == 0)
225     {
226      /*
227       * 1-bit B&W image...
228       */
229 
230       for (x = img->xsize, bit = 128, scanptr = scanline, p = in;
231            x > 0;
232            x --, p ++)
233       {
234 	if (*scanptr & bit)
235           *p = 255;
236         else
237           *p = 0;
238 
239 	if (bit > 1)
240           bit >>= 1;
241 	else
242 	{
243           bit = 128;
244           scanptr ++;
245 	}
246       }
247     }
248     else if (ras_depth == 1)
249     {
250      /*
251       * 1-bit colormapped image...
252       */
253 
254       for (x = img->xsize, bit = 128, scanptr = scanline, p = in;
255            x > 0;
256            x --)
257       {
258 	if (*scanptr & bit)
259 	{
260           *p++ = cmap[0][1];
261           *p++ = cmap[1][1];
262           *p++ = cmap[2][1];
263 	}
264         else
265 	{
266           *p++ = cmap[0][0];
267           *p++ = cmap[1][0];
268           *p++ = cmap[2][0];
269 	}
270 
271 	if (bit > 1)
272           bit >>= 1;
273 	else
274 	{
275           bit = 128;
276           scanptr ++;
277 	}
278       }
279     }
280     else if (ras_depth == 8 && ras_maplength > 0)
281     {
282      /*
283       * 8-bit colormapped image.
284       */
285 
286       for (x = img->xsize, scanptr = scanline, p = in;
287            x > 0;
288            x --)
289       {
290         *p++ = cmap[0][*scanptr];
291         *p++ = cmap[1][*scanptr];
292         *p++ = cmap[2][*scanptr++];
293       }
294     }
295     else if (ras_depth == 24 && ras_type != RT_FORMAT_RGB)
296     {
297      /*
298       * Convert BGR to RGB...
299       */
300 
301       for (x = img->xsize, scanptr = scanline, p = in;
302            x > 0;
303            x --, scanptr += 3)
304       {
305         *p++ = scanptr[2];
306         *p++ = scanptr[1];
307         *p++ = scanptr[0];
308       }
309     }
310 
311     if (ras_depth <= 8 && ras_maplength == 0)
312     {
313       if (img->colorspace == CUPS_IMAGE_WHITE)
314       {
315         if (lut)
316 	  cupsImageLut(in, img->xsize, lut);
317 
318         _cupsImagePutRow(img, 0, y, img->xsize, in);
319       }
320       else
321       {
322 	switch (img->colorspace)
323 	{
324 	  default :
325 	      break;
326 
327 	  case CUPS_IMAGE_RGB :
328 	      cupsImageWhiteToRGB(in, out, img->xsize);
329 	      break;
330 	  case CUPS_IMAGE_BLACK :
331 	      cupsImageWhiteToBlack(in, out, img->xsize);
332 	      break;
333 	  case CUPS_IMAGE_CMY :
334 	      cupsImageWhiteToCMY(in, out, img->xsize);
335 	      break;
336 	  case CUPS_IMAGE_CMYK :
337 	      cupsImageWhiteToCMYK(in, out, img->xsize);
338 	      break;
339 	}
340 
341         if (lut)
342 	  cupsImageLut(out, img->xsize * bpp, lut);
343 
344         _cupsImagePutRow(img, 0, y, img->xsize, out);
345       }
346     }
347     else
348     {
349       if ((saturation != 100 || hue != 0) && bpp > 1)
350 	cupsImageRGBAdjust(in, img->xsize, saturation, hue);
351 
352       switch (img->colorspace)
353       {
354 	default :
355 	    break;
356 
357 	case CUPS_IMAGE_WHITE :
358 	    cupsImageRGBToWhite(in, out, img->xsize);
359 	    break;
360 	case CUPS_IMAGE_BLACK :
361 	    cupsImageRGBToBlack(in, out, img->xsize);
362 	    break;
363 	case CUPS_IMAGE_CMY :
364 	    cupsImageRGBToCMY(in, out, img->xsize);
365 	    break;
366 	case CUPS_IMAGE_CMYK :
367 	    cupsImageRGBToCMYK(in, out, img->xsize);
368 	    break;
369       }
370 
371       if (lut)
372 	cupsImageLut(out, img->xsize * bpp, lut);
373 
374       _cupsImagePutRow(img, 0, y, img->xsize, out);
375     }
376   }
377 
378   free(scanline);
379   free(in);
380   free(out);
381 
382   fclose(fp);
383 
384   return (0);
385 }
386 
387 
388 /*
389  * 'read_unsigned()' - Read a 32-bit unsigned integer.
390  */
391 
392 static unsigned				/* O - Integer from file */
read_unsigned(FILE * fp)393 read_unsigned(FILE *fp)			/* I - File to read from */
394 {
395   unsigned	v;			/* Integer from file */
396 
397 
398   v = getc(fp);
399   v = (v << 8) | getc(fp);
400   v = (v << 8) | getc(fp);
401   v = (v << 8) | getc(fp);
402 
403   return (v);
404 }
405 
406