xref: /aosp_15_r20/external/libpng/contrib/examples/pngpixel.c (revision a67afe4df73cf47866eedc69947994b8ff839aba)
1*a67afe4dSAndroid Build Coastguard Worker /*- pngpixel
2*a67afe4dSAndroid Build Coastguard Worker  *
3*a67afe4dSAndroid Build Coastguard Worker  * COPYRIGHT: Written by John Cunningham Bowler, 2011.
4*a67afe4dSAndroid Build Coastguard Worker  * To the extent possible under law, the author has waived all copyright and
5*a67afe4dSAndroid Build Coastguard Worker  * related or neighboring rights to this work.  This work is published from:
6*a67afe4dSAndroid Build Coastguard Worker  * United States.
7*a67afe4dSAndroid Build Coastguard Worker  *
8*a67afe4dSAndroid Build Coastguard Worker  * Read a single pixel value from a PNG file.
9*a67afe4dSAndroid Build Coastguard Worker  *
10*a67afe4dSAndroid Build Coastguard Worker  * This code illustrates basic 'by-row' reading of a PNG file using libpng.
11*a67afe4dSAndroid Build Coastguard Worker  * Rows are read until a particular pixel is found; the value of this pixel is
12*a67afe4dSAndroid Build Coastguard Worker  * then printed on stdout.
13*a67afe4dSAndroid Build Coastguard Worker  *
14*a67afe4dSAndroid Build Coastguard Worker  * The code illustrates how to do this on interlaced as well as non-interlaced
15*a67afe4dSAndroid Build Coastguard Worker  * images.  Normally you would call png_set_interlace_handling() to have libpng
16*a67afe4dSAndroid Build Coastguard Worker  * deal with the interlace for you, but that obliges you to buffer half of the
17*a67afe4dSAndroid Build Coastguard Worker  * image to assemble the interlaced rows.  In this code
18*a67afe4dSAndroid Build Coastguard Worker  * png_set_interlace_handling() is not called and, instead, the code handles the
19*a67afe4dSAndroid Build Coastguard Worker  * interlace passes directly looking for the required pixel.
20*a67afe4dSAndroid Build Coastguard Worker  */
21*a67afe4dSAndroid Build Coastguard Worker #include <stdlib.h>
22*a67afe4dSAndroid Build Coastguard Worker #include <stdio.h>
23*a67afe4dSAndroid Build Coastguard Worker #include <setjmp.h> /* required for error handling */
24*a67afe4dSAndroid Build Coastguard Worker 
25*a67afe4dSAndroid Build Coastguard Worker /* Normally use <png.h> here to get the installed libpng, but this is done to
26*a67afe4dSAndroid Build Coastguard Worker  * ensure the code picks up the local libpng implementation:
27*a67afe4dSAndroid Build Coastguard Worker  */
28*a67afe4dSAndroid Build Coastguard Worker #include "../../png.h"
29*a67afe4dSAndroid Build Coastguard Worker 
30*a67afe4dSAndroid Build Coastguard Worker #if defined(PNG_READ_SUPPORTED) && defined(PNG_SEQUENTIAL_READ_SUPPORTED)
31*a67afe4dSAndroid Build Coastguard Worker 
32*a67afe4dSAndroid Build Coastguard Worker /* Return component 'c' of pixel 'x' from the given row. */
33*a67afe4dSAndroid Build Coastguard Worker static unsigned int
component(png_const_bytep row,png_uint_32 x,unsigned int c,unsigned int bit_depth,unsigned int channels)34*a67afe4dSAndroid Build Coastguard Worker component(png_const_bytep row, png_uint_32 x, unsigned int c,
35*a67afe4dSAndroid Build Coastguard Worker    unsigned int bit_depth, unsigned int channels)
36*a67afe4dSAndroid Build Coastguard Worker {
37*a67afe4dSAndroid Build Coastguard Worker    /* PNG images can be up to 2^31 pixels wide, but this means they can be up to
38*a67afe4dSAndroid Build Coastguard Worker     * 2^37 bits wide (for a 64-bit pixel - the largest possible) and hence 2^34
39*a67afe4dSAndroid Build Coastguard Worker     * bytes wide.  Since the row fitted into memory, however, the following must
40*a67afe4dSAndroid Build Coastguard Worker     * work:
41*a67afe4dSAndroid Build Coastguard Worker     */
42*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 bit_offset_hi = bit_depth * ((x >> 6) * channels);
43*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 bit_offset_lo = bit_depth * ((x & 0x3f) * channels + c);
44*a67afe4dSAndroid Build Coastguard Worker 
45*a67afe4dSAndroid Build Coastguard Worker    row = (png_const_bytep)(((const png_byte (*)[8])row) + bit_offset_hi);
46*a67afe4dSAndroid Build Coastguard Worker    row += bit_offset_lo >> 3;
47*a67afe4dSAndroid Build Coastguard Worker    bit_offset_lo &= 0x07;
48*a67afe4dSAndroid Build Coastguard Worker 
49*a67afe4dSAndroid Build Coastguard Worker    /* PNG pixels are packed into bytes to put the first pixel in the highest
50*a67afe4dSAndroid Build Coastguard Worker     * bits of the byte and into two bytes for 16-bit values with the high 8 bits
51*a67afe4dSAndroid Build Coastguard Worker     * first, so:
52*a67afe4dSAndroid Build Coastguard Worker     */
53*a67afe4dSAndroid Build Coastguard Worker    switch (bit_depth)
54*a67afe4dSAndroid Build Coastguard Worker    {
55*a67afe4dSAndroid Build Coastguard Worker       case 1: return (row[0] >> (7-bit_offset_lo)) & 0x01;
56*a67afe4dSAndroid Build Coastguard Worker       case 2: return (row[0] >> (6-bit_offset_lo)) & 0x03;
57*a67afe4dSAndroid Build Coastguard Worker       case 4: return (row[0] >> (4-bit_offset_lo)) & 0x0f;
58*a67afe4dSAndroid Build Coastguard Worker       case 8: return row[0];
59*a67afe4dSAndroid Build Coastguard Worker       case 16: return (row[0] << 8) + row[1];
60*a67afe4dSAndroid Build Coastguard Worker       default:
61*a67afe4dSAndroid Build Coastguard Worker          /* This should never happen; it indicates a bug in this program or in
62*a67afe4dSAndroid Build Coastguard Worker           * libpng itself:
63*a67afe4dSAndroid Build Coastguard Worker           */
64*a67afe4dSAndroid Build Coastguard Worker          fprintf(stderr, "pngpixel: invalid bit depth %u\n", bit_depth);
65*a67afe4dSAndroid Build Coastguard Worker          exit(1);
66*a67afe4dSAndroid Build Coastguard Worker    }
67*a67afe4dSAndroid Build Coastguard Worker }
68*a67afe4dSAndroid Build Coastguard Worker 
69*a67afe4dSAndroid Build Coastguard Worker /* Print a pixel from a row returned by libpng; determine the row format, find
70*a67afe4dSAndroid Build Coastguard Worker  * the pixel, and print the relevant information to stdout.
71*a67afe4dSAndroid Build Coastguard Worker  */
72*a67afe4dSAndroid Build Coastguard Worker static void
print_pixel(png_structp png_ptr,png_infop info_ptr,png_const_bytep row,png_uint_32 x)73*a67afe4dSAndroid Build Coastguard Worker print_pixel(png_structp png_ptr, png_infop info_ptr, png_const_bytep row,
74*a67afe4dSAndroid Build Coastguard Worker    png_uint_32 x)
75*a67afe4dSAndroid Build Coastguard Worker {
76*a67afe4dSAndroid Build Coastguard Worker    unsigned int bit_depth = png_get_bit_depth(png_ptr, info_ptr);
77*a67afe4dSAndroid Build Coastguard Worker 
78*a67afe4dSAndroid Build Coastguard Worker    switch (png_get_color_type(png_ptr, info_ptr))
79*a67afe4dSAndroid Build Coastguard Worker    {
80*a67afe4dSAndroid Build Coastguard Worker       case PNG_COLOR_TYPE_GRAY:
81*a67afe4dSAndroid Build Coastguard Worker          printf("GRAY %u\n", component(row, x, 0, bit_depth, 1));
82*a67afe4dSAndroid Build Coastguard Worker          return;
83*a67afe4dSAndroid Build Coastguard Worker 
84*a67afe4dSAndroid Build Coastguard Worker       /* The palette case is slightly more difficult - the palette and, if
85*a67afe4dSAndroid Build Coastguard Worker        * present, the tRNS ('transparency', though the values are really
86*a67afe4dSAndroid Build Coastguard Worker        * opacity) data must be read to give the full picture:
87*a67afe4dSAndroid Build Coastguard Worker        */
88*a67afe4dSAndroid Build Coastguard Worker       case PNG_COLOR_TYPE_PALETTE:
89*a67afe4dSAndroid Build Coastguard Worker          {
90*a67afe4dSAndroid Build Coastguard Worker             int index = component(row, x, 0, bit_depth, 1);
91*a67afe4dSAndroid Build Coastguard Worker             png_colorp palette = NULL;
92*a67afe4dSAndroid Build Coastguard Worker             int num_palette = 0;
93*a67afe4dSAndroid Build Coastguard Worker 
94*a67afe4dSAndroid Build Coastguard Worker             if ((png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) &
95*a67afe4dSAndroid Build Coastguard Worker                PNG_INFO_PLTE) && num_palette > 0 && palette != NULL)
96*a67afe4dSAndroid Build Coastguard Worker             {
97*a67afe4dSAndroid Build Coastguard Worker                png_bytep trans_alpha = NULL;
98*a67afe4dSAndroid Build Coastguard Worker                int num_trans = 0;
99*a67afe4dSAndroid Build Coastguard Worker                if ((png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans,
100*a67afe4dSAndroid Build Coastguard Worker                   NULL) & PNG_INFO_tRNS) && num_trans > 0 &&
101*a67afe4dSAndroid Build Coastguard Worker                   trans_alpha != NULL)
102*a67afe4dSAndroid Build Coastguard Worker                   printf("INDEXED %u = %d %d %d %d\n", index,
103*a67afe4dSAndroid Build Coastguard Worker                      palette[index].red, palette[index].green,
104*a67afe4dSAndroid Build Coastguard Worker                      palette[index].blue,
105*a67afe4dSAndroid Build Coastguard Worker                      index < num_trans ? trans_alpha[index] : 255);
106*a67afe4dSAndroid Build Coastguard Worker 
107*a67afe4dSAndroid Build Coastguard Worker                else /* no transparency */
108*a67afe4dSAndroid Build Coastguard Worker                   printf("INDEXED %u = %d %d %d\n", index,
109*a67afe4dSAndroid Build Coastguard Worker                      palette[index].red, palette[index].green,
110*a67afe4dSAndroid Build Coastguard Worker                      palette[index].blue);
111*a67afe4dSAndroid Build Coastguard Worker             }
112*a67afe4dSAndroid Build Coastguard Worker 
113*a67afe4dSAndroid Build Coastguard Worker             else
114*a67afe4dSAndroid Build Coastguard Worker                printf("INDEXED %u = invalid index\n", index);
115*a67afe4dSAndroid Build Coastguard Worker          }
116*a67afe4dSAndroid Build Coastguard Worker          return;
117*a67afe4dSAndroid Build Coastguard Worker 
118*a67afe4dSAndroid Build Coastguard Worker       case PNG_COLOR_TYPE_RGB:
119*a67afe4dSAndroid Build Coastguard Worker          printf("RGB %u %u %u\n", component(row, x, 0, bit_depth, 3),
120*a67afe4dSAndroid Build Coastguard Worker             component(row, x, 1, bit_depth, 3),
121*a67afe4dSAndroid Build Coastguard Worker             component(row, x, 2, bit_depth, 3));
122*a67afe4dSAndroid Build Coastguard Worker          return;
123*a67afe4dSAndroid Build Coastguard Worker 
124*a67afe4dSAndroid Build Coastguard Worker       case PNG_COLOR_TYPE_GRAY_ALPHA:
125*a67afe4dSAndroid Build Coastguard Worker          printf("GRAY+ALPHA %u %u\n", component(row, x, 0, bit_depth, 2),
126*a67afe4dSAndroid Build Coastguard Worker             component(row, x, 1, bit_depth, 2));
127*a67afe4dSAndroid Build Coastguard Worker          return;
128*a67afe4dSAndroid Build Coastguard Worker 
129*a67afe4dSAndroid Build Coastguard Worker       case PNG_COLOR_TYPE_RGB_ALPHA:
130*a67afe4dSAndroid Build Coastguard Worker          printf("RGBA %u %u %u %u\n", component(row, x, 0, bit_depth, 4),
131*a67afe4dSAndroid Build Coastguard Worker             component(row, x, 1, bit_depth, 4),
132*a67afe4dSAndroid Build Coastguard Worker             component(row, x, 2, bit_depth, 4),
133*a67afe4dSAndroid Build Coastguard Worker             component(row, x, 3, bit_depth, 4));
134*a67afe4dSAndroid Build Coastguard Worker          return;
135*a67afe4dSAndroid Build Coastguard Worker 
136*a67afe4dSAndroid Build Coastguard Worker       default:
137*a67afe4dSAndroid Build Coastguard Worker          png_error(png_ptr, "pngpixel: invalid color type");
138*a67afe4dSAndroid Build Coastguard Worker    }
139*a67afe4dSAndroid Build Coastguard Worker }
140*a67afe4dSAndroid Build Coastguard Worker 
main(int argc,const char ** argv)141*a67afe4dSAndroid Build Coastguard Worker int main(int argc, const char **argv)
142*a67afe4dSAndroid Build Coastguard Worker {
143*a67afe4dSAndroid Build Coastguard Worker    /* This program uses the default, <setjmp.h> based, libpng error handling
144*a67afe4dSAndroid Build Coastguard Worker     * mechanism, therefore any local variable that exists before the call to
145*a67afe4dSAndroid Build Coastguard Worker     * setjmp and is changed after the call to setjmp returns successfully must
146*a67afe4dSAndroid Build Coastguard Worker     * be declared with 'volatile' to ensure that their values don't get
147*a67afe4dSAndroid Build Coastguard Worker     * destroyed by longjmp:
148*a67afe4dSAndroid Build Coastguard Worker     */
149*a67afe4dSAndroid Build Coastguard Worker    volatile int result = 1/*fail*/;
150*a67afe4dSAndroid Build Coastguard Worker 
151*a67afe4dSAndroid Build Coastguard Worker    if (argc == 4)
152*a67afe4dSAndroid Build Coastguard Worker    {
153*a67afe4dSAndroid Build Coastguard Worker       long x = atol(argv[1]);
154*a67afe4dSAndroid Build Coastguard Worker       long y = atol(argv[2]);
155*a67afe4dSAndroid Build Coastguard Worker       FILE *f = fopen(argv[3], "rb");
156*a67afe4dSAndroid Build Coastguard Worker       volatile png_bytep row = NULL;
157*a67afe4dSAndroid Build Coastguard Worker 
158*a67afe4dSAndroid Build Coastguard Worker       if (f != NULL)
159*a67afe4dSAndroid Build Coastguard Worker       {
160*a67afe4dSAndroid Build Coastguard Worker          /* libpng requires a callback function for handling errors; this
161*a67afe4dSAndroid Build Coastguard Worker           * callback must not return.  The default callback function uses a
162*a67afe4dSAndroid Build Coastguard Worker           * stored <setjmp.h> style jmp_buf which is held in a png_struct and
163*a67afe4dSAndroid Build Coastguard Worker           * writes error messages to stderr.  Creating the png_struct is a
164*a67afe4dSAndroid Build Coastguard Worker           * little tricky; just copy the following code.
165*a67afe4dSAndroid Build Coastguard Worker           */
166*a67afe4dSAndroid Build Coastguard Worker          png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
167*a67afe4dSAndroid Build Coastguard Worker             NULL, NULL, NULL);
168*a67afe4dSAndroid Build Coastguard Worker 
169*a67afe4dSAndroid Build Coastguard Worker          if (png_ptr != NULL)
170*a67afe4dSAndroid Build Coastguard Worker          {
171*a67afe4dSAndroid Build Coastguard Worker             png_infop info_ptr = png_create_info_struct(png_ptr);
172*a67afe4dSAndroid Build Coastguard Worker 
173*a67afe4dSAndroid Build Coastguard Worker             if (info_ptr != NULL)
174*a67afe4dSAndroid Build Coastguard Worker             {
175*a67afe4dSAndroid Build Coastguard Worker                /* Declare stack variables to hold pointers to locally allocated
176*a67afe4dSAndroid Build Coastguard Worker                 * data.
177*a67afe4dSAndroid Build Coastguard Worker                 */
178*a67afe4dSAndroid Build Coastguard Worker 
179*a67afe4dSAndroid Build Coastguard Worker                /* Initialize the error control buffer: */
180*a67afe4dSAndroid Build Coastguard Worker                if (setjmp(png_jmpbuf(png_ptr)) == 0)
181*a67afe4dSAndroid Build Coastguard Worker                {
182*a67afe4dSAndroid Build Coastguard Worker                   png_uint_32 width, height;
183*a67afe4dSAndroid Build Coastguard Worker                   int bit_depth, color_type, interlace_method,
184*a67afe4dSAndroid Build Coastguard Worker                      compression_method, filter_method;
185*a67afe4dSAndroid Build Coastguard Worker                   png_bytep row_tmp;
186*a67afe4dSAndroid Build Coastguard Worker 
187*a67afe4dSAndroid Build Coastguard Worker                   /* Now associate the recently opened (FILE*) with the default
188*a67afe4dSAndroid Build Coastguard Worker                    * libpng initialization functions.  Sometimes libpng is
189*a67afe4dSAndroid Build Coastguard Worker                    * compiled without stdio support (it can be difficult to do
190*a67afe4dSAndroid Build Coastguard Worker                    * in some environments); in that case you will have to write
191*a67afe4dSAndroid Build Coastguard Worker                    * your own read callback to read data from the (FILE*).
192*a67afe4dSAndroid Build Coastguard Worker                    */
193*a67afe4dSAndroid Build Coastguard Worker                   png_init_io(png_ptr, f);
194*a67afe4dSAndroid Build Coastguard Worker 
195*a67afe4dSAndroid Build Coastguard Worker                   /* And read the first part of the PNG file - the header and
196*a67afe4dSAndroid Build Coastguard Worker                    * all the information up to the first pixel.
197*a67afe4dSAndroid Build Coastguard Worker                    */
198*a67afe4dSAndroid Build Coastguard Worker                   png_read_info(png_ptr, info_ptr);
199*a67afe4dSAndroid Build Coastguard Worker 
200*a67afe4dSAndroid Build Coastguard Worker                   /* This fills in enough information to tell us the width of
201*a67afe4dSAndroid Build Coastguard Worker                    * each row in bytes, allocate the appropriate amount of
202*a67afe4dSAndroid Build Coastguard Worker                    * space.  In this case png_malloc is used - it will not
203*a67afe4dSAndroid Build Coastguard Worker                    * return if memory isn't available.
204*a67afe4dSAndroid Build Coastguard Worker                    */
205*a67afe4dSAndroid Build Coastguard Worker                   row = png_malloc(png_ptr, png_get_rowbytes(png_ptr,
206*a67afe4dSAndroid Build Coastguard Worker                      info_ptr));
207*a67afe4dSAndroid Build Coastguard Worker 
208*a67afe4dSAndroid Build Coastguard Worker                   /* To avoid the overhead of using a volatile auto copy row_tmp
209*a67afe4dSAndroid Build Coastguard Worker                    * to a local here - just use row for the png_free below.
210*a67afe4dSAndroid Build Coastguard Worker                    */
211*a67afe4dSAndroid Build Coastguard Worker                   row_tmp = row;
212*a67afe4dSAndroid Build Coastguard Worker 
213*a67afe4dSAndroid Build Coastguard Worker                   /* All the information we need is in the header is returned by
214*a67afe4dSAndroid Build Coastguard Worker                    * png_get_IHDR, if this fails we can now use 'png_error' to
215*a67afe4dSAndroid Build Coastguard Worker                    * signal the error and return control to the setjmp above.
216*a67afe4dSAndroid Build Coastguard Worker                    */
217*a67afe4dSAndroid Build Coastguard Worker                   if (png_get_IHDR(png_ptr, info_ptr, &width, &height,
218*a67afe4dSAndroid Build Coastguard Worker                      &bit_depth, &color_type, &interlace_method,
219*a67afe4dSAndroid Build Coastguard Worker                      &compression_method, &filter_method))
220*a67afe4dSAndroid Build Coastguard Worker                   {
221*a67afe4dSAndroid Build Coastguard Worker                      int passes, pass;
222*a67afe4dSAndroid Build Coastguard Worker 
223*a67afe4dSAndroid Build Coastguard Worker                      /* png_set_interlace_handling returns the number of
224*a67afe4dSAndroid Build Coastguard Worker                       * passes required as well as turning on libpng's
225*a67afe4dSAndroid Build Coastguard Worker                       * handling, but since we do it ourselves this is
226*a67afe4dSAndroid Build Coastguard Worker                       * necessary:
227*a67afe4dSAndroid Build Coastguard Worker                       */
228*a67afe4dSAndroid Build Coastguard Worker                      switch (interlace_method)
229*a67afe4dSAndroid Build Coastguard Worker                      {
230*a67afe4dSAndroid Build Coastguard Worker                         case PNG_INTERLACE_NONE:
231*a67afe4dSAndroid Build Coastguard Worker                            passes = 1;
232*a67afe4dSAndroid Build Coastguard Worker                            break;
233*a67afe4dSAndroid Build Coastguard Worker 
234*a67afe4dSAndroid Build Coastguard Worker                         case PNG_INTERLACE_ADAM7:
235*a67afe4dSAndroid Build Coastguard Worker                            passes = PNG_INTERLACE_ADAM7_PASSES;
236*a67afe4dSAndroid Build Coastguard Worker                            break;
237*a67afe4dSAndroid Build Coastguard Worker 
238*a67afe4dSAndroid Build Coastguard Worker                         default:
239*a67afe4dSAndroid Build Coastguard Worker                            png_error(png_ptr, "pngpixel: unknown interlace");
240*a67afe4dSAndroid Build Coastguard Worker                      }
241*a67afe4dSAndroid Build Coastguard Worker 
242*a67afe4dSAndroid Build Coastguard Worker                      /* Now read the pixels, pass-by-pass, row-by-row: */
243*a67afe4dSAndroid Build Coastguard Worker                      png_start_read_image(png_ptr);
244*a67afe4dSAndroid Build Coastguard Worker 
245*a67afe4dSAndroid Build Coastguard Worker                      for (pass=0; pass<passes; ++pass)
246*a67afe4dSAndroid Build Coastguard Worker                      {
247*a67afe4dSAndroid Build Coastguard Worker                         png_uint_32 ystart, xstart, ystep, xstep;
248*a67afe4dSAndroid Build Coastguard Worker                         png_uint_32 py;
249*a67afe4dSAndroid Build Coastguard Worker 
250*a67afe4dSAndroid Build Coastguard Worker                         if (interlace_method == PNG_INTERLACE_ADAM7)
251*a67afe4dSAndroid Build Coastguard Worker                         {
252*a67afe4dSAndroid Build Coastguard Worker                            /* Sometimes the whole pass is empty because the
253*a67afe4dSAndroid Build Coastguard Worker                             * image is too narrow or too short.  libpng
254*a67afe4dSAndroid Build Coastguard Worker                             * expects to be called for each row that is
255*a67afe4dSAndroid Build Coastguard Worker                             * present in the pass, so it may be necessary to
256*a67afe4dSAndroid Build Coastguard Worker                             * skip the loop below (over py) if the image is
257*a67afe4dSAndroid Build Coastguard Worker                             * too narrow.
258*a67afe4dSAndroid Build Coastguard Worker                             */
259*a67afe4dSAndroid Build Coastguard Worker                            if (PNG_PASS_COLS(width, pass) == 0)
260*a67afe4dSAndroid Build Coastguard Worker                               continue;
261*a67afe4dSAndroid Build Coastguard Worker 
262*a67afe4dSAndroid Build Coastguard Worker                            /* We need the starting pixel and the offset
263*a67afe4dSAndroid Build Coastguard Worker                             * between each pixel in this pass; use the macros
264*a67afe4dSAndroid Build Coastguard Worker                             * in png.h:
265*a67afe4dSAndroid Build Coastguard Worker                             */
266*a67afe4dSAndroid Build Coastguard Worker                            xstart = PNG_PASS_START_COL(pass);
267*a67afe4dSAndroid Build Coastguard Worker                            ystart = PNG_PASS_START_ROW(pass);
268*a67afe4dSAndroid Build Coastguard Worker                            xstep = PNG_PASS_COL_OFFSET(pass);
269*a67afe4dSAndroid Build Coastguard Worker                            ystep = PNG_PASS_ROW_OFFSET(pass);
270*a67afe4dSAndroid Build Coastguard Worker                         }
271*a67afe4dSAndroid Build Coastguard Worker 
272*a67afe4dSAndroid Build Coastguard Worker                         else
273*a67afe4dSAndroid Build Coastguard Worker                         {
274*a67afe4dSAndroid Build Coastguard Worker                            ystart = xstart = 0;
275*a67afe4dSAndroid Build Coastguard Worker                            ystep = xstep = 1;
276*a67afe4dSAndroid Build Coastguard Worker                         }
277*a67afe4dSAndroid Build Coastguard Worker 
278*a67afe4dSAndroid Build Coastguard Worker                         /* To find the pixel, loop over 'py' for each pass
279*a67afe4dSAndroid Build Coastguard Worker                          * reading a row and then checking to see if it
280*a67afe4dSAndroid Build Coastguard Worker                          * contains the pixel.
281*a67afe4dSAndroid Build Coastguard Worker                          */
282*a67afe4dSAndroid Build Coastguard Worker                         for (py = ystart; py < height; py += ystep)
283*a67afe4dSAndroid Build Coastguard Worker                         {
284*a67afe4dSAndroid Build Coastguard Worker                            png_uint_32 px, ppx;
285*a67afe4dSAndroid Build Coastguard Worker 
286*a67afe4dSAndroid Build Coastguard Worker                            /* png_read_row takes two pointers.  When libpng
287*a67afe4dSAndroid Build Coastguard Worker                             * handles the interlace the first is filled in
288*a67afe4dSAndroid Build Coastguard Worker                             * pixel-by-pixel, and the second receives the same
289*a67afe4dSAndroid Build Coastguard Worker                             * pixels but they are replicated across the
290*a67afe4dSAndroid Build Coastguard Worker                             * unwritten pixels so far for each pass.  When we
291*a67afe4dSAndroid Build Coastguard Worker                             * do the interlace, however, they just contain
292*a67afe4dSAndroid Build Coastguard Worker                             * the pixels from the interlace pass - giving
293*a67afe4dSAndroid Build Coastguard Worker                             * both is wasteful and pointless, so we pass a
294*a67afe4dSAndroid Build Coastguard Worker                             * NULL pointer.
295*a67afe4dSAndroid Build Coastguard Worker                             */
296*a67afe4dSAndroid Build Coastguard Worker                            png_read_row(png_ptr, row_tmp, NULL);
297*a67afe4dSAndroid Build Coastguard Worker 
298*a67afe4dSAndroid Build Coastguard Worker                            /* Now find the pixel if it is in this row; there
299*a67afe4dSAndroid Build Coastguard Worker                             * are, of course, much better ways of doing this
300*a67afe4dSAndroid Build Coastguard Worker                             * than using a for loop:
301*a67afe4dSAndroid Build Coastguard Worker                             */
302*a67afe4dSAndroid Build Coastguard Worker                            if (y == py) for (px = xstart, ppx = 0;
303*a67afe4dSAndroid Build Coastguard Worker                               px < width; px += xstep, ++ppx) if (x == px)
304*a67afe4dSAndroid Build Coastguard Worker                            {
305*a67afe4dSAndroid Build Coastguard Worker                               /* 'ppx' is the index of the pixel in the row
306*a67afe4dSAndroid Build Coastguard Worker                                * buffer.
307*a67afe4dSAndroid Build Coastguard Worker                                */
308*a67afe4dSAndroid Build Coastguard Worker                               print_pixel(png_ptr, info_ptr, row_tmp, ppx);
309*a67afe4dSAndroid Build Coastguard Worker 
310*a67afe4dSAndroid Build Coastguard Worker                               /* Now terminate the loops early - we have
311*a67afe4dSAndroid Build Coastguard Worker                                * found and handled the required data.
312*a67afe4dSAndroid Build Coastguard Worker                                */
313*a67afe4dSAndroid Build Coastguard Worker                               goto pass_loop_end;
314*a67afe4dSAndroid Build Coastguard Worker                            } /* x loop */
315*a67afe4dSAndroid Build Coastguard Worker                         } /* y loop */
316*a67afe4dSAndroid Build Coastguard Worker                      } /* pass loop */
317*a67afe4dSAndroid Build Coastguard Worker 
318*a67afe4dSAndroid Build Coastguard Worker                      /* Finally free the temporary buffer: */
319*a67afe4dSAndroid Build Coastguard Worker                   pass_loop_end:
320*a67afe4dSAndroid Build Coastguard Worker                      row = NULL;
321*a67afe4dSAndroid Build Coastguard Worker                      png_free(png_ptr, row_tmp);
322*a67afe4dSAndroid Build Coastguard Worker                   }
323*a67afe4dSAndroid Build Coastguard Worker 
324*a67afe4dSAndroid Build Coastguard Worker                   else
325*a67afe4dSAndroid Build Coastguard Worker                      png_error(png_ptr, "pngpixel: png_get_IHDR failed");
326*a67afe4dSAndroid Build Coastguard Worker 
327*a67afe4dSAndroid Build Coastguard Worker                }
328*a67afe4dSAndroid Build Coastguard Worker 
329*a67afe4dSAndroid Build Coastguard Worker                else
330*a67afe4dSAndroid Build Coastguard Worker                {
331*a67afe4dSAndroid Build Coastguard Worker                   /* Else libpng has raised an error.  An error message has
332*a67afe4dSAndroid Build Coastguard Worker                    * already been output, so it is only necessary to clean up
333*a67afe4dSAndroid Build Coastguard Worker                    * locally allocated data:
334*a67afe4dSAndroid Build Coastguard Worker                    */
335*a67afe4dSAndroid Build Coastguard Worker                   if (row != NULL)
336*a67afe4dSAndroid Build Coastguard Worker                   {
337*a67afe4dSAndroid Build Coastguard Worker                      /* The default implementation of png_free never errors out
338*a67afe4dSAndroid Build Coastguard Worker                       * (it just crashes if something goes wrong), but the safe
339*a67afe4dSAndroid Build Coastguard Worker                       * way of using it is still to clear 'row' before calling
340*a67afe4dSAndroid Build Coastguard Worker                       * png_free:
341*a67afe4dSAndroid Build Coastguard Worker                       */
342*a67afe4dSAndroid Build Coastguard Worker                      png_bytep row_tmp = row;
343*a67afe4dSAndroid Build Coastguard Worker                      row = NULL;
344*a67afe4dSAndroid Build Coastguard Worker                      png_free(png_ptr, row_tmp);
345*a67afe4dSAndroid Build Coastguard Worker                   }
346*a67afe4dSAndroid Build Coastguard Worker                }
347*a67afe4dSAndroid Build Coastguard Worker 
348*a67afe4dSAndroid Build Coastguard Worker                png_destroy_info_struct(png_ptr, &info_ptr);
349*a67afe4dSAndroid Build Coastguard Worker             }
350*a67afe4dSAndroid Build Coastguard Worker 
351*a67afe4dSAndroid Build Coastguard Worker             else
352*a67afe4dSAndroid Build Coastguard Worker                fprintf(stderr, "pngpixel: out of memory allocating png_info\n");
353*a67afe4dSAndroid Build Coastguard Worker 
354*a67afe4dSAndroid Build Coastguard Worker             png_destroy_read_struct(&png_ptr, NULL, NULL);
355*a67afe4dSAndroid Build Coastguard Worker          }
356*a67afe4dSAndroid Build Coastguard Worker 
357*a67afe4dSAndroid Build Coastguard Worker          else
358*a67afe4dSAndroid Build Coastguard Worker             fprintf(stderr, "pngpixel: out of memory allocating png_struct\n");
359*a67afe4dSAndroid Build Coastguard Worker       }
360*a67afe4dSAndroid Build Coastguard Worker 
361*a67afe4dSAndroid Build Coastguard Worker       else
362*a67afe4dSAndroid Build Coastguard Worker          fprintf(stderr, "pngpixel: %s: could not open file\n", argv[3]);
363*a67afe4dSAndroid Build Coastguard Worker    }
364*a67afe4dSAndroid Build Coastguard Worker 
365*a67afe4dSAndroid Build Coastguard Worker    else
366*a67afe4dSAndroid Build Coastguard Worker       /* Wrong number of arguments */
367*a67afe4dSAndroid Build Coastguard Worker       fprintf(stderr, "pngpixel: usage: pngpixel x y png-file\n");
368*a67afe4dSAndroid Build Coastguard Worker 
369*a67afe4dSAndroid Build Coastguard Worker    return result;
370*a67afe4dSAndroid Build Coastguard Worker }
371*a67afe4dSAndroid Build Coastguard Worker #endif /* READ && SEQUENTIAL_READ */
372