Mercurial > fife-parpg
comparison ext/libpng-1.2.29/contrib/gregbook/readpng.c @ 0:4a0efb7baf70
* Datasets becomes the new trunk and retires after that :-)
author | mvbarracuda@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Sun, 29 Jun 2008 18:44:17 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4a0efb7baf70 |
---|---|
1 /*--------------------------------------------------------------------------- | |
2 | |
3 rpng - simple PNG display program readpng.c | |
4 | |
5 --------------------------------------------------------------------------- | |
6 | |
7 Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. | |
8 | |
9 This software is provided "as is," without warranty of any kind, | |
10 express or implied. In no event shall the author or contributors | |
11 be held liable for any damages arising in any way from the use of | |
12 this software. | |
13 | |
14 The contents of this file are DUAL-LICENSED. You may modify and/or | |
15 redistribute this software according to the terms of one of the | |
16 following two licenses (at your option): | |
17 | |
18 | |
19 LICENSE 1 ("BSD-like with advertising clause"): | |
20 | |
21 Permission is granted to anyone to use this software for any purpose, | |
22 including commercial applications, and to alter it and redistribute | |
23 it freely, subject to the following restrictions: | |
24 | |
25 1. Redistributions of source code must retain the above copyright | |
26 notice, disclaimer, and this list of conditions. | |
27 2. Redistributions in binary form must reproduce the above copyright | |
28 notice, disclaimer, and this list of conditions in the documenta- | |
29 tion and/or other materials provided with the distribution. | |
30 3. All advertising materials mentioning features or use of this | |
31 software must display the following acknowledgment: | |
32 | |
33 This product includes software developed by Greg Roelofs | |
34 and contributors for the book, "PNG: The Definitive Guide," | |
35 published by O'Reilly and Associates. | |
36 | |
37 | |
38 LICENSE 2 (GNU GPL v2 or later): | |
39 | |
40 This program is free software; you can redistribute it and/or modify | |
41 it under the terms of the GNU General Public License as published by | |
42 the Free Software Foundation; either version 2 of the License, or | |
43 (at your option) any later version. | |
44 | |
45 This program is distributed in the hope that it will be useful, | |
46 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
47 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
48 GNU General Public License for more details. | |
49 | |
50 You should have received a copy of the GNU General Public License | |
51 along with this program; if not, write to the Free Software Foundation, | |
52 Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
53 | |
54 ---------------------------------------------------------------------------*/ | |
55 | |
56 #include <stdio.h> | |
57 #include <stdlib.h> | |
58 | |
59 #include "png.h" /* libpng header; includes zlib.h */ | |
60 #include "readpng.h" /* typedefs, common macros, public prototypes */ | |
61 | |
62 /* future versions of libpng will provide this macro: */ | |
63 #ifndef png_jmpbuf | |
64 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) | |
65 #endif | |
66 | |
67 | |
68 static png_structp png_ptr = NULL; | |
69 static png_infop info_ptr = NULL; | |
70 | |
71 png_uint_32 width, height; | |
72 int bit_depth, color_type; | |
73 uch *image_data = NULL; | |
74 | |
75 | |
76 void readpng_version_info(void) | |
77 { | |
78 fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n", | |
79 PNG_LIBPNG_VER_STRING, png_libpng_ver); | |
80 fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n", | |
81 ZLIB_VERSION, zlib_version); | |
82 } | |
83 | |
84 | |
85 /* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */ | |
86 | |
87 int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight) | |
88 { | |
89 uch sig[8]; | |
90 | |
91 | |
92 /* first do a quick check that the file really is a PNG image; could | |
93 * have used slightly more general png_sig_cmp() function instead */ | |
94 | |
95 fread(sig, 1, 8, infile); | |
96 if (!png_check_sig(sig, 8)) | |
97 return 1; /* bad signature */ | |
98 | |
99 | |
100 /* could pass pointers to user-defined error handlers instead of NULLs: */ | |
101 | |
102 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); | |
103 if (!png_ptr) | |
104 return 4; /* out of memory */ | |
105 | |
106 info_ptr = png_create_info_struct(png_ptr); | |
107 if (!info_ptr) { | |
108 png_destroy_read_struct(&png_ptr, NULL, NULL); | |
109 return 4; /* out of memory */ | |
110 } | |
111 | |
112 | |
113 /* we could create a second info struct here (end_info), but it's only | |
114 * useful if we want to keep pre- and post-IDAT chunk info separated | |
115 * (mainly for PNG-aware image editors and converters) */ | |
116 | |
117 | |
118 /* setjmp() must be called in every function that calls a PNG-reading | |
119 * libpng function */ | |
120 | |
121 if (setjmp(png_jmpbuf(png_ptr))) { | |
122 png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | |
123 return 2; | |
124 } | |
125 | |
126 | |
127 png_init_io(png_ptr, infile); | |
128 png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */ | |
129 | |
130 png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ | |
131 | |
132 | |
133 /* alternatively, could make separate calls to png_get_image_width(), | |
134 * etc., but want bit_depth and color_type for later [don't care about | |
135 * compression_type and filter_type => NULLs] */ | |
136 | |
137 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, | |
138 NULL, NULL, NULL); | |
139 *pWidth = width; | |
140 *pHeight = height; | |
141 | |
142 | |
143 /* OK, that's all we need for now; return happy */ | |
144 | |
145 return 0; | |
146 } | |
147 | |
148 | |
149 | |
150 | |
151 /* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error; | |
152 * scales values to 8-bit if necessary */ | |
153 | |
154 int readpng_get_bgcolor(uch *red, uch *green, uch *blue) | |
155 { | |
156 png_color_16p pBackground; | |
157 | |
158 | |
159 /* setjmp() must be called in every function that calls a PNG-reading | |
160 * libpng function */ | |
161 | |
162 if (setjmp(png_jmpbuf(png_ptr))) { | |
163 png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | |
164 return 2; | |
165 } | |
166 | |
167 | |
168 if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) | |
169 return 1; | |
170 | |
171 /* it is not obvious from the libpng documentation, but this function | |
172 * takes a pointer to a pointer, and it always returns valid red, green | |
173 * and blue values, regardless of color_type: */ | |
174 | |
175 png_get_bKGD(png_ptr, info_ptr, &pBackground); | |
176 | |
177 | |
178 /* however, it always returns the raw bKGD data, regardless of any | |
179 * bit-depth transformations, so check depth and adjust if necessary */ | |
180 | |
181 if (bit_depth == 16) { | |
182 *red = pBackground->red >> 8; | |
183 *green = pBackground->green >> 8; | |
184 *blue = pBackground->blue >> 8; | |
185 } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { | |
186 if (bit_depth == 1) | |
187 *red = *green = *blue = pBackground->gray? 255 : 0; | |
188 else if (bit_depth == 2) | |
189 *red = *green = *blue = (255/3) * pBackground->gray; | |
190 else /* bit_depth == 4 */ | |
191 *red = *green = *blue = (255/15) * pBackground->gray; | |
192 } else { | |
193 *red = (uch)pBackground->red; | |
194 *green = (uch)pBackground->green; | |
195 *blue = (uch)pBackground->blue; | |
196 } | |
197 | |
198 return 0; | |
199 } | |
200 | |
201 | |
202 | |
203 | |
204 /* display_exponent == LUT_exponent * CRT_exponent */ | |
205 | |
206 uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes) | |
207 { | |
208 double gamma; | |
209 png_uint_32 i, rowbytes; | |
210 png_bytepp row_pointers = NULL; | |
211 | |
212 | |
213 /* setjmp() must be called in every function that calls a PNG-reading | |
214 * libpng function */ | |
215 | |
216 if (setjmp(png_jmpbuf(png_ptr))) { | |
217 png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | |
218 return NULL; | |
219 } | |
220 | |
221 | |
222 /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits, | |
223 * transparency chunks to full alpha channel; strip 16-bit-per-sample | |
224 * images to 8 bits per sample; and convert grayscale to RGB[A] */ | |
225 | |
226 if (color_type == PNG_COLOR_TYPE_PALETTE) | |
227 png_set_expand(png_ptr); | |
228 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) | |
229 png_set_expand(png_ptr); | |
230 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) | |
231 png_set_expand(png_ptr); | |
232 if (bit_depth == 16) | |
233 png_set_strip_16(png_ptr); | |
234 if (color_type == PNG_COLOR_TYPE_GRAY || | |
235 color_type == PNG_COLOR_TYPE_GRAY_ALPHA) | |
236 png_set_gray_to_rgb(png_ptr); | |
237 | |
238 | |
239 /* unlike the example in the libpng documentation, we have *no* idea where | |
240 * this file may have come from--so if it doesn't have a file gamma, don't | |
241 * do any correction ("do no harm") */ | |
242 | |
243 if (png_get_gAMA(png_ptr, info_ptr, &gamma)) | |
244 png_set_gamma(png_ptr, display_exponent, gamma); | |
245 | |
246 | |
247 /* all transformations have been registered; now update info_ptr data, | |
248 * get rowbytes and channels, and allocate image memory */ | |
249 | |
250 png_read_update_info(png_ptr, info_ptr); | |
251 | |
252 *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr); | |
253 *pChannels = (int)png_get_channels(png_ptr, info_ptr); | |
254 | |
255 if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) { | |
256 png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | |
257 return NULL; | |
258 } | |
259 if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) { | |
260 png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | |
261 free(image_data); | |
262 image_data = NULL; | |
263 return NULL; | |
264 } | |
265 | |
266 Trace((stderr, "readpng_get_image: channels = %d, rowbytes = %ld, height = %ld\n", *pChannels, rowbytes, height)); | |
267 | |
268 | |
269 /* set the individual row_pointers to point at the correct offsets */ | |
270 | |
271 for (i = 0; i < height; ++i) | |
272 row_pointers[i] = image_data + i*rowbytes; | |
273 | |
274 | |
275 /* now we can go ahead and just read the whole image */ | |
276 | |
277 png_read_image(png_ptr, row_pointers); | |
278 | |
279 | |
280 /* and we're done! (png_read_end() can be omitted if no processing of | |
281 * post-IDAT text/time/etc. is desired) */ | |
282 | |
283 free(row_pointers); | |
284 row_pointers = NULL; | |
285 | |
286 png_read_end(png_ptr, NULL); | |
287 | |
288 return image_data; | |
289 } | |
290 | |
291 | |
292 void readpng_cleanup(int free_image_data) | |
293 { | |
294 if (free_image_data && image_data) { | |
295 free(image_data); | |
296 image_data = NULL; | |
297 } | |
298 | |
299 if (png_ptr && info_ptr) { | |
300 png_destroy_read_struct(&png_ptr, &info_ptr, NULL); | |
301 png_ptr = NULL; | |
302 info_ptr = NULL; | |
303 } | |
304 } |