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