]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/image-png.c
Load cups into easysw/current.
[thirdparty/cups.git] / filter / image-png.c
CommitLineData
ef416fc2 1/*
2 * "$Id: image-png.c 4741 2005-10-02 04:25:52Z mike $"
3 *
4 * PNG image routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1993-2005 by Easy Software Products.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * This file is subject to the Apple OS-Developed Software exception.
25 *
26 * Contents:
27 *
28 * _cupsImageReadPNG() - Read a PNG image file.
29 */
30
31/*
32 * Include necessary headers...
33 */
34
35#include "image-private.h"
36
37#if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
38# include <png.h> /* Portable Network Graphics (PNG) definitions */
39
40
41/*
42 * '_cupsImageReadPNG()' - Read a PNG image file.
43 */
44
45int /* O - Read status */
46_cupsImageReadPNG(
47 cups_image_t *img, /* IO - cupsImage */
48 FILE *fp, /* I - cupsImage file */
49 cups_icspace_t primary, /* I - Primary choice for colorspace */
50 cups_icspace_t secondary, /* I - Secondary choice for colorspace */
51 int saturation, /* I - Color saturation (%) */
52 int hue, /* I - Color hue (degrees) */
53 const cups_ib_t *lut) /* I - Lookup table for gamma/brightness */
54{
55 int y; /* Looping var */
56 png_structp pp; /* PNG read pointer */
57 png_infop info; /* PNG info pointers */
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
86 fprintf(stderr, "DEBUG: PNG image: %dx%dx%d, color_type=%x (%s%s%s)\n",
87 (int)info->width, (int)info->height, info->bit_depth, info->color_type,
88 (info->color_type & PNG_COLOR_MASK_COLOR) ? "RGB" : "GRAYSCALE",
89 (info->color_type & PNG_COLOR_MASK_ALPHA) ? "+ALPHA" : "",
90 (info->color_type & PNG_COLOR_MASK_PALETTE) ? "+PALETTE" : "");
91
92 if (info->color_type & PNG_COLOR_MASK_PALETTE)
93 png_set_expand(pp);
94 else if (info->bit_depth < 8)
95 {
96 png_set_packing(pp);
97 png_set_expand(pp);
98 }
99 else if (info->bit_depth == 16)
100 png_set_strip_16(pp);
101
102 if (info->color_type & PNG_COLOR_MASK_COLOR)
103 img->colorspace = (primary == CUPS_IMAGE_RGB_CMYK) ? CUPS_IMAGE_RGB : primary;
104 else
105 img->colorspace = secondary;
106
107 if (info->width == 0 || info->width > CUPS_IMAGE_MAX_WIDTH ||
108 info->height == 0 || info->height > CUPS_IMAGE_MAX_HEIGHT)
109 {
110 fprintf(stderr, "ERROR: PNG image has invalid dimensions %ux%u!\n",
111 (unsigned)info->width, (unsigned)info->height);
112 fclose(fp);
113 return (1);
114 }
115
116 img->xsize = info->width;
117 img->ysize = info->height;
118
119 if (info->valid & PNG_INFO_pHYs &&
120 info->phys_unit_type == PNG_RESOLUTION_METER)
121 {
122 img->xppi = (int)((float)info->x_pixels_per_unit * 0.0254);
123 img->yppi = (int)((float)info->y_pixels_per_unit * 0.0254);
124
125 if (img->xppi == 0 || img->yppi == 0)
126 {
127 fprintf(stderr, "ERROR: PNG image has invalid resolution %dx%d PPI\n",
128 img->xppi, img->yppi);
129
130 img->xppi = img->yppi = 128;
131 }
132 }
133
134 cupsImageSetMaxTiles(img, 0);
135
136 passes = png_set_interlace_handling(pp);
137
138 /*
139 * Handle transparency...
140 */
141
142 if (png_get_valid(pp, info, PNG_INFO_tRNS))
143 png_set_tRNS_to_alpha(pp);
144
145 bg.red = 65535;
146 bg.green = 65535;
147 bg.blue = 65535;
148
149 png_set_background(pp, &bg, PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
150
151 if (passes == 1)
152 {
153 /*
154 * Load one row at a time...
155 */
156
157 if (info->color_type == PNG_COLOR_TYPE_GRAY ||
158 info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
159 in = malloc(img->xsize);
160 else
161 in = malloc(img->xsize * 3);
162 }
163 else
164 {
165 /*
166 * Interlaced images must be loaded all at once...
167 */
168
169 if (info->color_type == PNG_COLOR_TYPE_GRAY ||
170 info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
171 in = malloc(img->xsize * img->ysize);
172 else
173 in = malloc(img->xsize * img->ysize * 3);
174 }
175
176 bpp = cupsImageGetDepth(img);
177 out = malloc(img->xsize * bpp);
178
179 /*
180 * Read the image, interlacing as needed...
181 */
182
183 for (pass = 1; pass <= passes; pass ++)
184 for (inptr = in, y = 0; y < img->ysize; y ++)
185 {
186 png_read_row(pp, (png_bytep)inptr, NULL);
187
188 if (pass == passes)
189 {
190 /*
191 * Output this row...
192 */
193
194 if (info->color_type & PNG_COLOR_MASK_COLOR)
195 {
196 if ((saturation != 100 || hue != 0) && bpp > 1)
197 cupsImageRGBAdjust(inptr, img->xsize, saturation, hue);
198
199 switch (img->colorspace)
200 {
201 case CUPS_IMAGE_WHITE :
202 cupsImageRGBToWhite(inptr, out, img->xsize);
203 break;
204 case CUPS_IMAGE_RGB :
205 case CUPS_IMAGE_RGB_CMYK :
206 memcpy(out, inptr, img->xsize * 3);
207 break;
208 case CUPS_IMAGE_BLACK :
209 cupsImageRGBToBlack(inptr, out, img->xsize);
210 break;
211 case CUPS_IMAGE_CMY :
212 cupsImageRGBToCMY(inptr, out, img->xsize);
213 break;
214 case CUPS_IMAGE_CMYK :
215 cupsImageRGBToCMYK(inptr, out, img->xsize);
216 break;
217 }
218 }
219 else
220 {
221 switch (img->colorspace)
222 {
223 case CUPS_IMAGE_WHITE :
224 memcpy(out, inptr, img->xsize);
225 break;
226 case CUPS_IMAGE_RGB :
227 case CUPS_IMAGE_RGB_CMYK :
228 cupsImageWhiteToRGB(inptr, out, img->xsize);
229 break;
230 case CUPS_IMAGE_BLACK :
231 cupsImageWhiteToBlack(inptr, out, img->xsize);
232 break;
233 case CUPS_IMAGE_CMY :
234 cupsImageWhiteToCMY(inptr, out, img->xsize);
235 break;
236 case CUPS_IMAGE_CMYK :
237 cupsImageWhiteToCMYK(inptr, out, img->xsize);
238 break;
239 }
240 }
241
242 if (lut)
243 cupsImageLut(out, img->xsize * bpp, lut);
244
245 _cupsImagePutRow(img, 0, y, img->xsize, out);
246 }
247
248 if (passes > 1)
249 {
250 if (info->color_type & PNG_COLOR_MASK_COLOR)
251 inptr += img->xsize * 3;
252 else
253 inptr += img->xsize;
254 }
255 }
256
257 png_read_end(pp, info);
258 png_read_destroy(pp, info, NULL);
259
260 fclose(fp);
261 free(in);
262 free(out);
263
264 return (0);
265}
266#endif /* HAVE_LIBPNG && HAVE_LIBZ */
267
268
269/*
270 * End of "$Id: image-png.c 4741 2005-10-02 04:25:52Z mike $".
271 */