]>
Commit | Line | Data |
---|---|---|
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 | ||
45 | int /* 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 | */ |