|
fukasawa |
e60969 |
/*---------------------------------------------------------------------------
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
wpng - simple PNG-writing program writepng.c
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
---------------------------------------------------------------------------
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
Copyright (c) 1998-2007 Greg Roelofs. All rights reserved.
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
This software is provided "as is," without warranty of any kind,
|
|
fukasawa |
e60969 |
express or implied. In no event shall the author or contributors
|
|
fukasawa |
e60969 |
be held liable for any damages arising in any way from the use of
|
|
fukasawa |
e60969 |
this software.
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
The contents of this file are DUAL-LICENSED. You may modify and/or
|
|
fukasawa |
e60969 |
redistribute this software according to the terms of one of the
|
|
fukasawa |
e60969 |
following two licenses (at your option):
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
LICENSE 1 ("BSD-like with advertising clause"):
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
Permission is granted to anyone to use this software for any purpose,
|
|
fukasawa |
e60969 |
including commercial applications, and to alter it and redistribute
|
|
fukasawa |
e60969 |
it freely, subject to the following restrictions:
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
1. Redistributions of source code must retain the above copyright
|
|
fukasawa |
e60969 |
notice, disclaimer, and this list of conditions.
|
|
fukasawa |
e60969 |
2. Redistributions in binary form must reproduce the above copyright
|
|
fukasawa |
e60969 |
notice, disclaimer, and this list of conditions in the documenta-
|
|
fukasawa |
e60969 |
tion and/or other materials provided with the distribution.
|
|
fukasawa |
e60969 |
3. All advertising materials mentioning features or use of this
|
|
fukasawa |
e60969 |
software must display the following acknowledgment:
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
This product includes software developed by Greg Roelofs
|
|
fukasawa |
e60969 |
and contributors for the book, "PNG: The Definitive Guide,"
|
|
fukasawa |
e60969 |
published by O'Reilly and Associates.
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
LICENSE 2 (GNU GPL v2 or later):
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
This program is free software; you can redistribute it and/or modify
|
|
fukasawa |
e60969 |
it under the terms of the GNU General Public License as published by
|
|
fukasawa |
e60969 |
the Free Software Foundation; either version 2 of the License, or
|
|
fukasawa |
e60969 |
(at your option) any later version.
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
This program is distributed in the hope that it will be useful,
|
|
fukasawa |
e60969 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
fukasawa |
e60969 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
fukasawa |
e60969 |
GNU General Public License for more details.
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
You should have received a copy of the GNU General Public License
|
|
fukasawa |
e60969 |
along with this program; if not, write to the Free Software Foundation,
|
|
fukasawa |
e60969 |
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
---------------------------------------------------------------------------*/
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
#include <stdlib.h> /* for exit() prototype */</stdlib.h>
|
|
fukasawa |
e60969 |
#include <zlib.h></zlib.h>
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
#include "png.h" /* libpng header, includes setjmp.h */
|
|
fukasawa |
e60969 |
#include "writepng.h" /* typedefs, common macros, public prototypes */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* local prototype */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
static void writepng_error_handler(png_structp png_ptr, png_const_charp msg);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
void writepng_version_info(void)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n",
|
|
fukasawa |
e60969 |
PNG_LIBPNG_VER_STRING, png_libpng_ver);
|
|
fukasawa |
e60969 |
fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n",
|
|
fukasawa |
e60969 |
ZLIB_VERSION, zlib_version);
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* returns 0 for success, 2 for libpng problem, 4 for out of memory, 11 for
|
|
fukasawa |
e60969 |
* unexpected pnmtype; note that outfile might be stdout */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
int writepng_init(mainprog_info *mainprog_ptr)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
png_structp png_ptr; /* note: temporary variables! */
|
|
fukasawa |
e60969 |
png_infop info_ptr;
|
|
fukasawa |
e60969 |
int color_type, interlace_type;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* could also replace libpng warning-handler (final NULL), but no need: */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
png_ptr = png_create_write_struct(png_get_libpng_ver(NULL), mainprog_ptr,
|
|
fukasawa |
e60969 |
writepng_error_handler, NULL);
|
|
fukasawa |
e60969 |
if (!png_ptr)
|
|
fukasawa |
e60969 |
return 4; /* out of memory */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
info_ptr = png_create_info_struct(png_ptr);
|
|
fukasawa |
e60969 |
if (!info_ptr) {
|
|
fukasawa |
e60969 |
png_destroy_write_struct(&png_ptr, NULL);
|
|
fukasawa |
e60969 |
return 4; /* out of memory */
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* setjmp() must be called in every function that calls a PNG-writing
|
|
fukasawa |
e60969 |
* libpng function, unless an alternate error handler was installed--
|
|
fukasawa |
e60969 |
* but compatible error handlers must either use longjmp() themselves
|
|
fukasawa |
e60969 |
* (as in this program) or some other method to return control to
|
|
fukasawa |
e60969 |
* application code, so here we go: */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
if (setjmp(mainprog_ptr->jmpbuf)) {
|
|
fukasawa |
e60969 |
png_destroy_write_struct(&png_ptr, &info_ptr);
|
|
fukasawa |
e60969 |
return 2;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* make sure outfile is (re)opened in BINARY mode */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
png_init_io(png_ptr, mainprog_ptr->outfile);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* set the compression levels--in general, always want to leave filtering
|
|
fukasawa |
e60969 |
* turned on (except for palette images) and allow all of the filters,
|
|
fukasawa |
e60969 |
* which is the default; want 32K zlib window, unless entire image buffer
|
|
fukasawa |
e60969 |
* is 16K or smaller (unknown here)--also the default; usually want max
|
|
fukasawa |
e60969 |
* compression (NOT the default); and remaining compression flags should
|
|
fukasawa |
e60969 |
* be left alone */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
|
|
fukasawa |
e60969 |
/*
|
|
fukasawa |
e60969 |
>> this is default for no filtering; Z_FILTERED is default otherwise:
|
|
fukasawa |
e60969 |
png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
|
|
fukasawa |
e60969 |
>> these are all defaults:
|
|
fukasawa |
e60969 |
png_set_compression_mem_level(png_ptr, 8);
|
|
fukasawa |
e60969 |
png_set_compression_window_bits(png_ptr, 15);
|
|
fukasawa |
e60969 |
png_set_compression_method(png_ptr, 8);
|
|
fukasawa |
e60969 |
*/
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* set the image parameters appropriately */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
if (mainprog_ptr->pnmtype == 5)
|
|
fukasawa |
e60969 |
color_type = PNG_COLOR_TYPE_GRAY;
|
|
fukasawa |
e60969 |
else if (mainprog_ptr->pnmtype == 6)
|
|
fukasawa |
e60969 |
color_type = PNG_COLOR_TYPE_RGB;
|
|
fukasawa |
e60969 |
else if (mainprog_ptr->pnmtype == 8)
|
|
fukasawa |
e60969 |
color_type = PNG_COLOR_TYPE_RGB_ALPHA;
|
|
fukasawa |
e60969 |
else {
|
|
fukasawa |
e60969 |
png_destroy_write_struct(&png_ptr, &info_ptr);
|
|
fukasawa |
e60969 |
return 11;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
interlace_type = mainprog_ptr->interlaced? PNG_INTERLACE_ADAM7 :
|
|
fukasawa |
e60969 |
PNG_INTERLACE_NONE;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
png_set_IHDR(png_ptr, info_ptr, mainprog_ptr->width, mainprog_ptr->height,
|
|
fukasawa |
e60969 |
mainprog_ptr->sample_depth, color_type, interlace_type,
|
|
fukasawa |
e60969 |
PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
if (mainprog_ptr->gamma > 0.0)
|
|
fukasawa |
e60969 |
png_set_gAMA(png_ptr, info_ptr, mainprog_ptr->gamma);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
if (mainprog_ptr->have_bg) { /* we know it's RGBA, not gray+alpha */
|
|
fukasawa |
e60969 |
png_color_16 background;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
background.red = mainprog_ptr->bg_red;
|
|
fukasawa |
e60969 |
background.green = mainprog_ptr->bg_green;
|
|
fukasawa |
e60969 |
background.blue = mainprog_ptr->bg_blue;
|
|
fukasawa |
e60969 |
png_set_bKGD(png_ptr, info_ptr, &background);
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
if (mainprog_ptr->have_time) {
|
|
fukasawa |
e60969 |
png_time modtime;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
png_convert_from_time_t(&modtime, mainprog_ptr->modtime);
|
|
fukasawa |
e60969 |
png_set_tIME(png_ptr, info_ptr, &modtime);
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
if (mainprog_ptr->have_text) {
|
|
fukasawa |
e60969 |
png_text text[6];
|
|
fukasawa |
e60969 |
int num_text = 0;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
if (mainprog_ptr->have_text & TEXT_TITLE) {
|
|
fukasawa |
e60969 |
text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
|
|
fukasawa |
e60969 |
text[num_text].key = "Title";
|
|
fukasawa |
e60969 |
text[num_text].text = mainprog_ptr->title;
|
|
fukasawa |
e60969 |
++num_text;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
if (mainprog_ptr->have_text & TEXT_AUTHOR) {
|
|
fukasawa |
e60969 |
text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
|
|
fukasawa |
e60969 |
text[num_text].key = "Author";
|
|
fukasawa |
e60969 |
text[num_text].text = mainprog_ptr->author;
|
|
fukasawa |
e60969 |
++num_text;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
if (mainprog_ptr->have_text & TEXT_DESC) {
|
|
fukasawa |
e60969 |
text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
|
|
fukasawa |
e60969 |
text[num_text].key = "Description";
|
|
fukasawa |
e60969 |
text[num_text].text = mainprog_ptr->desc;
|
|
fukasawa |
e60969 |
++num_text;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
if (mainprog_ptr->have_text & TEXT_COPY) {
|
|
fukasawa |
e60969 |
text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
|
|
fukasawa |
e60969 |
text[num_text].key = "Copyright";
|
|
fukasawa |
e60969 |
text[num_text].text = mainprog_ptr->copyright;
|
|
fukasawa |
e60969 |
++num_text;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
if (mainprog_ptr->have_text & TEXT_EMAIL) {
|
|
fukasawa |
e60969 |
text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
|
|
fukasawa |
e60969 |
text[num_text].key = "E-mail";
|
|
fukasawa |
e60969 |
text[num_text].text = mainprog_ptr->email;
|
|
fukasawa |
e60969 |
++num_text;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
if (mainprog_ptr->have_text & TEXT_URL) {
|
|
fukasawa |
e60969 |
text[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
|
|
fukasawa |
e60969 |
text[num_text].key = "URL";
|
|
fukasawa |
e60969 |
text[num_text].text = mainprog_ptr->url;
|
|
fukasawa |
e60969 |
++num_text;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
png_set_text(png_ptr, info_ptr, text, num_text);
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* write all chunks up to (but not including) first IDAT */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
png_write_info(png_ptr, info_ptr);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* if we wanted to write any more text info *after* the image data, we
|
|
fukasawa |
e60969 |
* would set up text struct(s) here and call png_set_text() again, with
|
|
fukasawa |
e60969 |
* just the new data; png_set_tIME() could also go here, but it would
|
|
fukasawa |
e60969 |
* have no effect since we already called it above (only one tIME chunk
|
|
fukasawa |
e60969 |
* allowed) */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* set up the transformations: for now, just pack low-bit-depth pixels
|
|
fukasawa |
e60969 |
* into bytes (one, two or four pixels per byte) */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
png_set_packing(png_ptr);
|
|
fukasawa |
e60969 |
/* png_set_shift(png_ptr, &sig_bit); to scale low-bit-depth values */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* make sure we save our pointers for use in writepng_encode_image() */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
mainprog_ptr->png_ptr = png_ptr;
|
|
fukasawa |
e60969 |
mainprog_ptr->info_ptr = info_ptr;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* OK, that's all we need to do for now; return happy */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
return 0;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* returns 0 for success, 2 for libpng (longjmp) problem */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
int writepng_encode_image(mainprog_info *mainprog_ptr)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
|
|
fukasawa |
e60969 |
png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* as always, setjmp() must be called in every function that calls a
|
|
fukasawa |
e60969 |
* PNG-writing libpng function */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
if (setjmp(mainprog_ptr->jmpbuf)) {
|
|
fukasawa |
e60969 |
png_destroy_write_struct(&png_ptr, &info_ptr);
|
|
fukasawa |
e60969 |
mainprog_ptr->png_ptr = NULL;
|
|
fukasawa |
e60969 |
mainprog_ptr->info_ptr = NULL;
|
|
fukasawa |
e60969 |
return 2;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* and now we just write the whole image; libpng takes care of interlacing
|
|
fukasawa |
e60969 |
* for us */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
png_write_image(png_ptr, mainprog_ptr->row_pointers);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* since that's it, we also close out the end of the PNG file now--if we
|
|
fukasawa |
e60969 |
* had any text or time info to write after the IDATs, second argument
|
|
fukasawa |
e60969 |
* would be info_ptr, but we optimize slightly by sending NULL pointer: */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
png_write_end(png_ptr, NULL);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
return 0;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* returns 0 if succeeds, 2 if libpng problem */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
int writepng_encode_row(mainprog_info *mainprog_ptr) /* NON-interlaced only! */
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
|
|
fukasawa |
e60969 |
png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* as always, setjmp() must be called in every function that calls a
|
|
fukasawa |
e60969 |
* PNG-writing libpng function */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
if (setjmp(mainprog_ptr->jmpbuf)) {
|
|
fukasawa |
e60969 |
png_destroy_write_struct(&png_ptr, &info_ptr);
|
|
fukasawa |
e60969 |
mainprog_ptr->png_ptr = NULL;
|
|
fukasawa |
e60969 |
mainprog_ptr->info_ptr = NULL;
|
|
fukasawa |
e60969 |
return 2;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* image_data points at our one row of image data */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
png_write_row(png_ptr, mainprog_ptr->image_data);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
return 0;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* returns 0 if succeeds, 2 if libpng problem */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
int writepng_encode_finish(mainprog_info *mainprog_ptr) /* NON-interlaced! */
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
|
|
fukasawa |
e60969 |
png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* as always, setjmp() must be called in every function that calls a
|
|
fukasawa |
e60969 |
* PNG-writing libpng function */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
if (setjmp(mainprog_ptr->jmpbuf)) {
|
|
fukasawa |
e60969 |
png_destroy_write_struct(&png_ptr, &info_ptr);
|
|
fukasawa |
e60969 |
mainprog_ptr->png_ptr = NULL;
|
|
fukasawa |
e60969 |
mainprog_ptr->info_ptr = NULL;
|
|
fukasawa |
e60969 |
return 2;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* close out PNG file; if we had any text or time info to write after
|
|
fukasawa |
e60969 |
* the IDATs, second argument would be info_ptr: */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
png_write_end(png_ptr, NULL);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
return 0;
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
void writepng_cleanup(mainprog_info *mainprog_ptr)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
png_structp png_ptr = (png_structp)mainprog_ptr->png_ptr;
|
|
fukasawa |
e60969 |
png_infop info_ptr = (png_infop)mainprog_ptr->info_ptr;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
if (png_ptr && info_ptr)
|
|
fukasawa |
e60969 |
png_destroy_write_struct(&png_ptr, &info_ptr);
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
static void writepng_error_handler(png_structp png_ptr, png_const_charp msg)
|
|
fukasawa |
e60969 |
{
|
|
fukasawa |
e60969 |
mainprog_info *mainprog_ptr;
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* This function, aside from the extra step of retrieving the "error
|
|
fukasawa |
e60969 |
* pointer" (below) and the fact that it exists within the application
|
|
fukasawa |
e60969 |
* rather than within libpng, is essentially identical to libpng's
|
|
fukasawa |
e60969 |
* default error handler. The second point is critical: since both
|
|
fukasawa |
e60969 |
* setjmp() and longjmp() are called from the same code, they are
|
|
fukasawa |
e60969 |
* guaranteed to have compatible notions of how big a jmp_buf is,
|
|
fukasawa |
e60969 |
* regardless of whether _BSD_SOURCE or anything else has (or has not)
|
|
fukasawa |
e60969 |
* been defined. */
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
fprintf(stderr, "writepng libpng error: %s\n", msg);
|
|
fukasawa |
e60969 |
fflush(stderr);
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
mainprog_ptr = png_get_error_ptr(png_ptr);
|
|
fukasawa |
e60969 |
if (mainprog_ptr == NULL) { /* we are completely hosed now */
|
|
fukasawa |
e60969 |
fprintf(stderr,
|
|
fukasawa |
e60969 |
"writepng severe error: jmpbuf not recoverable; terminating.\n");
|
|
fukasawa |
e60969 |
fflush(stderr);
|
|
fukasawa |
e60969 |
exit(99);
|
|
fukasawa |
e60969 |
}
|
|
fukasawa |
e60969 |
|
|
fukasawa |
e60969 |
/* Now we have our data structure we can use the information in it
|
|
fukasawa |
e60969 |
* to return control to our own higher level code (all the points
|
|
fukasawa |
e60969 |
* where 'setjmp' is called in this file.) This will work with other
|
|
fukasawa |
e60969 |
* error handling mechanisms as well - libpng always calls png_error
|
|
fukasawa |
e60969 |
* when it can proceed no further, thus, so long as the error handler
|
|
fukasawa |
e60969 |
* is intercepted, application code can do its own error recovery.
|
|
fukasawa |
e60969 |
*/
|
|
fukasawa |
e60969 |
longjmp(mainprog_ptr->jmpbuf, 1);
|
|
fukasawa |
e60969 |
}
|