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