The PNG Guide is an eBook based on Greg Roelofs' book, originally published by O'Reilly.



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:

[102] For interlaced images, it gets called (with real data) an average of 1.875 times per row and at most 4 times per row (for a one-row image that is more than four pixels wide). Once per row is still a possibility, however, if the image has only one column.

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.




Last Update: 2010-Nov-26