FreeWRL/FreeX3D  3.0.0
readpng.c
1 /*
2 
3 
4 FreeWRL 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 
90 static png_structp png_ptr = NULL;
91 static png_infop info_ptr = NULL;
92 
93 png_uint_32 width, height;
94 int bit_depth, color_type;
95 uch *image_data = NULL;
96 
97 /* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */
98 
99 int 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 
169 uch *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 
254 void 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