readpng2_row_callback()
The heart of the progressive reader is the row-callback function. As with
the other two callbacks, it is called by
png_process_data() after
some amount of image data is read; unlike them, it gets called multiple
times, at least once for every row in the image.[102]
readpng2_row_callback() has four arguments: the main PNG struct pointer,
a pointer to the row of image data, the row number, and the pass number.
Its structure is actually quite simple; most of the action occurs within
libpng or back in the main program:
static void readpng2_row_callback(png_structp png_ptr,
png_bytep new_row,
png_uint_32 row_num,
int pass)
{
mainprog_info *mainprog_ptr;
if (!new_row)
return;
mainprog_ptr = (mainprog_info *)png_get_progressive_ptr(png_ptr);
png_progressive_combine_row(png_ptr,
mainprog_ptr->row_pointers[row_num], new_row);
(*mainprog_ptr->mainprog_display_row)(row_num);
return;
}
The first thing the routine does is check whether libpng provided any
row data; if not, it returns immediately. Otherwise the function
needs access to our mainprog_info struct, so it retrieves the
pointer to that. Recall that the definition of this struct included
two members that should look familiar: image_data and
row_pointers. The first is the pointer to our image buffer;
the second is an array of pointers giving the locations of every row
within the buffer. Both were allocated and initialized when
readpng2_info_callback() called its corresponding function in
the main program. libpng does not require a row-pointers array in a
progressive reader, but it happens to be a convenient and reasonably
efficient way to access the image buffer.
In any case, the row-callback function calls
png_progressive_combine_row() to combine the new image data with
the existing pixels or, in the case of a noninterlaced image, to copy
the row of data into the image buffer. Then it transfers control to its
counterpart in the main program in order to composite the new pixels with
the background, convert the row to a platform-dependent format, and
optionally display it.
|