writepng_encode_row()
If the user did not request interlacing, we can read and write the
image progressively, allowing very large images to be converted to PNG
without incurring a huge memory overhead. In this case, we forego the
row_pointers array and simply allocate image_data large
enough to hold one row. Then we start looping over all of the rows in
the image (i.e., height rows), reading the pixel data into our
buffer and passing it to writepng_encode_row():
int writepng_encode_row(mainprog_info *mainprog_ptr)
{
png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
if (setjmp(mainprog_ptr->jmpbuf)) {
png_destroy_write_struct(&png_ptr, &info_ptr);
mainprog_ptr->png_ptr = NULL;
mainprog_ptr->info_ptr = NULL;
return 2;
}
png_write_row(png_ptr, mainprog_ptr->image_data);
return 0;
}
Astute readers will perceive that this function is almost identical to the
previous one for interlaced images; the differences are the lack of a
png_write_end() call (for obvious reasons) and the call to
png_write_row() instead of png_write_image().
image_data now acts as our single row pointer.
Once the loop over rows completes, we call one last function to close out
the PNG file:
int writepng_encode_finish(mainprog_info *mainprog_ptr)
{
png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
if (setjmp(mainprog_ptr->jmpbuf)) {
png_destroy_write_struct(&png_ptr, &info_ptr);
mainprog_ptr->png_ptr = NULL;
mainprog_ptr->info_ptr = NULL;
return 2;
}
png_write_end(png_ptr, NULL);
return 0;
}
Again, the function is exactly like what we've seen before except that it
calls png_write_end(). Alternatively, it could have been combined with
writepng_encode_row() had we included in our mainprog_info
struct a flag indicating whether the given row was the last one in the
image.
|