1 /*
2 * Portable Any Map 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 * _cupsImageReadPNM() - Read a PNM image file.
15 */
16
17 /*
18 * Include necessary headers...
19 */
20
21 #include "image-private.h"
22
23
24 /*
25 * '_cupsImageReadPNM()' - Read a PNM image file.
26 */
27
28 int /* O - Read status */
_cupsImageReadPNM(cups_image_t * img,FILE * fp,cups_icspace_t primary,cups_icspace_t secondary,int saturation,int hue,const cups_ib_t * lut)29 _cupsImageReadPNM(
30 cups_image_t *img, /* IO - cupsImage */
31 FILE *fp, /* I - cupsImage file */
32 cups_icspace_t primary, /* I - Primary choice for colorspace */
33 cups_icspace_t secondary, /* I - Secondary choice for colorspace */
34 int saturation, /* I - Color saturation (%) */
35 int hue, /* I - Color hue (degrees) */
36 const cups_ib_t *lut) /* I - Lookup table for gamma/brightness */
37 {
38 int x, y; /* Looping vars */
39 int bpp; /* Bytes per pixel */
40 cups_ib_t *in, /* Input pixels */
41 *inptr, /* Current input pixel */
42 *out, /* Output pixels */
43 *outptr, /* Current output pixel */
44 bit; /* Bit in input line */
45 char line[255], /* Input line */
46 *lineptr; /* Pointer in line */
47 int format, /* Format of PNM file */
48 val, /* Pixel value */
49 maxval; /* Maximum pixel value */
50
51
52 /*
53 * Read the file header in the format:
54 *
55 * Pformat
56 * # comment1
57 * # comment2
58 * ...
59 * # commentN
60 * width
61 * height
62 * max sample
63 */
64
65 if ((lineptr = fgets(line, sizeof(line), fp)) == NULL)
66 {
67 fputs("DEBUG: Bad PNM header!\n", stderr);
68 fclose(fp);
69 return (1);
70 }
71
72 lineptr ++;
73
74 format = atoi(lineptr);
75 while (isdigit(*lineptr & 255))
76 lineptr ++;
77
78 while (lineptr != NULL && img->xsize == 0)
79 {
80 if (*lineptr == '\0' || *lineptr == '#')
81 lineptr = fgets(line, sizeof(line), fp);
82 else if (isdigit(*lineptr & 255))
83 {
84 img->xsize = atoi(lineptr);
85 while (isdigit(*lineptr & 255))
86 lineptr ++;
87 }
88 else
89 lineptr ++;
90 }
91
92 while (lineptr != NULL && img->ysize == 0)
93 {
94 if (*lineptr == '\0' || *lineptr == '#')
95 lineptr = fgets(line, sizeof(line), fp);
96 else if (isdigit(*lineptr & 255))
97 {
98 img->ysize = atoi(lineptr);
99 while (isdigit(*lineptr & 255))
100 lineptr ++;
101 }
102 else
103 lineptr ++;
104 }
105
106 if (format != 1 && format != 4)
107 {
108 maxval = 0;
109
110 while (lineptr != NULL && maxval == 0)
111 {
112 if (*lineptr == '\0' || *lineptr == '#')
113 lineptr = fgets(line, sizeof(line), fp);
114 else if (isdigit(*lineptr & 255))
115 {
116 maxval = atoi(lineptr);
117 while (isdigit(*lineptr & 255))
118 lineptr ++;
119 }
120 else
121 lineptr ++;
122 }
123 }
124 else
125 maxval = 1;
126
127 if (img->xsize == 0 || img->xsize > CUPS_IMAGE_MAX_WIDTH ||
128 img->ysize == 0 || img->ysize > CUPS_IMAGE_MAX_HEIGHT)
129 {
130 fprintf(stderr, "DEBUG: Bad PNM dimensions %dx%d!\n",
131 img->xsize, img->ysize);
132 fclose(fp);
133 return (1);
134 }
135
136 if (maxval == 0)
137 {
138 fprintf(stderr, "DEBUG: Bad PNM max value %d!\n", maxval);
139 fclose(fp);
140 return (1);
141 }
142
143 if (format == 1 || format == 2 || format == 4 || format == 5)
144 img->colorspace = secondary;
145 else
146 img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB : primary;
147
148 cupsImageSetMaxTiles(img, 0);
149
150 bpp = cupsImageGetDepth(img);
151
152 if ((in = malloc(img->xsize * 3)) == NULL)
153 {
154 fputs("DEBUG: Unable to allocate memory!\n", stderr);
155 fclose(fp);
156 return (1);
157 }
158
159 if ((out = malloc(img->xsize * bpp)) == NULL)
160 {
161 fputs("DEBUG: Unable to allocate memory!\n", stderr);
162 fclose(fp);
163 free(in);
164 return (1);
165 }
166
167 /*
168 * Read the image file...
169 */
170
171 for (y = 0; y < img->ysize; y ++)
172 {
173 switch (format)
174 {
175 case 1 :
176 for (x = img->xsize, inptr = in; x > 0; x --, inptr ++)
177 if (fscanf(fp, "%d", &val) == 1)
178 *inptr = val ? 0 : 255;
179 break;
180
181 case 2 :
182 for (x = img->xsize, inptr = in; x > 0; x --, inptr ++)
183 if (fscanf(fp, "%d", &val) == 1)
184 *inptr = 255 * val / maxval;
185 break;
186
187 case 3 :
188 for (x = img->xsize, inptr = in; x > 0; x --, inptr += 3)
189 {
190 if (fscanf(fp, "%d", &val) == 1)
191 inptr[0] = 255 * val / maxval;
192 if (fscanf(fp, "%d", &val) == 1)
193 inptr[1] = 255 * val / maxval;
194 if (fscanf(fp, "%d", &val) == 1)
195 inptr[2] = 255 * val / maxval;
196 }
197 break;
198
199 case 4 :
200 if (fread(out, (img->xsize + 7) / 8, 1, fp) == 0 && ferror(fp))
201 DEBUG_printf(("Error reading file!"));
202 for (x = img->xsize, inptr = in, outptr = out, bit = 128;
203 x > 0;
204 x --, inptr ++)
205 {
206 if (*outptr & bit)
207 *inptr = 0;
208 else
209 *inptr = 255;
210
211 if (bit > 1)
212 bit >>= 1;
213 else
214 {
215 bit = 128;
216 outptr ++;
217 }
218 }
219 break;
220
221 case 5 :
222 if (fread(in, img->xsize, 1, fp) == 0 && ferror(fp))
223 DEBUG_printf(("Error reading file!"));
224 break;
225
226 case 6 :
227 if (fread(in, img->xsize, 3, fp) == 0 && ferror(fp))
228 DEBUG_printf(("Error reading file!"));
229 break;
230 }
231
232 switch (format)
233 {
234 case 1 :
235 case 2 :
236 case 4 :
237 case 5 :
238 if (img->colorspace == CUPS_IMAGE_WHITE)
239 {
240 if (lut)
241 cupsImageLut(in, img->xsize, lut);
242
243 _cupsImagePutRow(img, 0, y, img->xsize, in);
244 }
245 else
246 {
247 switch (img->colorspace)
248 {
249 default :
250 break;
251
252 case CUPS_IMAGE_RGB :
253 cupsImageWhiteToRGB(in, out, img->xsize);
254 break;
255 case CUPS_IMAGE_BLACK :
256 cupsImageWhiteToBlack(in, out, img->xsize);
257 break;
258 case CUPS_IMAGE_CMY :
259 cupsImageWhiteToCMY(in, out, img->xsize);
260 break;
261 case CUPS_IMAGE_CMYK :
262 cupsImageWhiteToCMYK(in, out, img->xsize);
263 break;
264 }
265
266 if (lut)
267 cupsImageLut(out, img->xsize * bpp, lut);
268
269 _cupsImagePutRow(img, 0, y, img->xsize, out);
270 }
271 break;
272
273 default :
274 if ((saturation != 100 || hue != 0) && bpp > 1)
275 cupsImageRGBAdjust(in, img->xsize, saturation, hue);
276
277 switch (img->colorspace)
278 {
279 default :
280 break;
281
282 case CUPS_IMAGE_WHITE :
283 cupsImageRGBToWhite(in, out, img->xsize);
284 break;
285 case CUPS_IMAGE_RGB :
286 cupsImageRGBToRGB(in, out, img->xsize);
287 break;
288 case CUPS_IMAGE_BLACK :
289 cupsImageRGBToBlack(in, out, img->xsize);
290 break;
291 case CUPS_IMAGE_CMY :
292 cupsImageRGBToCMY(in, out, img->xsize);
293 break;
294 case CUPS_IMAGE_CMYK :
295 cupsImageRGBToCMYK(in, out, img->xsize);
296 break;
297 }
298
299 if (lut)
300 cupsImageLut(out, img->xsize * bpp, lut);
301
302 _cupsImagePutRow(img, 0, y, img->xsize, out);
303 break;
304 }
305 }
306
307 free(in);
308 free(out);
309
310 fclose(fp);
311
312 return (0);
313 }
314
315