writepng_encode_image()
Back in the main program, the first thing we do after returning is to
free the text buffer, since all of its data has already been written to
the PNG file. Then we calculate the number of bytes per row of image
data; since we accept only three basic file types, there are only three
possibilities for this: either one, three, or four times the image width.
What happens next depends on whether the user requested that the PNG image
be interlaced. If so, there's really no good way to read and write
the image progressively, so we simply allocate a buffer large enough for the
whole thing and read it in. We also allocate and initialize a
row_pointers array, where each
element points at the beginning of
a row of pixels, and then call writepng_encode_image():
int writepng_encode_image(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_image(png_ptr, mainprog_ptr->row_pointers);
png_write_end(png_ptr, NULL);
return 0;
}
One can see that the actual process of writing the image data is quite
simple. We first restore our two struct pointers; we could simply use them
as is, but that would require some ugly typecasts. Next we set up the usual
PNG error-handling code, followed by the call that really matters:
png_write_image(). This function writes all of the pixel data
to the file, reading from the row_pointers array we just set up
in the main program. Once that is complete, there is nothing left to do
but to write out the end of the PNG file with png_write_end().
As discussed earlier, this will write any new text or time chunks, but
not ones that have already been written; in our case, that means it does
nothing but write the final IEND chunk. The second parameter to
png_write_end() is ordinarily info_ptr, but since we have
no extra chunks to write, passing a NULL value is a tiny optimization.
|