FreeWRL / FreeX3D 4.3.0
readpng.c
1/*
2
3
4FreeWRL now only uses this on Linux machines.
5
6*/
7
8/****************************************************************************
9 This file is part of the FreeWRL/FreeX3D Distribution.
10
11 Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
12
13 FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
14 it under the terms of the GNU Lesser Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 FreeWRL/FreeX3D is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
25****************************************************************************/
26
27
28#include <config.h>
29
30// OLD_IPHONE_AQUA #if !defined(AQUA) && !defined(_ANDROID)
31#if !defined(_ANDROID)
32
33
34#include <png.h> /* libpng header; includes zlib.h */
35
36#include <system.h>
37#include <display.h>
38#include <internal.h>
39
40#include <libFreeWRL.h>
41
42#include "readpng.h" /* typedefs, common macros, public prototypes */
43
44/*---------------------------------------------------------------------------
45
46 rpng - simple PNG display program readpng.c
47
48 ---------------------------------------------------------------------------
49
50 Copyright (c) 1998-2000 Greg Roelofs. All rights reserved.
51
52 This software is provided "as is," without warranty of any kind,
53 express or implied. In no event shall the author or contributors
54 be held liable for any damages arising in any way from the use of
55 this software.
56
57 Permission is granted to anyone to use this software for any purpose,
58 including commercial applications, and to alter it and redistribute
59 it freely, subject to the following restrictions:
60
61 1. Redistributions of source code must retain the above copyright
62 notice, disclaimer, and this list of conditions.
63 2. Redistributions in binary form must reproduce the above copyright
64 notice, disclaimer, and this list of conditions in the documenta-
65 tion and/or other materials provided with the distribution.
66 3. All advertising materials mentioning features or use of this
67 software must display the following acknowledgment:
68
69 This product includes software developed by Greg Roelofs
70 and contributors for the book, "PNG: The Definitive Guide,"
71 published by O'Reilly and Associates.
72
73
74 JAS - changed to flip rows around - images were being used upside
75 down.
76
77 ---------------------------------------------------------------------------*/
78
79
80#ifndef UNUSED
81#define UNUSED(v) ((void) v)
82#endif
83
84/* future versions of libpng will provide this macro: */
85#ifndef png_jmpbuf
86# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
87#endif
88
89
90static png_structp png_ptr = NULL;
91static png_infop info_ptr = NULL;
92
93png_uint_32 width, height;
94int bit_depth, color_type;
95uch *image_data = NULL;
96
97/* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */
98
99int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight)
100{
101 uch sig[8];
102 size_t rv;
103
104 UNUSED(rv); // compiler warning mitigation
105
106 /* first do a quick check that the file really is a PNG image; could
107 * have used slightly more general png_sig_cmp() function instead */
108
109 rv=fread(sig, 1, 8, infile);
110#if ((PNG_LIBPNG_VER_MAJOR == 1) && (PNG_LIBPNG_VER_MINOR < 2))
111 if (!png_check_sig(sig, 8))
112#else
113 if (!png_sig_cmp(sig, 0, 8))
114#endif
115 return 1; /* bad signature */
116
117
118 /* could pass pointers to user-defined error handlers instead of NULLs: */
119
120 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
121 if (!png_ptr)
122 return 4; /* out of memory */
123
124 info_ptr = png_create_info_struct(png_ptr);
125 if (!info_ptr) {
126 png_destroy_read_struct(&png_ptr, NULL, NULL);
127 return 4; /* out of memory */
128 }
129
130
131 /* we could create a second info struct here (end_info), but it's only
132 * useful if we want to keep pre- and post-IDAT chunk info separated
133 * (mainly for PNG-aware image editors and converters) */
134
135
136 /* setjmp() must be called in every function that calls a PNG-reading
137 * libpng function */
138
139 if (setjmp(png_jmpbuf(png_ptr))) {
140 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
141 return 2;
142 }
143
144
145 png_init_io(png_ptr, infile);
146 png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */
147
148 png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */
149
150
151 /* alternatively, could make separate calls to png_get_image_width(),
152 * etc., but want bit_depth and color_type for later [don't care about
153 * compression_type and filter_type => NULLs] */
154
155 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
156 NULL, NULL, NULL);
157 *pWidth = width;
158 *pHeight = height;
159
160
161 /* OK, that's all we need for now; return happy */
162
163 return 0;
164}
165
166
167/* display_exponent == LUT_exponent * CRT_exponent */
168
169uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes)
170{
171 png_uint_32 i, rowbytes;
172 png_bytepp row_pointers = NULL;
173 UNUSED (display_exponent);
174
175
176 /* setjmp() must be called in every function that calls a PNG-reading
177 * libpng function */
178
179 if (setjmp(png_jmpbuf(png_ptr))) {
180 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
181 return NULL;
182 }
183
184
185 /* expand palette images to RGB, low-bit-depth grayscale images to 8 bits,
186 * transparency chunks to full alpha channel; strip 16-bit-per-sample
187 * images to 8 bits per sample; and convert grayscale to RGB[A] */
188
189 if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth <= 8)
190 png_set_expand(png_ptr);
191 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
192 png_set_expand(png_ptr);
193 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
194 png_set_expand(png_ptr);
195 if (bit_depth == 16)
196 png_set_strip_16(png_ptr);
197 /* JAS - breaks NIST testsif (color_type == PNG_COLOR_TYPE_GRAY ||
198 JAS - breaks NIST tests color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
199 JAS - breaks NIST tests png_set_gray_to_rgb(png_ptr); */
200
201
202 /* unlike the example in the libpng documentation, we have *no* idea where
203 * this file may have come from--so if it doesn't have a file gamma, don't
204 * do any correction ("do no harm") */
205
206 /*JAS - breaks NIST testsif (png_get_gAMA(png_ptr, info_ptr, &gamma))
207 //JAS - breaks NIST tests png_set_gamma(png_ptr, display_exponent, gamma); */
208
209
210 /* all transformations have been registered; now update info_ptr data,
211 * get rowbytes and channels, and allocate image memory */
212
213 png_read_update_info(png_ptr, info_ptr);
214
215 *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr);
216 *pChannels = (int)png_get_channels(png_ptr, info_ptr);
217
218 if ((image_data = MALLOC(uch *, rowbytes*height)) == NULL) {
219 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
220 return NULL;
221 }
222 if ((row_pointers = MALLOC(png_bytepp, height*sizeof(png_bytep))) == NULL) {
223 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
224 FREE_IF_NZ(image_data);
225 return NULL;
226 }
227
228 Trace((stderr, "readpng_get_image: channels = %d, rowbytes = %ld, height = %ld\n", *pChannels, rowbytes, height));
229
230
231 /* set the individual row_pointers to point at the correct offsets */
232
233 for (i = 0; i < height; ++i) {
234 /* JAS - flip rows around row_pointers[i] = image_data + i*rowbytes; */
235 row_pointers[i] = image_data + (height-i-1)*rowbytes;
236 }
237
238
239 /* now we can go ahead and just read the whole image */
240
241 png_read_image(png_ptr, row_pointers);
242
243
244 /* and we're done! (png_read_end() can be omitted if no processing of
245 * post-IDAT text/time/etc. is desired) */
246
247 FREE_IF_NZ(row_pointers);
248 row_pointers = NULL;
249
250 return image_data;
251}
252
253
254void readpng_cleanup(int free_image_data)
255{
256 if (free_image_data && image_data) {
257 FREE_IF_NZ(image_data);
258 }
259
260 if (png_ptr && info_ptr) {
261 png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
262 png_ptr = NULL;
263 info_ptr = NULL;
264 }
265}
266#endif
267