2 * "$Id: image-png.c 7437 2008-04-09 03:16:10Z mike $"
4 * PNG image routines for the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2008 by Apple Inc.
7 * Copyright 1993-2007 by Easy Software Products.
9 * These coded instructions, statements, and computer programs are the
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/".
15 * This file is subject to the Apple OS-Developed Software exception.
19 * _cupsImageReadPNG() - Read a PNG image file.
23 * Include necessary headers...
26 #include "image-private.h"
28 #if defined(HAVE_LIBPNG) && defined(HAVE_LIBZ)
29 # include <png.h> /* Portable Network Graphics (PNG) definitions */
33 * '_cupsImageReadPNG()' - Read a PNG image file.
36 int /* O - Read status */
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 */
46 int y
; /* Looping var */
47 png_structp pp
; /* PNG read pointer */
48 png_infop info
; /* PNG info pointers */
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 */
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 */
68 * Setup the PNG data structures...
71 pp
= png_create_read_struct(PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL
);
72 info
= png_create_info_struct(pp
);
75 * Initialize the PNG read "engine"...
81 * Get the image dimensions and load the output image...
84 png_read_info(pp
, info
);
86 png_get_IHDR(pp
, info
, &width
, &height
, &bit_depth
, &color_type
,
87 &interlace_type
, &compression_type
, &filter_type
);
89 fprintf(stderr
, "DEBUG: PNG image: %dx%dx%d, color_type=%x (%s%s%s)\n",
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" : "");
95 if (color_type
& PNG_COLOR_MASK_PALETTE
)
97 else if (bit_depth
< 8)
102 else if (bit_depth
== 16)
103 png_set_strip_16(pp
);
105 if (color_type
& PNG_COLOR_MASK_COLOR
)
106 img
->colorspace
= (primary
== CUPS_IMAGE_RGB_CMYK
) ? CUPS_IMAGE_RGB
:
109 img
->colorspace
= secondary
;
111 if (width
== 0 || width
> CUPS_IMAGE_MAX_WIDTH
||
112 height
== 0 || height
> CUPS_IMAGE_MAX_HEIGHT
)
114 fprintf(stderr
, "DEBUG: PNG image has invalid dimensions %ux%u!\n",
115 (unsigned)width
, (unsigned)height
);
123 if ((xppm
= png_get_x_pixels_per_meter(pp
, info
)) != 0 &&
124 (yppm
= png_get_y_pixels_per_meter(pp
, info
)) != 0)
126 img
->xppi
= (int)((float)xppm
* 0.0254);
127 img
->yppi
= (int)((float)yppm
* 0.0254);
129 if (img
->xppi
== 0 || img
->yppi
== 0)
131 fprintf(stderr
, "DEBUG: PNG image has invalid resolution %dx%d PPI\n",
132 img
->xppi
, img
->yppi
);
134 img
->xppi
= img
->yppi
= 128;
138 cupsImageSetMaxTiles(img
, 0);
140 passes
= png_set_interlace_handling(pp
);
143 * Handle transparency...
146 if (png_get_valid(pp
, info
, PNG_INFO_tRNS
))
147 png_set_tRNS_to_alpha(pp
);
153 png_set_background(pp
, &bg
, PNG_BACKGROUND_GAMMA_SCREEN
, 0, 1.0);
158 * Load one row at a time...
161 if (color_type
== PNG_COLOR_TYPE_GRAY
||
162 color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
163 in
= malloc(img
->xsize
);
165 in
= malloc(img
->xsize
* 3);
170 * Interlaced images must be loaded all at once...
173 size_t bufsize
; /* Size of buffer */
176 if (color_type
== PNG_COLOR_TYPE_GRAY
||
177 color_type
== PNG_COLOR_TYPE_GRAY_ALPHA
)
179 bufsize
= img
->xsize
* img
->ysize
;
181 if ((bufsize
/ img
->ysize
) != img
->xsize
)
183 fprintf(stderr
, "DEBUG: PNG image dimensions (%ux%u) too large!\n",
184 (unsigned)width
, (unsigned)height
);
191 bufsize
= img
->xsize
* img
->ysize
* 3;
193 if ((bufsize
/ (img
->ysize
* 3)) != img
->xsize
)
195 fprintf(stderr
, "DEBUG: PNG image dimensions (%ux%u) too large!\n",
196 (unsigned)width
, (unsigned)height
);
202 in
= malloc(bufsize
);
205 bpp
= cupsImageGetDepth(img
);
206 out
= malloc(img
->xsize
* bpp
);
210 fputs("DEBUG: Unable to allocate memory for PNG image!\n", stderr
);
224 * Read the image, interlacing as needed...
227 for (pass
= 1; pass
<= passes
; pass
++)
228 for (inptr
= in
, y
= 0; y
< img
->ysize
; y
++)
230 png_read_row(pp
, (png_bytep
)inptr
, NULL
);
238 if (color_type
& PNG_COLOR_MASK_COLOR
)
240 if ((saturation
!= 100 || hue
!= 0) && bpp
> 1)
241 cupsImageRGBAdjust(inptr
, img
->xsize
, saturation
, hue
);
243 switch (img
->colorspace
)
245 case CUPS_IMAGE_WHITE
:
246 cupsImageRGBToWhite(inptr
, out
, img
->xsize
);
248 case CUPS_IMAGE_RGB
:
249 case CUPS_IMAGE_RGB_CMYK
:
250 cupsImageRGBToRGB(inptr
, out
, img
->xsize
);
252 case CUPS_IMAGE_BLACK
:
253 cupsImageRGBToBlack(inptr
, out
, img
->xsize
);
255 case CUPS_IMAGE_CMY
:
256 cupsImageRGBToCMY(inptr
, out
, img
->xsize
);
258 case CUPS_IMAGE_CMYK
:
259 cupsImageRGBToCMYK(inptr
, out
, img
->xsize
);
265 switch (img
->colorspace
)
267 case CUPS_IMAGE_WHITE
:
268 memcpy(out
, inptr
, img
->xsize
);
270 case CUPS_IMAGE_RGB
:
271 case CUPS_IMAGE_RGB_CMYK
:
272 cupsImageWhiteToRGB(inptr
, out
, img
->xsize
);
274 case CUPS_IMAGE_BLACK
:
275 cupsImageWhiteToBlack(inptr
, out
, img
->xsize
);
277 case CUPS_IMAGE_CMY
:
278 cupsImageWhiteToCMY(inptr
, out
, img
->xsize
);
280 case CUPS_IMAGE_CMYK
:
281 cupsImageWhiteToCMYK(inptr
, out
, img
->xsize
);
287 cupsImageLut(out
, img
->xsize
* bpp
, lut
);
289 _cupsImagePutRow(img
, 0, y
, img
->xsize
, out
);
294 if (color_type
& PNG_COLOR_MASK_COLOR
)
295 inptr
+= img
->xsize
* 3;
301 png_read_end(pp
, info
);
302 png_destroy_read_struct(&pp
, &info
, NULL
);
310 #endif /* HAVE_LIBPNG && HAVE_LIBZ */
314 * End of "$Id: image-png.c 7437 2008-04-09 03:16:10Z mike $".