]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/image-png.c
Merge changes from CUPS 1.4svn-r8067 (tentative CUPS 1.4b1)
[thirdparty/cups.git] / filter / image-png.c
CommitLineData
ef416fc2 1/*
75bd9771 2 * "$Id: image-png.c 7437 2008-04-09 03:16:10Z mike $"
ef416fc2 3 *
4 * PNG image routines for the Common UNIX Printing System (CUPS).
5 *
839a51c8 6 * Copyright 2007-2008 by Apple Inc.
c0e1af83 7 * Copyright 1993-2007 by Easy Software Products.
ef416fc2 8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 14 *
15 * This file is subject to the Apple OS-Developed Software exception.
16 *
17 * Contents:
18 *
19 * _cupsImageReadPNG() - Read a PNG image file.
20 */
21
22/*
23 * Include necessary headers...
24 */
25
26#include "image-private.h"
27
28#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
29# include <png.h> /* Portable Network Graphics (PNG) definitions */
30
31
32/*
33 * '_cupsImageReadPNG()' - Read a PNG image file.
34 */
35
36int /* O - Read status */
37_cupsImageReadPNG(
38 cups_image_t *img, /* IO - cupsImage */
39 FILE *fp, /* I - cupsImage file */
40 cups_icspace_t primary, /* I - Primary choice for colorspace */
41 cups_icspace_t secondary, /* I - Secondary choice for colorspace */
42 int saturation, /* I - Color saturation (%) */
43 int hue, /* I - Color hue (degrees) */
44 const cups_ib_t *lut) /* I - Lookup table for gamma/brightness */
45{
46 int y; /* Looping var */
47 png_structp pp; /* PNG read pointer */
48 png_infop info; /* PNG info pointers */
89d46774 49 png_uint_32 width, /* Width of image */
50 height; /* Height of image */
51 int bit_depth, /* Bit depth */
52 color_type, /* Color type */
53 interlace_type, /* Interlace type */
54 compression_type, /* Compression type */
55 filter_type; /* Filter type */
56 png_uint_32 xppm, /* X pixels per meter */
57 yppm; /* Y pixels per meter */
ef416fc2 58 int bpp; /* Bytes per pixel */
59 int pass, /* Current pass */
60 passes; /* Number of passes required */
61 cups_ib_t *in, /* Input pixels */
62 *inptr, /* Pointer into pixels */
63 *out; /* Output pixels */
64 png_color_16 bg; /* Background color */
65
66
67 /*
68 * Setup the PNG data structures...
69 */
70
71 pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
72 info = png_create_info_struct(pp);
73
74 /*
75 * Initialize the PNG read "engine"...
76 */
77
78 png_init_io(pp, fp);
79
80 /*
81 * Get the image dimensions and load the output image...
82 */
83
84 png_read_info(pp, info);
85
89d46774 86 png_get_IHDR(pp, info, &width, &height, &bit_depth, &color_type,
87 &interlace_type, &compression_type, &filter_type);
88
ef416fc2 89 fprintf(stderr, "DEBUG: PNG image: %dx%dx%d, color_type=%x (%s%s%s)\n",
89d46774 90 (int)width, (int)height, bit_depth, color_type,
91 (color_type & PNG_COLOR_MASK_COLOR) ? "RGB" : "GRAYSCALE",
92 (color_type & PNG_COLOR_MASK_ALPHA) ? "+ALPHA" : "",
93 (color_type & PNG_COLOR_MASK_PALETTE) ? "+PALETTE" : "");
ef416fc2 94
89d46774 95 if (color_type & PNG_COLOR_MASK_PALETTE)
ef416fc2 96 png_set_expand(pp);
89d46774 97 else if (bit_depth < 8)
ef416fc2 98 {
99 png_set_packing(pp);
100 png_set_expand(pp);
101 }
89d46774 102 else if (bit_depth == 16)
ef416fc2 103 png_set_strip_16(pp);
104
89d46774 105 if (color_type & PNG_COLOR_MASK_COLOR)
106 img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB :
107 primary;
ef416fc2 108 else
109 img->colorspace = secondary;
110
89d46774 111 if (width == 0 || width > CUPS_IMAGE_MAX_WIDTH ||
112 height == 0 || height > CUPS_IMAGE_MAX_HEIGHT)
ef416fc2 113 {
c0e1af83 114 fprintf(stderr, "DEBUG: PNG image has invalid dimensions %ux%u!\n",
89d46774 115 (unsigned)width, (unsigned)height);
ef416fc2 116 fclose(fp);
117 return (1);
118 }
119
89d46774 120 img->xsize = width;
121 img->ysize = height;
ef416fc2 122
89d46774 123 if ((xppm = png_get_x_pixels_per_meter(pp, info)) != 0 &&
124 (yppm = png_get_y_pixels_per_meter(pp, info)) != 0)
ef416fc2 125 {
89d46774 126 img->xppi = (int)((float)xppm * 0.0254);
127 img->yppi = (int)((float)yppm * 0.0254);
ef416fc2 128
129 if (img->xppi == 0 || img->yppi == 0)
130 {
c0e1af83 131 fprintf(stderr, "DEBUG: PNG image has invalid resolution %dx%d PPI\n",
ef416fc2 132 img->xppi, img->yppi);
133
134 img->xppi = img->yppi = 128;
135 }
136 }
137
138 cupsImageSetMaxTiles(img, 0);
139
140 passes = png_set_interlace_handling(pp);
141
142 /*
143 * Handle transparency...
144 */
145
146 if (png_get_valid(pp, info, PNG_INFO_tRNS))
147 png_set_tRNS_to_alpha(pp);
148
149 bg.red = 65535;
150 bg.green = 65535;
151 bg.blue = 65535;
152
153 png_set_background(pp, &bg, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
154
155 if (passes == 1)
156 {
157 /*
158 * Load one row at a time...
159 */
160
89d46774 161 if (color_type == PNG_COLOR_TYPE_GRAY ||
162 color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
ef416fc2 163 in = malloc(img->xsize);
164 else
165 in = malloc(img->xsize * 3);
166 }
167 else
168 {
169 /*
170 * Interlaced images must be loaded all at once...
171 */
172
839a51c8
MS
173 size_t bufsize; /* Size of buffer */
174
175
89d46774 176 if (color_type == PNG_COLOR_TYPE_GRAY ||
177 color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
839a51c8
MS
178 {
179 bufsize = img->xsize * img->ysize;
180
28b9d139 181 if ((bufsize / img->xsize) != img->ysize)
839a51c8
MS
182 {
183 fprintf(stderr, "DEBUG: PNG image dimensions (%ux%u) too large!\n",
184 (unsigned)width, (unsigned)height);
185 fclose(fp);
186 return (1);
187 }
188 }
ef416fc2 189 else
839a51c8
MS
190 {
191 bufsize = img->xsize * img->ysize * 3;
192
28b9d139 193 if ((bufsize / (img->xsize * 3)) != img->ysize)
839a51c8
MS
194 {
195 fprintf(stderr, "DEBUG: PNG image dimensions (%ux%u) too large!\n",
196 (unsigned)width, (unsigned)height);
197 fclose(fp);
198 return (1);
199 }
200 }
201
202 in = malloc(bufsize);
ef416fc2 203 }
204
205 bpp = cupsImageGetDepth(img);
206 out = malloc(img->xsize * bpp);
207
839a51c8
MS
208 if (!in || !out)
209 {
210 fputs("DEBUG: Unable to allocate memory for PNG image!\n", stderr);
211
212 if (in)
213 free(in);
214
215 if (out)
216 free(out);
217
218 fclose(fp);
219
220 return (1);
221 }
222
ef416fc2 223 /*
224 * Read the image, interlacing as needed...
225 */
226
227 for (pass = 1; pass <= passes; pass ++)
228 for (inptr = in, y = 0; y < img->ysize; y ++)
229 {
230 png_read_row(pp, (png_bytep)inptr, NULL);
231
232 if (pass == passes)
233 {
234 /*
235 * Output this row...
236 */
237
89d46774 238 if (color_type & PNG_COLOR_MASK_COLOR)
ef416fc2 239 {
240 if ((saturation != 100 || hue != 0) && bpp > 1)
241 cupsImageRGBAdjust(inptr, img->xsize, saturation, hue);
242
243 switch (img->colorspace)
244 {
245 case CUPS_IMAGE_WHITE :
246 cupsImageRGBToWhite(inptr, out, img->xsize);
247 break;
248 case CUPS_IMAGE_RGB :
249 case CUPS_IMAGE_RGB_CMYK :
f301802f 250 cupsImageRGBToRGB(inptr, out, img->xsize);
ef416fc2 251 break;
252 case CUPS_IMAGE_BLACK :
253 cupsImageRGBToBlack(inptr, out, img->xsize);
254 break;
255 case CUPS_IMAGE_CMY :
256 cupsImageRGBToCMY(inptr, out, img->xsize);
257 break;
258 case CUPS_IMAGE_CMYK :
259 cupsImageRGBToCMYK(inptr, out, img->xsize);
260 break;
261 }
262 }
263 else
264 {
265 switch (img->colorspace)
266 {
267 case CUPS_IMAGE_WHITE :
268 memcpy(out, inptr, img->xsize);
269 break;
270 case CUPS_IMAGE_RGB :
271 case CUPS_IMAGE_RGB_CMYK :
272 cupsImageWhiteToRGB(inptr, out, img->xsize);
273 break;
274 case CUPS_IMAGE_BLACK :
275 cupsImageWhiteToBlack(inptr, out, img->xsize);
276 break;
277 case CUPS_IMAGE_CMY :
278 cupsImageWhiteToCMY(inptr, out, img->xsize);
279 break;
280 case CUPS_IMAGE_CMYK :
281 cupsImageWhiteToCMYK(inptr, out, img->xsize);
282 break;
283 }
284 }
285
286 if (lut)
287 cupsImageLut(out, img->xsize * bpp, lut);
288
289 _cupsImagePutRow(img, 0, y, img->xsize, out);
290 }
291
292 if (passes > 1)
293 {
89d46774 294 if (color_type & PNG_COLOR_MASK_COLOR)
ef416fc2 295 inptr += img->xsize * 3;
296 else
297 inptr += img->xsize;
298 }
299 }
300
301 png_read_end(pp, info);
89d46774 302 png_destroy_read_struct(&pp, &info, NULL);
ef416fc2 303
304 fclose(fp);
305 free(in);
306 free(out);
307
308 return (0);
309}
310#endif /* HAVE_LIBPNG && HAVE_LIBZ */
311
312
313/*
75bd9771 314 * End of "$Id: image-png.c 7437 2008-04-09 03:16:10Z mike $".
ef416fc2 315 */