xref: /aosp_15_r20/external/libpng/contrib/gregbook/readpng.c (revision a67afe4df73cf47866eedc69947994b8ff839aba)
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