Imported from libpng-0.96.tar

This commit is contained in:
Andreas Dilger 1997-05-16 02:46:07 -05:00 committed by Glenn Randers-Pehrson
parent 02ad0efbc8
commit 47a0c422ca
40 changed files with 6833 additions and 3520 deletions

69
CHANGES
View File

@ -37,7 +37,7 @@ version 0.7
finished dithering and other stuff finished dithering and other stuff
added test program added test program
changed name from pnglib to libpng changed name from pnglib to libpng
version 0.71 version 0.71 [June, 1995]
changed pngtest.png for zlib 0.93 changed pngtest.png for zlib 0.93
fixed error in libpng.txt and example.c fixed error in libpng.txt and example.c
version 0.8 version 0.8
@ -56,26 +56,28 @@ version 0.8
enabled png_set_shift to work with paletted images on read enabled png_set_shift to work with paletted images on read
added png_read_update_info() - updates info structure with added png_read_update_info() - updates info structure with
transformations transformations
version 0.81 version 0.81 [August, 1995]
incorporated Tim Wegner's medium model code (thanks, Tim) incorporated Tim Wegner's medium model code (thanks, Tim)
version 0.85 version 0.82 [September, 1995]
added more medium model code (almost everythings a far) [unspecified changes]
version 0.85 [December, 1995]
added more medium model code (almost everything's a far)
added i/o, error, and memory callback functions added i/o, error, and memory callback functions
fixed some bugs (16 bit, 4 bit interlaced, etc.) fixed some bugs (16 bit, 4 bit interlaced, etc.)
added first run progressive reader (barely tested) added first run progressive reader (barely tested)
version 0.86 version 0.86 [January, 1996]
fixed bugs fixed bugs
improved documentation improved documentation
version 0.87 version 0.87 [January, 1996]
fixed medium model bugs fixed medium model bugs
fixed other bugs introduced in 0.85 and 0.86 fixed other bugs introduced in 0.85 and 0.86
added some minor documentation added some minor documentation
version 0.88 version 0.88 [January, 1996]
fixed progressive bugs fixed progressive bugs
replaced tabs with spaces replaced tabs with spaces
cleaned up documentation cleaned up documentation
added callbacks for read/write and warning/error functions added callbacks for read/write and warning/error functions
version 0.89 version 0.89 [July, 1996]
added new initialization API to make libpng work better with shared libs added new initialization API to make libpng work better with shared libs
we now have png_create_read_struct(), png_create_write_struct(), we now have png_create_read_struct(), png_create_write_struct(),
png_create_info_struct(), png_destroy_read_struct(), and png_create_info_struct(), png_destroy_read_struct(), and
@ -101,14 +103,14 @@ version 0.89
into a binary when only reading or writing functionality is used into a binary when only reading or writing functionality is used
new pngtest image also has interlacing and zTXt new pngtest image also has interlacing and zTXt
updated documentation to reflect new API updated documentation to reflect new API
version 0.90 version 0.90 [January, 1997]
made CRC errors/warnings on critical and ancillary chunks configurable made CRC errors/warnings on critical and ancillary chunks configurable
libpng will use the zlib CRC routines by (compile-time) default libpng will use the zlib CRC routines by (compile-time) default
changed DOS small/medium model memory support - needs zlib 1.04 (Tim Wegner) changed DOS small/medium model memory support - needs zlib 1.04 (Tim Wegner)
added external C++ wrapper statements to png.h (Gilles Dauphin) added external C++ wrapper statements to png.h (Gilles Dauphin)
allow PNG file to be read when some or all of file signature has already allow PNG file to be read when some or all of file signature has already
been read from the beginning of the stream (this affects the size of been read from the beginning of the stream. ****This affects the size
info_struct and invalidates all programs that use a shared libpng) of info_struct and invalidates all programs that use a shared libpng****
fixed png_filler() declarations fixed png_filler() declarations
fixed? background color conversions fixed? background color conversions
fixed order of error function pointers to match documentation fixed order of error function pointers to match documentation
@ -120,3 +122,48 @@ version 0.90
routines can determine if the chunk is in the right place routines can determine if the chunk is in the right place
- all chunk handling routines have the same prototypes, so we will - all chunk handling routines have the same prototypes, so we will
be able to handle all chunks via a callback mechanism be able to handle all chunks via a callback mechanism
try to fix Linux "setjmp" buffer size problems
version 0.95 [March, 1997]
fixed bug in pngwutil.c allocating "up_row" twice and "avg_row" never
fixed bug in PNG file signature compares when start != 0
changed parameter type of png_set_filler(...filler...) from png_byte
to png_uint_32
added test for MACOS to ensure that both math.h and fp.h are not #included
added macros for libpng to be compiled as a Windows DLL (Andreas Kupries)
added "packswap" transformation, which changes the endianness of
packed-pixel bytes (Kevin Bracey)
added "strip_alpha" transformation, which removes the alpha channel of
input images without using it (not neccesarily a good idea)
added "swap_alpha" transformation, which puts the alpha channel in front
of the color bytes instead of after
removed all implicit variable tests which assume NULL == 0 (I think)
changed several variables to "png_size_t" to show 16/32-bit limitations
added new pCAL chunk read/write support
added experimental filter selection weighting (Greg Roelofs)
removed old png_set_rgbx() and png_set_xrgb() functions that have been
obsolete for about 2 years now (use png_set_filler() instead)
added macros to read 16- and 32-bit ints directly from buffer, to be
used only on those systems that support it (namely PowerPC and 680x0)
With some testing, this may become the default for MACOS/PPC systems.
only calculate CRC on data if we are going to use it
added macros for zTXt compression type PNG_zTXt_COMPRESSION_???
added macros for simple libpng debugging output selectable at compile time
removed PNG_READ_END_MODE in progressive reader (Smarasderagd)
more description of info_struct in libpng.txt and png.h
more instructions in example.c
more chunk types tested in pngtest.c
renamed pngrcb.c to pngset.c, and all png_read_<chunk> functions to be
png_set_<chunk>. We now have corresponding png_get_<chunk>
functions in pngget.c to get infomation in info_ptr. This isolates
the application from the internal organization of png_info_struct
(good for shared library implementations).
version 0.96 [May, 1997]
fixed serious bug with < 8bpp images introduced in 0.95
fixed 256-color transparency bug (Greg Roelofs)
fixed up documentation (Greg Roelofs, Laszlo Nyul)
fixed "error" in pngconf.h for Linux setjmp() behaviour
fixed DOS medium model support (Tim Wegner)
fixed png_check_keyword() for case with error in static string text
added read of CRC after IEND chunk for embedded PNGs (Laszlo Nyul)
added typecasts to quiet compiler errors
added more debugging info

90
README
View File

@ -1,55 +1,54 @@
readme.txt - for libpng 0.90 README for libpng 0.96
This is the fourth beta version of libpng 1.0. The changes from This is the sixth (and hopefully last) beta release of libpng 1.0.
libpng-0.89 include bug fixes, a C++ wrapper for png.h, some The changes from libpng-0.90 include bug fixes, a C++ wrapper for
additions to the API, as well as internal changes to the library. png.h, some additions to the API, as well as internal changes to
the library. See "CHANGES" for a detailed list of differences.
** ****
Note that some of the changes to the png_info structure render Note that some of the changes to the png_info structure render this
this version of the library binary incompatible with libpng-0.89 version of the library binary incompatible with libpng-0.89 or
if you are using a shared library. Re-compiling the application earlier versions if you are using a shared library. The type of the
should be enough to remove this problem. "filler" parameter for png_set_filler() has changed from png_byte to
** png_uint_32, which will affect shared-library applications which use
this function.
The additions to 0.89 include the ability to read from a PNG stream To avoid problems with changes to the internals of png_info_struct,
which has had some (or all) of the signature bytes read by the new APIs have been made available in 0.95 to avoid direct application
calling application. This also allows the reading of embedded PNG access to info_ptr. These functions are the png_set_<chunk> and
streams that do not have the PNG file signature. As well, it is png_get_<chunk> functions. These functions should be used when
now possible to set the library action on the detection of chunk accessing/storing the info_struct data, rather than manipulating it
CRC errors. It is possible to set different actions based on directly, to avoid such problems in the future.
whether the error occurred in a critical or an ancillary chunk. ****
The callback functions for the error/warning messages have changed Additions since 0.90 include the ability to compile libpng as a
since the 0.88 release because their implementation was broken, Windows DLL, and new APIs for accessing data in the info struct.
and it was thought best to change the API itself (which was only Experimental functions include the ability to set weighting and cost
introduced in libpng-0.88 itself) to alert the user to the change, factors for row filter selection, direct reads of integers from buffers
rather than mislead the user into thinking their application was on big-endian processors that support misaligned data access, faster
OK after re-compiling. This means that calls to png_set_message_fn() methods of doing alpha composition, and more accurate 16->8 bit color
no longer exist, because the previously suggested method of calling conversion.
them before png_read_init() or png_write_init() is now ineffective.
The preferred method of setting the error and warning callbacks The additions since 0.89 include the ability to read from a PNG stream
has been incorporated into the allocation of the png_struct and which has had some (or all) of the signature bytes read by the calling
info_struct itself, which allow them to be safely used during the application. This also allows the reading of embedded PNG streams that
initialization of the structure, as well as to keep the size of do not have the PNG file signature. As well, it is now possible to set
the png_struct internal to the library, rather than at compile time the library action on the detection of chunk CRC errors. It is possible
of the application. This will hopefully remove any problems with to set different actions based on whether the CRC error occurred in a
dynamically linked libraries, and should be considered the preferred critical or an ancillary chunk.
method of creating these structures, although the previous
initialization API is still available for compatibility. See libpng.txt
for more information on the new API.
The changes made to the library, and bugs fixed are based on discussions The changes made to the library, and bugs fixed are based on discussions
on the PNG implementation mailing list <png-implement@dworking.wustl.edu> on the PNG implementation mailing list <png-implement@dworking.wustl.edu>
and not on material submitted to Guy. and not on material submitted to Guy.
For a detailed description on using libpng, read libpng.txt. For For a detailed description on using libpng, read libpng.txt. For
usage information and restrictions (what little they are) on libpng, examples of libpng in a program, see example.c and pngtest.c. For usage
see png.h. For a description on using zlib (the compression library information and restrictions (what little they are) on libpng, see
used by libpng) and zlib's restrictions, see zlib.h png.h. For a description on using zlib (the compression library used by
libpng) and zlib's restrictions, see zlib.h
I have included a general makefile, as well as several machine and compiler I have included a general makefile, as well as several machine and
specific ones, but you may have to modify one for your own needs. compiler specific ones, but you may have to modify one for your own needs.
You should use zlib 1.0.4 or later to run this, but it MAY work with You should use zlib 1.0.4 or later to run this, but it MAY work with
versions as old as zlib 0.95. Even so, there are bugs in older zlib versions as old as zlib 0.95. Even so, there are bugs in older zlib
@ -113,7 +112,7 @@ gladly listen. Even if your suggestion is not used for version
Files in this distribution: Files in this distribution:
CHANGES.txt => Description of changes between libpng versions CHANGES => Description of changes between libpng versions
README => This file README => This file
TODO => Things not implemented in the current library TODO => Things not implemented in the current library
ansi2knr.c => Converts files to K&R style function declarations ansi2knr.c => Converts files to K&R style function declarations
@ -121,7 +120,7 @@ Files in this distribution:
descrip.mms => VMS project file descrip.mms => VMS project file
example.c => Example code for using libpng functions example.c => Example code for using libpng functions
libpng.txt => Description of libpng and its functions libpng.txt => Description of libpng and its functions
makefile => Defualt makefile makefile => Default Unixish makefile
makefile.aco => ACORN makefile makefile.aco => ACORN makefile
makefile.ama => Amiga makefile makefile.ama => Amiga makefile
makefile.atr => Atari makefile makefile.atr => Atari makefile
@ -140,11 +139,11 @@ Files in this distribution:
pngerror.c => Error/warning message I/O functions pngerror.c => Error/warning message I/O functions
pngmem.c => Memory handling functions pngmem.c => Memory handling functions
pngpread.c => Progressive reading functions pngpread.c => Progressive reading functions
pngrcb.c => Read callback (data handling) low-level functions
pngread.c => Read data/helper high-level functions pngread.c => Read data/helper high-level functions
pngrio.c => Lowest-level data read I/O functions pngrio.c => Lowest-level data read I/O functions
pngrtran.c => Read data transformation functions pngrtran.c => Read data transformation functions
pngrutil.c => Read data utility functions pngrutil.c => Read data utility functions
pngset.c => Functions for storing data into the info_struct
pngtest.c => Library test program pngtest.c => Library test program
pngtest.png => Library test sample image pngtest.png => Library test sample image
pngtrans.c => Common data transformation functions pngtrans.c => Common data transformation functions
@ -156,13 +155,12 @@ Files in this distribution:
Good luck, and happy coding. Good luck, and happy coding.
-Andreas Eric Dilger -Andreas Eric Dilger
University of Calgary
Internet: adilger@enel.ucalgary.ca Internet: adilger@enel.ucalgary.ca
Web: www-mddsp.enel.ucalgary.ca/People/adilger/ Web: http://www-mddsp.enel.ucalgary.ca/People/adilger/
-Guy Eric Schalnat -Guy Eric Schalnat
Group 42, Inc. Group 42, Inc.
Internet: schalnat@group42.com Internet: schalnat@group42.com
CompuServe: 75501,1625 CompuServe: 75501,1625
Web: www.group42.com Web: http://www.group42.com/

38
TODO
View File

@ -1,23 +1,19 @@
pngtodo.txt - list of things to do for libpng pngtodo.txt - list of things to do for libpng
for 0.9 add "grayscale->palette" transformation and "palette->grayscale" detection
improved dithering improved dithering
final bug fixes multi-lingual error and warning message support
cHRM transformation cHRM transformation
better documentation sRGB chunk handling
multi-lingual message support man pages for function calls
high-level API for reading images
after 1.0 final bug fixes
overlaying one image on top of another better documentation
optional palette creation better filter selection
histogram creation (counting huffman bits/precompression? filter inertia? filter costs?)
text conversion between different code types optional palette creation
support for application-defined chunk handlers histogram creation
support for embedded PNG usage (MNG) support for application-defined chunk handlers
pull writer keep up with public chunks
better dithering better C++ wrapper/full C++ implementation?
keep up with public chunks text conversion between different code pages (Latin-1 -> Mac and DOS)
better filter selection (counting huffman bits? filter type inertia?)
C++ wrapper
other languages (pascal, for one)
comments of > 64K for DOS

View File

@ -8,9 +8,9 @@ pref = /prefix=all
OBJS = png.obj, pngrcb.obj, pngrutil.obj, pngtrans.obj, pngwutil.obj,\ OBJS = png.obj, pngset.obj, pngget.obj, pngrutil.obj, pngtrans.obj,\
pngread.obj, pngmem.obj, pngwrite.obj, pngrtran.obj, pngwtran.obj,\ pngwutil.obj, pngread.obj, pngmem.obj, pngwrite.obj, pngrtran.obj,\
pngrio.obj, pngwio.obj, pngerror.obj, pngpread.obj pngwtran.obj, pngrio.obj, pngwio.obj, pngerror.obj, pngpread.obj
CFLAGS= $(C_DEB) $(CC_DEFS) $(PREF) CFLAGS= $(C_DEB) $(CC_DEFS) $(PREF)
@ -35,7 +35,8 @@ clean :
# Other dependencies. # Other dependencies.
png.obj : png.h, pngconf.h png.obj : png.h, pngconf.h
pngpread.obj : png.h, pngconf.h pngpread.obj : png.h, pngconf.h
pngrcb.obj : png.h, pngconf.h pngset.obj : png.h, pngconf.h
pngget.obj : png.h, pngconf.h
pngread.obj : png.h, pngconf.h pngread.obj : png.h, pngconf.h
pngrtran.obj : png.h, pngconf.h pngrtran.obj : png.h, pngconf.h
pngrutil.obj : png.h, pngconf.h pngrutil.obj : png.h, pngconf.h

565
example.c
View File

@ -1,92 +1,107 @@
/* example.c - an example of using libpng */ /* example.c - an example of using libpng */
/* this is an example of how to use libpng to read and write /* This is an example of how to use libpng to read and write PNG files.
png files. The file libpng.txt is much more verbose then The file libpng.txt is much more verbose then this. If you have not
this. If you have not read it, do so first. This was read it, do so first. This was designed to be a starting point of an
designed to be a starting point of an implementation. implementation. This is not officially part of libpng, and therefore
This is not officially part of libpng, and therefore
does not require a copyright notice. does not require a copyright notice.
This file does not currently compile, because it is missing This file does not currently compile, because it is missing certain
certain parts, like allocating memory to hold an image. parts, like allocating memory to hold an image. You will have to
You will have to supply these parts to get it to compile. supply these parts to get it to compile. For an example of a minimal
*/ working PNG reader/writer, see pngtest.c, included in this distribution.
*/
#include <png.h> #include <png.h>
/* Check to see if a file is a png file using png_check_sig(). /* Check to see if a file is a PNG file using png_check_sig(). Returns
non-zero if the image is a PNG, and 0 if it isn't a PNG.
If this call is successful, and you are going to keep the file If this call is successful, and you are going to keep the file open,
open, you should call png_set_sig_bytes_read(png_ptr, 8); you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once
once you have created the png_ptr, so that libpng knows it you have created the png_ptr, so that libpng knows your application
doesn't have to read the signature again. Make sure you don't has read that many bytes from the start of the file. Make sure you
call png_set_sig_bytes_read() with more than 8 bytes read or don't call png_set_sig_bytes() with more than 8 bytes read or give it
give it an incorrect number of bytes read, or you will either an incorrect number of bytes read, or you will either have read too
have read too many bytes (your fault), or you are telling libpng many bytes (your fault), or you are telling libpng to read the wrong
to read the wrong number of magic bytes (also your fault). */ number of magic bytes (also your fault).
int check_png(char *file_name, FILE **fp)
Many applications already read the first 2 or 4 bytes from the start
of the image to determine the file type, so it would be easiest just
to pass the bytes to png_check_sig() or even skip that if you know
you have a PNG file, and call png_set_sig_bytes().
*/
#define PNG_BYTES_TO_CHECK 4
int check_if_png(char *file_name, FILE **fp)
{ {
char buf[8]; char buf[PNG_BYTES_TO_CHECK];
int ret;
*fp = fopen(file_name, "rb"); /* Open the prospective PNG file. */
if (!fp) if ((*fp = fopen(file_name, "rb")) != NULL);
return 0;
ret = fread(buf, 1, 8, *fp);
if (ret != 8)
return 0; return 0;
/* Check the signature starting at byte 0, and check all 8 bytes */ /* Read in the signature bytes */
ret = png_check_sig(buf, 0, 8); if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK)
return 0;
return (ret); /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. */
return(png_check_sig(buf, PNG_BYTES_TO_CHECK));
} }
/* read a png file. You may want to return an error code if the read /* Read a PNG file. You may want to return an error code if the read
fails (depending upon the failure). There are two "prototypes" given fails (depending upon the failure). There are two "prototypes" given
here - one where we are given the filename, and we need to open the here - one where we are given the filename, and we need to open the
file, and the other where we are given an open file (possibly with file, and the other where we are given an open file (possibly with
some or all of the magic bytes read - see above) and an opened file some or all of the magic bytes read - see comments above). */
for reading. */ **** prototype 1 ****
------- prototype 1 ----------
void read_png(char *file_name) /* We need to open the file */ void read_png(char *file_name) /* We need to open the file */
{ {
png_structp png_ptr; png_structp png_ptr;
png_infop info_ptr; png_infop info_ptr;
unsigned int sig_read = 0;
png_uint_32 width, height;
int bit_depth, color_type, interlace_type;
FILE *fp; FILE *fp;
if ((fp = fopen(file_name, "rb")) == NULL) if ((fp = fopen(file_name, "rb")) == NULL)
return; return;
------- prototype 2 ---------- **** prototype 2 ****
void read_png(FILE *fp, unsigned int sig_read) /* file is already open */ void read_png(FILE *fp, unsigned int sig_read) /* file is already open */
{ {
png_structp png_ptr; png_structp png_ptr;
png_infop info_ptr; png_infop info_ptr;
------- only use one! -------- png_uint_32 width, height;
int bit_depth, color_type, interlace_type;
**** only use one prototype! ****
/* Create and initialize the png_struct with the desired error handler /* Create and initialize the png_struct with the desired error handler
functions. If you want to use the default stderr and longjump method, * functions. If you want to use the default stderr and longjump method,
you can supply NULL for the last three parameters. We also check that * you can supply NULL for the last three parameters. We also supply the
the header file is compatible with the library version. */ * the compiler header file version, so that we know if the application
* was compiled with a compatible version of the library. REQUIRED
*/
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
(void *)user_error_ptr, user_error_fn, user_warning_fn); (void *)user_error_ptr, user_error_fn, user_warning_fn);
if (!png_ptr) if (png_ptr == NULL)
{ {
fclose(fp); fclose(fp);
return; return;
} }
/* Allocate/initialize the memory for image information. REQUIRED. */
info_ptr = png_create_info_struct(); info_ptr = png_create_info_struct();
if (!info_ptr) if (info_ptr == NULL)
{ {
fclose(fp); fclose(fp);
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
return; return;
} }
/* set error handling if you are using the setjmp/longjmp method */ /* Set error handling if you are using the setjmp/longjmp method (this is
* the normal method of doing things with libpng). REQUIRED unless you
* set up your own error handlers in the png_create_read_struct() earlier.
*/
if (setjmp(png_ptr->jmpbuf)) if (setjmp(png_ptr->jmpbuf))
{ {
/* Free all of the memory associated with the png_ptr and info_ptr */ /* Free all of the memory associated with the png_ptr and info_ptr */
@ -96,152 +111,221 @@ void read_png(FILE *fp, unsigned int sig_read) /* file is already open */
return; return;
} }
/* set up the input control if you are using standard C streams */ /* One of the following I/O initialization methods is REQUIRED */
**** PNG file I/O method 1 ****
/* Set up the input control if you are using standard C streams */
png_init_io(png_ptr, fp); png_init_io(png_ptr, fp);
/* if you are using replacement read functions, instead of calling **** PNG file I/O method 2 ****
png_init_io() here you would call */ /* If you are using replacement read functions, instead of calling
* png_init_io() here you would call */
png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn); png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn);
/* where user_io_ptr is a structure you want available to the callbacks */ /* where user_io_ptr is a structure you want available to the callbacks */
**** Use only one I/O method! ****
/* if we have already read some of the signature from the beginning call */ /* If we have already read some of the signature */
png_set_sig_bytes_read(png_ptr, sig_read); png_set_sig_bytes_read(png_ptr, sig_read);
/* The call to png_read_info() gives us all of the information /* The call to png_read_info() gives us all of the information from the
from the PNG file before the first IDAT (image data chunk). */ * PNG file before the first IDAT (image data chunk). REQUIRED
*/
png_read_info(png_ptr, info_ptr); png_read_info(png_ptr, info_ptr);
/* set up the transformations you want. Note that these are png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
all optional. Only call them if you want them */ &interlace_type, NULL, NULL);
/**** Set up the data transformations you want. Note that these are all
**** optional. Only call them if you want/need them. Many of the
**** transformations only work on specific types of images, and many
**** are mutually exclusive.
****/
/* tell libpng to strip 16 bit/color files down to 8 bits/color */
png_set_strip_16(png_ptr);
/* strip alpha bytes from the input data without combining with th
* background (not recommended) */
png_set_strip_alpha(png_ptr);
/* extract multiple pixels with bit depths of 1, 2, and 4 from a single
* byte into separate bytes (useful for paletted and grayscale images).
*/
png_set_packing(png_ptr);
/* change the order of packed pixels to least significant bit first
* (not useful if you are using png_set_packing). */
png_set_packswap(png_ptr);
/* expand paletted colors into true RGB triplets */ /* expand paletted colors into true RGB triplets */
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_expand(png_ptr); png_set_expand(png_ptr);
/* expand grayscale images to the full 8 bits */ /* expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel */
if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY && info_ptr->bit_depth < 8) if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
png_set_expand(png_ptr); png_set_expand(png_ptr);
/* expand paletted or RGB images with transparency to full alpha channels /* expand paletted or RGB images with transparency to full alpha channels
* so the data will be available as RGBA quartets */ * so the data will be available as RGBA quartets */
if (info_ptr->valid & PNG_INFO_tRNS) if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
png_set_expand(png_ptr); png_set_expand(png_ptr);
/* Set the background color to draw transparent and alpha /* Set the background color to draw transparent and alpha images over.
images over. It is possible to set the red, green, and blue * It is possible to set the red, green, and blue components directly
components directly for paletted images. */ * for paletted images instead of supplying a palette index. Note that
* even if the PNG file supplies a background, you are not required to
* use it - you should use the (solid) application background if it has one.
*/
png_color_16 my_background; png_color_16 my_background, *image_background);
if (info_ptr->valid & PNG_INFO_bKGD) if (png_get_bKGD(png_ptr, info_ptr, &image_background);
png_set_background(png_ptr, &(info_ptr->background), png_set_background(png_ptr, image_background),
PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
else else
png_set_background(png_ptr, &my_background, png_set_background(png_ptr, &my_background,
PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
/* tell libpng to handle the gamma conversion for you. We only /* Some suggestions as to how to get a screen gamma value */
need the second call if the screen_gamma isn't the usual 2.2 if (/* We have a user-defined screen gamma value */)
or if it is controllable by the user. It may also be a good {
idea to allow the user to set the file gamma if it is unknown. */ screen_gamma = user-defined screen_gamma;
if (info_ptr->valid & PNG_INFO_gAMA) }
png_set_gamma(png_ptr, screen_gamma, info_ptr->gamma); /* This is one way that applications share the same screen gamma value */
else if ((gamma_str = getenv("DISPLAY_GAMMA")) != NULL)
{
screen_gamma = atof(gamma_str);
}
/* If we don't have another value */
else
{
screen_gamma = 2.2; /* A good guess for PC monitors */
screen_gamma = 1.7 or 1.0; /* A good guess for Mac systems */
}
/* Tell libpng to handle the gamma conversion for you. The second call
* is a good guess for PC generated images, but it should be configurable
* by the user at run time by the user. It is strongly suggested that
* your application support gamma correction.
*/
if (png_get_gAMA(png_ptr, info_ptr, &image_gamma);
png_set_gamma(png_ptr, screen_gamma, image_gamma);
else else
png_set_gamma(png_ptr, screen_gamma, 0.45); png_set_gamma(png_ptr, screen_gamma, 0.45);
/* tell libpng to strip 16 bit/color files down to 8 bits/color */ /* Dither RGB files down to 8 bit palette or reduce palettes
if (info_ptr->bit_depth == 16)
png_set_strip_16(png_ptr);
/* dither rgb files down to 8 bit palette & reduce palettes
to the number of colors available on your screen */ to the number of colors available on your screen */
if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) if (color_type & PNG_COLOR_MASK_COLOR)
{ {
if (info_ptr->valid & PNG_INFO_PLTE) png_uint_32 num_palette;
png_set_dither(png_ptr, info_ptr->palette, info_ptr->num_palette, png_colorp palette;
max_screen_colors, info_ptr->histogram);
else /* This reduces the image to the application supplied palette */
if (we have our own palette)
{ {
png_color std_color_cube[MAX_SCREEN_COLORS] = /* An array of colors to which the image should be dithered */
{/* ... colors ... */}; png_color std_color_cube[MAX_SCREEN_COLORS];
png_set_dither(png_ptr, std_color_cube, MAX_SCREEN_COLORS, png_set_dither(png_ptr, std_color_cube, MAX_SCREEN_COLORS,
MAX_SCREEN_COLORS, NULL); MAX_SCREEN_COLORS, NULL, 0);
}
/* This reduces the image to the palette supplied in the file */
else if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette)))
{
png_color16p histogram;
png_get_hIST(png_ptr, info_ptr, &histogram);
png_set_dither(png_ptr, palette, num_palette,
max_screen_colors, histogram, 0);
} }
} }
/* invert monocrome files to have 0 as white and 1 as black */ /* invert monocrome files to have 0 as white and 1 as black */
if (info_ptr->bit_depth == 1 && info_ptr->color_type == PNG_COLOR_GRAY) png_set_invert(png_ptr);
png_set_invert(png_ptr);
/* shift the pixels down to their true bit depth */ /* If you want to shift the pixel values from the range [0,255] or
if (info_ptr->valid & PNG_INFO_sBIT && * [0,65535] to the original [0,7] or [0,31], or whatever range the
info_ptr->bit_depth > info_ptr->sig_bit) * colors were originally in:
png_set_shift(png_ptr, &(info_ptr->sig_bit)); */
if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
{
png_color8p sig_bit;
/* pack multiple pixels with bit depths of 1, 2, and 4 into bytes png_get_sBIT(png_ptr, info_ptr, &sig_bit);
(useful only for paletted and grayscale images) */ png_set_shift(png_ptr, sig_bit);
if (info_ptr->bit_depth < 8) }
png_set_packing(png_ptr);
/* flip the rgb pixels to bgr */ /* flip the RGB pixels to BGR (or RGBA to BGRA) */
if (info_ptr->color_type == PNG_COLOR_TYPE_RGB || png_set_bgr(png_ptr);
info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
png_set_bgr(png_ptr);
/* swap bytes of 16 bit files to least significant bit first */ /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
if (info_ptr->bit_depth == 16) png_set_swap_alpha(png_ptr);
png_set_swap(png_ptr);
/* add a filler byte to RGB files (before or after each RGB triplet) */ /* swap bytes of 16 bit files to least significant byte first */
if (info_ptr->bit_depth == 8 && info_ptr->color_type == PNG_COLOR_TYPE_RGB) png_set_swap(png_ptr);
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
/* turn on interlace handling if you are not using png_read_image() */ /* Add filler (or alpha) byte (before/after each RGB triplet) */
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
/* Turn on interlace handling. REQUIRED if you are not using
* png_read_image(). To see how to handle interlacing passes,
* see the png_read_row() method below.
*/
number_passes = png_set_interlace_handling(png_ptr); number_passes = png_set_interlace_handling(png_ptr);
/* optional call to gamma correct and add the background to the palette /* optional call to gamma correct and add the background to the palette
and update info structure. */ * and update info structure. REQUIRED if you are expecting libpng to
* update the palette for you (ie you selected such a transform above).
*/
png_read_update_info(png_ptr, info_ptr); png_read_update_info(png_ptr, info_ptr);
/* allocate the memory to hold the image using the fields /* allocate the memory to hold the image using the fields of info_ptr. */
of png_info. */
/* the easiest way to read the image */ /* the easiest way to read the image */
png_bytep row_pointers[height]; png_bytep row_pointers[height];
for (row = 0; row < height; row++) for (row = 0; row < height; row++)
{ {
row_pointers[row] = malloc(info_ptr->rowbytes); row_pointers[row] = malloc(png_get_rowbytes(png_ptr, info_ptr));
} }
/* Now it's time to read the image. One of these methods is REQUIRED */
**** Read the entire image in one go ****
png_read_image(png_ptr, row_pointers); png_read_image(png_ptr, row_pointers);
**** Read the image one or more scanlines at a time ****
/* the other way to read images - deal with interlacing */ /* the other way to read images - deal with interlacing */
for (pass = 0; pass < number_passes; pass++) for (pass = 0; pass < number_passes; pass++)
{ {
/* Read the image using the "sparkle" effect. */ [[[[[[[ Read the image a single row at a time ]]]]]]]
png_read_rows(png_ptr, row_pointers, NULL, number_of_rows);
/* If you are only reading on row at a time, this works */
for (y = 0; y < height; y++) for (y = 0; y < height; y++)
{ {
png_bytep row_pointers = row[y]; png_bytep row_pointers = row[y];
png_read_rows(png_ptr, &row_pointers, NULL, 1); png_read_rows(png_ptr, &row_pointers, NULL, 1);
} }
/* to get the rectangle effect, use the third parameter */ [[[[[[[ Read the image several rows at a time ]]]]]]]
png_read_rows(png_ptr, NULL, row_pointers, number_of_rows); for (y = 0; y < height; y += number_of_rows)
{
<<<<<<<<<< Read the image using the "sparkle" effect. >>>>>>>>>>
png_read_rows(png_ptr, row_pointers, NULL, number_of_rows);
<<<<<<<<<< Read the image using the "rectangle" effect >>>>>>>>>>
png_read_rows(png_ptr, NULL, row_pointers, number_of_rows);
<<<<<<<<<< use only one of these two methods >>>>>>>>>>
}
/* if you want to display the image after every pass, do /* if you want to display the image after every pass, do
so here */ so here */
[[[[[[[ use only one of these two methods ]]]]]]]
} }
**** use only one of these two methods ****
/* read the rest of the file, getting any additional chunks in info_ptr */ /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
png_read_end(png_ptr, info_ptr); png_read_end(png_ptr, info_ptr);
/* clean up after the read, and free any memory allocated */ /* clean up after the read, and free any memory allocated - REQUIRED */
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL); png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
/* close the file */ /* close the file */
@ -257,15 +341,15 @@ int
initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr) initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr)
{ {
/* Create and initialize the png_struct with the desired error handler /* Create and initialize the png_struct with the desired error handler
functions. If you want to use the default stderr and longjump method, * functions. If you want to use the default stderr and longjump method,
you can supply NULL for the last three parameters. We also check that * you can supply NULL for the last three parameters. We also check that
the library version is compatible in case we are using dynamically * the library version is compatible in case we are using dynamically
linked libraries. * linked libraries.
*/ */
*png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
(void *)user_error_ptr, user_error_fn, user_warning_fn); (void *)user_error_ptr, user_error_fn, user_warning_fn);
if (! *png_ptr) if (*png_ptr == NULL)
{ {
*info_ptr = NULL; *info_ptr = NULL;
return ERROR; return ERROR;
@ -273,7 +357,7 @@ initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr)
*info_ptr = png_create_info_struct(png_ptr); *info_ptr = png_create_info_struct(png_ptr);
if (! *info_ptr) if (*info_ptr == NULL)
{ {
png_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL); png_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL);
return ERROR; return ERROR;
@ -286,13 +370,14 @@ initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr)
} }
/* this one's new. You will need to provide all three /* this one's new. You will need to provide all three
function callbacks, even if you aren't using them all. * function callbacks, even if you aren't using them all.
These functions shouldn't be dependent on global or * These functions shouldn't be dependent on global or
static variables if you are decoding several images * static variables if you are decoding several images
simultaneously. You should store stream specific data * simultaneously. You should store stream specific data
in a separate struct, given as the second parameter, * in a separate struct, given as the second parameter,
and retrieve the pointer from inside the callbacks using * and retrieve the pointer from inside the callbacks using
the function png_get_progressive_ptr(png_ptr). */ * the function png_get_progressive_ptr(png_ptr).
*/
png_set_progressive_read_fn(*png_ptr, (void *)stream_data, png_set_progressive_read_fn(*png_ptr, (void *)stream_data,
info_callback, row_callback, end_callback); info_callback, row_callback, end_callback);
@ -310,15 +395,16 @@ process_data(png_structp *png_ptr, png_infop *info_ptr,
return ERROR; return ERROR;
} }
/* this one's new also. Simply give it chunks of data as /* This one's new also. Simply give it chunks of data as
they arrive from the data stream (in order, of course). * they arrive from the data stream (in order, of course).
On Segmented machines, don't give it any more than 64K. * On Segmented machines, don't give it any more than 64K.
The library seems to run fine with sizes of 4K, although * The library seems to run fine with sizes of 4K, although
you can give it much less if necessary (I assume you can * you can give it much less if necessary (I assume you can
give it chunks of 1 byte, but I haven't tried with less * give it chunks of 1 byte, but I haven't tried with less
than 256 bytes yet). When this function returns, you may * than 256 bytes yet). When this function returns, you may
want to display any rows that were generated in the row * want to display any rows that were generated in the row
callback, if you aren't already displaying them there. */ * callback, if you aren't already displaying them there.
*/
png_process_data(*png_ptr, *info_ptr, buffer, length); png_process_data(*png_ptr, *info_ptr, buffer, length);
return OK; return OK;
} }
@ -326,52 +412,56 @@ process_data(png_structp *png_ptr, png_infop *info_ptr,
info_callback(png_structp png_ptr, png_infop info) info_callback(png_structp png_ptr, png_infop info)
{ {
/* do any setup here, including setting any of the transformations /* do any setup here, including setting any of the transformations
mentioned in the Reading PNG files section. For now, you _must_ * mentioned in the Reading PNG files section. For now, you _must_
call either png_start_read_image() or png_read_update_info() * call either png_start_read_image() or png_read_update_info()
after all the transformations are set (even if you don't set * after all the transformations are set (even if you don't set
any). You may start getting rows before png_process_data() * any). You may start getting rows before png_process_data()
returns, so this is your last chance to prepare for that. */ * returns, so this is your last chance to prepare for that.
*/
} }
row_callback(png_structp png_ptr, png_bytep new_row, row_callback(png_structp png_ptr, png_bytep new_row,
png_uint_32 row_num, int pass) png_uint_32 row_num, int pass)
{ {
/* this function is called for every row in the image. If the /* this function is called for every row in the image. If the
image is interlacing, and you turned on the interlace handler, * image is interlacing, and you turned on the interlace handler,
this function will be called for every row in every pass. * this function will be called for every row in every pass.
Some of these rows will not be changed from the previous pass. * Some of these rows will not be changed from the previous pass.
When the row is not changed, the new_row variable will be NULL. * When the row is not changed, the new_row variable will be NULL.
The rows and passes are called in order, so you don't really * The rows and passes are called in order, so you don't really
need the row_num and pass, but I'm supplying them because it * need the row_num and pass, but I'm supplying them because it
may make your life easier. * may make your life easier.
*
For the non-NULL rows of interlaced images, you must call * For the non-NULL rows of interlaced images, you must call
png_progressive_combine_row() passing in the row and the * png_progressive_combine_row() passing in the row and the
old row. You can call this function for NULL rows (it will * old row. You can call this function for NULL rows (it will
just return) and for non-interlaced images (it just does the * just return) and for non-interlaced images (it just does the
memcpy for you) if it will make the code easier. Thus, you * memcpy for you) if it will make the code easier. Thus, you
can just do this for all cases: */ * can just do this for all cases:
*/
png_progressive_combine_row(png_ptr, old_row, new_row); png_progressive_combine_row(png_ptr, old_row, new_row);
/* where old_row is what was displayed for previous rows. Note /* where old_row is what was displayed for previous rows. Note
that the first pass (pass == 0 really) will completely cover * that the first pass (pass == 0 really) will completely cover
the old row, so the rows do not have to be initialized. After * the old row, so the rows do not have to be initialized. After
the first pass (and only for interlaced images), you will have * the first pass (and only for interlaced images), you will have
to pass the current row, and the function will combine the * to pass the current row, and the function will combine the
old row and the new row. */ * old row and the new row.
*/
} }
end_callback(png_structp png_ptr, png_infop info) end_callback(png_structp png_ptr, png_infop info)
{ {
/* this function is called when the whole image has been read, /* this function is called when the whole image has been read,
including any chunks after the image (up to and including * including any chunks after the image (up to and including
the IEND). You will usually have the same info chunk as you * the IEND). You will usually have the same info chunk as you
had in the header, although some data may have been added * had in the header, although some data may have been added
to the comments and time fields. * to the comments and time fields.
*
Most people won't do much here, perhaps setting a flag that * Most people won't do much here, perhaps setting a flag that
marks the image as finished. */ * marks the image as finished.
*/
} }
/* write a png file */ /* write a png file */
@ -383,33 +473,36 @@ void write_png(char *file_name, ... other image information ...)
/* open the file */ /* open the file */
fp = fopen(file_name, "wb"); fp = fopen(file_name, "wb");
if (!fp) if (fp == NULL)
return; return;
/* Create and initialize the png_struct with the desired error handler /* Create and initialize the png_struct with the desired error handler
functions. If you want to use the default stderr and longjump method, * functions. If you want to use the default stderr and longjump method,
you can supply NULL for the last three parameters. We also check that * you can supply NULL for the last three parameters. We also check that
the library version is compatible in case we are using dynamically * the library version is compatible with the one used at compile time,
linked libraries. * in case we are using dynamically linked libraries. REQUIRED.
*/ */
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
(void *)user_error_ptr, user_error_fn, user_warning_fn); (void *)user_error_ptr, user_error_fn, user_warning_fn);
if (!png_ptr) if (png_ptr == NULL)
{ {
fclose(fp); fclose(fp);
return; return;
} }
/* Allocate/initialize the image information data. REQUIRED */
info_ptr = png_create_info_struct(png_ptr); info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) if (info_ptr == NULL)
{ {
fclose(fp); fclose(fp);
png_destroy_write_struct(&png_ptr, (png_infopp)NULL); png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
return; return;
} }
/* set error handling */ /* Set error handling. REQUIRED if you aren't supplying your own
* error hadnling functions in the png_create_write_struct() call.
*/
if (setjmp(png_ptr->jmpbuf)) if (setjmp(png_ptr->jmpbuf))
{ {
/* If we get here, we had a problem reading the file */ /* If we get here, we had a problem reading the file */
@ -418,63 +511,101 @@ void write_png(char *file_name, ... other image information ...)
return; return;
} }
/* One of the following I/O initialization functions is REQUIRED */
**** I/O initialization method 1 ****
/* set up the output control if you are using standard C streams */ /* set up the output control if you are using standard C streams */
png_init_io(png_ptr, fp); png_init_io(png_ptr, fp);
**** I/O initialization method 2 ****
/* If you are using replacement read functions, instead of calling
* png_init_io() here you would call */
png_set_write_fn(png_ptr, (void *)user_io_ptr, user_write_fn,
user_IO_flush_function);
/* where user_io_ptr is a structure you want available to the callbacks */
**** only use 1 initialization method ****
/* set the file information here */ /* Set the image information here. Width and height are up to 2^31,
info_ptr->width = ; * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
info_ptr->height = ; * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
etc. * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
* or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
* PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
* currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
*/
png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, PNG_COLOR_TYPE_???,
PNG_INTERLACE_????, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
/* set the palette if there is one */ /* set the palette if there is one. REQUIRED for indexed-color images */
info_ptr->valid |= PNG_INFO_PLTE; palette = png_malloc(png_ptr, 256 * sizeof (png_color));
info_ptr->palette = malloc(256 * sizeof (png_color));
info_ptr->num_palette = 256;
... set palette colors ... ... set palette colors ...
png_set_PLTE(png_ptr, info_ptr, palette, 256);
/* optional significant bit chunk */ /* optional significant bit chunk */
info_ptr->valid |= PNG_INFO_sBIT;
/* if we are dealing with a grayscale image then */ /* if we are dealing with a grayscale image then */
info_ptr->sig_bit.gray = true_bit_depth; sig_bit.gray = true_bit_depth;
/* otherwise, if we are dealing with a color image then */ /* otherwise, if we are dealing with a color image then */
info_ptr->sig_bit.red = true_red_bit_depth; sig_bit.red = true_red_bit_depth;
info_ptr->sig_bit.green = true_green_bit_depth; sig_bit.green = true_green_bit_depth;
info_ptr->sig_bit.blue = true_blue_bit_depth; sig_bit.blue = true_blue_bit_depth;
/* if the image has an alpha channel then */ /* if the image has an alpha channel then */
info_ptr->sig_bit.alpha = true_alpha_bit_depth; sig_bit.alpha = true_alpha_bit_depth;
png_set_sBIT(png_ptr, info_ptr, sig_bit);
/* optional gamma chunk is strongly suggested if you have any guess /* Optional gamma chunk is strongly suggested if you have any guess
as to the correct gamma of the image */ * as to the correct gamma of the image. */
info_ptr->valid |= PNG_INFO_gAMA; png_set_gAMA(png_ptr, info_ptr, gamma);
info_ptr->gamma = gamma;
/* other optional chunks like cHRM, bKGD, tRNS, tEXt, tIME, oFFs, pHYs, */ /* Optionally write comments into the image */
text_ptr[0].key = "Title";
text_ptr[0].text = "Mona Lisa";
text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
text_ptr[1].key = "Author";
text_ptr[1].text = "Leonardo DaVinci";
text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
text_ptr[2].key = "Description";
text_ptr[2].text = "<long text>";
text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt;
png_set_text(png_ptr, info_ptr, text_ptr, 2);
/* write the file header information */ /* other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs, */
/* Write the file header information. REQUIRED */
png_write_info(png_ptr, info_ptr); png_write_info(png_ptr, info_ptr);
/* Once we write out the header, the compression type on the text
* chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
* PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again
* at the end.
*/
/* set up the transformations you want. Note that these are /* set up the transformations you want. Note that these are
all optional. Only call them if you want them */ * all optional. Only call them if you want them. */
/* invert monocrome pixels */ /* invert monocrome pixels */
png_set_invert(png_ptr); png_set_invert(png_ptr);
/* shift the pixels up to a legal bit depth and fill in /* Shift the pixels up to a legal bit depth and fill in
as appropriate to correctly scale the image */ * as appropriate to correctly scale the image */
png_set_shift(png_ptr, &(info_ptr->sig_bit)); png_set_shift(png_ptr, &sig_bit);
/* pack pixels into bytes */ /* pack pixels into bytes */
png_set_packing(png_ptr); png_set_packing(png_ptr);
/* flip bgr pixels to rgb */ /* swap location of alpha bytes from ARGB to RGBA */
png_set_swap_alpha(png_ptr);
/* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into
* RGB (4 channels -> 3 channels). The second parameter is not used. */
png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
/* flip BGR pixels to RGB */
png_set_bgr(png_ptr); png_set_bgr(png_ptr);
/* swap bytes of 16 bit files to most significant bit first */ /* swap bytes of 16-bit files to most significant byte first */
png_set_swap(png_ptr); png_set_swap(png_ptr);
/* get rid of filler bytes, pack rgb into 3 bytes. The /* swap bits of 1, 2, 4 bit packed pixel formats */
filler number is not used. */ png_set_packswap(png_ptr);
png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
/* turn on interlace handling if you are not using png_write_image() */ /* turn on interlace handling if you are not using png_write_image() */
if (interlacing) if (interlacing)
@ -482,14 +613,22 @@ void write_png(char *file_name, ... other image information ...)
else else
number_passes = 1; number_passes = 1;
/* the easiest way to write the image (you may choose to allocate the /* The easiest way to write the image (you may have a different memory
memory differently, however) */ * layout, however, so choose what fits your needs best). You need to
* use the first method if you aren't handling interlacing yourself.
*/
png_byte row_pointers[height][width]; png_byte row_pointers[height][width];
/* One of the following output methods is REQUIRED */
**** write out the entire image data in one call ***
png_write_image(png_ptr, row_pointers); png_write_image(png_ptr, row_pointers);
/* the other way to write the image - deal with interlacing */ /* the other way to write the image - deal with interlacing */
**** write out the image data by one or more scanlines ****
/* The number of passes is either 1 for non-interlaced images,
* or 7 for interlaced images.
*/
for (pass = 0; pass < number_passes; pass++) for (pass = 0; pass < number_passes; pass++)
{ {
/* Write a few rows at a time. */ /* Write a few rows at a time. */
@ -502,24 +641,22 @@ void write_png(char *file_name, ... other image information ...)
png_write_rows(png_ptr, &row_pointers, 1); png_write_rows(png_ptr, &row_pointers, 1);
} }
} }
**** use only one output method ****
/* You can write optional chunks like tEXt, tIME at the end as well. /* You can write optional chunks like tEXt, zTXt, and tIME at the end
* Note that if you wrote tEXt or zTXt chunks before the image, and * as well.
* you aren't writing out more at the end, you have to set
* info_ptr->num_text = 0 or they will be written out again.
*/ */
/* write the rest of the file */ /* It is REQUIRED to call this to finish writing the rest of the file */
png_write_end(png_ptr, info_ptr); png_write_end(png_ptr, info_ptr);
/* if you malloced the palette, free it here */ /* if you malloced the palette, free it here */
if (info_ptr->palette) free(info_ptr->palette);
free(info_ptr->palette);
/* if you allocated any text comments, free them here */ /* if you allocated any text comments, free them here */
/* clean up after the write, and free any memory allocated */ /* clean up after the write, and free any memory allocated */
png_destroy_write_struct(&png_ptr, (png_infopp)NULL); png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
/* close the file */ /* close the file */
fclose(fp); fclose(fp);

View File

@ -1,16 +1,19 @@
libpng.txt - a description on how to use and modify libpng libpng.txt - a description on how to use and modify libpng
libpng 1.0 beta 3 - version 0.89 libpng 1.0 beta 5 - version 0.95
Updated and distributed by Andreas Dilger <adilger@enel.ucalgary.ca>, Updated and distributed by Andreas Dilger <adilger@enel.ucalgary.ca>,
based on: Copyright (c) 1996, 1997 Andreas Dilger
March 15, 1997
based on:
libpng 1.0 beta 2 - version 0.88 libpng 1.0 beta 2 - version 0.88
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
May 24, 1996 January 26, 1996
Updated/rewritten per request in the libpng FAQ
Copyright (c) 1995 Frank J. T. Wojcik Updated/rewritten per request in the libpng FAQ
December 18, 1995 && January 20, 1996 Copyright (c) 1995 Frank J. T. Wojcik
December 18, 1995 && January 20, 1996
I. Introduction I. Introduction
@ -32,10 +35,10 @@ only supports C. Support for other languages is being considered.
Libpng has been designed to handle multiple sessions at one time, Libpng has been designed to handle multiple sessions at one time,
to be easily modifiable, to be portable to the vast majority of to be easily modifiable, to be portable to the vast majority of
machines (ANSI, K&R, 16 bit, 32 bit) available, and to be easy to machines (ANSI, K&R, 16-, 32-, and 64-bit) available, and to be easy
use. The ultimate goal of libpng is to promote the acceptance of to use. The ultimate goal of libpng is to promote the acceptance of
the PNG file format in whatever way possible. While there is still the PNG file format in whatever way possible. While there is still
work to be done (see the pngtodo.txt file), libpng should cover the work to be done (see the TODO file), libpng should cover the
majority of the needs of it's users. majority of the needs of it's users.
Libpng uses zlib for its compression and decompression of PNG files. Libpng uses zlib for its compression and decompression of PNG files.
@ -59,10 +62,14 @@ will not, for the most part, be used by a user except as the first
variable passed to every libpng function call. variable passed to every libpng function call.
The png_info structure is designed to provide information about the The png_info structure is designed to provide information about the
png file. All of its fields are intended to be examined or modified PNG file. At one time, the fields of png_info were intended to be
by the user. See png.h for a good description of the png_info fields. directly accessible to the user. However, this tended to cause problems
png.h is also an invaluable reference for programming with libpng. with applications using dynamically loaded libraries, and as a result
a set of interface functions for png_info were delevoped. The fields
of png_info are still available for older applications, but it is
suggested that applications use the new interfaces if at all possible.
The png.h header file is an invaluable reference for programming with libpng.
And while I'm on the topic, make sure you include the libpng header file: And while I'm on the topic, make sure you include the libpng header file:
#include <png.h> #include <png.h>
@ -110,24 +117,27 @@ Customizing libpng.
return; return;
} }
Next, png_struct and png_info need to be allocated and initialized. Next, png_struct and png_info need to be allocated and initialized. In
In order to ensure that the size of these structures is correct even order to ensure that the size of these structures is correct even with a
with a dynamically linked libpng, there are functions to initialize dynamically linked libpng, there are functions to initialize and
and allocate the structures. We also pass the library version, and allocate the structures. We also pass the library version, optional
optionally pointers to error handling functions (these can be NULL pointers to error handling functions, and a pointer to a data struct for
if the default error handlers are to be used). See the section on use by the error functions, if necessary (the pointer and functions can
Changes to Libpng below regarding the old initialization functions. be NULL if the default error handlers are to be used). See the section
on Changes to Libpng below regarding the old initialization functions.
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
(void *)user_error_ptr, user_error_fn, user_warning_fn); (void *)user_error_ptr, user_error_fn, user_warning_fn);
if (!png_ptr) if (!png_ptr)
return; return;
png_infop info_ptr = png_create_info_struct(png_ptr); png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr) if (!info_ptr)
{ {
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL); png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
return; return;
} }
png_infop end_info = png_create_info_struct(png_ptr); png_infop end_info = png_create_info_struct(png_ptr);
if (!end_info) if (!end_info)
{ {
@ -160,9 +170,10 @@ free any memory.
Now you need to set up the input code. The default for libpng is to Now you need to set up the input code. The default for libpng is to
use the C function fread(). If you use this, you will need to pass a use the C function fread(). If you use this, you will need to pass a
valid FILE * in the function png_init_io(). Be sure that the file is valid FILE * in the function png_init_io(). Be sure that the file is
opened in binary mode. Again, if you wish to handle reading data in opened in binary mode. If you wish to handle reading data in another
another way, see the discussion on libpng I/O handling in the Customizing way, you need not call the png_init_io() function, but you must then
Libpng section below. implement the libpng I/O methods discussed in the Customizing Libpng
section below.
png_init_io(png_ptr, fp); png_init_io(png_ptr, fp);
@ -177,76 +188,127 @@ image data. You do this with a call to png_read_info().
png_read_info(png_ptr, info_ptr); png_read_info(png_ptr, info_ptr);
The png_info structure is now filled in with all the data necessary Functions are used to get the information from the info_ptr:
to read the file. Some of the more important parts of the info_ptr are:
width - holds the width of the file png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
height - holds the height of the file &interlace_type, &compression_type, &filter_type);
bit_depth - holds the bit depth of one of the image channels
color_type - describes the channels and what they mean width - holds the width of the image in pixels (up to 2^31).
(see the PNG_COLOR_TYPE_ macros for more information) height - holds the height of the image in pixels (up to 2^31).
bit_depth - holds the bit depth of one of the image channels.
(valid values are 1, 2, 4, 8, 16 and depend also on the
color_type. See also significant bits (sBIT) below).
color_type - describes which color/alpha channels are present.
PNG_COLOR_TYPE_GRAY (bit depths 1, 2, 4, 8, 16)
PNG_COLOR_TYPE_GRAY_ALPHA (bit depths 8, 16)
PNG_COLOR_TYPE_PALETTE (bit depths 1, 2, 4, 8)
PNG_COLOR_TYPE_RGB (bit_depths 8, 16)
PNG_COLOR_TYPE_RGB_ALPHA (bit_depths 8, 16)
PNG_COLOR_MASK_PALETTE
PNG_COLOR_MASK_COLOR
PNG_COLOR_MASK_ALPHA
interlace_type - PNG_INTERLACE_TYPE_NONE or PNG_INTERLACE_TYPE_ADAM7
compression_type - (must be PNG_COMPRESSION_TYPE_BASE for PNG 1.0)
filter_type - (must be PNG_FILTER_TYPE_BASE for PNG 1.0)
channels = png_get_channels(png_ptr, info_ptr);
channels - number of channels of info for the color type channels - number of channels of info for the color type
pixel_depth - bits per pixel, the result of multiplying the (valid values are 1 (GRAY, PALETTE), 2 (GRAY_ALPHA),
bit_depth times the channels 3 (RGB), 4 (RGB_ALPHA or RGB + filler byte))
rowbytes = png_get_rowbytes(png_ptr, info_ptr);
rowbytes - number of bytes needed to hold a row rowbytes - number of bytes needed to hold a row
interlace_type - currently 0 for none, 1 for interlaced
signature = png_get_signature(png_ptr, info_ptr);
signature - holds the signature read from the file (if any). The signature - holds the signature read from the file (if any). The
data is kept in the same offset it would be if the data is kept in the same offset it would be if the
whole signature were read (ie if you had already read whole signature were read (ie if an application had
in 4 bytes of signature, the remaining 4 bytes would already read in 4 bytes of signature before staring
be in signature[4] through signature[7]). libpng, the remaining 4 bytes would be in signature[4]
valid - this details which optional chunks were found in the through signature[7] (see png_set_sig_bytes())).
file. To see if a chunk was present, AND '&' valid with
the appropriate PNG_INFO_<chunk name> define.
These are also important, but their validity depends on whether a These are also important, but their validity depends on whether the chunk
corresponding chunk exists. Use valid (see above) to ensure that what has been read. The png_get_valid(png_ptr, info_ptr, PNG_INFO_<chunk>) and
you're doing with these values makes sense. png_get_<chunk>(png_ptr, info_ptr, ...) functions return non-zero if the
data has been read, or zero if it is missing. The parameters to the
png_get_<chunk> are set directly if they are simple data types, or a pointer
into the info_ptr is returned for any complex types.
palette - the palette for the file (PNG_INFO_PLTE) png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette);
palette - the palette for the file (array of png_color)
num_palette - number of entries in the palette num_palette - number of entries in the palette
png_get_gAMA(png_ptr, info_ptr, &gamma);
gamma - the gamma the file is written at (PNG_INFO_gAMA) gamma - the gamma the file is written at (PNG_INFO_gAMA)
sig_bit - the number of significant bits (PNG_INFO_sBIT)
for the gray, red, green, and blue channels, whichever png_get_sBIT(png_ptr, info_ptr, &sig_bit);
are appropriate for the given color type. sig_bit - the number of significant bits for (PNG_INFO_sBIT)
the gray, red, green, and blue channels, whichever
are appropriate for the given color type (png_color_16)
png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, &trans_values);
trans - array of transparent entries for palette (PNG_INFO_tRNS)
trans_values - transparent pixel for non-paletted images (PNG_INFO_tRNS) trans_values - transparent pixel for non-paletted images (PNG_INFO_tRNS)
trans - array of transparent entries for paletted images num_trans - number of transparent entries (PNG_INFO_tRNS)
num_trans - number of transparent entries
hist - histogram of palette (PNG_INFO_hIST) png_get_hIST(png_ptr, info_ptr, &hist); (PNG_INFO_hIST)
hist - histogram of palette (array of png_color_16)
png_get_tIME(png_ptr, info_ptr, &mod_time);
mod_time - time image was last modified (PNG_VALID_tIME) mod_time - time image was last modified (PNG_VALID_tIME)
png_get_bKGD(png_ptr, info_ptr, &background);
background - background color (PNG_VALID_bKGD) background - background color (PNG_VALID_bKGD)
text - text comments in the file.
num_text = png_get_text(png_ptr, info_ptr, &text_ptr);
text_ptr - array of png_text holding image comments
text_ptr[i]->key - keyword for comment.
text_ptr[i]->text - text comments for current keyword.
text_ptr[i]->compression - type of compression used on "text"
PNG_TEXT_COMPRESSION_NONE or
PNG_TEXT_COMPRESSION_zTXt
num_text - number of comments num_text - number of comments
for more information, see the png_info definition in png.h and the png_get_oFFs(png_ptr, info_ptr, &offset_x, &offset_y, &unit_type);
offset_x - positive offset from the left edge of the screen
offset_y - positive offset from the top edge of the screen
unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER
png_get_pHYs(png_ptr, info_ptr, &res_x, &res_y, &unit_type);
res_x - pixels/unit physical resolution in x direction
res_y - pixels/unit physical resolution in x direction
unit_type - PNG_RESOLUTION_UNKOWN, PNG_RESOLUTION_METER
For more information, see the png_info definition in png.h and the
PNG specification for chunk contents. Be careful with trusting PNG specification for chunk contents. Be careful with trusting
rowbytes, as some of the transformations could increase the space rowbytes, as some of the transformations could increase the space
needed to hold a row (expand, RGBX, XRGB, gray_to_rgb, etc.). needed to hold a row (expand, filler, gray_to_rgb, etc.).
See png_update_info(), below. See png_read_update_info(), below.
A quick word about text and num_text. PNG stores comments in A quick word about text_ptr and num_text. PNG stores comments in
keyword/text pairs, one pair per chunk. While there are suggested keyword/text pairs, one pair per chunk, with no limit on the number
keywords, there is no requirement to restrict the use to these of text chunks, and a 2^31 byte limit on their size. While there are
strings. There is a requirement to have at least one character for a suggested keywords, there is no requirement to restrict the use to these
keyword. It is strongly suggested that keywords be sensible to humans strings. It is strongly suggested that keywords and text be sensible
(that's the point), so don't use abbreviations. See the PNG to humans (that's the point), so don't use abbreviations or non-printing
specification for more details. There is also no requirement to have symbols. See the PNG specification for more details. There is also
text after the keyword. no requirement to have text after the keyword.
Keywords should be limited to 80 characters without leading or trailing Keywords should be limited to 79 Latin-1 characters without leading or
spaces, but non-consecutive spaces are allowed within the keyword. It is trailing spaces, but non-consecutive spaces are allowed within the
possible to have the same keyword any number of times. The text field keyword. It is possible to have the same keyword any number of times.
is an array of png_text structures, each holding pointer to a keyword The text_ptr is an array of png_text structures, each holding pointer
and a pointer to a text string. Only the text string may be null. to a keyword and a pointer to a text string. Only the text string may
The keyword/text pairs are put into the array in the order that be null. The keyword/text pairs are put into the array in the order
they are received. However, some or all of the text chunks may be that they are received. However, some or all of the text chunks may be
after the image, so, to make sure you have read all the text chunks, after the image, so, to make sure you have read all the text chunks,
don't mess with these until after you read the stuff after the image. don't mess with these until after you read the stuff after the image.
This will be mentioned again below in the discussion that goes with This will be mentioned again below in the discussion that goes with
png_read_end(). png_read_end().
After you've read the file information, you can set up the library to After you've read the header information, you can set up the library
handle any special transformations of the image data. The various to handle any special transformations of the image data. The various
ways to transform the data will be described in the order that they ways to transform the data will be described in the order that they
should occur. This is important, as some of these change the color should occur. This is important, as some of these change the color
type and/or bit depth of the data, and some others only work on type and/or bit depth of the data, and some others only work on
@ -260,7 +322,7 @@ supplied in the same format/depth as the current image data. They
are stored in the same format/depth as the image data in a bKGD or tRNS are stored in the same format/depth as the image data in a bKGD or tRNS
chunk, so this is what libpng expects for this data. The colors are chunk, so this is what libpng expects for this data. The colors are
transformed to keep in sync with the image data when an application transformed to keep in sync with the image data when an application
calls the png_update_info() routine (see below). calls the png_read_update_info() routine (see below).
Data will be decoded into the supplied row buffers packed into bytes Data will be decoded into the supplied row buffers packed into bytes
unless the library has been told to transform it into another format. unless the library has been told to transform it into another format.
@ -279,97 +341,141 @@ transparency information in a tRNS chunk. This is most useful on
grayscale images with bit depths of 2 or 4 or if there is a multiple-image grayscale images with bit depths of 2 or 4 or if there is a multiple-image
viewing application that wishes to treat all images in the same way. viewing application that wishes to treat all images in the same way.
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE && if (color_type == PNG_COLOR_TYPE_PALETTE && bit_depth < 8)
info_ptr->bit_depth < 8)
png_set_expand(png_ptr); png_set_expand(png_ptr);
if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY && if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
info_ptr->bit_depth < 8) png_set_expand(png_ptr);
png_set_expand(png_ptr);
if (info_ptr->valid & PNG_INFO_tRNS) if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
png_set_expand(png_ptr); png_set_expand(png_ptr);
PNG can have files with 16 bits per channel. If you only can handle PNG can have files with 16 bits per channel. If you only can handle
8 bits per channel, this will strip the pixels down to 8 bit. 8 bits per channel, this will strip the pixels down to 8 bit.
if (info_ptr->bit_depth == 16) if (bit_depth == 16)
png_set_strip_16(png_ptr); png_set_strip_16(png_ptr);
If, for some reason, you don't need the alpha channel on an image,
and you want to remove it rather than combining it with the background:
if (color_type & PNG_COLOR_MASK_ALPHA)
png_set_strip_alpha(png_ptr);
PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as
they can, resulting in, for example, 8 pixels per byte for 1 bit they can, resulting in, for example, 8 pixels per byte for 1 bit
files. This code expands to 1 pixel per byte without changing the files. This code expands to 1 pixel per byte without changing the
values of the pixels: values of the pixels:
if (info_ptr->bit_depth < 8) if (bit_depth < 8)
png_set_packing(png_ptr); png_set_packing(png_ptr);
PNG files have possible bit depths of 1, 2, 4, 8, and 16. It is then PNG files have possible bit depths of 1, 2, 4, 8, and 16. All pixels
required that values be "scaled" or "shifted" up to the bit depth used stored in a PNG image whave been "scaled" or "shifted" up to the next
in the file (ie from 5 bits/sample in the range [0,31] to 8 bits/sample higher possible bit depth (eg from 5 bits/sample in the range [0,31] to
in the range [0, 255]). However, they also provide a way to describe 8 bits/sample in the range [0, 255]). However, it is also possible to
the true bit depth of the image. See the PNG specification for details. convert the PNG pixel data back to the original bit depth of the image.
This call reduces the pixels back down to the true bit depth: This call reduces the pixels back down to the original bit depth:
if (info_ptr->valid & PNG_INFO_sBIT) png_color_16p sig_bit;
png_set_shift(png_ptr, &(info_ptr->sig_bit));
PNG files store 3 color pixels in red, green, blue order. This code if (png_get_sBIT(png_ptr, info_ptr, &sig_bit))
png_set_shift(png_ptr, sig_bit);
PNG files store 3-color pixels in red, green, blue order. This code
changes the storage of the pixels to blue, green, red: changes the storage of the pixels to blue, green, red:
if (info_ptr->color_type == PNG_COLOR_TYPE_RGB || if (color_type == PNG_COLOR_TYPE_RGB ||
info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) color_type == PNG_COLOR_TYPE_RGB_ALPHA)
png_set_bgr(png_ptr); png_set_bgr(png_ptr);
PNG files store RGB pixels packed into 3 bytes. This code expands them PNG files store RGB pixels packed into 3 bytes. This code expands them
into 4 bytes for windowing systems that need them in this format: into 4 bytes for windowing systems that need them in this format:
if (info_ptr->bit_depth == 8 && if (bit_depth == 8 && color_type == PNG_COLOR_TYPE_RGB)
info_ptr->color_type == PNG_COLOR_TYPE_RGB) png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE);
png_set_filler(png_ptr, filler_byte, PNG_FILLER_BEFORE);
where filler_byte is the number to fill with, and the location is where "filler" is the number to fill with, and the location is
either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether
you want the filler before the RGB or after. you want the filler before the RGB or after. This transformation
does not affect images that already have full alpha channels.
For some uses, you may want a gray-scale image to be represented as If you are reading an image with an alpha channel, and you need the
data as ARGB instead of the normal PNG format RGBA:
if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
png_set_swap_alpha(png_ptr);
For some uses, you may want a grayscale image to be represented as
RGB. This code will do that conversion: RGB. This code will do that conversion:
if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY || if (color_type == PNG_COLOR_TYPE_GRAY ||
info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png_ptr); png_set_gray_to_rgb(png_ptr);
The following code handles alpha and transparency by replacing it with The png_set_background() function tells libpng to composite images
a background value. If there was a valid bKGD in the file, you can use with alpha or simple transparency against the supplied background
it if you want. However, you can replace it with your own if you want color. If the PNG file contains a bKGD chunk (PNG_INFO_bKGD valid),
also. If there wasn't one in the file, you must supply a color. If you may use this color, or supply another color more suitable for
libpng is doing gamma correction, you will need to tell libpng where the current display (e.g., the background color from a web page). You
the background came from so it can do the appropriate gamma need to tell libpng whether the color is in the gamma space of the
correction. If you have a grayscale and you are using png_set_expand() dispay (PNG_BACKGROUND_GAMMA_SCREEN for colors you supply), the file
to change to a higher bit-depth you must indicate if the background gray (PNG_BACKGROUND_GAMMA_FILE for colors from the bKGD chunk), or one
needs to be expanded to the new bit-depth. Similarly, if you are reading that is neither of these gammas (PNG_BACKGROUND_GAMMA_UNIQUE - I don't
know why anyone would use this, but it's here).
If you have a grayscale and you are using png_set_expand() to change to
a higher bit-depth you must indicate if the supplied background gray
is supplied in the original file bit depth (need_expand = 1) or in the
expanded bit depth (need_expand = 0). Similarly, if you are reading
a paletted image, you must indicate if you have supplied the background a paletted image, you must indicate if you have supplied the background
index that needs to be expanded to RGB values. You can always specify as a palette index that needs to be expanded (need_expand = 1). You can
RGB color values directly when setting your background for paletted images. also specify an RGB triplet that isn't in the palette when setting your
background for a paletted image.
png_color_16 my_background; png_color_16 my_background;
png_color_16p image_background;
if (info_ptr->valid & PNG_INFO_bKGD) if (png_get_bKGD(png_ptr, info_ptr, &image_background))
png_set_backgrond(png_ptr, &(info_ptr->background), png_set_background(png_ptr, image_background),
PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
else
png_set_background(png_ptr, &my_background,
PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
To properly display PNG images on any kind of system, the application needs
to know what the display gamma is. Ideally, the user will know this, and
the application will allow them to set it. One method of allowing the user
to set the display gamma separately for each system is to check for the
DISPLAY_GAMMA environment variable, which will hopefully be correctly set.
if (/* We have a user-defined screen gamma value */)
{
screen_gamma = user_defined_screen_gamma;
}
/* One way that applications can share the same screen gamma value */
else if ((gamma_str = getenv("DISPLAY_GAMMA")) != NULL)
{
screen_gamma = atof(gamma_str);
}
/* If we don't have another value */
else else
png_set_background(png_ptr, &my_background, {
PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); screen_gamma = 2.2; /* A good guess for PC monitors */
screen_gamma = 1.7 or 1.0; /* A good guess for Mac systems */
}
The following code handles gamma transformations of the data. Pass The png_set_gamma() function handles gamma transformations of the data.
both the file gamma and the desired screen gamma. If the file does Pass both the file gamma and the current screen_gamma. If the file does
not have a gamma value, you can pass one anyway if you wish. Note not have a gamma value, you can pass one anyway if you have an idea what
it is (usually 0.45 is a good guess for GIF images on PCs). Note
that file gammas are inverted from screen gammas. See the discussions that file gammas are inverted from screen gammas. See the discussions
on gamma in the PNG specification for more information. It is on gamma in the PNG specification for an excellent description of what
strongly recommended that viewers support gamma correction. gamma is, and why all applications should support it. It is strongly
recommended that PNG viewers support gamma correction.
if (info_ptr->valid & PNG_INFO_gAMA) if (png_get_gAMA(png_ptr, info_ptr, &gamma))
png_set_gamma(png_ptr, screen_gamma, info_ptr->gamma); png_set_gamma(png_ptr, screen_gamma, gamma);
else else
png_set_gamma(png_ptr, screen_gamma, 0.45); png_set_gamma(png_ptr, screen_gamma, 0.45);
@ -384,13 +490,15 @@ maximum_colors. If there is a histogram, it will use it to make
more intelligent choices when reducing the palette. If there is no more intelligent choices when reducing the palette. If there is no
histogram, it may not do as good a job. histogram, it may not do as good a job.
if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) if (color_type & PNG_COLOR_MASK_COLOR)
{ {
if (info_ptr->valid & PNG_INFO_PLTE) if (png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE))
{ {
png_set_dither(png_ptr, info_ptr->palette, png_color_16p histogram;
info_ptr->num_palette, max_screen_colors,
info_ptr->histogram, 1); png_get_hIST(png_ptr, info_ptr, &histogram);
png_set_dither(png_ptr, palette, num_palette, max_screen_colors,
histogram, 1);
} }
else else
{ {
@ -406,8 +514,7 @@ PNG files describe monochrome as black being zero and white being one.
The following code will reverse this (make black be one and white be The following code will reverse this (make black be one and white be
zero): zero):
if (info_ptr->bit_depth == 1 && if (bit_depth == 1 && color_type == PNG_COLOR_GRAY)
info_ptr->color_type == PNG_COLOR_GRAY)
png_set_invert_mono(png_ptr); png_set_invert_mono(png_ptr);
PNG files store 16 bit pixels in network byte order (big-endian, PNG files store 16 bit pixels in network byte order (big-endian,
@ -415,19 +522,24 @@ ie. most significant bits first). This code chages the storage to the
other way (little-endian, ie. least significant bits first, eg. the other way (little-endian, ie. least significant bits first, eg. the
way PCs store them): way PCs store them):
if (info_ptr->bit_depth == 16) if (bit_depth == 16)
png_set_swap(png_ptr); png_set_swap(png_ptr);
If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you
need to change the order the pixels are packed into bytes, you can use:
if (bit_depth < 8)
png_set_packswap(png_ptr);
The last thing to handle is interlacing; this is covered in detail below, The last thing to handle is interlacing; this is covered in detail below,
but you must call the function here. but you must call the function here.
if (info_ptr->interlace_type) number_passes = png_set_interlace_handling(png_ptr);
number_passes = png_set_interlace_handling(png_ptr);
After setting the transformations, libpng can update your png_info After setting the transformations, libpng can update your png_info
structure to reflect any transformations you've requested with this structure to reflect any transformations you've requested with this
call. This is most useful to update the info structures rowbytes call. This is most useful to update the info structure's rowbytes
field, so you can use it to allocate your image memory. This function field so you can use it to allocate your image memory. This function
will also update your palette with the correct display gamma and will also update your palette with the correct display gamma and
background if these have been given with the calls above. background if these have been given with the calls above.
@ -462,7 +574,7 @@ You can point to void or char or whatever you use for pixels.
If you don't want to read int the whole image at once, you can If you don't want to read int the whole image at once, you can
use png_read_rows() instead. If there is no interlacing (check use png_read_rows() instead. If there is no interlacing (check
info_ptr->interlace_type), this is simple: interlace_type == PNG_INTERLACE_TYPE_NONE), this is simple:
png_read_rows(png_ptr, row_pointers, NULL, number_of_rows); png_read_rows(png_ptr, row_pointers, NULL, number_of_rows);
@ -475,11 +587,11 @@ row_pointers:
png_read_row(png_ptr, &row_pointers, NULL); png_read_row(png_ptr, &row_pointers, NULL);
If the file is interlaced (info_ptr->interlace_type != 0), things get If the file is interlaced (info_ptr->interlace_type != 0), things get
somewhat harder. The only currently (as of 6/96 -- PNG somewhat harder. The only current (PNG Specification version 1.0)
Specification version 1.0) defined interlacing scheme for PNG files interlacing type for PNG is (interlace_type == PNG_INTERLACE_TYPE_ADAM7)
(info_ptr->interlace_type == 1) is a someewhat complicated 2D interlace is a someewhat complicated 2D interlace scheme, known as Adam7, that
scheme, known as Adam7, that breaks down an image into seven smaller breaks down an image into seven smaller images of varying size, based
images of varying size, based on an 8x8 grid. on an 8x8 grid.
libpng can fill out those images or it can give them to you "as is". libpng can fill out those images or it can give them to you "as is".
If you want them filled out, there are two ways to do that. The one If you want them filled out, there are two ways to do that. The one
@ -515,7 +627,7 @@ numbered scanlines. Phew!
If you want libpng to expand the images, call this before calling If you want libpng to expand the images, call this before calling
png_start_read_image() or png_read_update_info(): png_start_read_image() or png_read_update_info():
if (info_ptr->interlace_type) if (interlace_type == PNG_INTERLACE_TYPE_ADAM7)
number_passes = png_set_interlace_handling(png_ptr); number_passes = png_set_interlace_handling(png_ptr);
This will return the number of passes needed. Currently, this This will return the number of passes needed. Currently, this
@ -755,7 +867,7 @@ section below for more information on the libpng error handling.
return; return;
} }
Now you need to set up the input code. The default for libpng is to Now you need to set up the output code. The default for libpng is to
use the C function fwrite(). If you use this, you will need to pass a use the C function fwrite(). If you use this, you will need to pass a
valid FILE * in the function png_init_io(). Be sure that the file is valid FILE * in the function png_init_io(). Be sure that the file is
opened in binary mode. Again, if you wish to handle writing data in opened in binary mode. Again, if you wish to handle writing data in
@ -810,32 +922,74 @@ contain, see the PNG specification.
Some of the more important parts of the png_info are: Some of the more important parts of the png_info are:
width - holds the width of the file png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type,
height - holds the height of the file interlace_type,
bit_depth - holds the bit depth of one of the image channels width - holds the width of the image in pixels (up to 2^31).
color_type - describes the channels and what they mean height - holds the height of the image in pixels (up to 2^31).
see the PNG_COLOR_TYPE_ defines for more information bit_depth - holds the bit depth of one of the image channels.
interlace_type - allowed values are 0 for none, 1 for interlaced (valid values are 1, 2, 4, 8, 16 and depend also on the
valid - this describes which optional chunks to write to the color_type. See also significant bits (sBIT) below).
file. Note that if you are writing a color_type - describes which color/alpha channels are present.
PNG_COLOR_TYPE_PALETTE file, the PLTE chunk is not PNG_COLOR_TYPE_GRAY (bit depths 1, 2, 4, 8, 16)
optional, but must still be marked for writing. To PNG_COLOR_TYPE_GRAY_ALPHA (bit depths 8, 16)
mark chunks for writing, logical OR '|' valid with PNG_COLOR_TYPE_PALETTE (bit depths 1, 2, 4, 8)
the appropriate PNG_INFO_<chunk name> define. PNG_COLOR_TYPE_RGB (bit_depths 8, 16)
palette - the palette for the file (PNG_INFO_PLTE) PNG_COLOR_TYPE_RGB_ALPHA (bit_depths 8, 16)
PNG_COLOR_MASK_PALETTE
PNG_COLOR_MASK_COLOR
PNG_COLOR_MASK_ALPHA
interlace_type - PNG_INTERLACE_TYPE_NONE or PNG_INTER_LACE_TYPE_ADAM7
compression_type - (must be PNG_COMPRESSION_TYPE_DEFAULT for PNG 1.0)
filter_type - (must be PNG_FILTER_TYPE_DEFAULT for PNG 1.0)
Any or all of interlace_type, compression_type, of filter_type can be
NULL if you are not interested in their values.
png_set_PLTE(png_ptr, info_ptr, palette, num_palette);
palette - the palette for the file (array of png_color)
num_palette - number of entries in the palette num_palette - number of entries in the palette
gamma - the gamma the file is written at (PNG_INFO_gAMA)
sig_bit - the number of significant bits (PNG_INFO_sBIT) png_set_gAMA(png_ptr, info_ptr, gamma);
for the gray, red, green, and blue channels, whichever gamma - the gamma the image was created at (PNG_INFO_gAMA)
are appropriate for the given color type.
png_set_sBIT(png_ptr, info_ptr, sig_bit);
sig_bit - the number of significant bits for (PNG_INFO_sBIT)
the gray, red, green, and blue channels, whichever
are appropriate for the given color type (png_color_16)
png_set_tRNS(png_ptr, info_ptr, trans, num_trans, trans_values);
trans - array of transparent entries for palette (PNG_INFO_tRNS)
trans_values - transparent pixel for non-paletted images (PNG_INFO_tRNS) trans_values - transparent pixel for non-paletted images (PNG_INFO_tRNS)
trans - array of transparent entries for paletted images num_trans - number of transparent entries (PNG_INFO_tRNS)
num_trans - number of transparent entries
hist - histogram of palette (PNG_INFO_hIST) png_set_hIST(png_ptr, info_ptr, hist); (PNG_INFO_hIST)
hist - histogram of palette (array of png_color_16)
png_set_tIME(png_ptr, info_ptr, mod_time);
mod_time - time image was last modified (PNG_VALID_tIME) mod_time - time image was last modified (PNG_VALID_tIME)
png_set_bKGD(png_ptr, info_ptr, background);
background - background color (PNG_VALID_bKGD) background - background color (PNG_VALID_bKGD)
text - text comments in the file.
num_text - number of comments png_set_text(png_ptr, info_ptr, text_ptr, num_text);
text_ptr - array of png_text holding image comments
text_ptr[i]->key - keyword for comment.
text_ptr[i]->text - text comments for current keyword.
text_ptr[i]->compression - type of compression used on "text"
PNG_TEXT_COMPRESSION_NONE or
PNG_TEXT_COMPRESSION_zTXt
num_text - number of comments in text_ptr
png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
offset_x - positive offset from the left edge of the screen
offset_y - positive offset from the top edge of the screen
unit_type - PNG_OFFSET_PIXEL, PNG_OFFSET_MICROMETER
png_get_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
res_x - pixels/unit physical resolution in x direction
res_y - pixels/unit physical resolution in x direction
unit_type - PNG_RESOLUTION_UNKOWN, PNG_RESOLUTION_METER
A quick word about text and num_text. text is an array of png_text A quick word about text and num_text. text is an array of png_text
structures. num_text is the number of valid structures in the array. structures. num_text is the number of valid structures in the array.
@ -846,8 +1000,12 @@ The compression types have the same valid numbers as the compression
types of the image data. Currently, the only valid number is zero. types of the image data. Currently, the only valid number is zero.
However, you can store text either compressed or uncompressed, unlike However, you can store text either compressed or uncompressed, unlike
images which always have to be compressed. So if you don't want the images which always have to be compressed. So if you don't want the
text compressed, set the compression type to -1. Until text gets text compressed, set the compression type to PNG_TEXT_COMPRESSION_NONE.
around 1000 bytes, it is not worth compressing it. Until text gets around 1000 bytes, it is not worth compressing it.
After the text has been written out to the file, the compression type
is set to PNG_TEXT_COMPRESSION_NONE_WR or PNG_TEXT_COMPRESSION_zTXt_WR,
so that it isn't written out again at the end (in case you are calling
png_write_end() with the same struct.
The keywords that are given in the PNG Specification are: The keywords that are given in the PNG Specification are:
@ -889,7 +1047,8 @@ time_t routine uses gmtime(). You don't have to use either of
these, but if you wish to fill in the png_time structure directly, these, but if you wish to fill in the png_time structure directly,
you should provide the time in universal time (GMT) if possible you should provide the time in universal time (GMT) if possible
instead of your local time. Note that the year number is the full instead of your local time. Note that the year number is the full
year (ie 1996, rather than 96), and that months start with 1. year (ie 1996, rather than 96 - PNG is year 2000 compliant!), and
that months start with 1.
You are now ready to write all the file information up to the actual You are now ready to write all the file information up to the actual
image data. You do this with a call to png_write_info(). image data. You do this with a call to png_write_info().
@ -926,39 +1085,44 @@ PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. If your
data is of another bit depth, you can write an sBIT chunk into the data is of another bit depth, you can write an sBIT chunk into the
file so that decoders can get the original data if desired. file so that decoders can get the original data if desired.
/* Do this before png_write_info() */
info_ptr->valid |= PNG_INFO_sBIT;
/* Set the true bit depth of the image data */ /* Set the true bit depth of the image data */
if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) if (color_type & PNG_COLOR_MASK_COLOR)
{ {
info_ptr->sig_bit.red = true_bit_depth; sig_bit.red = true_bit_depth;
info_ptr->sig_bit.green = true_bit_depth; sig_bit.green = true_bit_depth;
info_ptr->sig_bit.blue = true_bit_depth; sig_bit.blue = true_bit_depth;
} }
else else
{ {
info_ptr->sig_bit.gray = true_bit_depth; sig_bit.gray = true_bit_depth;
}
if (color_type & PNG_COLOR_MASK_ALPHA)
{
sig_bit.alpha = true_bit_depth;
} }
if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) png_set_sBIT(png_ptr, info_ptr, &sig_bit);
{
info_ptr->sig_bit.alpha = true_bit_depth;
}
If the data is stored in the row buffer in a bit depth other than If the data is stored in the row buffer in a bit depth other than
one supported by PNG (ie 3 bit data in the range 0-7 for a 4-bit PNG), one supported by PNG (ie 3 bit data in the range 0-7 for a 4-bit PNG),
this will scale the values to appear to be the correct bit depth as this will scale the values to appear to be the correct bit depth as
is required by PNG. is required by PNG.
png_set_shift(png_ptr, &(info_ptr->sig_bit)); png_set_shift(png_ptr, &sig_bit);
PNG files store 16 bit pixels in network byte order (big-endian, PNG files store 16 bit pixels in network byte order (big-endian,
ie. most significant bits first). This code would be used if they are ie. most significant bits first). This code would be used if they are
supplied the other way (little-endian, ie. least significant bits supplied the other way (little-endian, ie. least significant bits
first, eg. the way PCs store them): first, eg. the way PCs store them):
png_set_swap(png_ptr); if (bit_depth > 8)
png_set_swap(png_ptr);
If you are using packed-pixel images (1, 2, or 4 bits/pixel), and you
need to change the order the pixels are packed into bytes, you can use:
if (bit_depth < 8)
png_set_packswap(png_ptr);
PNG files store 3 color pixels in red, green, blue order. This code PNG files store 3 color pixels in red, green, blue order. This code
would be used if they are supplied as blue, green, red: would be used if they are supplied as blue, green, red:
@ -1056,9 +1220,7 @@ and only update the rows that are actually used.
After you are finished writing the image, you should finish writing After you are finished writing the image, you should finish writing
the file. If you are interested in writing comments or time, you should the file. If you are interested in writing comments or time, you should
pass the an appropriately filled png_info pointer. If you pass the an appropriately filled png_info pointer. If you
are not interested, you can pass NULL. If you have written text at are not interested, you can pass NULL.
the beginning and are not writing more at the end, you should set
info_ptr->num_text = 0, or the text will be written again here.
png_write_end(png_ptr, info_ptr); png_write_end(png_ptr, info_ptr);
@ -1079,26 +1241,27 @@ standard things like memory allocation, input/output, and error handling.
The second deals with more complicated things like adding new chunks, The second deals with more complicated things like adding new chunks,
adding new transformations, and generally changing how libpng works. adding new transformations, and generally changing how libpng works.
All of the memory allocation, input/output, and error handling in All of the memory allocation, input/output, and error handling in libpng
libpng goes through callbacks which are user setable. The default goes through callbacks which are user setable. The default routines are
routines are in pngmem.c, pngrio.c, pngwio.c, and pngerror.c respectively. in pngmem.c, pngrio.c, pngwio.c, and pngerror.c respectively. To change
To change these functions, call the approprate png_set_???_fn() function. these functions, call the approprate png_set_???_fn() function.
Memory allocation is done through the functions png_large_malloc(), Memory allocation is done through the functions png_large_malloc(),
png_malloc(), png_realloc(), png_large_free(), and png_free(). These png_malloc(), png_realloc(), png_large_free(), and png_free(). These
currently just call the standard C functions. The large functions must currently just call the standard C functions. The large functions must
handle exactly 64K, but they don't have to handle more than that. If handle exactly 64K, but they don't have to handle more than that. If
your pointers can't access more then 64K at a time, you will want to your pointers can't access more then 64K at a time, you will want to set
set MAXSEG_64K in zlib.h. Since it is unlikely that the method of MAXSEG_64K in zlib.h. Since it is unlikely that the method of handling
handling memory allocation on a platform will change between applications, memory allocation on a platform will change between applications, these
these functions must be modified in the library at compile time. functions must be modified in the library at compile time.
Input/Output in libpng is done throught png_read() and png_write(), which Input/Output in libpng is done throught png_read() and png_write(),
currently just call fread() and fwrite(). The FILE * is stored in which currently just call fread() and fwrite(). The FILE * is stored in
png_struct, and is initialized via png_init_io(). If you wish to change png_struct and is initialized via png_init_io(). If you wish to change
the method of I/O, the library supplies callbacks that you can set through the method of I/O, the library supplies callbacks that you can set
the function png_set_read_fn() and png_set_write_fn() at run time. These through the function png_set_read_fn() and png_set_write_fn() at run
functions also provide a void pointer that can be retrieved via the function time, instead of calling the png_init_io() function. These functions
also provide a void pointer that can be retrieved via the function
png_get_io_ptr(). For example: png_get_io_ptr(). For example:
png_set_read_fn(png_structp png_ptr, voidp io_ptr, png_set_read_fn(png_structp png_ptr, voidp io_ptr,
@ -1123,7 +1286,7 @@ a write stream, and vice versa.
Error handling in libpng is done through png_error() and png_warning(). Error handling in libpng is done through png_error() and png_warning().
Errors handled through png_error() are fatal, meaning that png_error() Errors handled through png_error() are fatal, meaning that png_error()
should never return to it's caller. Currently, this is handled via should never return to its caller. Currently, this is handled via
setjmp() and longjmp(), but you could change this to do things like setjmp() and longjmp(), but you could change this to do things like
exit() if you should wish. On non-fatal errors, png_warning() is called exit() if you should wish. On non-fatal errors, png_warning() is called
to print a warning message, and then control returns to the calling code. to print a warning message, and then control returns to the calling code.
@ -1152,7 +1315,7 @@ catch exception handling methods. This makes the code much easier to write,
as there is no need to check every return code of every function call. as there is no need to check every return code of every function call.
However, there are some uncertainties about the status of local variables However, there are some uncertainties about the status of local variables
after a longjmp, so the user may want to be careful about doing anything after after a longjmp, so the user may want to be careful about doing anything after
setjmp returns non zero besides returning itself. Consult your compiler setjmp returns non-zero besides returning itself. Consult your compiler
documentation for more details. documentation for more details.
If you need to read or write custom chunks, you will need to get deeper If you need to read or write custom chunks, you will need to get deeper
@ -1220,16 +1383,16 @@ Configuring zlib:
There are special functions to configure the compression. Perhaps the There are special functions to configure the compression. Perhaps the
most useful one changes the compression level, which currently uses most useful one changes the compression level, which currently uses
input compression values in the range 0 - 9. The library normally input compression values in the range 0 - 9. The library normally
uses the default compression level (Z_DEFAULT_COMPRESSION = 6), but if uses the default compression level (Z_DEFAULT_COMPRESSION = 6). Tests
speed is not critical it is possible to configure it for maximum have shown that for a large majority of images, compression values in
compression (Z_BEST_COMPRESSION = 9) to generate smaller PNG files. the range 3-6 compress as well as higher levels, and do so much faster.
For online applications it may be desirable to have maximum speed For online applications it may be desirable to have maximum speed
(Z_BEST_SPEED = 1). With versions of zlib after v0.99, you can also (Z_BEST_SPEED = 1). With versions of zlib after v0.99, you can also
specify no compression (Z_NO_COMPRESSION = 0), but this would create specify no compression (Z_NO_COMPRESSION = 0), but this would create
files larger than just storing the raw bitmap. You can specify the files larger than just storing the raw bitmap. You can specify the
compression level by calling: compression level by calling:
png_set_compression_mem_level(png_ptr, level); png_set_compression_level(png_ptr, level);
Another useful one is to reduce the memory level used by the library. Another useful one is to reduce the memory level used by the library.
The memory level defaults to 8, but it can be lowered if you are The memory level defaults to 8, but it can be lowered if you are
@ -1237,9 +1400,20 @@ short on memory (running DOS, for example, where you only have 640K).
png_set_compression_mem_level(png_ptr, level); png_set_compression_mem_level(png_ptr, level);
If you want to control whether libpng uses filtering or not, you The other functions are for configuring zlib. They are not recommended
can call this function. Filtering is enabled by default for RGB for normal use and may result in writing an invalid PNG file. See
and grayscale images (with and without alpha), and for 8-bit zlib.h for more information on what these mean.
png_set_compression_strategy(png_ptr, strategy);
png_set_compression_window_bits(png_ptr, window_bits);
png_set_compression_method(png_ptr, method);
Controlling row filtering:
If you want to control whether libpng uses filtering or not, which
filters are used, and how it goes about picking row filters, you
can call one of these functions. Filtering is enabled by default for
RGB and grayscale images (with and without alpha), and for 8-bit
paletted images, but not for paletted images with bit depths less paletted images, but not for paletted images with bit depths less
than 8 bits/pixel. The 'method' parameter sets the main filtering than 8 bits/pixel. The 'method' parameter sets the main filtering
method, which is currently only '0' in the PNG 1.0 specification. method, which is currently only '0' in the PNG 1.0 specification.
@ -1255,23 +1429,46 @@ the image, you should start with flags set for all of the filters
you intend to use so that libpng can initialize its internal you intend to use so that libpng can initialize its internal
structures appropriately for all of the filter types. structures appropriately for all of the filter types.
png_set_filter(png_ptr, method, filters); filters = PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP;
png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, filters);
The other functions are for configuring zlib. They are not recommended It is also possible to influence how libpng chooses from among the
for normal use and may result in writing an invalid PNG file. See available filters. This is done in two ways - by telling it how
zlib.h for more information on what these mean. important it is to keep the same filter for successive rows, and
by telling it the relative computational costs of the filters.
png_set_compression_strategy(png_ptr, strategy); double weights[3] = {1.5, 1.3, 1.1},
png_set_compression_window_bits(png_ptr, window_bits); costs[PNG_FILTER_VALUE_LAST] = {1.0, 1.3, 1.3, 1.5, 1.7};
png_set_compression_method(png_ptr, method);
Except for png_set_filter(), all of these are just controlling zlib, png_set_filter_selection(png_ptr, PNG_FILTER_SELECTION_WEIGHTED,
so see the zlib documentation (zlib.h and zconf.h) for more information. 3, weights, costs);
The weights are multiplying factors which indicate to libpng that row
should be the same for successive rows unless another row filter is that
many times better than the previous filter. In the above example, if
the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a
"sum of absolute differences" 1.5 x 1.3 times higher than other filters
and still be chosen, while the NONE filter could have a sum 1.1 times
higher than other filters and still be chosen. Unspecified weights are
taken to be 1.0, and the specified weights should probably be declining
like those above in order to emphasize recent filters over older filters.
The filter costs specify for each filter type a relative decoding cost
to be considered when selecting row filters. This means that filters
with higher costs are less likely to be chosen over filters with lower
costs, unless their "sum of absolute differences" is that much smaller.
The costs do not necessarily reflect the exact computational speeds of
the various filters, since this would unduely influence the final image
size.
Note that the numbers above were invented purely for this example and
are given only to help explain the function usage. Little testing has
been done to find optimum values for either the costs or the weights.
Removing unwanted object code: Removing unwanted object code:
There are a bunch of #define's in pngconf.h that control what parts of There are a bunch of #define's in pngconf.h that control what parts of
libpng are compiled. All the defines end in _SUPPORT. If you are libpng are compiled. All the defines end in _SUPPORTED. If you are
never going to use an ability, you can change the #define to #undef never going to use an ability, you can change the #define to #undef
before recompiling libpng and save yourself code and data space. All before recompiling libpng and save yourself code and data space. All
the reading and writing specific code are in seperate files, so the the reading and writing specific code are in seperate files, so the
@ -1283,32 +1480,34 @@ are used for both reading and writing, and always need to be included.
The progressive reader is in pngpread.c The progressive reader is in pngpread.c
If you are creating or distributing a dynamically linked library (a .so If you are creating or distributing a dynamically linked library (a .so
or DLL file), you should not remove or disable any parts of the or DLL file), you should not remove or disable any parts of the library,
library, as this will cause applications linked with different versions as this will cause applications linked with different versions of the
of the library to fail if they call functions not available in your library to fail if they call functions not available in your library.
library. The size of the library itself should not be an issue, because The size of the library itself should not be an issue, because only
only those sections which are actually used will be loaded into memory. those sections which are actually used will be loaded into memory.
Changes to Libpng from version 0.88 to version 0.89
It should be noted that version 0.89 of libpng is not distributed by Changes to Libpng from version 0.88
the original author, Guy Schalnat, but rather Andreas Dilger, although
all of the copyright messages have been left in Guy's name.
The old libpng functions png_read_init(), png_write_init() and It should be noted that versions of libpng later than 0.88 are not
png_info_init() still exist in the 0.89 version of the library, as distributed by the original libpng author, Guy Schalnat, but rather
do png_read_destroy() and png_write_destroy(). The preferred method another member of the original PNG Group, Andreas Dilger. Guy is still
of creating and initializing the libpng structures is via the alive and well, but he has moved on to other things.
png_create_read_struct(), png_create_write_struct(), and
The old libpng functions png_read_init(), png_write_init(),
png_info_init(), png_read_destroy(), and png_write_destory() have been
moved to PNG_INTERNAL in version 0.95 to discourage their use. The
preferred method of creating and initializing the libpng structures is
via the png_create_read_struct(), png_create_write_struct(), and
png_create_info_struct() because they isolate the size of the structures png_create_info_struct() because they isolate the size of the structures
from the application, allow version error checking, and also allow from the application, allow version error checking, and also allow the
the use of custom error handling routines during the initialization, use of custom error handling routines during the initialization, which
which the old functions do not. The functions png_read_destroy() and the old functions do not. The functions png_read_destroy() and
png_write_destroy() do not actually free the memory that libpng allocated png_write_destroy() do not actually free the memory that libpng
for these structs, but just reset the data structures, so they can be allocated for these structs, but just reset the data structures, so they
used instead of png_destroy_read_struct() and png_destroy_write_struct() can be used instead of png_destroy_read_struct() and
if you feel there is too much system overhead allocating and freeing the png_destroy_write_struct() if you feel there is too much system overhead
png_struct for each image read. allocating and freeing the png_struct for each image read.
Setting the error callbacks via png_set_message_fn() before Setting the error callbacks via png_set_message_fn() before
png_read_init() as was suggested in libpng-0.88 is no longer supported png_read_init() as was suggested in libpng-0.88 is no longer supported
@ -1316,5 +1515,5 @@ because this caused applications which do not use custom error functions
to fail if the png_ptr was not initialized to zero. It is still possible to fail if the png_ptr was not initialized to zero. It is still possible
to set the error callbacks AFTER png_read_init(), or to change them with to set the error callbacks AFTER png_read_init(), or to change them with
png_set_error_fn(), which is essentially the same function, but with a png_set_error_fn(), which is essentially the same function, but with a
new name to force compilation errors with the new library. new name to force compilation errors with applications that try to use
the old method.

View File

@ -2,17 +2,23 @@
# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. # Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc.
# For conditions of distribution and use, see copyright notice in png.h # For conditions of distribution and use, see copyright notice in png.h
CC=cc # Where the zlib library and include files are located
CFLAGS=-I../zlib -O #ZLIBLIB=/usr/local/lib
LDFLAGS=-L. -L../zlib/ -lpng -lz -lm #ZLIBINC=/usr/local/include
ZLIBLIB=../zlib
ZLIBINC=../zlib
#RANLIB=ranlib CC=cc
RANLIB=echo CFLAGS=-I$(ZLIBINC) -O # -g -DPNG_DEBUG=1
LDFLAGS=-L. -L$(ZLIBLIB) -lpng -lz -lm
#RANLIB=echo
RANLIB=ranlib
# where make install puts libpng.a and png.h # where make install puts libpng.a and png.h
prefix=/usr/local prefix=/usr/local
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \ OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \
pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \
pngwtran.o pngmem.o pngerror.o pngpread.o pngwtran.o pngmem.o pngerror.o pngpread.o
@ -48,7 +54,8 @@ pngerror.o: png.h pngconf.h
pngrio.o: png.h pngconf.h pngrio.o: png.h pngconf.h
pngwio.o: png.h pngconf.h pngwio.o: png.h pngconf.h
pngmem.o: png.h pngconf.h pngmem.o: png.h pngconf.h
pngrcb.o: png.h pngconf.h pngset.o: png.h pngconf.h
pngget.o: png.h pngconf.h
pngread.o: png.h pngconf.h pngread.o: png.h pngconf.h
pngrtran.o: png.h pngconf.h pngrtran.o: png.h pngconf.h
pngrutil.o: png.h pngconf.h pngrutil.o: png.h pngconf.h

View File

@ -13,23 +13,25 @@ Squeezeflags = -o $@
# Final targets: # Final targets:
@.libpng-lib: @.o.png @.o.pngerror @.o.pngrio @.o.pngwio @.o.pngmem \ @.libpng-lib: @.o.png @.o.pngerror @.o.pngrio @.o.pngwio @.o.pngmem \
@.o.pngpread @.o.pngrcb @.o.pngread @.o.pngrtran @.o.pngrutil @.o.pngtrans @.o.pngwrite \ @.o.pngpread @.o.pngset @.o.pngget @.o.pngread @.o.pngrtran \
@.o.pngwtran @.o.pngwutil @.o.pngrutil @.o.pngtrans @.o.pngwrite @.o.pngwtran @.o.pngwutil
LibFile $(LibFileflags) @.o.png @.o.pngerror @.o.pngrio @.o.pngwio \ LibFile $(LibFileflags) @.o.png @.o.pngerror @.o.pngrio @.o.pngrtran \
@.o.pngmem @.o.pngpread @.o.pngrcb @.o.pngread @.o.pngrtran @.o.pngrutil @.o.pngtrans \ @.o.pngmem @.o.pngpread @.o.pngset @.o.pngget @.o.pngread @.o.pngwio \
@.o.pngwrite @.o.pngwtran @.o.pngwutil @.o.pngrutil @.o.pngtrans @.o.pngwrite @.o.pngwtran @.o.pngwutil
@.mm-libpng-lib: @.mm.png @.mm.pngerror @.mm.pngrio @.mm.pngwio @.mm.pngmem \ @.mm-libpng-lib: @.mm.png @.mm.pngerror @.mm.pngrio @.mm.pngwio @.mm.pngmem \
@.mm.pngpread @.mm.pngrcb @.mm.pngread @.mm.pngrtran @.mm.pngrutil @.mm.pngtrans \ @.mm.pngpread @.mm.pngset @.mm.pngget @.mm.pngread @.mm.pngrtran \
@.mm.pngwrite @.mm.pngwtran @.mm.pngwutil @.mm.pngrutil @.mm.pngtrans @.mm.pngwrite @.mm.pngwtran @.mm.pngwutil
LibFile $(LibFileflags) @.mm.png @.mm.pngerror @.mm.pngrio @.mm.pngwio \ LibFile $(LibFileflags) @.mm.png @.mm.pngerror @.mm.pngrio \
@.mm.pngmem @.mm.pngpread @.mm.pngrcb @.mm.pngread @.mm.pngrtran @.mm.pngrutil \ @.mm.pngwio @.mm.pngmem @.mm.pngpread @.mm.pngset @.mm.pngget \
@.mm.pngtrans @.mm.pngwrite @.mm.pngwtran @.mm.pngwutil @.mm.pngread @.mm.pngrtran @.mm.pngrutil @.mm.pngtrans @.mm.pngwrite \
@.mm.pngwtran @.mm.pngwutil
# User-editable dependencies: # User-editable dependencies:
# (C) Copyright 1997 Tom Tanner
Test: @.pngtest Test: @.pngtest
<Prefix$Dir>.PngTest <Prefix$Dir>.pngtest
@remove <Prefix$Dir>.pngout_png @remove <Prefix$Dir>.pngtest
#It would be nice if you could stop "make" listing from here on! #It would be nice if you could stop "make" listing from here on!
@.pngtest: @.o.pngtest @.libpng-lib C:o.Stubs Zlib:zlib_lib @.pngtest: @.o.pngtest @.libpng-lib C:o.Stubs Zlib:zlib_lib
@ -47,3 +49,173 @@ Test: @.pngtest
# Dynamic dependencies: # Dynamic dependencies:
o.pngtest: c.pngtest
o.pngtest: h.png
o.pngtest: Zlib:h.zlib
o.pngtest: Zlib:h.zconf
o.pngtest: h.pngconf
mm.png: LibPng:c.png
mm.png: LibPng:h.png
mm.png: Zlib:h.zlib
mm.png: Zlib:h.zconf
mm.png: LibPng:h.pngconf
mm.png: MemCheck:ANSI.h.stdio
mm.pngerror: LibPng:c.pngerror
mm.pngerror: LibPng:h.png
mm.pngerror: Zlib:h.zlib
mm.pngerror: Zlib:h.zconf
mm.pngerror: LibPng:h.pngconf
mm.pngerror: MemCheck:ANSI.h.stdio
mm.pngrio: LibPng:c.pngrio
mm.pngrio: LibPng:h.png
mm.pngrio: Zlib:h.zlib
mm.pngrio: Zlib:h.zconf
mm.pngrio: LibPng:h.pngconf
mm.pngrio: MemCheck:ANSI.h.stdio
mm.pngwio: LibPng:c.pngwio
mm.pngwio: LibPng:h.png
mm.pngwio: Zlib:h.zlib
mm.pngwio: Zlib:h.zconf
mm.pngwio: LibPng:h.pngconf
mm.pngwio: MemCheck:ANSI.h.stdio
mm.pngmem: LibPng:c.pngmem
mm.pngmem: LibPng:h.png
mm.pngmem: Zlib:h.zlib
mm.pngmem: Zlib:h.zconf
mm.pngmem: LibPng:h.pngconf
mm.pngmem: MemCheck:ANSI.h.stdio
mm.pngpread: LibPng:c.pngpread
mm.pngpread: LibPng:h.png
mm.pngpread: Zlib:h.zlib
mm.pngpread: Zlib:h.zconf
mm.pngpread: LibPng:h.pngconf
mm.pngpread: MemCheck:ANSI.h.stdio
mm.pngset: LibPng:c.pngset
mm.pngset: LibPng:h.png
mm.pngset: Zlib:h.zlib
mm.pngset: Zlib:h.zconf
mm.pngset: LibPng:h.pngconf
mm.pngset: MemCheck:ANSI.h.stdio
mm.pngget: LibPng:c.pngget
mm.pngget: LibPng:h.png
mm.pngget: Zlib:h.zlib
mm.pngget: Zlib:h.zconf
mm.pngget: LibPng:h.pngconf
mm.pngget: MemCheck:ANSI.h.stdio
mm.pngread: LibPng:c.pngread
mm.pngread: LibPng:h.png
mm.pngread: Zlib:h.zlib
mm.pngread: Zlib:h.zconf
mm.pngread: LibPng:h.pngconf
mm.pngread: MemCheck:ANSI.h.stdio
mm.pngrtran: LibPng:c.pngrtran
mm.pngrtran: LibPng:h.png
mm.pngrtran: Zlib:h.zlib
mm.pngrtran: Zlib:h.zconf
mm.pngrtran: LibPng:h.pngconf
mm.pngrtran: MemCheck:ANSI.h.stdio
mm.pngrutil: LibPng:c.pngrutil
mm.pngrutil: LibPng:h.png
mm.pngrutil: Zlib:h.zlib
mm.pngrutil: Zlib:h.zconf
mm.pngrutil: LibPng:h.pngconf
mm.pngrutil: MemCheck:ANSI.h.stdio
mm.pngtrans: LibPng:c.pngtrans
mm.pngtrans: LibPng:h.png
mm.pngtrans: Zlib:h.zlib
mm.pngtrans: Zlib:h.zconf
mm.pngtrans: LibPng:h.pngconf
mm.pngtrans: MemCheck:ANSI.h.stdio
mm.pngwrite: LibPng:c.pngwrite
mm.pngwrite: LibPng:h.png
mm.pngwrite: Zlib:h.zlib
mm.pngwrite: Zlib:h.zconf
mm.pngwrite: LibPng:h.pngconf
mm.pngwrite: MemCheck:ANSI.h.stdio
mm.pngwtran: LibPng:c.pngwtran
mm.pngwtran: LibPng:h.png
mm.pngwtran: Zlib:h.zlib
mm.pngwtran: Zlib:h.zconf
mm.pngwtran: LibPng:h.pngconf
mm.pngwtran: MemCheck:ANSI.h.stdio
mm.pngwutil: LibPng:c.pngwutil
mm.pngwutil: LibPng:h.png
mm.pngwutil: Zlib:h.zlib
mm.pngwutil: Zlib:h.zconf
mm.pngwutil: LibPng:h.pngconf
mm.pngwutil: MemCheck:ANSI.h.stdio
o.png: c.png
o.png: h.png
o.png: Zlib:h.zlib
o.png: Zlib:h.zconf
o.png: h.pngconf
o.pngerror: c.pngerror
o.pngerror: h.png
o.pngerror: Zlib:h.zlib
o.pngerror: Zlib:h.zconf
o.pngerror: h.pngconf
o.pngrio: c.pngrio
o.pngrio: h.png
o.pngrio: Zlib:h.zlib
o.pngrio: Zlib:h.zconf
o.pngrio: h.pngconf
o.pngwio: c.pngwio
o.pngwio: h.png
o.pngwio: Zlib:h.zlib
o.pngwio: Zlib:h.zconf
o.pngwio: h.pngconf
o.pngmem: c.pngmem
o.pngmem: h.png
o.pngmem: Zlib:h.zlib
o.pngmem: Zlib:h.zconf
o.pngmem: h.pngconf
o.pngpread: c.pngpread
o.pngpread: h.png
o.pngpread: Zlib:h.zlib
o.pngpread: Zlib:h.zconf
o.pngpread: h.pngconf
o.pngset: c.pngset
o.pngset: h.png
o.pngset: Zlib:h.zlib
o.pngset: Zlib:h.zconf
o.pngset: h.pngconf
o.pngget: c.pngget
o.pngget: h.png
o.pngget: Zlib:h.zlib
o.pngget: Zlib:h.zconf
o.pngget: h.pngconf
o.pngread: c.pngread
o.pngread: h.png
o.pngread: Zlib:h.zlib
o.pngread: Zlib:h.zconf
o.pngread: h.pngconf
o.pngrtran: c.pngrtran
o.pngrtran: h.png
o.pngrtran: Zlib:h.zlib
o.pngrtran: Zlib:h.zconf
o.pngrtran: h.pngconf
o.pngrutil: c.pngrutil
o.pngrutil: h.png
o.pngrutil: Zlib:h.zlib
o.pngrutil: Zlib:h.zconf
o.pngrutil: h.pngconf
o.pngtrans: c.pngtrans
o.pngtrans: h.png
o.pngtrans: Zlib:h.zlib
o.pngtrans: Zlib:h.zconf
o.pngtrans: h.pngconf
o.pngwrite: c.pngwrite
o.pngwrite: h.png
o.pngwrite: Zlib:h.zlib
o.pngwrite: Zlib:h.zconf
o.pngwrite: h.pngconf
o.pngwtran: c.pngwtran
o.pngwtran: h.png
o.pngwtran: Zlib:h.zlib
o.pngwtran: Zlib:h.zconf
o.pngwtran: h.pngconf
o.pngwutil: c.pngwutil
o.pngwutil: h.png
o.pngwutil: Zlib:h.zlib
o.pngwutil: Zlib:h.zconf
o.pngwutil: h.pngconf

View File

@ -22,7 +22,7 @@ AR= oml
# make directory command # make directory command
MKDIR= makedir MKDIR= makedir
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o pngpread.o \ OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o pngpread.o \
pngread.o pngerror.o pngwrite.o pngrtran.o pngwtran.o pngrio.o pngwio.o pngmem.o pngread.o pngerror.o pngwrite.o pngrtran.o pngwtran.o pngrio.o pngwio.o pngmem.o
all: libpng.lib pngtest all: libpng.lib pngtest

View File

@ -10,7 +10,7 @@ LDFLAGS=-lpng -lz -lm
# where make install puts libpng.a and png.h # where make install puts libpng.a and png.h
OBJS = $(LBR)(png.o) $(LBR)(pngrcb.o) $(LBR)(pngrutil.o)\ OBJS = $(LBR)(png.o) $(LBR)(pngset.o) $(LBR)(pngget.o) $(LBR)(pngrutil.o)\
$(LBR)(pngtrans.o) $(LBR)(pngwutil.o)\ $(LBR)(pngtrans.o) $(LBR)(pngwutil.o)\
$(LBR)(pngread.o) $(LBR)(pngerror.o) $(LBR)(pngwrite.o)\ $(LBR)(pngread.o) $(LBR)(pngerror.o) $(LBR)(pngwrite.o)\
$(LBR)(pngrtran.o) $(LBR)(pngwtran.o)\ $(LBR)(pngrtran.o) $(LBR)(pngwtran.o)\

View File

@ -74,7 +74,8 @@ OBJS = \
pngerror.$(O) \ pngerror.$(O) \
pngmem.$(O) \ pngmem.$(O) \
pngpread.$(O) \ pngpread.$(O) \
pngrcb.$(O) \ pngset.$(O) \
pngget.$(O) \
pngread.$(O) \ pngread.$(O) \
pngrio.$(O) \ pngrio.$(O) \
pngrtran.$(O) \ pngrtran.$(O) \
@ -91,7 +92,8 @@ LIBOBJS = \
+pngmem.$(O) \ +pngmem.$(O) \
+pngpread.$(O) \ +pngpread.$(O) \
+pngread.$(O) \ +pngread.$(O) \
+pngrcb.$(O) \ +pngset.$(O) \
+pngget.$(O) \
+pngrio.$(O) \ +pngrio.$(O) \
+pngrtran.$(O) \ +pngrtran.$(O) \
+pngrutil.$(O) \ +pngrutil.$(O) \
@ -126,7 +128,8 @@ test:
## Minor Targets ## Minor Targets
png.obj: png.c png.obj: png.c
pngrcb.obj: pngrcb.c pngset.obj: pngset.c
pngget.obj: pngget.c
pngread.obj: pngread.c pngread.obj: pngread.c
pngpread.obj: pngpread.c pngpread.obj: pngpread.c
pngrtran.obj: pngrtran.c pngrtran.obj: pngrtran.c

View File

@ -12,7 +12,7 @@ RANLIB=ranlib
#prefix=/usr/local #prefix=/usr/local
prefix=. prefix=.
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \ OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \
pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o pngwtran.o \ pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o pngwtran.o \
pngmem.o pngerror.o pngpread.o pngmem.o pngerror.o pngpread.o
@ -38,7 +38,8 @@ pngerror.o: png.h pngconf.h
pngrio.o: png.h pngconf.h pngrio.o: png.h pngconf.h
pngwio.o: png.h pngconf.h pngwio.o: png.h pngconf.h
pngmem.o: png.h pngconf.h pngmem.o: png.h pngconf.h
pngrcb.o: png.h pngconf.h pngset.o: png.h pngconf.h
pngget.o: png.h pngconf.h
pngread.o: png.h pngconf.h pngread.o: png.h pngconf.h
pngpread.o: png.h pngconf.h pngpread.o: png.h pngconf.h
pngrtran.o: png.h pngconf.h pngrtran.o: png.h pngconf.h

View File

@ -3,21 +3,32 @@
# For conditions of distribution and use, see copyright notice in png.h # For conditions of distribution and use, see copyright notice in png.h
CC=gcc CC=gcc
CFLAGS=-I../zlib -Wall -Wwrite-strings -Wpointer-arith \
-Wstrict-prototypes -Wmissing-prototypes -O2 -fPIC # Where the zlib library and include files are located
LDFLAGS=-L. -Wl,-rpath,. -L../zlib/ -Wl,-rpath,../zlib/ -lpng -lz -lm #ZLIBLIB=/usr/local/lib
#ZLIBINC=/usr/local/include
ZLIBLIB=../zlib
ZLIBINC=../zlib
WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow \
-Wmissing-declarations -Wtraditional -Wcast-align \
-Wstrict-prototypes -Wmissing-prototypes #-Wconversion
CFLAGS=-I$(ZLIBINC) -Wall -O2 -fPIC # $(WARNMORE) # -g -DPNG_DEBUG=3
LDFLAGS=-L. -Wl,-rpath,. -L$(ZLIBLIB) -Wl,-rpath,$(ZLIBLIB) -lpng -lz -lm
RANLIB=ranlib RANLIB=ranlib
#RANLIB=echo #RANLIB=echo
PNGMAJ = 0 PNGMAJ = 0
PNGMIN = 90 PNGMIN = 96
PNGVER = $(PNGMAJ).$(PNGMIN) PNGVER = $(PNGMAJ).$(PNGMIN)
# where make install puts libpng.a, libpng.so*, and png.h # where make install puts libpng.a, libpng.so*, and png.h
prefix=/usr/local prefix=/usr/local
INCPATH=$(prefix)/include
LIBPATH=$(prefix)/lib
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \ OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \
pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \
pngwtran.o pngmem.o pngerror.o pngpread.o pngwtran.o pngmem.o pngerror.o pngpread.o
@ -37,22 +48,19 @@ libpng.so.$(PNGVER): $(OBJS)
gcc -shared -Wl,-soname,libpng.so.$(PNGMAJ) -o libpng.so.$(PNGVER) $(OBJS) gcc -shared -Wl,-soname,libpng.so.$(PNGMAJ) -o libpng.so.$(PNGVER) $(OBJS)
pngtest: pngtest.o libpng.so pngtest: pngtest.o libpng.so
$(CC) -o pngtest $(CCFLAGS) pngtest.o $(LDFLAGS) $(CC) -o pngtest pngtest.o $(LDFLAGS)
test: pngtest test: pngtest
./pngtest ./pngtest
install: libpng.so.$(PNGVER) install: libpng.so.$(PNGVER)
-@mkdir $(prefix)/include -@mkdir $(INCPATH) $(LIBPATH)
-@mkdir $(prefix)/lib cp png.h pngconf.h $(INCPATH)
cp png.h $(prefix)/include chmod 644 $(INCPATH)/png.h $(INCPATH)/pngconf.h
cp pngconf.h $(prefix)/include cp libpng.so.$(PNGVER) $(LIBPATH)
chmod 644 $(prefix)/include/png.h chmod 755 $(LIBPATH)/libpng.so.$(PNGVER)
chmod 644 $(prefix)/include/pngconf.h -@/bin/rm $(LIBPATH)/libpng.so.$(PNGMAJ) $(LIBPATH)/libpng.so
cp libpng.so.$(PNGVER) $(prefix)/lib (cd $(LIBPATH); ln -sf libpng.so.$(PNGVER) libpng.so.$(PNGMAJ); \
chmod 755 $(prefix)/lib/libpng.so.$(PNGVER)
-@/bin/rm $(prefix)/lib/libpng.so.$(PNGMAJ) $(prefix)/lib/libpng.so
(cd $(prefix)/lib; ln -sf libpng.so.$(PNGVER) libpng.so.$(PNGMAJ); \
ln -sf libpng.so.$(PNGMAJ) libpng.so) ln -sf libpng.so.$(PNGMAJ) libpng.so)
clean: clean:
@ -65,7 +73,8 @@ pngerror.o: png.h pngconf.h
pngrio.o: png.h pngconf.h pngrio.o: png.h pngconf.h
pngwio.o: png.h pngconf.h pngwio.o: png.h pngconf.h
pngmem.o: png.h pngconf.h pngmem.o: png.h pngconf.h
pngrcb.o: png.h pngconf.h pngset.o: png.h pngconf.h
pngget.o: png.h pngconf.h
pngread.o: png.h pngconf.h pngread.o: png.h pngconf.h
pngrtran.o: png.h pngconf.h pngrtran.o: png.h pngconf.h
pngrutil.o: png.h pngconf.h pngrutil.o: png.h pngconf.h

View File

@ -14,7 +14,7 @@ RANLIB=ranlib
# where make install puts libpng.a and png.h # where make install puts libpng.a and png.h
prefix=/usr/local prefix=/usr/local
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \ OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \
pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \
pngwtran.o pngmem.o pngerror.o pngpread.o pngwtran.o pngmem.o pngerror.o pngpread.o
@ -60,7 +60,8 @@ pngerror.o: png.h pngconf.h
pngrio.o: png.h pngconf.h pngrio.o: png.h pngconf.h
pngwio.o: png.h pngconf.h pngwio.o: png.h pngconf.h
pngmem.o: png.h pngconf.h pngmem.o: png.h pngconf.h
pngrcb.o: png.h pngconf.h pngset.o: png.h pngconf.h
pngget.o: png.h pngconf.h
pngread.o: png.h pngconf.h pngread.o: png.h pngconf.h
pngpread.o: png.h pngconf.h pngpread.o: png.h pngconf.h
pngrtran.o: png.h pngconf.h pngrtran.o: png.h pngconf.h

View File

@ -13,7 +13,7 @@ RANLIB=echo
# where make install puts libpng.a and png.h # where make install puts libpng.a and png.h
prefix=/usr/local prefix=/usr/local
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \ OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \
pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \
pngwtran.o pngmem.o pngerror.o pngpread.o pngwtran.o pngmem.o pngerror.o pngpread.o
@ -49,7 +49,8 @@ pngerror.o: png.h pngconf.h
pngrio.o: png.h pngconf.h pngrio.o: png.h pngconf.h
pngwio.o: png.h pngconf.h pngwio.o: png.h pngconf.h
pngmem.o: png.h pngconf.h pngmem.o: png.h pngconf.h
pngrcb.o: png.h pngconf.h pngset.o: png.h pngconf.h
pngget.o: png.h pngconf.h
pngread.o: png.h pngconf.h pngread.o: png.h pngconf.h
pngpread.o: png.h pngconf.h pngpread.o: png.h pngconf.h
pngrtran.o: png.h pngconf.h pngrtran.o: png.h pngconf.h

View File

@ -16,15 +16,19 @@ O=.obj
ERRFILE= >> pngerrs ERRFILE= >> pngerrs
# variables # variables
OBJS1 = png$(O) pngrcb$(O) pngrutil$(O) pngtrans$(O) pngwutil$(O) pngmem$(O) pngpread$(O) OBJS1 = png$(O) pngset$(O) pngget$(O) pngrutil$(O) pngtrans$(O) pngwutil$(O)
OBJS2 = pngread$(O) pngerror$(O) pngwrite$(O) pngrtran$(O) pngwtran$(O) pngrio$(O) pngwio$(O) OBJS2 = pngmem$(O) pngpread$(O) pngread$(O) pngerror$(O) pngwrite$(O)
OBJS3 = pngrtran$(O) pngwtran$(O) pngrio$(O) pngwio$(O)
all: libpng.lib all: libpng.lib
png$(O): png.h pngconf.h png$(O): png.h pngconf.h
$(CC) -c $(CFLAGS) $*.c $(ERRFILE) $(CC) -c $(CFLAGS) $*.c $(ERRFILE)
pngrcb$(O): png.h pngconf.h pngset$(O): png.h pngconf.h
$(CC) -c $(CFLAGS) $*.c $(ERRFILE)
pngget$(O): png.h pngconf.h
$(CC) -c $(CFLAGS) $*.c $(ERRFILE) $(CC) -c $(CFLAGS) $*.c $(ERRFILE)
pngread$(O): png.h pngconf.h pngread$(O): png.h pngconf.h
@ -66,10 +70,11 @@ pngwtran$(O): png.h pngconf.h
pngwutil$(O): png.h pngconf.h pngwutil$(O): png.h pngconf.h
$(CC) -c $(CFLAGS) $*.c $(ERRFILE) $(CC) -c $(CFLAGS) $*.c $(ERRFILE)
libpng.lib: $(OBJS1) $(OBJS2) libpng.lib: $(OBJS1) $(OBJS2) $(OBJS3)
del libpng.lib del libpng.lib
lib libpng $(OBJS1); lib libpng $(OBJS1);
lib libpng $(OBJS2); lib libpng $(OBJS2);
lib libpng $(OBJS3);
pngtest.exe: pngtest.obj libpng.lib pngtest.exe: pngtest.obj libpng.lib
$(LD) $(LDFLAGS) pngtest.obj,,,libpng.lib ..\zlib\zlib.lib ; $(LD) $(LDFLAGS) pngtest.obj,,,libpng.lib ..\zlib\zlib.lib ;

View File

@ -2,17 +2,23 @@
# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. # Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc.
# For conditions of distribution and use, see copyright notice in png.h # For conditions of distribution and use, see copyright notice in png.h
CC=cc # Where the zlib library and include files are located
CFLAGS=-I../zlib -O #ZLIBLIB=/usr/local/lib
LDFLAGS=-L. -L../zlib/ -lpng -lz -lm #ZLIBINC=/usr/local/include
ZLIBLIB=../zlib
ZLIBINC=../zlib
#RANLIB=ranlib CC=cc
RANLIB=echo CFLAGS=-I$(ZLIBINC) -O # -g -DPNG_DEBUG=1
LDFLAGS=-L. -L$(ZLIBLIB) -lpng -lz -lm
#RANLIB=echo
RANLIB=ranlib
# where make install puts libpng.a and png.h # where make install puts libpng.a and png.h
prefix=/usr/local prefix=/usr/local
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \ OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \
pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \ pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \
pngwtran.o pngmem.o pngerror.o pngpread.o pngwtran.o pngmem.o pngerror.o pngpread.o
@ -48,7 +54,8 @@ pngerror.o: png.h pngconf.h
pngrio.o: png.h pngconf.h pngrio.o: png.h pngconf.h
pngwio.o: png.h pngconf.h pngwio.o: png.h pngconf.h
pngmem.o: png.h pngconf.h pngmem.o: png.h pngconf.h
pngrcb.o: png.h pngconf.h pngset.o: png.h pngconf.h
pngget.o: png.h pngconf.h
pngread.o: png.h pngconf.h pngread.o: png.h pngconf.h
pngrtran.o: png.h pngconf.h pngrtran.o: png.h pngconf.h
pngrutil.o: png.h pngconf.h pngrutil.o: png.h pngconf.h

72
makefile.sun Normal file
View File

@ -0,0 +1,72 @@
# makefile for libpng
# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc.
# For conditions of distribution and use, see copyright notice in png.h
# Where the zlib library and include files are located
#ZLIBLIB=/usr/local/lib
#ZLIBINC=/usr/local/include
ZLIBLIB=../zlib
ZLIBINC=../zlib
WARNMORE=-Wwrite-strings -Wpointer-arith -Wshadow -Wconversion \
-Wmissing-declarations -Wtraditional -Wcast-align \
-Wstrict-prototypes -Wmissing-prototypes
CC=gcc
CFLAGS=-I$(ZLIBINC) -O $(WARNMORE) -DPNG_DEBUG=4
LDFLAGS=-L. -L$(ZLIBLIB) -lpng -lz -lm
RANLIB=ranlib
#RANLIB=echo
# where make install puts libpng.a and png.h
prefix=/usr/local
OBJS = png.o pngset.o pngget.o pngrutil.o pngtrans.o pngwutil.o \
pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \
pngwtran.o pngmem.o pngerror.o pngpread.o
all: libpng.a pngtest
libpng.a: $(OBJS)
ar rc $@ $(OBJS)
$(RANLIB) $@
pngtest: pngtest.o libpng.a
$(CC) -o pngtest $(CCFLAGS) pngtest.o $(LDFLAGS)
test: pngtest
./pngtest
install: libpng.a
-@mkdir $(prefix)/include
-@mkdir $(prefix)/lib
cp png.h $(prefix)/include
cp pngconf.h $(prefix)/include
chmod 644 $(prefix)/include/png.h
chmod 644 $(prefix)/include/pngconf.h
cp libpng.a $(prefix)/lib
chmod 644 $(prefix)/lib/libpng.a
clean:
rm -f *.o libpng.a pngtest pngout.png
# DO NOT DELETE THIS LINE -- make depend depends on it.
png.o: png.h pngconf.h
pngerror.o: png.h pngconf.h
pngrio.o: png.h pngconf.h
pngwio.o: png.h pngconf.h
pngmem.o: png.h pngconf.h
pngset.o: png.h pngconf.h
pngget.o: png.h pngconf.h
pngread.o: png.h pngconf.h
pngrtran.o: png.h pngconf.h
pngrutil.o: png.h pngconf.h
pngtest.o: png.h pngconf.h
pngtrans.o: png.h pngconf.h
pngwrite.o: png.h pngconf.h
pngwtran.o: png.h pngconf.h
pngwutil.o: png.h pngconf.h
pngpread.o: png.h pngconf.h

View File

@ -13,17 +13,22 @@ LDFLAGS=$(MODEL)
O=.obj O=.obj
# variables # variables
OBJS1 = png$(O) pngrcb$(O) pngrutil$(O) pngtrans$(O) pngwutil$(O) pngmem$(O) pngpread$(O) OBJS1 = png$(O) pngset$(O) pngget$(O) pngrutil$(O) pngtrans$(O) pngwutil$(O)
OBJS2 = pngread$(O) pngerror$(O) pngwrite$(O) pngrtran$(O) pngwtran$(O) pngrio$(O) pngwio$(O) OBJS2 = pngmem$(O) pngpread$(O) pngread$(O) pngerror$(O) pngwrite$(O)
OBJSL1 = +png$(O) +pngrcb$(O) +pngrutil$(O) +pngtrans$(O) +pngwutil$(O) +pngmem$(O) +pngpread$(O) OBJS3 = pngrtran$(O) pngwtran$(O) pngrio$(O) pngwio$(O)
OBJSL2 = +pngread$(O) +pngerror$(O) +pngwrite$(O) +pngrtran$(O) +pngwtran$(O) +pngrio$(O) +pngwio$(O) OBJSL1 = +png$(O) +pngset$(O) +pngget$(O) +pngrutil$(O) +pngtrans$(O)
OBJSL2 = +pngwutil$(O) +pngmem$(O) +pngpread$(O) +pngread$(O) +pngerror$(O)
OBJSL3 = +pngwrite$(O) +pngrtran$(O) +pngwtran$(O) +pngrio$(O) +pngwio$(O)
all: libpng.lib all: libpng.lib
png$(O): png.h pngconf.h png$(O): png.h pngconf.h
$(CC) -c $(CFLAGS) $*.c $(CC) -c $(CFLAGS) $*.c
pngrcb$(O): png.h pngconf.h pngset$(O): png.h pngconf.h
$(CC) -c $(CFLAGS) $*.c
pngget$(O): png.h pngconf.h
$(CC) -c $(CFLAGS) $*.c $(CC) -c $(CFLAGS) $*.c
pngread$(O): png.h pngconf.h pngread$(O): png.h pngconf.h
@ -65,8 +70,9 @@ pngwtran$(O): png.h pngconf.h
pngwutil$(O): png.h pngconf.h pngwutil$(O): png.h pngconf.h
$(CC) -c $(CFLAGS) $*.c $(CC) -c $(CFLAGS) $*.c
libpng.lib: $(OBJS1) $(OBJS2) libpng.lib: $(OBJS1) $(OBJS2) $(OBJS3)
$(LIB) libpng +$(OBJSL1) $(LIB) libpng +$(OBJSL1)
$(LIB) libpng +$(OBJSL2) $(LIB) libpng +$(OBJSL2)
$(LIB) libpng +$(OBJSL3)
# End of makefile for libpng # End of makefile for libpng

View File

@ -38,8 +38,10 @@ $ CALL MAKE png.OBJ "cc ''CCOPT' png" -
png.c png.h pngconf.h png.c png.h pngconf.h
$ CALL MAKE pngpread.OBJ "cc ''CCOPT' pngpread" - $ CALL MAKE pngpread.OBJ "cc ''CCOPT' pngpread" -
pngpread.c png.h pngconf.h pngpread.c png.h pngconf.h
$ CALL MAKE pngrcb.OBJ "cc ''CCOPT' pngrcb" - $ CALL MAKE pngset.OBJ "cc ''CCOPT' pngset" -
pngrcb.c png.h pngconf.h pngset.c png.h pngconf.h
$ CALL MAKE pngget.OBJ "cc ''CCOPT' pngget" -
pngget.c png.h pngconf.h
$ CALL MAKE pngread.OBJ "cc ''CCOPT' pngread" - $ CALL MAKE pngread.OBJ "cc ''CCOPT' pngread" -
pngread.c png.h pngconf.h pngread.c png.h pngconf.h
$ CALL MAKE pngpread.OBJ "cc ''CCOPT' pngpread" - $ CALL MAKE pngpread.OBJ "cc ''CCOPT' pngpread" -

142
png.c
View File

@ -1,41 +1,43 @@
/* png.c - location for general purpose png functions /* png.c - location for general purpose png functions
libpng 1.0 beta 4 - version 0.90 libpng 1.0 beta 6 - version 0.96
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 10, 1997 Copyright (c) 1996, 1997 Andreas Dilger
May 12, 1997
*/ */
#define PNG_INTERNAL #define PNG_INTERNAL
#define PNG_NO_EXTERN #define PNG_NO_EXTERN
#include "png.h" #include "png.h"
/* version information for c files. This better match the version /* Version information for C files. This had better match the version
string defined in png.h */ string defined in png.h */
char png_libpng_ver[] = "0.90"; char png_libpng_ver[] = "0.95";
/* place to hold the signiture string for a png file. */ /* Place to hold the signiture string for a PNG file. */
png_byte FARDATA png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; png_byte FARDATA png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
/* constant strings for known chunk types. If you need to add a chunk, /* constant strings for known chunk types. If you need to add a chunk,
add a string holding the name here. If you want to make the code add a string holding the name here. If you want to make the code
portable to EBCDIC machines, use ASCII numbers, not characters. */ portable to EBCDIC machines, use ASCII numbers, not characters. */
png_byte FARDATA png_IHDR[4] = { 73, 72, 68, 82}; png_byte FARDATA png_IHDR[5] = { 73, 72, 68, 82, '\0'};
png_byte FARDATA png_IDAT[4] = { 73, 68, 65, 84}; png_byte FARDATA png_IDAT[5] = { 73, 68, 65, 84, '\0'};
png_byte FARDATA png_IEND[4] = { 73, 69, 78, 68}; png_byte FARDATA png_IEND[5] = { 73, 69, 78, 68, '\0'};
png_byte FARDATA png_PLTE[4] = { 80, 76, 84, 69}; png_byte FARDATA png_PLTE[5] = { 80, 76, 84, 69, '\0'};
png_byte FARDATA png_gAMA[4] = {103, 65, 77, 65}; png_byte FARDATA png_bKGD[5] = { 98, 75, 71, 68, '\0'};
png_byte FARDATA png_sBIT[4] = {115, 66, 73, 84}; png_byte FARDATA png_cHRM[5] = { 99, 72, 82, 77, '\0'};
png_byte FARDATA png_cHRM[4] = { 99, 72, 82, 77}; png_byte FARDATA png_gAMA[5] = {103, 65, 77, 65, '\0'};
png_byte FARDATA png_tRNS[4] = {116, 82, 78, 83}; png_byte FARDATA png_hIST[5] = {104, 73, 83, 84, '\0'};
png_byte FARDATA png_bKGD[4] = { 98, 75, 71, 68}; png_byte FARDATA png_oFFs[5] = {111, 70, 70, 115, '\0'};
png_byte FARDATA png_hIST[4] = {104, 73, 83, 84}; png_byte FARDATA png_pCAL[5] = {112, 67, 65, 76, '\0'};
png_byte FARDATA png_tEXt[4] = {116, 69, 88, 116}; png_byte FARDATA png_pHYs[5] = {112, 72, 89, 115, '\0'};
png_byte FARDATA png_zTXt[4] = {122, 84, 88, 116}; png_byte FARDATA png_sBIT[5] = {115, 66, 73, 84, '\0'};
png_byte FARDATA png_pHYs[4] = {112, 72, 89, 115}; png_byte FARDATA png_tEXt[5] = {116, 69, 88, 116, '\0'};
png_byte FARDATA png_oFFs[4] = {111, 70, 70, 115}; png_byte FARDATA png_tIME[5] = {116, 73, 77, 69, '\0'};
png_byte FARDATA png_tIME[4] = {116, 73, 77, 69}; png_byte FARDATA png_tRNS[5] = {116, 82, 78, 83, '\0'};
png_byte FARDATA png_zTXt[5] = {122, 84, 88, 116, '\0'};
/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
@ -78,6 +80,7 @@ int FARDATA png_pass_dsp_mask[] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
void void
png_set_sig_bytes(png_structp png_ptr, int num_bytes) png_set_sig_bytes(png_structp png_ptr, int num_bytes)
{ {
png_debug(1, "in png_set_sig_bytes\n");
if (num_bytes > 8) if (num_bytes > 8)
png_error(png_ptr, "Too many bytes for PNG signature."); png_error(png_ptr, "Too many bytes for PNG signature.");
@ -93,20 +96,20 @@ png_set_sig_bytes(png_structp png_ptr, int num_bytes)
* PNG signature (this is the same behaviour as strcmp, memcmp, etc). * PNG signature (this is the same behaviour as strcmp, memcmp, etc).
*/ */
int int
png_sig_cmp(png_bytep sig, int start, int num_to_check) png_sig_cmp(png_bytep sig, png_size_t start, png_size_t num_to_check)
{ {
if (num_to_check > 8) if (num_to_check > 8)
num_to_check = 8; num_to_check = 8;
else if (num_to_check < 1) else if (num_to_check < 1)
return 0; return 0;
if (start > 7 || start < 0) if (start > 7)
return 0; return 0;
if (start + num_to_check > 8) if (start + num_to_check > 8)
num_to_check = 8 - start; num_to_check = 8 - start;
return (png_memcmp(sig, &png_sig[start], (unsigned int)num_to_check)); return (png_memcmp(&sig[start], &png_sig[start], num_to_check));
} }
/* (Obsolete) function to check signature bytes. It does not allow one /* (Obsolete) function to check signature bytes. It does not allow one
@ -115,7 +118,7 @@ png_sig_cmp(png_bytep sig, int start, int num_to_check)
int int
png_check_sig(png_bytep sig, int num) png_check_sig(png_bytep sig, int num)
{ {
return !png_sig_cmp(sig, 0, num); return !png_sig_cmp(sig, (png_size_t)0, (png_size_t)num);
} }
/* Function to allocate memory for zlib. */ /* Function to allocate memory for zlib. */
@ -125,10 +128,9 @@ png_zalloc(voidpf png_ptr, uInt items, uInt size)
png_voidp ptr; png_voidp ptr;
png_uint_32 num_bytes; png_uint_32 num_bytes;
ptr = png_malloc((png_structp)png_ptr, num_bytes = (png_uint_32)items * size;
(png_uint_32)items * (png_uint_32)size); ptr = png_malloc((png_structp)png_ptr, num_bytes);
num_bytes = (png_uint_32)items * (png_uint_32)size; if (num_bytes > (png_uint_32)0x8000)
if (num_bytes > (png_uint_32)0x7fff)
{ {
png_memset(ptr, 0, (png_size_t)0x8000L); png_memset(ptr, 0, (png_size_t)0x8000L);
png_memset((png_bytep)ptr + (png_size_t)0x8000L, 0, png_memset((png_bytep)ptr + (png_size_t)0x8000L, 0,
@ -153,7 +155,7 @@ png_zfree(voidpf png_ptr, voidpf ptr)
void void
png_reset_crc(png_structp png_ptr) png_reset_crc(png_structp png_ptr)
{ {
/* set crc to all 1's */ /* set CRC to all 1's */
#ifdef PNG_USE_OWN_CRC #ifdef PNG_USE_OWN_CRC
png_ptr->crc = 0xffffffffL; png_ptr->crc = 0xffffffffL;
#else #else
@ -162,7 +164,8 @@ png_reset_crc(png_structp png_ptr)
} }
#ifdef PNG_USE_OWN_CRC #ifdef PNG_USE_OWN_CRC
/* Table of CRC's of all 8-bit messages. If you wish to png_malloc this /* Table of CRCs of all 8-bit messages. By default, we use the tables made
by zlib, to save some memory. If you wish to png_malloc() this
table, turn this into a pointer, and png_malloc() it in make_crc_table(). table, turn this into a pointer, and png_malloc() it in make_crc_table().
You may then want to hook it into png_struct and free it with the You may then want to hook it into png_struct and free it with the
destroy functions. Another alternative is to pre-fill the table. */ destroy functions. Another alternative is to pre-fill the table. */
@ -188,11 +191,11 @@ make_crc_table(void)
crc_table_computed = 1; crc_table_computed = 1;
} }
/* Update a running CRC with the bytes buf[0..len-1]--the crc should be /* Update a running CRC with the bytes buf[0..len-1] - the CRC should be
initialized to all 1's, and the transmitted value is the 1's complement initialized to all 1's, and the transmitted value is the 1's complement
of the final running CRC. */ of the final running CRC. */
static png_uint_32 static png_uint_32
update_crc(png_uint_32 crc, png_bytep buf, png_uint_32 len) update_crc(png_uint_32 crc, png_bytep buf, png_size_t len)
{ {
png_uint_32 c; png_uint_32 c;
png_bytep p; png_bytep p;
@ -216,18 +219,32 @@ update_crc(png_uint_32 crc, png_bytep buf, png_uint_32 len)
} }
#endif /* PNG_USE_OWN_CRC */ #endif /* PNG_USE_OWN_CRC */
/* Calculate the crc over a section of data. Note that while we /* Calculate the CRC over a section of data. We can only pass as
are passing in a 32 bit value for length, on 16 bit machines, you much data to this routine as the largest single buffer size. We
would need to use huge pointers to access all that data. If you also check that this data will actually be used before going to the
need this, put huge here and above. */ trouble of calculating it. */
void void
png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_calculate_crc(png_structp png_ptr, png_bytep ptr, png_size_t length)
png_uint_32 length)
{ {
int need_crc = 1;
if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
{
if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
(PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
need_crc = 0;
}
else /* critical */
{
if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
need_crc = 0;
}
if (need_crc)
#ifdef PNG_USE_OWN_CRC #ifdef PNG_USE_OWN_CRC
png_ptr->crc = update_crc(png_ptr->crc, ptr, length); png_ptr->crc = update_crc(png_ptr->crc, ptr, length);
#else #else
png_ptr->crc = crc32(png_ptr->crc, ptr, length); png_ptr->crc = crc32(png_ptr->crc, ptr, length);
#endif #endif
} }
@ -241,6 +258,7 @@ png_create_info_struct(png_structp png_ptr)
{ {
png_infop info_ptr; png_infop info_ptr;
png_debug(1, "in png_create_info_struct\n");
if ((info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO)) != NULL) if ((info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO)) != NULL)
{ {
png_info_init(info_ptr); png_info_init(info_ptr);
@ -250,7 +268,7 @@ png_create_info_struct(png_structp png_ptr)
} }
/* This function frees the memory associated with a single info struct. /* This function frees the memory associated with a single info struct.
Normally, one would use either png_destroy_read_struct() or Normally, one would use either png_destroy_read_struct() or
png_destroy_write_struct() to free an info struct, but this may be png_destroy_write_struct() to free an info struct, but this may be
useful for some applications. */ useful for some applications. */
void void
@ -258,10 +276,11 @@ png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr)
{ {
png_infop info_ptr = NULL; png_infop info_ptr = NULL;
if (info_ptr_ptr) png_debug(1, "in png_destroy_info_struct\n");
if (info_ptr_ptr != NULL)
info_ptr = *info_ptr_ptr; info_ptr = *info_ptr_ptr;
if (info_ptr) if (info_ptr != NULL)
{ {
png_info_destroy(png_ptr, info_ptr); png_info_destroy(png_ptr, info_ptr);
@ -276,24 +295,42 @@ png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr)
void void
png_info_init(png_infop info_ptr) png_info_init(png_infop info_ptr)
{ {
png_debug(1, "in png_info_init\n");
/* set everything to 0 */ /* set everything to 0 */
png_memset(info_ptr, 0, sizeof (png_info)); png_memset(info_ptr, 0, sizeof (png_info));
} }
/* This is an internal routine to free any memory that the info struct is /* This is an internal routine to free any memory that the info struct is
pointing to before re-using it or freeing the struct itself. */ * pointing to before re-using it or freeing the struct itself. Recall
* that png_free() checks for NULL pointers for us.
*/
void void
png_info_destroy(png_structp png_ptr, png_infop info_ptr) png_info_destroy(png_structp png_ptr, png_infop info_ptr)
{ {
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED) #if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
int i; int i;
for (i = 0; i < info_ptr->num_text; i++) png_debug(1, "in png_info_destroy\n");
if (info_ptr->text != NULL)
{ {
png_free(png_ptr, info_ptr->text[i].key); for (i = 0; i < info_ptr->num_text; i++)
{
png_free(png_ptr, info_ptr->text[i].key);
}
png_free(png_ptr, info_ptr->text);
}
#endif
#if defined(PNG_READ_pCAL_SUPPORTED)
png_free(png_ptr, info_ptr->pcal_purpose);
png_free(png_ptr, info_ptr->pcal_units);
if (info_ptr->pcal_params != NULL)
{
for (i = 0; i < info_ptr->pcal_nparams; i++)
{
png_free(png_ptr, info_ptr->pcal_params[i]);
}
png_free(png_ptr, info_ptr->pcal_params);
} }
png_free(png_ptr, info_ptr->text);
#endif #endif
png_info_init(info_ptr); png_info_init(info_ptr);
@ -307,12 +344,15 @@ png_get_io_ptr(png_structp png_ptr)
{ {
return png_ptr->io_ptr; return png_ptr->io_ptr;
} }
/* Initialize the default input/output functions for the png file. If you #if !defined(PNG_NO_STDIO)
change the read, or write routines, you can call either png_set_read_fn() /* Initialize the default input/output functions for the PNG file. If you
use your own read or write routines, you can call either png_set_read_fn()
or png_set_write_fn() instead of png_init_io(). */ or png_set_write_fn() instead of png_init_io(). */
void void
png_init_io(png_structp png_ptr, FILE *fp) png_init_io(png_structp png_ptr, FILE *fp)
{ {
png_debug(1, "in png_init_io\n");
png_ptr->io_ptr = (png_voidp)fp; png_ptr->io_ptr = (png_voidp)fp;
} }
#endif

1865
png.h

File diff suppressed because it is too large Load Diff

205
pngconf.h
View File

@ -1,10 +1,11 @@
/* pngconf.c - machine configurable file for libpng /* pngconf.c - machine configurable file for libpng
libpng 1.0 beta 4 - version 0.90 libpng 1.0 beta 6 - version 0.96
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
December 3, 1996 Copyright (c) 1996, 1997 Andreas Dilger
May 12, 1997
*/ */
/* Any machine specific code is near the front of this file, so if you /* Any machine specific code is near the front of this file, so if you
@ -29,16 +30,16 @@
#define PNG_ZBUF_SIZE 8192 #define PNG_ZBUF_SIZE 8192
/* If you are running on a machine where you cannot allocate more then /* If you are running on a machine where you cannot allocate more
64K of memory, uncomment this. While libpng will not normally need than 64K of memory at once, uncomment this. While libpng will not
that much memory in a chunk (unless you load up a very large file), normally need that much memory in a chunk (unless you load up a very
zlib needs to know how big of a chunk it can use, and libpng thus large file), zlib needs to know how big of a chunk it can use, and
makes sure to check any memory allocation to verify it will fit libpng thus makes sure to check any memory allocation to verify it
into memory. will fit into memory.
#define PNG_MAX_ALLOC_64K #define PNG_MAX_MALLOC_64K
*/ */
#ifdef MAXSEG_64K #if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
#define PNG_MAX_ALLOC_64K #define PNG_MAX_MALLOC_64K
#endif #endif
/* This protects us against compilers which run on a windowing system /* This protects us against compilers which run on a windowing system
@ -56,12 +57,13 @@
/* This macro protects us against machines that don't have function /* This macro protects us against machines that don't have function
prototypes (ie K&R style headers). If your compiler does not handle prototypes (ie K&R style headers). If your compiler does not handle
function prototypes, define this macro. I've always been able to use function prototypes, define this macro and use the included ansi2knr.
_NO_PROTO as the indicator, but you may need to drag the empty declaration I've always been able to use _NO_PROTO as the indicator, but you may
out in front of here, or change the ifdef to suit your own needs. */ need to drag the empty declaration out in front of here, or change the
ifdef to suit your own needs. */
#ifndef PNGARG #ifndef PNGARG
#ifdef OF /* Zlib prototype munger */ #ifdef OF /* zlib prototype munger */
#define PNGARG(arglist) OF(arglist) #define PNGARG(arglist) OF(arglist)
#else #else
@ -85,17 +87,16 @@
#include <sys/types.h> #include <sys/types.h>
#endif #endif
/* need the time information for reading tIME chunks */ /* This is an attempt to force a single setjmp behaviour on Linux. If
#include <time.h> the X config stuff didn't define _BSD_SOURCE we wouldn't need this. */
/* This is an attempt to force a single setjmp behaviour on Linux */
#ifdef linux #ifdef linux
#ifdef _BSD_SOURCE #ifdef _BSD_SOURCE
#define _PNG_SAVE_BSD_SOURCE #define _PNG_SAVE_BSD_SOURCE
#undef _BSD_SOURCE #undef _BSD_SOURCE
#endif #endif
#ifdef _SETJMP_H #ifdef _SETJMP_H
error: png.h already includes setjmp.h #error __png_h_already_includes_setjmp_h__
#error __dont_include_it_again__
#endif #endif
#endif /* linux */ #endif /* linux */
@ -115,25 +116,39 @@ error: png.h already includes setjmp.h
#include <string.h> #include <string.h>
#endif #endif
/* Other defines for things like memory and the like can go here. These /* Other defines for things like memory and the like can go here. */
are the only files included in libpng, so if you need to change them,
change them here. They are only included if PNG_INTERNAL is defined. */
#ifdef PNG_INTERNAL #ifdef PNG_INTERNAL
#include <stdlib.h> #include <stdlib.h>
/* Where do we need this???
#include <ctype.h> #include <ctype.h>
*/
/* The functions exported by PNG_EXTERN are PNG_INTERNAL functions, which
* aren't usually used outside the library (as far as I know), so it is
* debatable if they should be exported at all. In the future, when it is
* possible to have run-time registry of chunk-handling functions, some of
* these will be made available again.
#define PNG_EXTERN extern
*/
#define PNG_EXTERN
/* Other defines specific to compilers can go here. Try to keep /* Other defines specific to compilers can go here. Try to keep
them inside an appropriate ifdef/endif pair for portability */ them inside an appropriate ifdef/endif pair for portability */
#ifdef MACOS #if defined(MACOS)
/* We need to check that <math.h> hasn't already been included earlier
as it seems it doesn't agree with <fp.h>, yet we should really use
<fp.h> if possible. */
#if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__)
#include <fp.h> #include <fp.h>
#endif
#else #else
#include <math.h> #include <math.h>
#endif #endif
/* For some reason, Borland C++ defines memcmp, etc. in mem.h, not /* For some reason, Borland C++ defines memcmp, etc. in mem.h, not
stdlib.h like it should (I think). Or perhaps this is a C++ stdlib.h like it should (I think). Or perhaps this is a C++
feature? */ "feature"? */
#ifdef __TURBOC__ #ifdef __TURBOC__
#include <mem.h> #include <mem.h>
#include "alloc.h" #include "alloc.h"
@ -159,6 +174,10 @@ error: png.h already includes setjmp.h
#define PNG_MAX_GAMMA_8 11 #define PNG_MAX_GAMMA_8 11
/* This controls how much a difference in gamma we can tolerate before
we actually start doing gamma conversion. */
#define PNG_GAMMA_THRESHOLD 0.05
#endif /* PNG_INTERNAL */ #endif /* PNG_INTERNAL */
/* The following uses const char * instead of char * for error /* The following uses const char * instead of char * for error
@ -167,8 +186,7 @@ error: png.h already includes setjmp.h
normally defined to make configuration easier, as it is not a normally defined to make configuration easier, as it is not a
critical part of the code. critical part of the code.
*/ */
#undef PNG_USE_CONST
#define PNG_USE_CONST
#ifdef PNG_USE_CONST #ifdef PNG_USE_CONST
# define PNG_CONST const # define PNG_CONST const
@ -191,12 +209,14 @@ error: png.h already includes setjmp.h
/* Any transformations you will not be using can be undef'ed here */ /* Any transformations you will not be using can be undef'ed here */
#define PNG_PROGRESSIVE_READ_SUPPORTED #define PNG_PROGRESSIVE_READ_SUPPORTED
#define PNG_READ_OPT_PLTE_SUPPORTED
#define PNG_READ_INTERLACING_SUPPORTED #define PNG_READ_INTERLACING_SUPPORTED
#define PNG_READ_EXPAND_SUPPORTED #define PNG_READ_EXPAND_SUPPORTED
#define PNG_READ_SHIFT_SUPPORTED #define PNG_READ_SHIFT_SUPPORTED
#define PNG_READ_PACK_SUPPORTED #define PNG_READ_PACK_SUPPORTED
#define PNG_READ_BGR_SUPPORTED #define PNG_READ_BGR_SUPPORTED
#define PNG_READ_SWAP_SUPPORTED #define PNG_READ_SWAP_SUPPORTED
#define PNG_READ_PACKSWAP_SUPPORTED
#define PNG_READ_INVERT_SUPPORTED #define PNG_READ_INVERT_SUPPORTED
#define PNG_READ_DITHER_SUPPORTED #define PNG_READ_DITHER_SUPPORTED
#define PNG_READ_BACKGROUND_SUPPORTED #define PNG_READ_BACKGROUND_SUPPORTED
@ -204,55 +224,79 @@ error: png.h already includes setjmp.h
#define PNG_READ_FILLER_SUPPORTED #define PNG_READ_FILLER_SUPPORTED
#define PNG_READ_GAMMA_SUPPORTED #define PNG_READ_GAMMA_SUPPORTED
#define PNG_READ_GRAY_TO_RGB_SUPPORTED #define PNG_READ_GRAY_TO_RGB_SUPPORTED
#define PNG_READ_SWAP_ALPHA_SUPPORTED
#define PNG_READ_STRIP_ALPHA_SUPPORTED
#define PNG_WRITE_INTERLACING_SUPPORTED #define PNG_WRITE_INTERLACING_SUPPORTED
#define PNG_WRITE_SHIFT_SUPPORTED #define PNG_WRITE_SHIFT_SUPPORTED
#define PNG_WRITE_PACK_SUPPORTED #define PNG_WRITE_PACK_SUPPORTED
#define PNG_WRITE_BGR_SUPPORTED #define PNG_WRITE_BGR_SUPPORTED
#define PNG_WRITE_SWAP_SUPPORTED #define PNG_WRITE_SWAP_SUPPORTED
#define PNG_WRITE_PACKSWAP_SUPPORTED
#define PNG_WRITE_INVERT_SUPPORTED #define PNG_WRITE_INVERT_SUPPORTED
#define PNG_WRITE_FILLER_SUPPORTED #define PNG_WRITE_FILLER_SUPPORTED /* This is the same as WRITE_STRIP_ALPHA */
#define PNG_WRITE_FLUSH_SUPPORTED #define PNG_WRITE_FLUSH_SUPPORTED
#define PNG_WRITE_SWAP_ALPHA_SUPPORTED
#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
/* These are currently experimental features */
#undef PNG_READ_16_TO_8_ACCURATE_SHIFT_SUPPORTED /* very little testing */
#undef PNG_READ_COMPOSITE_NODIV_SUPPORTED /* very little testing */
/* This is only for PowerPC big-endian and 680x0 systems */
#undef PNG_READ_BIG_ENDIAN_SUPPORTED /* some testing */
/* These functions are turned off by default, as they will be phased out. */ /* These functions are turned off by default, as they will be phased out. */
#undef PNG_USE_OWN_CRC #undef PNG_USE_OWN_CRC
#undef PNG_USELESS_TESTS_SUPPORTED
#undef PNG_CORRECT_PALETTE_SUPPORTED #undef PNG_CORRECT_PALETTE_SUPPORTED
/* any chunks you are not interested in, you can undef here. The /* Any chunks you are not interested in, you can undef here. The
ones that allocate memory may be expecially important (hIST, * ones that allocate memory may be expecially important (hIST,
tEXt, zTXt, tRNS) Others will just save time and make png_info * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info
smaller. OPT_PLTE only disables the optional palette in RGB * a bit smaller. OPT_PLTE only disables the optional palette in RGB
and RGB Alpha images. */ * and RGBA images.
*/
#define PNG_READ_gAMA_SUPPORTED
#define PNG_READ_sBIT_SUPPORTED
#define PNG_READ_cHRM_SUPPORTED
#define PNG_READ_tRNS_SUPPORTED
#define PNG_READ_bKGD_SUPPORTED #define PNG_READ_bKGD_SUPPORTED
#define PNG_READ_cHRM_SUPPORTED
#define PNG_READ_gAMA_SUPPORTED
#define PNG_READ_hIST_SUPPORTED #define PNG_READ_hIST_SUPPORTED
#define PNG_READ_pHYs_SUPPORTED
#define PNG_READ_oFFs_SUPPORTED #define PNG_READ_oFFs_SUPPORTED
#define PNG_READ_tIME_SUPPORTED #define PNG_READ_pCAL_SUPPORTED
#define PNG_READ_pHYs_SUPPORTED
#define PNG_READ_sBIT_SUPPORTED
#define PNG_READ_tEXt_SUPPORTED #define PNG_READ_tEXt_SUPPORTED
#define PNG_READ_tIME_SUPPORTED
#define PNG_READ_tRNS_SUPPORTED
#define PNG_READ_zTXt_SUPPORTED #define PNG_READ_zTXt_SUPPORTED
#define PNG_READ_OPT_PLTE_SUPPORTED
#define PNG_WRITE_gAMA_SUPPORTED
#define PNG_WRITE_sBIT_SUPPORTED
#define PNG_WRITE_cHRM_SUPPORTED
#define PNG_WRITE_tRNS_SUPPORTED
#define PNG_WRITE_bKGD_SUPPORTED #define PNG_WRITE_bKGD_SUPPORTED
#define PNG_WRITE_cHRM_SUPPORTED
#define PNG_WRITE_gAMA_SUPPORTED
#define PNG_WRITE_hIST_SUPPORTED #define PNG_WRITE_hIST_SUPPORTED
#define PNG_WRITE_pHYs_SUPPORTED
#define PNG_WRITE_oFFs_SUPPORTED #define PNG_WRITE_oFFs_SUPPORTED
#define PNG_WRITE_tIME_SUPPORTED #define PNG_WRITE_pCAL_SUPPORTED
#define PNG_WRITE_pHYs_SUPPORTED
#define PNG_WRITE_sBIT_SUPPORTED
#define PNG_WRITE_tEXt_SUPPORTED #define PNG_WRITE_tEXt_SUPPORTED
#define PNG_WRITE_tIME_SUPPORTED
#define PNG_WRITE_tRNS_SUPPORTED
#define PNG_WRITE_zTXt_SUPPORTED #define PNG_WRITE_zTXt_SUPPORTED
/* need the time information for reading tIME chunks */
#if defined(PNG_READ_tIME_SUPPORTED) || defined(PNG_WRITE_tIME_SUPPORTED)
#include <time.h>
#endif
/* Some typedefs to get us started. These should be safe on most of the /* Some typedefs to get us started. These should be safe on most of the
common platforms. The typedefs should be at least as large as the * common platforms. The typedefs should be at least as large as the
numbers suggest (a png_uint_32 must be at least 32 bits long), but they * numbers suggest (a png_uint_32 must be at least 32 bits long), but they
don't have to be exactly that size. */ * don't have to be exactly that size. Some compilers dislike passing
* unsigned shorts as function parameters, so you may be better off using
* unsigned int for png_uint_16. Likewise, for 64-bit systems, you may
* want to have unsigned int for png_uint_32 instead of unsigned long.
*/
typedef unsigned long png_uint_32; typedef unsigned long png_uint_32;
typedef long png_int_32; typedef long png_int_32;
@ -264,14 +308,14 @@ typedef unsigned char png_byte;
change (I'm not sure if you will or not, so I thought I'd be safe) */ change (I'm not sure if you will or not, so I thought I'd be safe) */
typedef size_t png_size_t; typedef size_t png_size_t;
/* The following is needed for medium model support. It cannot be in the /* The following is needed for medium model support. It cannot be in the
PNG_INTERNAL section. Needs modification for other compilers besides * PNG_INTERNAL section. Needs modification for other compilers besides
MSC. Model independent support declares all arrays that might be very * MSC. Model independent support declares all arrays and pointers to be
large using the far keyword. The Zlib version used must also support * large using the far keyword. The zlib version used must also support
model independent data. As of version Zlib .95, the necessary changes * model independent data. As of version zlib 1.0.4, the necessary changes
have been made in Zlib. The USE_FAR_KEYWORD define triggers other * have been made in zlib. The USE_FAR_KEYWORD define triggers other
changes that are needed. Most of the far keyword changes are hidden * changes that are needed. (Tim Wegner)
inside typedefs with suffix "f". (Tim Wegner) */ */
/* Separate compiler dependencies (problem here is that zlib.h always /* Separate compiler dependencies (problem here is that zlib.h always
defines FAR. (SJT) */ defines FAR. (SJT) */
@ -319,17 +363,12 @@ typedef size_t png_size_t;
# define FAR # define FAR
#endif #endif
/* SJT: At this point FAR is always defined */ /* At this point FAR is always defined */
/* SJT: */
#ifndef FARDATA #ifndef FARDATA
#define FARDATA #define FARDATA
#endif #endif
/* Not used anymore (as of 0.88), but kept for compatability (for now). */ /* Add typedefs for pointers */
typedef unsigned char FAR png_bytef;
/* SJT: Add typedefs for pointers */
typedef void FAR * png_voidp; typedef void FAR * png_voidp;
typedef png_byte FAR * png_bytep; typedef png_byte FAR * png_bytep;
typedef png_uint_32 FAR * png_uint_32p; typedef png_uint_32 FAR * png_uint_32p;
@ -338,8 +377,9 @@ typedef png_uint_16 FAR * png_uint_16p;
typedef png_int_16 FAR * png_int_16p; typedef png_int_16 FAR * png_int_16p;
typedef PNG_CONST char FAR * png_const_charp; typedef PNG_CONST char FAR * png_const_charp;
typedef char FAR * png_charp; typedef char FAR * png_charp;
typedef double FAR * png_doublep;
/* SJT: Pointers to pointers; i.e. arrays */ /* Pointers to pointers; i.e. arrays */
typedef png_byte FAR * FAR * png_bytepp; typedef png_byte FAR * FAR * png_bytepp;
typedef png_uint_32 FAR * FAR * png_uint_32pp; typedef png_uint_32 FAR * FAR * png_uint_32pp;
typedef png_int_32 FAR * FAR * png_int_32pp; typedef png_int_32 FAR * FAR * png_int_32pp;
@ -347,16 +387,29 @@ typedef png_uint_16 FAR * FAR * png_uint_16pp;
typedef png_int_16 FAR * FAR * png_int_16pp; typedef png_int_16 FAR * FAR * png_int_16pp;
typedef PNG_CONST char FAR * FAR * png_const_charpp; typedef PNG_CONST char FAR * FAR * png_const_charpp;
typedef char FAR * FAR * png_charpp; typedef char FAR * FAR * png_charpp;
typedef double FAR * FAR * png_doublepp;
/* Pointers to pointers to pointers; i.e. pointer to array */
typedef char FAR * FAR * FAR * png_charppp;
/* SJT: libpng typedefs for types in zlib. If Zlib changes /* libpng typedefs for types in zlib. If zlib changes
or another compression library is used, then change these. * or another compression library is used, then change these.
Eliminates need to change all the source files. * Eliminates need to change all the source files.
*/ */
typedef charf * png_zcharp; typedef charf * png_zcharp;
typedef charf * FAR * png_zcharpp; typedef charf * FAR * png_zcharpp;
typedef z_stream FAR * png_zstreamp; typedef z_stream FAR * png_zstreamp;
/* allow for compilation as dll under windows */
#ifdef __WIN32DLL__
#define PNG_EXPORT(type,symbol) __declspec(dllexport) type symbol
#endif
#ifndef PNG_EXPORT
#define PNG_EXPORT(t,s) t s
#endif
/* User may want to use these so not in PNG_INTERNAL. Any library functions /* User may want to use these so not in PNG_INTERNAL. Any library functions
that are passed far data must be model independent. */ that are passed far data must be model independent. */
@ -366,25 +419,27 @@ typedef z_stream FAR * png_zstreamp;
# define NOCHECK 0 # define NOCHECK 0
# define CVT_PTR(ptr) (far_to_near(png_ptr,ptr,CHECK)) # define CVT_PTR(ptr) (far_to_near(png_ptr,ptr,CHECK))
# define CVT_PTR_NOCHECK(ptr) (far_to_near(png_ptr,ptr,NOCHECK)) # define CVT_PTR_NOCHECK(ptr) (far_to_near(png_ptr,ptr,NOCHECK))
# define png_strcpy _fstrcpy
# define png_strcat _fstrcat
# define png_strlen _fstrlen # define png_strlen _fstrlen
# define png_strcmp _fstrcmp
# define png_memcmp _fmemcmp /* SJT: added */ # define png_memcmp _fmemcmp /* SJT: added */
# define png_memcpy _fmemcpy # define png_memcpy _fmemcpy
# define png_memset _fmemset # define png_memset _fmemset
#else /* use the usual functions */ #else /* use the usual functions */
# define CVT_PTR(ptr) (ptr) # define CVT_PTR(ptr) (ptr)
# define CVT_PTR_NOCHECK(ptr) (ptr) # define CVT_PTR_NOCHECK(ptr) (ptr)
# define png_strcpy strcpy
# define png_strcat strcat
# define png_strlen strlen # define png_strlen strlen
# define png_strcmp strcmp
# define png_memcmp memcmp /* SJT: added */ # define png_memcmp memcmp /* SJT: added */
# define png_memcpy memcpy # define png_memcpy memcpy
# define png_memset memset # define png_memset memset
#endif #endif
/* End of memory model independent support */ /* End of memory model independent support */
/* Just a double check that someone hasn't tried to define something
* contradictory.
*/
#if (PNG_ZBUF_SIZE > 65536) && defined(PNG_MAX_MALLOC_64K)
#undef PNG_ZBUF_SIZE
#define PNG_ZBUF_SIZE 65536
#endif
#endif /* PNGCONF_H */ #endif /* PNGCONF_H */

View File

@ -1,10 +1,11 @@
/* pngerror.c - stub functions for i/o and memory allocation /* pngerror.c - stub functions for i/o and memory allocation
libpng 1.0 beta 4 - version 0.90 libpng 1.0 beta 6 - version 0.96
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 10, 1997 Copyright (c) 1996, 1997 Andreas Dilger
May 12, 1997
This file provides a location for all error handling. Users which This file provides a location for all error handling. Users which
need special error handling are expected to write replacement functions need special error handling are expected to write replacement functions
@ -26,7 +27,7 @@ static void png_default_warning PNGARG((png_structp png_ptr,
void void
png_error(png_structp png_ptr, png_const_charp message) png_error(png_structp png_ptr, png_const_charp message)
{ {
if (png_ptr->error_fn) if (png_ptr->error_fn != NULL)
(*(png_ptr->error_fn))(png_ptr, message); (*(png_ptr->error_fn))(png_ptr, message);
/* if the following returns or doesn't exist, use the default function, /* if the following returns or doesn't exist, use the default function,
@ -41,7 +42,7 @@ png_error(png_structp png_ptr, png_const_charp message)
void void
png_warning(png_structp png_ptr, png_const_charp message) png_warning(png_structp png_ptr, png_const_charp message)
{ {
if (png_ptr->warning_fn) if (png_ptr->warning_fn != NULL)
(*(png_ptr->warning_fn))(png_ptr, message); (*(png_ptr->warning_fn))(png_ptr, message);
else else
png_default_warning(png_ptr, message); png_default_warning(png_ptr, message);
@ -76,7 +77,7 @@ png_default_error(png_structp png_ptr, png_const_charp message)
static void static void
png_default_warning(png_structp png_ptr, png_const_charp message) png_default_warning(png_structp png_ptr, png_const_charp message)
{ {
if (!png_ptr) if (png_ptr == NULL)
return; return;
#ifndef PNG_NO_STDIO #ifndef PNG_NO_STDIO

300
pngget.c Normal file
View File

@ -0,0 +1,300 @@
/* pngget.c - retrieval of values from info struct
libpng 1.0 beta 6 - version 0.96
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
Copyright (c) 1996, 1997 Andreas Dilger
May 12, 1997
*/
#define PNG_INTERNAL
#include "png.h"
png_uint_32
png_get_valid(png_structp png_ptr, png_infop info_ptr, png_uint_32 flag)
{
if (info_ptr != NULL)
return(info_ptr->valid & flag);
else
return(0);
}
png_uint_32
png_get_rowbytes(png_structp png_ptr, png_infop info_ptr)
{
if (info_ptr != NULL)
return(info_ptr->rowbytes);
else
return(0);
}
png_byte
png_get_channels(png_structp png_ptr, png_infop info_ptr)
{
if (info_ptr != NULL)
return(info_ptr->channels);
else
return(0);
}
png_bytep
png_get_signature(png_structp png_ptr, png_infop info_ptr)
{
if (info_ptr != NULL)
return(info_ptr->signature);
else
return(NULL);
}
#if defined(PNG_READ_bKGD_SUPPORTED)
png_uint_32
png_get_bKGD(png_structp png_ptr, png_infop info_ptr,
png_color_16p *background)
{
if (info_ptr != NULL && info_ptr->valid & PNG_INFO_bKGD &&
background != NULL)
{
png_debug1(1, "in %s retrieval function\n", "bKGD");
*background = &(info_ptr->background);
return (PNG_INFO_bKGD);
}
return (0);
}
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
png_uint_32
png_get_cHRM(png_structp png_ptr, png_infop info_ptr,
double *white_x, double *white_y, double *red_x, double *red_y,
double *green_x, double *green_y, double *blue_x, double *blue_y)
{
if (info_ptr != NULL && info_ptr->valid & PNG_INFO_cHRM)
{
png_debug1(1, "in %s retrieval function\n", "cHRM");
if (white_x != NULL)
*white_x = (double)info_ptr->x_white;
if (white_y != NULL)
*white_y = (double)info_ptr->y_white;
if (red_x != NULL)
*red_x = (double)info_ptr->x_red;
if (red_y != NULL)
*red_y = (double)info_ptr->y_red;
if (green_x != NULL)
*green_x = (double)info_ptr->x_green;
if (green_y != NULL)
*green_y = (double)info_ptr->y_green;
if (blue_x != NULL)
*blue_x = (double)info_ptr->x_blue;
if (blue_y != NULL)
*blue_y = (double)info_ptr->y_blue;
return (PNG_INFO_cHRM);
}
return (0);
}
#endif
#if defined(PNG_READ_gAMA_SUPPORTED)
png_uint_32
png_get_gAMA(png_structp png_ptr, png_infop info_ptr, double *file_gamma)
{
if (info_ptr != NULL && info_ptr->valid & PNG_INFO_gAMA &&
file_gamma != NULL)
{
png_debug1(1, "in %s retrieval function\n", "gAMA");
*file_gamma = (double)info_ptr->gamma;
return (PNG_INFO_gAMA);
}
return (0);
}
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
png_uint_32
png_get_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p *hist)
{
if (info_ptr != NULL && info_ptr->valid & PNG_INFO_hIST && hist != NULL)
{
png_debug1(1, "in %s retrieval function\n", "hIST");
*hist = info_ptr->hist;
return (PNG_INFO_hIST);
}
return (0);
}
#endif
png_uint_32
png_get_IHDR(png_structp png_ptr, png_infop info_ptr,
png_uint_32 *width, png_uint_32 *height, int *bit_depth,
int *color_type, int *interlace_type, int *compression_type,
int *filter_type)
{
if (info_ptr != NULL && width != NULL && height != NULL &&
bit_depth != NULL && color_type != NULL)
{
png_debug1(1, "in %s retrieval function\n", "IHDR");
*width = info_ptr->width;
*height = info_ptr->height;
*bit_depth = info_ptr->bit_depth;
*color_type = info_ptr->color_type;
if (compression_type != NULL)
*compression_type = info_ptr->compression_type;
if (filter_type != NULL)
*filter_type = info_ptr->filter_type;
if (interlace_type != NULL)
*interlace_type = info_ptr->interlace_type;
return (1);
}
return (0);
}
#if defined(PNG_READ_oFFs_SUPPORTED)
png_uint_32
png_get_oFFs(png_structp png_ptr, png_infop info_ptr,
png_uint_32 *offset_x, png_uint_32 *offset_y, int *unit_type)
{
if (info_ptr != NULL && info_ptr->valid & PNG_INFO_oFFs &&
offset_x != NULL && offset_y != NULL && unit_type != NULL)
{
png_debug1(1, "in %s retrieval function\n", "oFFs");
*offset_x = info_ptr->x_offset;
*offset_y = info_ptr->y_offset;
*unit_type = (int)info_ptr->offset_unit_type;
return (PNG_INFO_oFFs);
}
return (0);
}
#endif
#if defined(PNG_READ_pCAL_SUPPORTED)
png_uint_32
png_get_pCAL(png_structp png_ptr, png_infop info_ptr,
png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams,
png_charp *units, png_charpp *params)
{
if (info_ptr != NULL && info_ptr->valid & PNG_INFO_pCAL &&
purpose != NULL && X0 != NULL && X1 != NULL && type != NULL &&
nparams != NULL && units != NULL && params != NULL)
{
png_debug1(1, "in %s retrieval function\n", "pCAL");
*purpose = info_ptr->pcal_purpose;
*X0 = info_ptr->pcal_X0;
*X1 = info_ptr->pcal_X1;
*type = (int)info_ptr->pcal_type;
*nparams = (int)info_ptr->pcal_nparams;
*units = info_ptr->pcal_units;
*params = info_ptr->pcal_params;
return (PNG_INFO_pCAL);
}
return (0);
}
#endif
#if defined(PNG_READ_pHYs_SUPPORTED)
png_uint_32
png_get_pHYs(png_structp png_ptr, png_infop info_ptr,
png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
{
if (info_ptr != NULL && info_ptr->valid & PNG_INFO_pHYs &&
res_x != NULL && res_y != NULL && unit_type != NULL)
{
png_debug1(1, "in %s retrieval function\n", "pHYs");
*res_x = info_ptr->x_pixels_per_unit;
*res_y = info_ptr->y_pixels_per_unit;
*unit_type = (int)info_ptr->phys_unit_type;
return (PNG_INFO_pHYs);
}
return (0);
}
#endif
png_uint_32
png_get_PLTE(png_structp png_ptr, png_infop info_ptr, png_colorp *palette,
int *num_palette)
{
if (info_ptr != NULL && info_ptr->valid & PNG_INFO_PLTE && palette != NULL)
{
png_debug1(1, "in %s retrieval function\n", "PLTE");
*palette = info_ptr->palette;
*num_palette = info_ptr->num_palette;
png_debug1(3, "num_palette = %d\n", *num_palette);
return (PNG_INFO_PLTE);
}
return (0);
}
#if defined(PNG_READ_sBIT_SUPPORTED)
png_uint_32
png_get_sBIT(png_structp png_ptr, png_infop info_ptr, png_color_8p *sig_bit)
{
if (info_ptr != NULL && info_ptr->valid & PNG_INFO_sBIT && sig_bit != NULL)
{
png_debug1(1, "in %s retrieval function\n", "sBIT");
*sig_bit = &(info_ptr->sig_bit);
return (PNG_INFO_sBIT);
}
return (0);
}
#endif
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
png_uint_32
png_get_text(png_structp png_ptr, png_infop info_ptr, png_textp *text_ptr,
int *num_text)
{
if ((info_ptr != NULL) || (info_ptr->num_text > 0))
{
png_debug1(1, "in %s retrieval function\n",
(png_ptr->chunk_name[0] == '\0' ? "text" : png_ptr->chunk_name));
if (text_ptr != NULL)
*text_ptr = info_ptr->text;
if (num_text != NULL)
*num_text = info_ptr->num_text;
return (info_ptr->num_text);
}
return(0);
}
#endif
#if defined(PNG_READ_tIME_SUPPORTED)
png_uint_32
png_get_tIME(png_structp png_ptr, png_infop info_ptr, png_timep *mod_time)
{
if (info_ptr != NULL && info_ptr->valid & PNG_INFO_tIME && mod_time != NULL)
{
png_debug1(1, "in %s retrieval function\n", "tIME");
*mod_time = &(info_ptr->mod_time);
return (PNG_INFO_tIME);
}
return (0);
}
#endif
#if defined(PNG_READ_tRNS_SUPPORTED)
png_uint_32
png_get_tRNS(png_structp png_ptr, png_infop info_ptr,
png_bytep *trans, int *num_trans, png_color_16p *trans_values)
{
if (info_ptr != NULL && info_ptr->valid & PNG_INFO_tRNS)
{
png_debug1(1, "in %s retrieval function\n", "tRNS");
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE && trans != NULL)
{
*trans = info_ptr->trans;
}
else if (trans_values != NULL)
{
*trans_values = &(info_ptr->trans_values);
}
else
{
return (0);
}
*num_trans = info_ptr->num_trans;
return (PNG_INFO_tRNS);
}
return (0);
}
#endif

133
pngmem.c
View File

@ -1,10 +1,11 @@
/* pngmem.c - stub functions for memory allocation /* pngmem.c - stub functions for memory allocation
libpng 1.0 beta 4 - version 0.90 libpng 1.0 beta 6 - version 0.96
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 10, 1997 Copyright (c) 1996, 1997 Andreas Dilger
May 12, 1997
This file provides a location for all memory allocation. Users which This file provides a location for all memory allocation. Users which
need special memory handling are expected to modify the code in this file need special memory handling are expected to modify the code in this file
@ -45,30 +46,34 @@ png_create_struct(int type)
void void
png_destroy_struct(png_voidp struct_ptr) png_destroy_struct(png_voidp struct_ptr)
{ {
if (struct_ptr) if (struct_ptr != NULL)
farfree (struct_ptr); farfree (struct_ptr);
} }
/* Allocate memory. For reasonable files, size should never exceed /* Allocate memory. For reasonable files, size should never exceed
64K. However, zlib may allocate more then 64K if you don't tell * 64K. However, zlib may allocate more then 64K if you don't tell
it not to. See zconf.h and png.h for more information. zlib does * it not to. See zconf.h and png.h for more information. zlib does
need to allocate exactly 64K, so whatever you call here must * need to allocate exactly 64K, so whatever you call here must
have the ability to do that. */ * have the ability to do that.
*
/* Borland seems to have a problem in DOS mode for exactly 64K. * Borland seems to have a problem in DOS mode for exactly 64K.
It gives you a segment with an offset of 8 (perhaps to store it's * It gives you a segment with an offset of 8 (perhaps to store it's
memory stuff). zlib doesn't like this at all, so we have to * memory stuff). zlib doesn't like this at all, so we have to
detect and deal with it. This code should not be needed in * detect and deal with it. This code should not be needed in
Windows or OS/2 modes, and only in 16 bit mode. This code has * Windows or OS/2 modes, and only in 16 bit mode. This code has
been updated by Alexander Lehmann for version 0.89 to waste less * been updated by Alexander Lehmann for version 0.89 to waste less
memory. * memory.
*/ *
* Note that we can't use png_size_t for the "size" declaration,
* since on some systems a png_size_t is a 16-bit quantity, and as a
* result, we would be truncating potentially larger memory requests
* (which should cause a fatal error) and introducing major problems.
*/
png_voidp png_voidp
png_malloc(png_structp png_ptr, png_uint_32 size) png_malloc(png_structp png_ptr, png_uint_32 size)
{ {
png_voidp ret; png_voidp ret;
if (!png_ptr || !size) if (png_ptr == NULL || size == 0)
return ((voidp)NULL); return ((voidp)NULL);
#ifdef PNG_MAX_MALLOC_64K #ifdef PNG_MAX_MALLOC_64K
@ -78,11 +83,11 @@ png_malloc(png_structp png_ptr, png_uint_32 size)
if (size == (png_uint_32)(65536L)) if (size == (png_uint_32)(65536L))
{ {
if (!png_ptr->offset_table) if (png_ptr->offset_table == NULL)
{ {
/* try to see if we need to do any of this fancy stuff */ /* try to see if we need to do any of this fancy stuff */
ret = farmalloc(size); ret = farmalloc(size);
if (!ret || ((long)ret & 0xffff)) if (ret == NULL || ((png_size_t)ret & 0xffff))
{ {
int num_blocks; int num_blocks;
png_uint_32 total_size; png_uint_32 total_size;
@ -90,7 +95,7 @@ png_malloc(png_structp png_ptr, png_uint_32 size)
int i; int i;
png_byte huge * hptr; png_byte huge * hptr;
if (ret) if (ret != NULL)
farfree(ret); farfree(ret);
ret = NULL; ret = NULL;
@ -106,27 +111,27 @@ png_malloc(png_structp png_ptr, png_uint_32 size)
table = farmalloc(total_size); table = farmalloc(total_size);
if (!table) if (table == NULL)
{ {
png_error(png_ptr, "Out of Memory"); png_error(png_ptr, "Out of Memory");
} }
if ((long)table & 0xfff0) if ((png_size_t)table & 0xfff0)
{ {
png_error(png_ptr, "Farmalloc didn't return normalized pointer"); png_error(png_ptr, "Farmalloc didn't return normalized pointer");
} }
png_ptr->offset_table = table; png_ptr->offset_table = table;
png_ptr->offset_table_ptr = farmalloc( png_ptr->offset_table_ptr = farmalloc(num_blocks *
num_blocks * sizeof (png_bytep)); sizeof (png_bytep));
if (!png_ptr->offset_table_ptr) if (png_ptr->offset_table_ptr == NULL)
{ {
png_error(png_ptr, "Out of memory"); png_error(png_ptr, "Out of memory");
} }
hptr = (png_byte huge *)table; hptr = (png_byte huge *)table;
if ((long)hptr & 0xf) if ((png_size_t)hptr & 0xf)
{ {
hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L); hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
hptr += 16L; hptr += 16L;
@ -165,36 +170,33 @@ png_malloc(png_structp png_ptr, png_uint_32 size)
void void
png_free(png_structp png_ptr, png_voidp ptr) png_free(png_structp png_ptr, png_voidp ptr)
{ {
if (!png_ptr) if (png_ptr == NULL || ptr == NULL)
return; return;
if (ptr != NULL) if (png_ptr->offset_table != NULL)
{ {
if (png_ptr->offset_table) int i;
{
int i;
for (i = 0; i < png_ptr->offset_table_count; i++) for (i = 0; i < png_ptr->offset_table_count; i++)
{
if (ptr == png_ptr->offset_table_ptr[i])
{ {
if (ptr == png_ptr->offset_table_ptr[i]) ptr = NULL;
{ png_ptr->offset_table_count_free++;
ptr = 0; break;
png_ptr->offset_table_count_free++;
break;
}
}
if (png_ptr->offset_table_count_free == png_ptr->offset_table_count)
{
farfree(png_ptr->offset_table);
farfree(png_ptr->offset_table_ptr);
png_ptr->offset_table = 0;
png_ptr->offset_table_ptr = 0;
} }
} }
if (png_ptr->offset_table_count_free == png_ptr->offset_table_count)
if (ptr) {
farfree(ptr); farfree(png_ptr->offset_table);
farfree(png_ptr->offset_table_ptr);
png_ptr->offset_table = NULL;
png_ptr->offset_table_ptr = NULL;
}
} }
if (ptr != NULL)
farfree(ptr);
} }
#else /* Not the Borland DOS special memory handler */ #else /* Not the Borland DOS special memory handler */
@ -205,15 +207,15 @@ png_free(png_structp png_ptr, png_voidp ptr)
png_voidp png_voidp
png_create_struct(int type) png_create_struct(int type)
{ {
size_t size; png_size_t size;
png_voidp struct_ptr; png_voidp struct_ptr;
if (type == PNG_STRUCT_INFO) if (type == PNG_STRUCT_INFO)
size = sizeof(png_info); size = sizeof(png_info);
else if (type == PNG_STRUCT_PNG) else if (type == PNG_STRUCT_PNG)
size = sizeof(png_struct); size = sizeof(png_struct);
else else
return (png_voidp)NULL; return (png_voidp)NULL;
#if defined(__TURBOC__) && !defined(__FLAT__) #if defined(__TURBOC__) && !defined(__FLAT__)
if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL) if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL)
@ -236,7 +238,7 @@ png_create_struct(int type)
void void
png_destroy_struct(png_voidp struct_ptr) png_destroy_struct(png_voidp struct_ptr)
{ {
if (struct_ptr) if (struct_ptr != NULL)
#if defined(__TURBOC__) && !defined(__FLAT__) #if defined(__TURBOC__) && !defined(__FLAT__)
farfree(struct_ptr); farfree(struct_ptr);
#else #else
@ -251,17 +253,16 @@ png_destroy_struct(png_voidp struct_ptr)
/* Allocate memory. For reasonable files, size should never exceed /* Allocate memory. For reasonable files, size should never exceed
64K. However, zlib may allocate more then 64K if you don't tell 64K. However, zlib may allocate more then 64K if you don't tell
it not to. See zconf.h and png.h for more information. zlib does it not to. See zconf.h and png.h for more information. zlib does
need to allocate exactly 64K, so whatever you call here must need to allocate exactly 64K, so whatever you call here must
have the ability to do that. */ have the ability to do that. */
#ifndef FORTIFY
png_voidp png_voidp
png_malloc(png_structp png_ptr, png_uint_32 size) png_malloc(png_structp png_ptr, png_uint_32 size)
{ {
png_voidp ret; png_voidp ret;
if (!png_ptr || !size) if (png_ptr == NULL || size == 0)
return ((voidp)0); return (NULL);
#ifdef PNG_MAX_MALLOC_64K #ifdef PNG_MAX_MALLOC_64K
if (size > (png_uint_32)65536L) if (size > (png_uint_32)65536L)
@ -269,7 +270,7 @@ png_malloc(png_structp png_ptr, png_uint_32 size)
#endif #endif
#if defined(__TURBOC__) && !defined(__FLAT__) #if defined(__TURBOC__) && !defined(__FLAT__)
ret = farmalloc(size); ret = farmalloc((png_size_t)size);
#else #else
# if defined(_MSC_VER) && defined(MAXSEG_64K) # if defined(_MSC_VER) && defined(MAXSEG_64K)
ret = halloc(size, 1); ret = halloc(size, 1);
@ -286,29 +287,25 @@ png_malloc(png_structp png_ptr, png_uint_32 size)
return ret; return ret;
} }
/* free a pointer allocated by png_malloc(). In the default /* Free a pointer allocated by png_malloc(). In the default
configuration, png_ptr is not used, but is passed in case it configuration, png_ptr is not used, but is passed in case it
is needed. If ptr is NULL, return without taking any action. */ is needed. If ptr is NULL, return without taking any action. */
void void
png_free(png_structp png_ptr, png_voidp ptr) png_free(png_structp png_ptr, png_voidp ptr)
{ {
if (!png_ptr) if (png_ptr == NULL || ptr == NULL)
return; return;
if (ptr != NULL)
{
#if defined(__TURBOC__) && !defined(__FLAT__) #if defined(__TURBOC__) && !defined(__FLAT__)
farfree(ptr); farfree(ptr);
#else #else
# if defined(_MSC_VER) && defined(MAXSEG_64K) # if defined(_MSC_VER) && defined(MAXSEG_64K)
hfree(ptr); hfree(ptr);
# else # else
free(ptr); free(ptr);
# endif # endif
#endif #endif
}
} }
#endif /* FORTIFY */
#endif /* Not Borland DOS special memory handler */ #endif /* Not Borland DOS special memory handler */

View File

@ -1,10 +1,11 @@
/* pngpread.c - read a png file in push mode /* pngpread.c - read a png file in push mode
libpng 1.0 beta 4 - version 0.90 libpng 1.0 beta 6 - version 0.96
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 10, 1997 Copyright (c) 1996, 1997 Andreas Dilger
May 12, 1997
*/ */
#define PNG_INTERNAL #define PNG_INTERNAL
@ -14,7 +15,7 @@
void void
png_process_data(png_structp png_ptr, png_infop info_ptr, png_process_data(png_structp png_ptr, png_infop info_ptr,
png_bytep buffer, png_uint_32 buffer_size) png_bytep buffer, png_size_t buffer_size)
{ {
png_push_restore_buffer(png_ptr, buffer, buffer_size); png_push_restore_buffer(png_ptr, buffer, buffer_size);
@ -61,14 +62,9 @@ png_process_some_data(png_structp png_ptr, png_infop info_ptr)
break; break;
} }
#endif #endif
case PNG_READ_END_MODE:
{
png_push_read_chunk(png_ptr, info_ptr);
break;
}
case PNG_SKIP_MODE: case PNG_SKIP_MODE:
{ {
png_push_skip(png_ptr); png_push_crc_finish(png_ptr);
break; break;
} }
default: default:
@ -87,8 +83,8 @@ png_process_some_data(png_structp png_ptr, png_infop info_ptr)
void void
png_push_read_sig(png_structp png_ptr, png_infop info_ptr) png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
{ {
int num_checked = png_ptr->sig_bytes, png_size_t num_checked = png_ptr->sig_bytes,
num_to_check = 8 - num_checked; num_to_check = 8 - num_checked;
if (png_ptr->buffer_size < num_to_check) if (png_ptr->buffer_size < num_to_check)
{ {
@ -96,7 +92,7 @@ png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
} }
png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
(png_uint_32)num_to_check); num_to_check);
png_ptr->sig_bytes += num_to_check; png_ptr->sig_bytes += num_to_check;
if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
@ -137,8 +133,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
png_push_fill_buffer(png_ptr, chunk_length, 4); png_push_fill_buffer(png_ptr, chunk_length, 4);
png_ptr->push_length = png_get_uint_32(chunk_length); png_ptr->push_length = png_get_uint_32(chunk_length);
png_reset_crc(png_ptr); png_reset_crc(png_ptr);
png_push_fill_buffer(png_ptr, png_ptr->chunk_name, 4); png_crc_read(png_ptr, png_ptr->chunk_name, 4);
png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);
png_ptr->flags |= PNG_FLAG_HAVE_CHUNK_HEADER; png_ptr->flags |= PNG_FLAG_HAVE_CHUNK_HEADER;
} }
@ -292,6 +287,18 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
} }
#endif #endif
#if defined(PNG_READ_pCAL_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
{
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
{
png_push_save_buffer(png_ptr);
return;
}
png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#if defined(PNG_READ_tIME_SUPPORTED) #if defined(PNG_READ_tIME_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
{ {
@ -325,21 +332,21 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
} }
void void
png_push_crc_skip(png_structp png_ptr, png_uint_32 length) png_push_crc_skip(png_structp png_ptr, png_uint_32 skip)
{ {
png_ptr->process_mode = PNG_SKIP_MODE; png_ptr->process_mode = PNG_SKIP_MODE;
png_ptr->skip_length = length; png_ptr->skip_length = skip;
} }
void void
png_push_skip(png_structp png_ptr) png_push_crc_finish(png_structp png_ptr)
{ {
if (png_ptr->skip_length && png_ptr->save_buffer_size) if (png_ptr->skip_length && png_ptr->save_buffer_size)
{ {
png_uint_32 save_size; png_size_t save_size;
if (png_ptr->skip_length < png_ptr->save_buffer_size) if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size)
save_size = png_ptr->skip_length; save_size = (png_size_t)png_ptr->skip_length;
else else
save_size = png_ptr->save_buffer_size; save_size = png_ptr->save_buffer_size;
@ -348,14 +355,14 @@ png_push_skip(png_structp png_ptr)
png_ptr->skip_length -= save_size; png_ptr->skip_length -= save_size;
png_ptr->buffer_size -= save_size; png_ptr->buffer_size -= save_size;
png_ptr->save_buffer_size -= save_size; png_ptr->save_buffer_size -= save_size;
png_ptr->save_buffer_ptr += (png_size_t)save_size; png_ptr->save_buffer_ptr += save_size;
} }
if (png_ptr->skip_length && png_ptr->current_buffer_size) if (png_ptr->skip_length && png_ptr->current_buffer_size)
{ {
png_uint_32 save_size; png_size_t save_size;
if (png_ptr->skip_length < png_ptr->current_buffer_size) if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size)
save_size = png_ptr->skip_length; save_size = (png_size_t)png_ptr->skip_length;
else else
save_size = png_ptr->current_buffer_size; save_size = png_ptr->current_buffer_size;
@ -364,7 +371,7 @@ png_push_skip(png_structp png_ptr)
png_ptr->skip_length -= save_size; png_ptr->skip_length -= save_size;
png_ptr->buffer_size -= save_size; png_ptr->buffer_size -= save_size;
png_ptr->current_buffer_size -= save_size; png_ptr->current_buffer_size -= save_size;
png_ptr->current_buffer_ptr += (png_size_t)save_size; png_ptr->current_buffer_ptr += save_size;
} }
if (!png_ptr->skip_length) if (!png_ptr->skip_length)
{ {
@ -375,50 +382,45 @@ png_push_skip(png_structp png_ptr)
} }
png_crc_finish(png_ptr, 0); png_crc_finish(png_ptr, 0);
png_ptr->process_mode = PNG_READ_CHUNK_MODE;
if (png_ptr->mode & PNG_AFTER_IDAT)
png_ptr->process_mode = PNG_READ_END_MODE;
else
png_ptr->process_mode = PNG_READ_CHUNK_MODE;
} }
} }
void void
png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
png_uint_32 length)
{ {
png_bytep ptr; png_bytep ptr;
ptr = buffer; ptr = buffer;
if (png_ptr->save_buffer_size) if (png_ptr->save_buffer_size)
{ {
png_uint_32 save_size; png_size_t save_size;
if (length < png_ptr->save_buffer_size) if (length < png_ptr->save_buffer_size)
save_size = length; save_size = length;
else else
save_size = png_ptr->save_buffer_size; save_size = png_ptr->save_buffer_size;
png_memcpy(ptr, png_ptr->save_buffer_ptr, (png_size_t)save_size); png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
length -= save_size; length -= save_size;
ptr += (png_size_t)save_size; ptr += save_size;
png_ptr->buffer_size -= save_size; png_ptr->buffer_size -= save_size;
png_ptr->save_buffer_size -= save_size; png_ptr->save_buffer_size -= save_size;
png_ptr->save_buffer_ptr += (png_size_t)save_size; png_ptr->save_buffer_ptr += save_size;
} }
if (length && png_ptr->current_buffer_size) if (length && png_ptr->current_buffer_size)
{ {
png_uint_32 save_size; png_size_t save_size;
if (length < png_ptr->current_buffer_size) if (length < png_ptr->current_buffer_size)
save_size = length; save_size = length;
else else
save_size = png_ptr->current_buffer_size; save_size = png_ptr->current_buffer_size;
png_memcpy(ptr, png_ptr->current_buffer_ptr, (png_size_t)save_size); png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
png_ptr->buffer_size -= save_size; png_ptr->buffer_size -= save_size;
png_ptr->current_buffer_size -= save_size; png_ptr->current_buffer_size -= save_size;
png_ptr->current_buffer_ptr += (png_size_t)save_size; png_ptr->current_buffer_ptr += save_size;
} }
} }
@ -429,7 +431,7 @@ png_push_save_buffer(png_structp png_ptr)
{ {
if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
{ {
int i; png_size_t i;
png_bytep sp; png_bytep sp;
png_bytep dp; png_bytep dp;
@ -444,25 +446,20 @@ png_push_save_buffer(png_structp png_ptr)
if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
png_ptr->save_buffer_max) png_ptr->save_buffer_max)
{ {
png_uint_32 new_max; png_size_t new_max;
png_bytep old_buffer; png_bytep old_buffer;
new_max = (int)(png_ptr->save_buffer_size + new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
png_ptr->current_buffer_size + 256);
old_buffer = png_ptr->save_buffer; old_buffer = png_ptr->save_buffer;
png_ptr->save_buffer = (png_bytep) png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr, new_max);
png_malloc(png_ptr, new_max); png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
png_memcpy(png_ptr->save_buffer, old_buffer,
(png_size_t)png_ptr->save_buffer_size);
png_free(png_ptr, old_buffer); png_free(png_ptr, old_buffer);
png_ptr->save_buffer_max = new_max; png_ptr->save_buffer_max = new_max;
} }
if (png_ptr->current_buffer_size) if (png_ptr->current_buffer_size)
{ {
png_memcpy(png_ptr->save_buffer + png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
(png_size_t)png_ptr->save_buffer_size, png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
png_ptr->current_buffer_ptr,
(png_size_t)png_ptr->current_buffer_size);
png_ptr->save_buffer_size += png_ptr->current_buffer_size; png_ptr->save_buffer_size += png_ptr->current_buffer_size;
png_ptr->current_buffer_size = 0; png_ptr->current_buffer_size = 0;
} }
@ -472,7 +469,7 @@ png_push_save_buffer(png_structp png_ptr)
void void
png_push_restore_buffer(png_structp png_ptr, png_bytep buffer, png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,
png_uint_32 buffer_length) png_size_t buffer_length)
{ {
png_ptr->current_buffer = buffer; png_ptr->current_buffer = buffer;
png_ptr->current_buffer_size = buffer_length; png_ptr->current_buffer_size = buffer_length;
@ -497,13 +494,12 @@ png_push_read_IDAT(png_structp png_ptr)
png_ptr->push_length = png_get_uint_32(chunk_length); png_ptr->push_length = png_get_uint_32(chunk_length);
png_reset_crc(png_ptr); png_reset_crc(png_ptr);
png_push_fill_buffer(png_ptr, png_ptr->chunk_name, 4); png_crc_read(png_ptr, png_ptr->chunk_name, 4);
png_calculate_crc(png_ptr, chunk_length, 4);
png_ptr->flags |= PNG_FLAG_HAVE_CHUNK_HEADER; png_ptr->flags |= PNG_FLAG_HAVE_CHUNK_HEADER;
if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
{ {
png_ptr->process_mode = PNG_READ_END_MODE; png_ptr->process_mode = PNG_READ_CHUNK_MODE;
if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
png_error(png_ptr, "Not enough compressed data"); png_error(png_ptr, "Not enough compressed data");
return; return;
@ -513,9 +509,9 @@ png_push_read_IDAT(png_structp png_ptr)
} }
if (png_ptr->idat_size && png_ptr->save_buffer_size) if (png_ptr->idat_size && png_ptr->save_buffer_size)
{ {
png_uint_32 save_size; png_size_t save_size;
if (png_ptr->idat_size < png_ptr->save_buffer_size) if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size)
save_size = png_ptr->idat_size; save_size = png_ptr->idat_size;
else else
save_size = png_ptr->save_buffer_size; save_size = png_ptr->save_buffer_size;
@ -526,13 +522,13 @@ png_push_read_IDAT(png_structp png_ptr)
png_ptr->idat_size -= save_size; png_ptr->idat_size -= save_size;
png_ptr->buffer_size -= save_size; png_ptr->buffer_size -= save_size;
png_ptr->save_buffer_size -= save_size; png_ptr->save_buffer_size -= save_size;
png_ptr->save_buffer_ptr += (png_size_t)save_size; png_ptr->save_buffer_ptr += save_size;
} }
if (png_ptr->idat_size && png_ptr->current_buffer_size) if (png_ptr->idat_size && png_ptr->current_buffer_size)
{ {
png_uint_32 save_size; png_size_t save_size;
if (png_ptr->idat_size < png_ptr->current_buffer_size) if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size)
save_size = png_ptr->idat_size; save_size = png_ptr->idat_size;
else else
save_size = png_ptr->current_buffer_size; save_size = png_ptr->current_buffer_size;
@ -543,7 +539,7 @@ png_push_read_IDAT(png_structp png_ptr)
png_ptr->idat_size -= save_size; png_ptr->idat_size -= save_size;
png_ptr->buffer_size -= save_size; png_ptr->buffer_size -= save_size;
png_ptr->current_buffer_size -= save_size; png_ptr->current_buffer_size -= save_size;
png_ptr->current_buffer_ptr += (png_size_t)save_size; png_ptr->current_buffer_ptr += save_size;
} }
if (!png_ptr->idat_size) if (!png_ptr->idat_size)
{ {
@ -560,7 +556,7 @@ png_push_read_IDAT(png_structp png_ptr)
void void
png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
png_uint_32 buffer_length) png_size_t buffer_length)
{ {
int ret; int ret;
@ -569,22 +565,25 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
png_ptr->zstream.next_in = buffer; png_ptr->zstream.next_in = buffer;
png_ptr->zstream.avail_in = (uInt)buffer_length; png_ptr->zstream.avail_in = (uInt)buffer_length;
do while(1)
{ {
ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
if (ret == Z_STREAM_END) if (ret == Z_STREAM_END)
{ {
if (png_ptr->zstream.avail_in) if (png_ptr->zstream.avail_in)
png_error(png_ptr, "Extra compressed data"); png_error(png_ptr, "Extra compressed data");
if (!png_ptr->zstream.avail_out) if (!(png_ptr->zstream.avail_out))
{ {
png_push_process_row(png_ptr); png_push_process_row(png_ptr);
} }
png_ptr->mode = PNG_AFTER_IDAT;
png_ptr->mode |= PNG_AFTER_IDAT;
png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
break; break;
} }
if (ret != Z_OK) else if (ret == Z_BUF_ERROR)
break;
else if (ret != Z_OK)
png_error(png_ptr, "Decompression Error"); png_error(png_ptr, "Decompression Error");
if (!(png_ptr->zstream.avail_out)) if (!(png_ptr->zstream.avail_out))
{ {
@ -592,8 +591,9 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
png_ptr->zstream.next_out = png_ptr->row_buf; png_ptr->zstream.next_out = png_ptr->row_buf;
} }
else
} while (png_ptr->zstream.avail_in); break;
}
} }
void void
@ -611,19 +611,18 @@ png_push_process_row(png_structp png_ptr)
png_ptr->row_buf + 1, png_ptr->prev_row + 1, png_ptr->row_buf + 1, png_ptr->prev_row + 1,
(int)(png_ptr->row_buf[0])); (int)(png_ptr->row_buf[0]));
png_memcpy(png_ptr->prev_row, png_ptr->row_buf, (png_size_t)png_ptr->rowbytes + 1); png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1);
if (png_ptr->transformations) if (png_ptr->transformations)
png_do_read_transformations(png_ptr); png_do_read_transformations(png_ptr);
#if defined(PNG_READ_INTERLACING_SUPPORTED) #if defined(PNG_READ_INTERLACING_SUPPORTED)
/* blow up interlaced rows to full size */ /* blow up interlaced rows to full size */
if (png_ptr->interlaced && if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
(png_ptr->transformations & PNG_INTERLACE))
{ {
if (png_ptr->pass < 6) if (png_ptr->pass < 6)
png_do_read_interlace(&(png_ptr->row_info), png_do_read_interlace(&(png_ptr->row_info),
png_ptr->row_buf + 1, png_ptr->pass); png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
switch (png_ptr->pass) switch (png_ptr->pass)
{ {
@ -747,7 +746,7 @@ png_read_push_finish_row(png_structp png_ptr)
if (png_ptr->interlaced) if (png_ptr->interlaced)
{ {
png_ptr->row_number = 0; png_ptr->row_number = 0;
png_memset(png_ptr->prev_row, 0, (png_size_t)png_ptr->rowbytes + 1); png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
do do
{ {
png_ptr->pass++; png_ptr->pass++;
@ -781,8 +780,19 @@ png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length
if (png_ptr->mode == PNG_BEFORE_IHDR || png_ptr->mode & PNG_HAVE_IEND) if (png_ptr->mode == PNG_BEFORE_IHDR || png_ptr->mode & PNG_HAVE_IEND)
png_error(png_ptr, "Out of place tEXt"); png_error(png_ptr, "Out of place tEXt");
png_ptr->current_text = (png_charp)png_malloc(png_ptr, length + 1); #ifdef PNG_MAX_MALLOC_64K
png_ptr->current_text[(png_size_t)length] = '\0'; png_ptr->skip_length = 0; /* This may not be necessary */
if (length > 65535L) /* We can't hold the entire string in memory */
{
png_warning(png_ptr, "tEXt chunk too large to fit in memory");
png_ptr->skip_length = length - 65535L;
length = 65535L;
}
#endif
png_ptr->current_text = (png_charp)png_malloc(png_ptr, length+1);
png_ptr->current_text[length] = '\0';
png_ptr->current_text_ptr = png_ptr->current_text; png_ptr->current_text_ptr = png_ptr->current_text;
png_ptr->current_text_size = length; png_ptr->current_text_size = length;
png_ptr->current_text_left = length; png_ptr->current_text_left = length;
@ -794,21 +804,19 @@ png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr)
{ {
if (png_ptr->buffer_size && png_ptr->current_text_left) if (png_ptr->buffer_size && png_ptr->current_text_left)
{ {
png_uint_32 text_size; png_size_t text_size;
if (png_ptr->buffer_size < png_ptr->current_text_left) if (png_ptr->buffer_size < png_ptr->current_text_left)
text_size = png_ptr->buffer_size; text_size = png_ptr->buffer_size;
else else
text_size = png_ptr->current_text_left; text_size = png_ptr->current_text_left;
png_push_fill_buffer(png_ptr, (png_bytep)png_ptr->current_text_ptr, png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
text_size);
png_calculate_crc(png_ptr, (png_bytep)png_ptr->current_text_ptr,
text_size);
png_ptr->current_text_left -= text_size; png_ptr->current_text_left -= text_size;
png_ptr->current_text_ptr += (png_size_t)text_size; png_ptr->current_text_ptr += text_size;
} }
if (!(png_ptr->current_text_left)) if (!(png_ptr->current_text_left))
{ {
png_textp text_ptr;
png_charp text; png_charp text;
png_charp key; png_charp key;
@ -818,7 +826,12 @@ png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr)
return; return;
} }
png_crc_finish(png_ptr, 0); png_push_crc_finish(png_ptr);
#if defined(PNG_MAX_MALLOC_64K)
if (png_ptr->skip_length)
return;
#endif
key = png_ptr->current_text; key = png_ptr->current_text;
png_ptr->current_text = 0; png_ptr->current_text = 0;
@ -826,20 +839,17 @@ png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr)
for (text = key; *text; text++) for (text = key; *text; text++)
/* empty loop */ ; /* empty loop */ ;
if (text != key + (png_size_t)png_ptr->current_text_size) if (text != key + png_ptr->current_text_size)
text++; text++;
png_read_tEXt(png_ptr, info_ptr, key, text, text_ptr = (png_textp)png_malloc(png_ptr, sizeof(png_text));
png_ptr->current_text_size - (text - key)); text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
text_ptr->key = key;
text_ptr->text = text;
if (png_ptr->mode == PNG_AFTER_IDAT) png_set_text(png_ptr, info_ptr, text_ptr, 1);
{
png_ptr->process_mode = PNG_READ_END_MODE; png_free(png_ptr, text_ptr);
}
else
{
png_ptr->process_mode = PNG_READ_CHUNK_MODE;
}
} }
} }
#endif #endif
@ -851,8 +861,21 @@ png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length
if (png_ptr->mode == PNG_BEFORE_IHDR || png_ptr->mode & PNG_HAVE_IEND) if (png_ptr->mode == PNG_BEFORE_IHDR || png_ptr->mode & PNG_HAVE_IEND)
png_error(png_ptr, "Out of place zTXt"); png_error(png_ptr, "Out of place zTXt");
png_ptr->current_text = (png_charp)png_malloc(png_ptr, length + 1); #ifdef PNG_MAX_MALLOC_64K
png_ptr->current_text[(png_size_t)length] = '\0'; /* We can't handle zTXt chunks > 64K, since we don't have enough space
* to be able to store the uncompressed data. Actually, the threshold
* is probably around 32K, but it isn't as definite as 64K is.
*/
if (length > 65535L)
{
png_warning(png_ptr, "zTXt chunk too large to fit in memory");
png_push_crc_skip(png_ptr, length);
return;
}
#endif
png_ptr->current_text = (png_charp)png_malloc(png_ptr, length+1);
png_ptr->current_text[length] = '\0';
png_ptr->current_text_ptr = png_ptr->current_text; png_ptr->current_text_ptr = png_ptr->current_text;
png_ptr->current_text_size = length; png_ptr->current_text_size = length;
png_ptr->current_text_left = length; png_ptr->current_text_left = length;
@ -864,25 +887,23 @@ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
{ {
if (png_ptr->buffer_size && png_ptr->current_text_left) if (png_ptr->buffer_size && png_ptr->current_text_left)
{ {
png_uint_32 text_size; png_size_t text_size;
if (png_ptr->buffer_size < png_ptr->current_text_left) if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left)
text_size = png_ptr->buffer_size; text_size = png_ptr->buffer_size;
else else
text_size = png_ptr->current_text_left; text_size = png_ptr->current_text_left;
png_push_fill_buffer(png_ptr, (png_bytep)png_ptr->current_text_ptr, png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
text_size);
png_calculate_crc(png_ptr, (png_bytep)png_ptr->current_text_ptr,
text_size);
png_ptr->current_text_left -= text_size; png_ptr->current_text_left -= text_size;
png_ptr->current_text_ptr += (png_size_t)text_size; png_ptr->current_text_ptr += text_size;
} }
if (!(png_ptr->current_text_left)) if (!(png_ptr->current_text_left))
{ {
png_textp text_ptr;
png_charp text; png_charp text;
png_charp key; png_charp key;
int ret; int ret;
png_uint_32 text_size, key_size; png_size_t text_size, key_size;
if (png_ptr->buffer_size < 4) if (png_ptr->buffer_size < 4)
{ {
@ -890,7 +911,7 @@ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
return; return;
} }
png_crc_finish(png_ptr, 0); png_push_crc_finish(png_ptr);
key = png_ptr->current_text; key = png_ptr->current_text;
png_ptr->current_text = 0; png_ptr->current_text = 0;
@ -899,7 +920,7 @@ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
/* empty loop */ ; /* empty loop */ ;
/* zTXt can't have zero text */ /* zTXt can't have zero text */
if (text == key + (png_size_t)png_ptr->current_text_size) if (text == key + png_ptr->current_text_size)
{ {
png_free(png_ptr, key); png_free(png_ptr, key);
return; return;
@ -907,7 +928,7 @@ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
text++; text++;
if (*text) /* check compression byte */ if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */
{ {
png_free(png_ptr, key); png_free(png_ptr, key);
return; return;
@ -919,7 +940,7 @@ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size -
(text - key)); (text - key));
png_ptr->zstream.next_out = png_ptr->zbuf; png_ptr->zstream.next_out = png_ptr->zbuf;
png_ptr->zstream.avail_out = (png_size_t)png_ptr->zbuf_size; png_ptr->zstream.avail_out = png_ptr->zbuf_size;
key_size = text - key; key_size = text - key;
text_size = 0; text_size = 0;
@ -937,19 +958,19 @@ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
png_free(png_ptr, text); png_free(png_ptr, text);
return; return;
} }
if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END) if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END)
{ {
if (!text) if (text == NULL)
{ {
text = (png_charp)png_malloc(png_ptr, text = (png_charp)png_malloc(png_ptr,
png_ptr->zbuf_size - png_ptr->zstream.avail_out + png_ptr->zbuf_size - png_ptr->zstream.avail_out +
key_size + 1); key_size + 1);
png_memcpy(text + (png_size_t)key_size, png_ptr->zbuf, png_memcpy(text + key_size, png_ptr->zbuf,
(png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out)); png_ptr->zbuf_size - png_ptr->zstream.avail_out);
png_memcpy(text, key, (png_size_t)key_size); png_memcpy(text, key, key_size);
text_size = key_size + (png_size_t)png_ptr->zbuf_size - text_size = key_size + png_ptr->zbuf_size -
png_ptr->zstream.avail_out; png_ptr->zstream.avail_out;
*(text + (png_size_t)text_size) = '\0'; *(text + text_size) = '\0';
} }
else else
{ {
@ -958,12 +979,12 @@ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
tmp = text; tmp = text;
text = png_malloc(png_ptr, text_size + text = png_malloc(png_ptr, text_size +
png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1); png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1);
png_memcpy(text, tmp, (png_size_t)text_size); png_memcpy(text, tmp, text_size);
png_free(png_ptr, tmp); png_free(png_ptr, tmp);
png_memcpy(text + (png_size_t)text_size, png_ptr->zbuf, png_memcpy(text + text_size, png_ptr->zbuf,
(png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out)); png_ptr->zbuf_size - png_ptr->zstream.avail_out);
text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
*(text + (png_size_t)text_size) = '\0'; *(text + text_size) = '\0';
} }
if (ret != Z_STREAM_END) if (ret != Z_STREAM_END)
{ {
@ -992,18 +1013,17 @@ png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
png_free(png_ptr, key); png_free(png_ptr, key);
key = text; key = text;
text += (png_size_t)key_size; text += key_size;
text_size -= key_size; text_size -= key_size;
png_read_zTXt(png_ptr, info_ptr, key, text, text_size, 0); text_ptr = (png_textp)png_malloc(png_ptr, sizeof(png_text));
if (png_ptr->mode == PNG_AFTER_IDAT) text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt;
{ text_ptr->key = key;
png_ptr->process_mode = PNG_READ_END_MODE; text_ptr->text = text;
}
else png_set_text(png_ptr, info_ptr, text_ptr, 1);
{
png_ptr->process_mode = PNG_READ_CHUNK_MODE; png_free(png_ptr, text_ptr);
}
} }
} }
#endif #endif
@ -1033,21 +1053,21 @@ png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 len
void void
png_push_have_info(png_structp png_ptr, png_infop info_ptr) png_push_have_info(png_structp png_ptr, png_infop info_ptr)
{ {
if (png_ptr->info_fn) if (png_ptr->info_fn != NULL)
(*(png_ptr->info_fn))(png_ptr, info_ptr); (*(png_ptr->info_fn))(png_ptr, info_ptr);
} }
void void
png_push_have_end(png_structp png_ptr, png_infop info_ptr) png_push_have_end(png_structp png_ptr, png_infop info_ptr)
{ {
if (png_ptr->end_fn) if (png_ptr->end_fn != NULL)
(*(png_ptr->end_fn))(png_ptr, info_ptr); (*(png_ptr->end_fn))(png_ptr, info_ptr);
} }
void void
png_push_have_row(png_structp png_ptr, png_bytep row) png_push_have_row(png_structp png_ptr, png_bytep row)
{ {
if (png_ptr->row_fn) if (png_ptr->row_fn != NULL)
(*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
(int)png_ptr->pass); (int)png_ptr->pass);
} }
@ -1056,7 +1076,7 @@ void
png_progressive_combine_row (png_structp png_ptr, png_progressive_combine_row (png_structp png_ptr,
png_bytep old_row, png_bytep new_row) png_bytep old_row, png_bytep new_row)
{ {
if (new_row) if (new_row != NULL)
png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]); png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]);
} }

243
pngrcb.c
View File

@ -1,243 +0,0 @@
/* pngrcb.c - callbacks while reading a png file
libpng 1.0 beta 4 - version 0.90
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 10, 1997
*/
#define PNG_INTERNAL
#include "png.h"
void
png_read_IHDR(png_structp png_ptr, png_infop info,
png_uint_32 width, png_uint_32 height, int bit_depth,
int color_type, int compression_type, int filter_type,
int interlace_type)
{
if (!info)
return;
info->width = width;
info->height = height;
info->bit_depth = (png_byte)bit_depth;
info->color_type =(png_byte) color_type;
info->compression_type = (png_byte)compression_type;
info->filter_type = (png_byte)filter_type;
info->interlace_type = (png_byte)interlace_type;
if (info->color_type == PNG_COLOR_TYPE_PALETTE)
info->channels = 1;
else if (info->color_type & PNG_COLOR_MASK_COLOR)
info->channels = 3;
else
info->channels = 1;
if (info->color_type & PNG_COLOR_MASK_ALPHA)
info->channels++;
info->pixel_depth = (png_byte)(info->channels * info->bit_depth);
info->rowbytes = ((info->width * info->pixel_depth + 7) >> 3);
}
void
png_read_PLTE(png_structp png_ptr, png_infop info,
png_colorp palette, int num)
{
if (!info)
return;
info->palette = palette;
info->num_palette = (png_uint_16)num;
info->valid |= PNG_INFO_PLTE;
}
#if defined(PNG_READ_gAMA_SUPPORTED)
void
png_read_gAMA(png_structp png_ptr, png_infop info, double gamma)
{
if (!info)
return;
info->gamma = (float)gamma;
info->valid |= PNG_INFO_gAMA;
}
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
void
png_read_sBIT(png_structp png_ptr, png_infop info,
png_color_8p sig_bit)
{
if (!info)
return;
png_memcpy(&(info->sig_bit), sig_bit, sizeof (png_color_8));
info->valid |= PNG_INFO_sBIT;
}
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
void
png_read_cHRM(png_structp png_ptr, png_infop info,
double white_x, double white_y, double red_x, double red_y,
double green_x, double green_y, double blue_x, double blue_y)
{
if (!info)
return;
info->x_white = (float)white_x;
info->y_white = (float)white_y;
info->x_red = (float)red_x;
info->y_red = (float)red_y;
info->x_green = (float)green_x;
info->y_green = (float)green_y;
info->x_blue = (float)blue_x;
info->y_blue = (float)blue_y;
info->valid |= PNG_INFO_cHRM;
}
#endif
#if defined(PNG_READ_tRNS_SUPPORTED)
void
png_read_tRNS(png_structp png_ptr, png_infop info,
png_bytep trans, int num_trans, png_color_16p trans_values)
{
if (!info)
return;
if (trans)
{
info->trans = trans;
}
else
{
png_memcpy(&(info->trans_values), trans_values,
sizeof(png_color_16));
}
info->num_trans = (png_uint_16)num_trans;
info->valid |= PNG_INFO_tRNS;
}
#endif
#if defined(PNG_READ_bKGD_SUPPORTED)
void
png_read_bKGD(png_structp png_ptr, png_infop info,
png_color_16p background)
{
if (!info)
return;
png_memcpy(&(info->background), background, sizeof(png_color_16));
info->valid |= PNG_INFO_bKGD;
}
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
void
png_read_hIST(png_structp png_ptr, png_infop info, png_uint_16p hist)
{
if (!info)
return;
info->hist = hist;
info->valid |= PNG_INFO_hIST;
}
#endif
#if defined(PNG_READ_pHYs_SUPPORTED)
void
png_read_pHYs(png_structp png_ptr, png_infop info,
png_uint_32 res_x, png_uint_32 res_y, int unit_type)
{
if (!info)
return;
info->x_pixels_per_unit = res_x;
info->y_pixels_per_unit = res_y;
info->phys_unit_type = (png_byte)unit_type;
info->valid |= PNG_INFO_pHYs;
}
#endif
#if defined(PNG_READ_oFFs_SUPPORTED)
void
png_read_oFFs(png_structp png_ptr, png_infop info,
png_uint_32 offset_x, png_uint_32 offset_y, int unit_type)
{
if (!info)
return;
info->x_offset = offset_x;
info->y_offset = offset_y;
info->offset_unit_type = (png_byte)unit_type;
info->valid |= PNG_INFO_oFFs;
}
#endif
#if defined(PNG_READ_tIME_SUPPORTED)
void
png_read_tIME(png_structp png_ptr, png_infop info,
png_timep mod_time)
{
if (!info)
return;
png_memcpy(&(info->mod_time), mod_time, sizeof (png_time));
info->valid |= PNG_INFO_tIME;
}
#endif
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
void
png_read_zTXt(png_structp png_ptr, png_infop info,
png_charp key, png_charp text, png_uint_32 text_len, int compression)
{
if (!info)
return;
if (info->max_text <= info->num_text)
{
if (info->text)
{
png_uint_32 old_max;
old_max = info->max_text;
info->max_text = info->num_text + 16;
{
png_textp old_text;
old_text = info->text;
info->text = (png_textp)png_malloc(png_ptr,
info->max_text * sizeof (png_text));
png_memcpy(info->text, old_text,
(png_size_t)(old_max * sizeof (png_text)));
png_free(png_ptr, old_text);
}
}
else
{
info->max_text = 16;
info->num_text = 0;
info->text = (png_textp)png_malloc(png_ptr,
info->max_text * sizeof (png_text));
}
}
info->text[info->num_text].key = key;
info->text[info->num_text].text = text;
info->text[info->num_text].text_length = text_len;
info->text[info->num_text].compression = compression;
info->num_text++;
}
#endif
#if defined(PNG_READ_tEXt_SUPPORTED)
void
png_read_tEXt(png_structp png_ptr, png_infop info,
png_charp key, png_charp text, png_uint_32 text_len)
{
if (!info)
return;
png_read_zTXt(png_ptr, info, key, text, text_len, -1);
}
#endif

307
pngread.c
View File

@ -1,24 +1,26 @@
/* pngread.c - read a png file /* pngread.c - read a PNG file
libpng 1.0 beta 4 - version 0.90 libpng 1.0 beta 6 - version 0.96
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 10, 1997 Copyright (c) 1996, 1997 Andreas Dilger
May 12, 1997
*/ */
#define PNG_INTERNAL #define PNG_INTERNAL
#include "png.h" #include "png.h"
/* Create a png structure for reading, and allocate any memory needed. */ /* Create a PNG structure for reading, and allocate any memory needed. */
png_structp png_structp
png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr, png_create_read_struct(png_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn) png_error_ptr error_fn, png_error_ptr warn_fn)
{ {
png_structp png_ptr; png_structp png_ptr;
#ifdef USE_FAR_KEYWORD #ifdef USE_FAR_KEYWORD
jmp_buf jmpbuf; jmp_buf jmpbuf;
#endif #endif
png_debug(1, "in png_create_read_struct\n");
if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL) if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
{ {
return (png_structp)NULL; return (png_structp)NULL;
@ -38,17 +40,16 @@ png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr,
#endif #endif
png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
/* This is what will be used for the final version. For the /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
(ongoing) development library, we know that ALL of the * we must recompile any applications that use any older library version.
older library versions are out of date because of the * For versions after libpng 1.0, we will be compatible, so we need
change in the info_struct size. */ * only check the first digit.
/* */
if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0]) if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
*/ (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
if (user_png_ver == NULL || atof(user_png_ver) < atof(png_libpng_ver))
{ {
png_error(png_ptr, png_error(png_ptr,
"Incompatible libpng version in application and library"); "Incompatible libpng version in application and library");
} }
/* initialize zbuf - compression buffer */ /* initialize zbuf - compression buffer */
@ -76,7 +77,7 @@ png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr,
} }
/* Initialize png structure for reading, and allocate any memory needed. /* Initialize PNG structure for reading, and allocate any memory needed.
This interface is depreciated in favour of the png_create_read_struct(), This interface is depreciated in favour of the png_create_read_struct(),
and it will eventually disappear. */ and it will eventually disappear. */
void void
@ -84,6 +85,7 @@ png_read_init(png_structp png_ptr)
{ {
jmp_buf tmp_jmp; /* to save current jump buffer */ jmp_buf tmp_jmp; /* to save current jump buffer */
png_debug(1, "in png_read_init\n");
/* save jump buffer and error functions */ /* save jump buffer and error functions */
png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf)); png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
@ -126,14 +128,15 @@ png_read_init(png_structp png_ptr)
void void
png_read_info(png_structp png_ptr, png_infop info_ptr) png_read_info(png_structp png_ptr, png_infop info_ptr)
{ {
png_debug(1, "in png_read_info\n");
/* save jump buffer and error functions */
/* If we haven't checked all of the PNG signature bytes, do so now. */ /* If we haven't checked all of the PNG signature bytes, do so now. */
if (png_ptr->sig_bytes < 8) if (png_ptr->sig_bytes < 8)
{ {
int num_checked = png_ptr->sig_bytes, png_size_t num_checked = png_ptr->sig_bytes,
num_to_check = 8 - num_checked; num_to_check = 8 - num_checked;
png_read_data(png_ptr, &(info_ptr->signature[num_checked]), png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check);
(png_uint_32)num_to_check);
png_ptr->sig_bytes = 8; png_ptr->sig_bytes = 8;
if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
@ -157,56 +160,17 @@ png_read_info(png_structp png_ptr, png_infop info_ptr)
png_reset_crc(png_ptr); png_reset_crc(png_ptr);
png_crc_read(png_ptr, png_ptr->chunk_name, 4); png_crc_read(png_ptr, png_ptr->chunk_name, 4);
png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name);
/* This should be a binary subdivision search or a hash for
* matching the chunk name rather than a linear search.
*/
if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
png_handle_IHDR(png_ptr, info_ptr, length); png_handle_IHDR(png_ptr, info_ptr, length);
else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
png_handle_PLTE(png_ptr, info_ptr, length); png_handle_PLTE(png_ptr, info_ptr, length);
else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
png_handle_IEND(png_ptr, info_ptr, length); png_handle_IEND(png_ptr, info_ptr, length);
#if defined(PNG_READ_gAMA_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
png_handle_gAMA(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
png_handle_sBIT(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
png_handle_cHRM(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_tRNS_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
png_handle_tRNS(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_bKGD_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
png_handle_bKGD(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
png_handle_hIST(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_pHYs_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
png_handle_pHYs(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_oFFs_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
png_handle_oFFs(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_tIME_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
png_handle_tIME(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_tEXt_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
png_handle_tEXt(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_zTXt_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
png_handle_zTXt(png_ptr, info_ptr, length);
#endif
else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
{ {
if (!(png_ptr->mode & PNG_HAVE_IHDR)) if (!(png_ptr->mode & PNG_HAVE_IHDR))
@ -219,6 +183,54 @@ png_read_info(png_structp png_ptr, png_infop info_ptr)
png_ptr->mode |= PNG_HAVE_IDAT; png_ptr->mode |= PNG_HAVE_IDAT;
break; break;
} }
#if defined(PNG_READ_bKGD_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
png_handle_bKGD(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
png_handle_cHRM(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_gAMA_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
png_handle_gAMA(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
png_handle_hIST(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_oFFs_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
png_handle_oFFs(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_pCAL_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
png_handle_pCAL(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_pHYs_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
png_handle_pHYs(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
png_handle_sBIT(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_tEXt_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
png_handle_tEXt(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_tIME_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
png_handle_tIME(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_tRNS_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
png_handle_tRNS(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_zTXt_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
png_handle_zTXt(png_ptr, info_ptr, length);
#endif
else else
png_handle_unknown(png_ptr, info_ptr, length); png_handle_unknown(png_ptr, info_ptr, length);
} }
@ -228,6 +240,8 @@ png_read_info(png_structp png_ptr, png_infop info_ptr)
void void
png_read_update_info(png_structp png_ptr, png_infop info_ptr) png_read_update_info(png_structp png_ptr, png_infop info_ptr)
{ {
png_debug(1, "in png_read_update_info\n");
/* save jump buffer and error functions */
if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
png_read_start_row(png_ptr); png_read_start_row(png_ptr);
png_read_transform_info(png_ptr, info_ptr); png_read_transform_info(png_ptr, info_ptr);
@ -240,6 +254,8 @@ png_read_update_info(png_structp png_ptr, png_infop info_ptr)
void void
png_start_read_image(png_structp png_ptr) png_start_read_image(png_structp png_ptr)
{ {
png_debug(1, "in png_start_read_image\n");
/* save jump buffer and error functions */
if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
png_read_start_row(png_ptr); png_read_start_row(png_ptr);
} }
@ -248,6 +264,9 @@ void
png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
{ {
int ret; int ret;
png_debug2(1, "in png_read_row (row %d, pass %d)\n",
png_ptr->row_number, png_ptr->pass);
/* save jump buffer and error functions */
if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
png_read_start_row(png_ptr); png_read_start_row(png_ptr);
@ -260,7 +279,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
case 0: case 0:
if (png_ptr->row_number & 7) if (png_ptr->row_number & 7)
{ {
if (dsp_row) if (dsp_row != NULL)
png_combine_row(png_ptr, dsp_row, png_combine_row(png_ptr, dsp_row,
png_pass_dsp_mask[png_ptr->pass]); png_pass_dsp_mask[png_ptr->pass]);
png_read_finish_row(png_ptr); png_read_finish_row(png_ptr);
@ -270,7 +289,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
case 1: case 1:
if ((png_ptr->row_number & 7) || png_ptr->width < 5) if ((png_ptr->row_number & 7) || png_ptr->width < 5)
{ {
if (dsp_row) if (dsp_row != NULL)
png_combine_row(png_ptr, dsp_row, png_combine_row(png_ptr, dsp_row,
png_pass_dsp_mask[png_ptr->pass]); png_pass_dsp_mask[png_ptr->pass]);
png_read_finish_row(png_ptr); png_read_finish_row(png_ptr);
@ -280,7 +299,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
case 2: case 2:
if ((png_ptr->row_number & 7) != 4) if ((png_ptr->row_number & 7) != 4)
{ {
if (dsp_row && (png_ptr->row_number & 4)) if (dsp_row != NULL && (png_ptr->row_number & 4))
png_combine_row(png_ptr, dsp_row, png_combine_row(png_ptr, dsp_row,
png_pass_dsp_mask[png_ptr->pass]); png_pass_dsp_mask[png_ptr->pass]);
png_read_finish_row(png_ptr); png_read_finish_row(png_ptr);
@ -290,7 +309,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
case 3: case 3:
if ((png_ptr->row_number & 3) || png_ptr->width < 3) if ((png_ptr->row_number & 3) || png_ptr->width < 3)
{ {
if (dsp_row) if (dsp_row != NULL)
png_combine_row(png_ptr, dsp_row, png_combine_row(png_ptr, dsp_row,
png_pass_dsp_mask[png_ptr->pass]); png_pass_dsp_mask[png_ptr->pass]);
png_read_finish_row(png_ptr); png_read_finish_row(png_ptr);
@ -300,7 +319,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
case 4: case 4:
if ((png_ptr->row_number & 3) != 2) if ((png_ptr->row_number & 3) != 2)
{ {
if (dsp_row && (png_ptr->row_number & 2)) if (dsp_row != NULL && (png_ptr->row_number & 2))
png_combine_row(png_ptr, dsp_row, png_combine_row(png_ptr, dsp_row,
png_pass_dsp_mask[png_ptr->pass]); png_pass_dsp_mask[png_ptr->pass]);
png_read_finish_row(png_ptr); png_read_finish_row(png_ptr);
@ -310,7 +329,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
case 5: case 5:
if ((png_ptr->row_number & 1) || png_ptr->width < 2) if ((png_ptr->row_number & 1) || png_ptr->width < 2)
{ {
if (dsp_row) if (dsp_row != NULL)
png_combine_row(png_ptr, dsp_row, png_combine_row(png_ptr, dsp_row,
png_pass_dsp_mask[png_ptr->pass]); png_pass_dsp_mask[png_ptr->pass]);
png_read_finish_row(png_ptr); png_read_finish_row(png_ptr);
@ -355,7 +374,8 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
png_ptr->zstream.next_in = png_ptr->zbuf; png_ptr->zstream.next_in = png_ptr->zbuf;
if (png_ptr->zbuf_size > png_ptr->idat_size) if (png_ptr->zbuf_size > png_ptr->idat_size)
png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in); png_crc_read(png_ptr, png_ptr->zbuf,
(png_size_t)png_ptr->zstream.avail_in);
png_ptr->idat_size -= png_ptr->zstream.avail_in; png_ptr->idat_size -= png_ptr->zstream.avail_in;
} }
ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
@ -386,7 +406,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
png_ptr->row_buf + 1, png_ptr->prev_row + 1, png_ptr->row_buf + 1, png_ptr->prev_row + 1,
(int)(png_ptr->row_buf[0])); (int)(png_ptr->row_buf[0]));
png_memcpy(png_ptr->prev_row, png_ptr->row_buf, (png_size_t)png_ptr->rowbytes + 1); png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1);
if (png_ptr->transformations) if (png_ptr->transformations)
png_do_read_transformations(png_ptr); png_do_read_transformations(png_ptr);
@ -398,41 +418,41 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
{ {
if (png_ptr->pass < 6) if (png_ptr->pass < 6)
png_do_read_interlace(&(png_ptr->row_info), png_do_read_interlace(&(png_ptr->row_info),
png_ptr->row_buf + 1, png_ptr->pass); png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
if (dsp_row) if (dsp_row != NULL)
png_combine_row(png_ptr, dsp_row, png_combine_row(png_ptr, dsp_row,
png_pass_dsp_mask[png_ptr->pass]); png_pass_dsp_mask[png_ptr->pass]);
if (row) if (row != NULL)
png_combine_row(png_ptr, row, png_combine_row(png_ptr, row,
png_pass_mask[png_ptr->pass]); png_pass_mask[png_ptr->pass]);
} }
else else
#endif #endif
{ {
if (row) if (row != NULL)
png_combine_row(png_ptr, row, 0xff); png_combine_row(png_ptr, row, 0xff);
if (dsp_row) if (dsp_row != NULL)
png_combine_row(png_ptr, dsp_row, 0xff); png_combine_row(png_ptr, dsp_row, 0xff);
} }
png_read_finish_row(png_ptr); png_read_finish_row(png_ptr);
} }
/* read a one or more rows of image data. If the image is interlaced, /* Read one or more rows of image data. If the image is interlaced,
and png_set_interlace_handling() has been called, the rows need to and png_set_interlace_handling() has been called, the rows need to
to contain the contents of the rows from the previous pass. If to contain the contents of the rows from the previous pass. If
the image has alpha or transparency, and png_handle_alpha() has been the image has alpha or transparency, and png_handle_alpha() has been
called, the rows contents must be initialized to the contents of the called, the rows contents must be initialized to the contents of the
screen. row holds the actual image, and pixels are placed in it screen. "row" holds the actual image, and pixels are placed in it
as they arrive. If the image is displayed after each pass, it will as they arrive. If the image is displayed after each pass, it will
appear to "sparkle" in. display_row can be used to display a appear to "sparkle" in. "display_row" can be used to display a
"chunky" progressive image, with finer detail added as it becomes "chunky" progressive image, with finer detail added as it becomes
available. If you do not want this "chunky" display, you may pass available. If you do not want this "chunky" display, you may pass
NULL for display_rows. If you do not want the sparkle display, and NULL for display_row. If you do not want the sparkle display, and
you have not called png_handle_alpha(), you may pass NULL for rows. you have not called png_handle_alpha(), you may pass NULL for rows.
If you have called png_handle_alpha(), and the image has either an If you have called png_handle_alpha(), and the image has either an
alpha channel or a transparency chunk, you must provide a buffer for alpha channel or a transparency chunk, you must provide a buffer for
rows. In this case, you do not have to provide a display_rows buffer rows. In this case, you do not have to provide a display_row buffer
also, but you may. If the image is not interlaced, or if you have also, but you may. If the image is not interlaced, or if you have
not called png_set_interlace_handling(), the display_row buffer will not called png_set_interlace_handling(), the display_row buffer will
be ignored, so pass NULL to it. */ be ignored, so pass NULL to it. */
@ -445,6 +465,8 @@ png_read_rows(png_structp png_ptr, png_bytepp row,
png_bytepp rp; png_bytepp rp;
png_bytepp dp; png_bytepp dp;
png_debug(1, "in png_read_rows\n");
/* save jump buffer and error functions */
rp = row; rp = row;
dp = display_row; dp = display_row;
for (i = 0; i < num_rows; i++) for (i = 0; i < num_rows; i++)
@ -452,30 +474,30 @@ png_read_rows(png_structp png_ptr, png_bytepp row,
png_bytep rptr; png_bytep rptr;
png_bytep dptr; png_bytep dptr;
if (rp) if (rp != NULL)
rptr = *rp; rptr = *rp;
else else
rptr = NULL; rptr = NULL;
if (dp) if (dp != NULL)
dptr = *dp; dptr = *dp;
else else
dptr = NULL; dptr = NULL;
png_read_row(png_ptr, rptr, dptr); png_read_row(png_ptr, rptr, dptr);
if (row) if (row != NULL)
rp++; rp++;
if (display_row) if (display_row != NULL)
dp++; dp++;
} }
} }
/* read the image. If the image has an alpha channel or a transparency /* Read the entire image. If the image has an alpha channel or a tRNS
chunk, and you have called png_handle_alpha(), you will need to chunk, and you have called png_handle_alpha(), you will need to
initialize the image to the current image that png will be overlaying. initialize the image to the current image that PNG will be overlaying.
We set the num_rows again here, in case it was incorrectly set in We set the num_rows again here, in case it was incorrectly set in
png_read_start_row() by a call to png_read_update_info() or png_read_start_row() by a call to png_read_update_info() or
png_start_read_image() if png_set_interlace_handling() wasn't called png_start_read_image() if png_set_interlace_handling() wasn't called
prior to either of these functions like it should have been. You only prior to either of these functions like it should have been. You can
need to call this function once. If you desire to have an image for only call this function once. If you desire to have an image for
each pass of a interlaced image, use png_read_rows() instead */ each pass of a interlaced image, use png_read_rows() instead */
void void
png_read_image(png_structp png_ptr, png_bytepp image) png_read_image(png_structp png_ptr, png_bytepp image)
@ -484,6 +506,8 @@ png_read_image(png_structp png_ptr, png_bytepp image)
int pass, j; int pass, j;
png_bytepp rp; png_bytepp rp;
png_debug(1, "in png_read_image\n");
/* save jump buffer and error functions */
pass = png_set_interlace_handling(png_ptr); pass = png_set_interlace_handling(png_ptr);
png_ptr->num_rows = png_ptr->height; /* Make sure this is set correctly */ png_ptr->num_rows = png_ptr->height; /* Make sure this is set correctly */
@ -499,7 +523,7 @@ png_read_image(png_structp png_ptr, png_bytepp image)
} }
} }
/* read the end of the png file. Will not read past the end of the /* Read the end of the PNG file. Will not read past the end of the
file, will verify the end is accurate, and will read any comments file, will verify the end is accurate, and will read any comments
or time information at the end of the file, if info is not NULL. */ or time information at the end of the file, if info is not NULL. */
void void
@ -508,7 +532,9 @@ png_read_end(png_structp png_ptr, png_infop info_ptr)
png_byte chunk_length[4]; png_byte chunk_length[4];
png_uint_32 length; png_uint_32 length;
png_crc_finish(png_ptr, 0); png_debug(1, "in png_read_end\n");
/* save jump buffer and error functions */
png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */
do do
{ {
@ -518,45 +544,72 @@ png_read_end(png_structp png_ptr, png_infop info_ptr)
png_reset_crc(png_ptr); png_reset_crc(png_ptr);
png_crc_read(png_ptr, png_ptr->chunk_name, 4); png_crc_read(png_ptr, png_ptr->chunk_name, 4);
png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name);
if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
png_handle_IHDR(png_ptr, info_ptr, length); png_handle_IHDR(png_ptr, info_ptr, length);
else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
png_handle_PLTE(png_ptr, info_ptr, length);
else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
png_handle_gAMA(png_ptr, info_ptr, length);
else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
png_handle_sBIT(png_ptr, info_ptr, length);
else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
png_handle_cHRM(png_ptr, info_ptr, length);
else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
png_handle_tRNS(png_ptr, info_ptr, length);
else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
png_handle_bKGD(png_ptr, info_ptr, length);
else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
png_handle_hIST(png_ptr, info_ptr, length);
else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
png_handle_pHYs(png_ptr, info_ptr, length);
else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
png_handle_oFFs(png_ptr, info_ptr, length);
else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
{ {
/* Zero length IDATs are legal after the last IDAT has been
* read, but not after other chunks have been read.
*/
if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT) if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT)
png_error(png_ptr, "Too many IDAT's found"); png_error(png_ptr, "Too many IDAT's found");
else
png_crc_finish(png_ptr, 0);
} }
#if defined(PNG_READ_tIME_SUPPORTED) else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) png_handle_PLTE(png_ptr, info_ptr, length);
png_handle_tIME(png_ptr, info_ptr, length); else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
png_handle_IEND(png_ptr, info_ptr, length);
#if defined(PNG_READ_bKGD_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
png_handle_bKGD(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
png_handle_cHRM(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_gAMA_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
png_handle_gAMA(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
png_handle_hIST(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_oFFs_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
png_handle_oFFs(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_pCAL_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
png_handle_pCAL(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_pHYs_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
png_handle_pHYs(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
png_handle_sBIT(png_ptr, info_ptr, length);
#endif #endif
#if defined(PNG_READ_tEXt_SUPPORTED) #if defined(PNG_READ_tEXt_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
png_handle_tEXt(png_ptr, info_ptr, length); png_handle_tEXt(png_ptr, info_ptr, length);
#endif #endif
#if defined(PNG_READ_tIME_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
png_handle_tIME(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_tRNS_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
png_handle_tRNS(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_zTXt_SUPPORTED) #if defined(PNG_READ_zTXt_SUPPORTED)
else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
png_handle_zTXt(png_ptr, info_ptr, length); png_handle_zTXt(png_ptr, info_ptr, length);
#endif #endif
else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
png_handle_IEND(png_ptr, info_ptr, length);
else else
png_handle_unknown(png_ptr, info_ptr, length); png_handle_unknown(png_ptr, info_ptr, length);
} while (!(png_ptr->mode & PNG_HAVE_IEND)); } while (!(png_ptr->mode & PNG_HAVE_IEND));
@ -570,30 +623,32 @@ png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
png_structp png_ptr = NULL; png_structp png_ptr = NULL;
png_infop info_ptr = NULL, end_info_ptr = NULL; png_infop info_ptr = NULL, end_info_ptr = NULL;
if (png_ptr_ptr) png_debug(1, "in png_destroy_read_struct\n");
/* save jump buffer and error functions */
if (png_ptr_ptr != NULL)
png_ptr = *png_ptr_ptr; png_ptr = *png_ptr_ptr;
if (info_ptr_ptr) if (info_ptr_ptr != NULL)
info_ptr = *info_ptr_ptr; info_ptr = *info_ptr_ptr;
if (end_info_ptr_ptr) if (end_info_ptr_ptr != NULL)
end_info_ptr = *end_info_ptr_ptr; end_info_ptr = *end_info_ptr_ptr;
png_read_destroy(png_ptr, info_ptr, end_info_ptr); png_read_destroy(png_ptr, info_ptr, end_info_ptr);
if (info_ptr) if (info_ptr != NULL)
{ {
png_destroy_struct((png_voidp)info_ptr); png_destroy_struct((png_voidp)info_ptr);
*info_ptr_ptr = (png_infop)NULL; *info_ptr_ptr = (png_infop)NULL;
} }
if (end_info_ptr) if (end_info_ptr != NULL)
{ {
png_destroy_struct((png_voidp)end_info_ptr); png_destroy_struct((png_voidp)end_info_ptr);
*end_info_ptr_ptr = (png_infop)NULL; *end_info_ptr_ptr = (png_infop)NULL;
} }
if (png_ptr) if (png_ptr != NULL)
{ {
png_destroy_struct((png_voidp)png_ptr); png_destroy_struct((png_voidp)png_ptr);
*png_ptr_ptr = (png_structp)NULL; *png_ptr_ptr = (png_structp)NULL;
@ -610,10 +665,12 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr
png_error_ptr warning_fn; png_error_ptr warning_fn;
png_voidp error_ptr; png_voidp error_ptr;
if (info_ptr) png_debug(1, "in png_read_destroy\n");
/* save jump buffer and error functions */
if (info_ptr != NULL)
png_info_destroy(png_ptr, info_ptr); png_info_destroy(png_ptr, info_ptr);
if (end_info_ptr) if (end_info_ptr != NULL)
png_info_destroy(png_ptr, end_info_ptr); png_info_destroy(png_ptr, end_info_ptr);
png_free(png_ptr, png_ptr->zbuf); png_free(png_ptr, png_ptr->zbuf);
@ -641,7 +698,7 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr
png_free(png_ptr, png_ptr->hist); png_free(png_ptr, png_ptr->hist);
#endif #endif
#if defined(PNG_READ_GAMMA_SUPPORTED) #if defined(PNG_READ_GAMMA_SUPPORTED)
if (png_ptr->gamma_16_table) if (png_ptr->gamma_16_table != NULL)
{ {
for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++) for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
{ {
@ -651,7 +708,7 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr
#endif #endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED) #if defined(PNG_READ_BACKGROUND_SUPPORTED)
png_free(png_ptr, png_ptr->gamma_16_table); png_free(png_ptr, png_ptr->gamma_16_table);
if (png_ptr->gamma_16_from_1) if (png_ptr->gamma_16_from_1 != NULL)
{ {
for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++) for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
{ {
@ -659,7 +716,7 @@ png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr
} }
} }
png_free(png_ptr, png_ptr->gamma_16_from_1); png_free(png_ptr, png_ptr->gamma_16_from_1);
if (png_ptr->gamma_16_to_1) if (png_ptr->gamma_16_to_1 != NULL)
{ {
for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++) for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
{ {

View File

@ -1,10 +1,11 @@
/* pngrio.c - functions for data input /* pngrio.c - functions for data input
libpng 1.0 beta 4 - version 0.90 libpng 1.0 beta 6 - version 0.96
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 10, 1997 Copyright (c) 1996, 1997 Andreas Dilger
May 12, 1997
This file provides a location for all input. Users which need This file provides a location for all input. Users which need
special handling are expected to write a function which has the same special handling are expected to write a function which has the same
@ -20,12 +21,12 @@
reads from a file pointer. Note that this routine sometimes gets called reads from a file pointer. Note that this routine sometimes gets called
with very small lengths, so you should implement some kind of simple with very small lengths, so you should implement some kind of simple
buffering if you are using unbuffered reads. This should never be asked buffering if you are using unbuffered reads. This should never be asked
to read more then 64K on a 16 bit machine. The cast to png_size_t is to read more then 64K on a 16 bit machine. */
there to quiet some compilers */
void void
png_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length) png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{ {
if (png_ptr->read_data_fn) png_debug1(4,"reading %d bytes\n", length);
if (png_ptr->read_data_fn != NULL)
(*(png_ptr->read_data_fn))(png_ptr, data, length); (*(png_ptr->read_data_fn))(png_ptr, data, length);
else else
png_error(png_ptr, "Call to NULL read function"); png_error(png_ptr, "Call to NULL read function");
@ -37,11 +38,16 @@ png_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
than changing the library. */ than changing the library. */
#ifndef USE_FAR_KEYWORD #ifndef USE_FAR_KEYWORD
static void static void
png_default_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length) png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{ {
png_uint_32 check; png_size_t check;
/* fread() returns 0 on error, so it is OK to store this in a png_size_t
* instead of an int, which is what fread() actually returns.
*/
check = (png_size_t)fread(data, (png_size_t)1, length,
(FILE *)png_ptr->io_ptr);
check = fread(data, 1, (size_t)length, (FILE *)png_ptr->io_ptr);
if (check != length) if (check != length)
{ {
png_error(png_ptr, "Read Error"); png_error(png_ptr, "Read Error");
@ -57,9 +63,9 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
#define MIN(a,b) (a <= b ? a : b) #define MIN(a,b) (a <= b ? a : b)
static void static void
png_default_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length) png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{ {
png_uint_32 check; int check;
png_byte *n_data; png_byte *n_data;
FILE *io_ptr; FILE *io_ptr;
@ -68,18 +74,18 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
io_ptr = (FILE *)CVT_PTR(png_ptr->io_ptr); io_ptr = (FILE *)CVT_PTR(png_ptr->io_ptr);
if ((png_bytep)n_data == data) if ((png_bytep)n_data == data)
{ {
check = fread(n_data, 1, (size_t)length, io_ptr); check = fread(n_data, 1, length, io_ptr);
} }
else else
{ {
png_byte buf[NEAR_BUF_SIZE]; png_byte buf[NEAR_BUF_SIZE];
png_size_t read, remaining, err; png_size_t read, remaining, err;
check = 0; check = 0;
remaining = (png_size_t)length; remaining = length;
do do
{ {
read = MIN(NEAR_BUF_SIZE, remaining); read = MIN(NEAR_BUF_SIZE, remaining);
err = fread(buf, 1, read, io_ptr); err = fread(buf, (png_size_t)1, read, io_ptr);
png_memcpy(data, buf, read); /* copy far buffer to near buffer */ png_memcpy(data, buf, read); /* copy far buffer to near buffer */
if(err != read) if(err != read)
break; break;
@ -116,7 +122,7 @@ png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
{ {
png_ptr->io_ptr = io_ptr; png_ptr->io_ptr = io_ptr;
if (read_data_fn) if (read_data_fn != NULL)
png_ptr->read_data_fn = read_data_fn; png_ptr->read_data_fn = read_data_fn;
else else
png_ptr->read_data_fn = png_default_read_data; png_ptr->read_data_fn = png_default_read_data;

1416
pngrtran.c

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

312
pngset.c Normal file
View File

@ -0,0 +1,312 @@
/* pngset.c - storage of image information into info struct
libpng 1.0 beta 6 - version 0.96
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
Copyright (c) 1996, 1997 Andreas Dilger
May 12, 1997
*/
#define PNG_INTERNAL
#include "png.h"
#if defined(PNG_READ_bKGD_SUPPORTED) || defined(PNG_WRITE_bKGD_SUPPORTED)
void
png_set_bKGD(png_structp png_ptr, png_infop info_ptr, png_color_16p background)
{
png_debug1(1, "in %s storage function\n", "bKGD");
if (info_ptr == NULL)
return;
png_memcpy(&(info_ptr->background), background, sizeof(png_color_16));
info_ptr->valid |= PNG_INFO_bKGD;
}
#endif
#if defined(PNG_READ_cHRM_SUPPORTED) || defined(PNG_WRITE_cHRM_SUPPORTED)
void
png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
double white_x, double white_y, double red_x, double red_y,
double green_x, double green_y, double blue_x, double blue_y)
{
png_debug1(1, "in %s storage function\n", "cHRM");
if (info_ptr == NULL)
return;
info_ptr->x_white = (float)white_x;
info_ptr->y_white = (float)white_y;
info_ptr->x_red = (float)red_x;
info_ptr->y_red = (float)red_y;
info_ptr->x_green = (float)green_x;
info_ptr->y_green = (float)green_y;
info_ptr->x_blue = (float)blue_x;
info_ptr->y_blue = (float)blue_y;
info_ptr->valid |= PNG_INFO_cHRM;
}
#endif
#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_WRITE_gAMA_SUPPORTED)
void
png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
{
png_debug1(1, "in %s storage function\n", "gAMA");
if (info_ptr == NULL)
return;
info_ptr->gamma = (float)file_gamma;
info_ptr->valid |= PNG_INFO_gAMA;
}
#endif
#if defined(PNG_READ_hIST_SUPPORTED) || defined(PNG_WRITE_hIST_SUPPORTED)
void
png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_16p hist)
{
png_debug1(1, "in %s storage function\n", "hIST");
if (info_ptr == NULL)
return;
info_ptr->hist = hist;
info_ptr->valid |= PNG_INFO_hIST;
}
#endif
void
png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
png_uint_32 width, png_uint_32 height, int bit_depth,
int color_type, int interlace_type, int compression_type,
int filter_type)
{
png_debug1(1, "in %s storage function\n", "IHDR");
if (info_ptr == NULL)
return;
info_ptr->width = width;
info_ptr->height = height;
info_ptr->bit_depth = (png_byte)bit_depth;
info_ptr->color_type =(png_byte) color_type;
info_ptr->compression_type = (png_byte)compression_type;
info_ptr->filter_type = (png_byte)filter_type;
info_ptr->interlace_type = (png_byte)interlace_type;
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
info_ptr->channels = 1;
else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
info_ptr->channels = 3;
else
info_ptr->channels = 1;
if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
info_ptr->channels++;
info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
info_ptr->rowbytes = ((info_ptr->width * info_ptr->pixel_depth + 7) >> 3);
}
#if defined(PNG_READ_oFFs_SUPPORTED) || defined(PNG_WRITE_oFFs_SUPPORTED)
void
png_set_oFFs(png_structp png_ptr, png_infop info_ptr,
png_uint_32 offset_x, png_uint_32 offset_y, int unit_type)
{
png_debug1(1, "in %s storage function\n", "oFFs");
if (info_ptr == NULL)
return;
info_ptr->x_offset = offset_x;
info_ptr->y_offset = offset_y;
info_ptr->offset_unit_type = (png_byte)unit_type;
info_ptr->valid |= PNG_INFO_oFFs;
}
#endif
#if defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED)
void
png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams,
png_charp units, png_charpp params)
{
png_size_t length;
int i;
png_debug1(1, "in %s storage function\n", "pCAL");
if (info_ptr == NULL)
return;
length = png_strlen(purpose) + 1;
png_debug1(3, "allocating purpose for info (%d bytes)\n", length);
info_ptr->pcal_purpose = (png_charp)png_malloc(png_ptr, length);
png_memcpy(info_ptr->pcal_purpose, purpose, length);
png_debug(3, "storing X0, X1, type, and nparams in info\n");
info_ptr->pcal_X0 = X0;
info_ptr->pcal_X1 = X1;
info_ptr->pcal_type = (png_byte)type;
info_ptr->pcal_nparams = (png_byte)nparams;
length = png_strlen(units) + 1;
png_debug1(3, "allocating units for info (%d bytes)\n", length);
info_ptr->pcal_units = (png_charp)png_malloc(png_ptr, length);
png_memcpy(info_ptr->pcal_units, units, length);
info_ptr->pcal_params = (png_charpp)png_malloc(png_ptr,
(nparams + 1) * sizeof(png_charp));
info_ptr->pcal_params[nparams] = NULL;
for (i = 0; i < nparams; i++)
{
length = png_strlen(params[i]) + 1;
png_debug2(3, "allocating parameter %d for info (%d bytes)\n", i, length);
info_ptr->pcal_params[i] = (png_charp)png_malloc(png_ptr, length);
png_memcpy(info_ptr->pcal_params[i], params[i], length);
}
info_ptr->valid |= PNG_INFO_pCAL;
}
#endif
#if defined(PNG_READ_pHYs_SUPPORTED) || defined(PNG_WRITE_pHYs_SUPPORTED)
void
png_set_pHYs(png_structp png_ptr, png_infop info_ptr,
png_uint_32 res_x, png_uint_32 res_y, int unit_type)
{
png_debug1(1, "in %s storage function\n", "pHYs");
if (info_ptr == NULL)
return;
info_ptr->x_pixels_per_unit = res_x;
info_ptr->y_pixels_per_unit = res_y;
info_ptr->phys_unit_type = (png_byte)unit_type;
info_ptr->valid |= PNG_INFO_pHYs;
}
#endif
void
png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
png_colorp palette, int num_palette)
{
png_debug1(1, "in %s storage function\n", "PLTE");
if (info_ptr == NULL)
return;
info_ptr->palette = palette;
info_ptr->num_palette = (png_uint_16)num_palette;
info_ptr->valid |= PNG_INFO_PLTE;
}
#if defined(PNG_READ_sBIT_SUPPORTED) || defined(PNG_WRITE_sBIT_SUPPORTED)
void
png_set_sBIT(png_structp png_ptr, png_infop info_ptr,
png_color_8p sig_bit)
{
png_debug1(1, "in %s storage function\n", "sBIT");
if (info_ptr == NULL)
return;
png_memcpy(&(info_ptr->sig_bit), sig_bit, sizeof (png_color_8));
info_ptr->valid |= PNG_INFO_sBIT;
}
#endif
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED) || \
defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
void
png_set_text(png_structp png_ptr, png_infop info_ptr, png_textp text_ptr,
int num_text)
{
int i;
png_debug1(1, "in %s storage function\n", (png_ptr->chunk_name[0] == '\0' ?
"text" : png_ptr->chunk_name));
if (info_ptr == NULL || num_text == 0)
return;
/* Make sure we have enough space in the "text" array in info_struct
* to hold all of the incoming text_ptr objects.
*/
if (info_ptr->num_text + num_text > info_ptr->max_text)
{
if (info_ptr->text != NULL)
{
png_textp old_text;
int old_max;
old_max = info_ptr->max_text;
info_ptr->max_text = info_ptr->num_text + num_text + 8;
old_text = info_ptr->text;
info_ptr->text = (png_textp)png_malloc(png_ptr,
info_ptr->max_text * sizeof (png_text));
png_memcpy(info_ptr->text, old_text, old_max * sizeof(png_text));
png_free(png_ptr, old_text);
}
else
{
info_ptr->max_text = num_text + 8;
info_ptr->num_text = 0;
info_ptr->text = (png_textp)png_malloc(png_ptr,
info_ptr->max_text * sizeof (png_text));
}
png_debug1(3, "allocated %d entries for info_ptr->text\n",
info_ptr->max_text);
}
for (i = 0; i < num_text; i++)
{
png_textp textp = &(info_ptr->text[info_ptr->num_text]);
if (text_ptr[i].text == NULL)
text_ptr[i].text = "";
if (text_ptr[i].text[0] == '\0')
{
textp->text_length = 0;
textp->compression = PNG_TEXT_COMPRESSION_NONE;
}
else
{
textp->text_length = png_strlen(text_ptr[i].text);
textp->compression = text_ptr[i].compression;
}
textp->text = text_ptr[i].text;
textp->key = text_ptr[i].key;
info_ptr->num_text++;
png_debug1(3, "transferred text chunk %d\n", info_ptr->num_text);
}
}
#endif
#if defined(PNG_READ_tIME_SUPPORTED) || defined(PNG_WRITE_tIME_SUPPORTED)
void
png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_timep mod_time)
{
png_debug1(1, "in %s storage function\n", "tIME");
if (info_ptr == NULL)
return;
png_memcpy(&(info_ptr->mod_time), mod_time, sizeof (png_time));
info_ptr->valid |= PNG_INFO_tIME;
}
#endif
#if defined(PNG_READ_tRNS_SUPPORTED) || defined(PNG_WRITE_tRNS_SUPPORTED)
void
png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
png_bytep trans, int num_trans, png_color_16p trans_values)
{
png_debug1(1, "in %s storage function\n", "tRNS");
if (info_ptr == NULL)
return;
if (trans != NULL)
{
info_ptr->trans = trans;
}
if (trans_values != NULL)
{
png_memcpy(&(info_ptr->trans_values), trans_values,
sizeof(png_color_16));
}
info_ptr->num_trans = (png_uint_16)num_trans;
info_ptr->valid |= PNG_INFO_tRNS;
}
#endif

270
pngtest.c
View File

@ -1,14 +1,21 @@
/* pngtest.c - a simple test program to test libpng /* pngtest.c - a simple test program to test libpng
libpng 1.0 beta 4 - version 0.90 libpng 1.0 beta 6 - version 0.96
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 10, 1997 Copyright (c) 1996, 1997 Andreas Dilger
*/ May 12, 1997
*/
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
/* Makes pngtest verbose so we can find problems (needs to be before png.h) */
#ifndef PNG_DEBUG
#define PNG_DEBUG 0
#endif
#include "png.h" #include "png.h"
#ifdef __TURBOC__ #ifdef __TURBOC__
@ -30,23 +37,21 @@ char *outname = "pngout.png";
char inbuf[256], outbuf[256]; char inbuf[256], outbuf[256];
int main(int argc, char *argv[]) int
main(int argc, char *argv[])
{ {
FILE *fpin, *fpout; FILE *fpin, *fpout;
png_structp read_ptr; png_structp read_ptr, write_ptr;
png_structp write_ptr; png_infop read_info_ptr, write_info_ptr, end_info_ptr;
png_infop info_ptr;
png_infop end_info;
png_bytep row_buf; png_bytep row_buf;
png_byte *near_row_buf;
png_uint_32 rowbytes;
png_uint_32 y; png_uint_32 y;
int channels, num_pass, pass; png_uint_32 width, height;
int num_pass, pass;
int bit_depth, color_type;
#ifdef USE_FAR_KEYWORD #ifdef USE_FAR_KEYWORD
jmp_buf jmpbuf; jmp_buf jmpbuf;
#endif #endif
row_buf = (png_bytep)NULL; row_buf = (png_bytep)NULL;
near_row_buf = (png_byte *)NULL;
fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING); fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
@ -70,28 +75,30 @@ int main(int argc, char *argv[])
exit(1); exit(1);
} }
fpin = fopen(inname, "rb"); if ((fpin = fopen(inname, "rb")) == NULL)
if (!fpin)
{ {
fprintf(STDERR, "Could not find input file %s\n", inname); fprintf(STDERR, "Could not find input file %s\n", inname);
return 1; return 1;
} }
fpout = fopen(outname, "wb"); if ((fpout = fopen(outname, "wb")) == NULL)
if (!fpout)
{ {
fprintf(STDERR, "Could not open output file %s\n", outname); fprintf(STDERR, "Could not open output file %s\n", outname);
fclose(fpin); fclose(fpin);
return 1; return 1;
} }
png_debug(0, "Allocating read and write structures\n");
read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
(png_error_ptr)NULL, (png_error_ptr)NULL); (png_error_ptr)NULL, (png_error_ptr)NULL);
write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL, write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp)NULL,
(png_error_ptr)NULL, (png_error_ptr)NULL); (png_error_ptr)NULL, (png_error_ptr)NULL);
info_ptr = png_create_info_struct(read_ptr); png_debug(0, "Allocating read_info, write_info and end_info structures\n");
end_info = png_create_info_struct(read_ptr); read_info_ptr = png_create_info_struct(read_ptr);
write_info_ptr = png_create_info_struct(read_ptr);
end_info_ptr = png_create_info_struct(read_ptr);
png_debug(0, "Setting jmpbuf for read struct\n");
#ifdef USE_FAR_KEYWORD #ifdef USE_FAR_KEYWORD
if (setjmp(jmpbuf)) if (setjmp(jmpbuf))
#else #else
@ -99,12 +106,14 @@ int main(int argc, char *argv[])
#endif #endif
{ {
fprintf(STDERR, "libpng read error\n"); fprintf(STDERR, "libpng read error\n");
png_destroy_read_struct(&read_ptr, &info_ptr, &end_info); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
png_destroy_write_struct(&write_ptr, (png_infopp)NULL); png_destroy_write_struct(&write_ptr, &write_info_ptr);
fclose(fpin); fclose(fpin);
fclose(fpout); fclose(fpout);
return 1; return 1;
} }
png_debug(0, "Setting jmpbuf for write struct\n");
#ifdef USE_FAR_KEYWORD #ifdef USE_FAR_KEYWORD
png_memcpy(read_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf)); png_memcpy(read_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
if (setjmp(jmpbuf)) if (setjmp(jmpbuf))
@ -113,92 +122,227 @@ int main(int argc, char *argv[])
#endif #endif
{ {
fprintf(STDERR, "libpng write error\n"); fprintf(STDERR, "libpng write error\n");
png_destroy_read_struct(&read_ptr, &info_ptr, &end_info); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
png_destroy_write_struct(&write_ptr, (png_infopp)NULL); png_destroy_write_struct(&write_ptr, &write_info_ptr);
fclose(fpin); fclose(fpin);
fclose(fpout); fclose(fpout);
return 1; return 1;
} }
#ifdef USE_FAR_KEYWORD #ifdef USE_FAR_KEYWORD
png_memcpy(write_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf)); png_memcpy(write_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
#endif #endif
png_debug(0, "Initializing input and output streams\n");
png_init_io(read_ptr, fpin); png_init_io(read_ptr, fpin);
png_init_io(write_ptr, fpout); png_init_io(write_ptr, fpout);
png_read_info(read_ptr, info_ptr); png_debug(0, "Reading info struct\n");
png_write_info(write_ptr, info_ptr); png_read_info(read_ptr, read_info_ptr);
if ((info_ptr->color_type & PNG_COLOR_TYPE_PALETTE)==PNG_COLOR_TYPE_PALETTE) png_debug(0, "Transferring info struct\n");
channels = 1; {
else int interlace_type, compression_type, filter_type;
channels = 3;
if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
channels++;
rowbytes = ((info_ptr->width * info_ptr->bit_depth * channels + 7) >> 3); if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth,
near_row_buf = (png_byte *)malloc((size_t)rowbytes); &color_type, &interlace_type, &compression_type, &filter_type))
row_buf = (png_bytep)near_row_buf; {
if (!row_buf) png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth,
color_type, interlace_type, compression_type, filter_type);
}
}
#if defined(PNG_READ_bKGD_SUPPORTED) && defined(PNG_WRITE_bKGD_SUPPORTED)
{
png_color_16p background;
if (png_get_bKGD(read_ptr, read_info_ptr, &background))
{
png_set_bKGD(write_ptr, write_info_ptr, background);
}
}
#endif
#if defined(PNG_READ_cHRM_SUPPORTED) && defined(PNG_WRITE_cHRM_SUPPORTED)
{
double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x,
&red_y, &green_x, &green_y, &blue_x, &blue_y))
{
png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x,
red_y, green_x, green_y, blue_x, blue_y);
}
}
#endif
#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_WRITE_gAMA_SUPPORTED)
{
double gamma;
if (png_get_gAMA(read_ptr, read_info_ptr, &gamma))
{
png_set_gAMA(write_ptr, write_info_ptr, gamma);
}
}
#endif
#if defined(PNG_READ_hIST_SUPPORTED) && defined(PNG_WRITE_hIST_SUPPORTED)
{
png_uint_16p hist;
if (png_get_hIST(read_ptr, read_info_ptr, &hist))
{
png_set_hIST(write_ptr, write_info_ptr, hist);
}
}
#endif
#if defined(PNG_READ_oFFs_SUPPORTED) && defined(PNG_WRITE_oFFs_SUPPORTED)
{
png_uint_32 offset_x, offset_y;
int unit_type;
if (png_get_oFFs(read_ptr, read_info_ptr,&offset_x,&offset_y,&unit_type))
{
png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type);
}
}
#endif
#if defined(PNG_READ_pCAL_SUPPORTED) && defined(PNG_WRITE_pCAL_SUPPORTED)
{
png_charp purpose, units;
png_charpp params;
png_int_32 X0, X1;
int type, nparams;
if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type,
&nparams, &units, &params))
{
png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type,
nparams, units, params);
}
}
#endif
#if defined(PNG_READ_pHYs_SUPPORTED) && defined(PNG_WRITE_pHYs_SUPPORTED)
{
png_uint_32 res_x, res_y;
int unit_type;
if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, &unit_type))
{
png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type);
}
}
#endif
{
png_colorp palette;
int num_palette;
if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette))
{
png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette);
}
}
#if defined(PNG_READ_sBIT_SUPPORTED) && defined(PNG_WRITE_sBIT_SUPPORTED)
{
png_color_8p sig_bit;
if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit))
{
png_set_sBIT(write_ptr, write_info_ptr, sig_bit);
}
}
#endif
#if (defined(PNG_READ_tEXt_SUPPORTED) && defined(PNG_WRITE_tEXt_SUPPORTED)) || \
(defined(PNG_READ_zTXt_SUPPORTED) && defined(PNG_WRITE_zTXt_SUPPORTED))
{
png_textp text_ptr;
int num_text;
if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0)
{
png_debug1(0, "Handling %d tEXt/zTXt chunks\n", num_text);
png_set_text(write_ptr, write_info_ptr, text_ptr, num_text);
}
}
#endif
#if defined(PNG_READ_tIME_SUPPORTED) && defined(PNG_WRITE_tIME_SUPPORTED)
{
png_timep mod_time;
if (png_get_tIME(read_ptr, read_info_ptr, &mod_time))
{
png_set_tIME(write_ptr, write_info_ptr, mod_time);
}
}
#endif
#if defined(PNG_READ_tRNS_SUPPORTED) && defined(PNG_WRITE_tRNS_SUPPORTED)
{
png_bytep trans;
int num_trans;
png_color_16p trans_values;
if (png_get_tRNS(read_ptr, read_info_ptr, &trans, &num_trans,
&trans_values))
{
png_set_tRNS(write_ptr, write_info_ptr, trans, num_trans,
trans_values);
}
}
#endif
png_debug(0, "\nWriting info struct\n");
png_write_info(write_ptr, write_info_ptr);
row_buf = (png_bytep)png_malloc(read_ptr,
png_get_rowbytes(read_ptr, read_info_ptr));
if (row_buf == NULL)
{ {
fprintf(STDERR, "No memory to allocate row buffer\n"); fprintf(STDERR, "No memory to allocate row buffer\n");
png_destroy_read_struct(&read_ptr, &info_ptr, &end_info); png_destroy_read_struct(&read_ptr, &read_info_ptr, (png_infopp)NULL);
png_destroy_write_struct(&write_ptr, (png_infopp)NULL); png_destroy_write_struct(&write_ptr, &write_info_ptr);
fclose(fpin); fclose(fpin);
fclose(fpout); fclose(fpout);
return 1; return 1;
} }
if (info_ptr->interlace_type) num_pass = png_set_interlace_handling(read_ptr);
{ png_set_interlace_handling(write_ptr);
num_pass = png_set_interlace_handling(read_ptr);
num_pass = png_set_interlace_handling(write_ptr);
}
else
{
num_pass = 1;
}
for (pass = 0; pass < num_pass; pass++) for (pass = 0; pass < num_pass; pass++)
{ {
for (y = 0; y < info_ptr->height; y++) for (y = 0; y < height; y++)
{ {
#ifdef TESTING png_read_rows(read_ptr, (png_bytepp)&row_buf, (png_bytepp)NULL, 1);
fprintf(STDERR, "Processing line #%ld\n", y);
#endif
png_read_rows(read_ptr, (png_bytepp)&row_buf, (png_bytepp)0, 1);
png_write_rows(write_ptr, (png_bytepp)&row_buf, 1); png_write_rows(write_ptr, (png_bytepp)&row_buf, 1);
} }
} }
png_read_end(read_ptr, end_info); png_debug(0, "Reading and writing end_info data\n");
png_write_end(write_ptr, end_info); png_read_end(read_ptr, end_info_ptr);
png_write_end(write_ptr, end_info_ptr);
png_destroy_read_struct(&read_ptr, &info_ptr, &end_info); png_debug(0, "Destroying data structs\n");
png_destroy_write_struct(&write_ptr, (png_infopp)NULL); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
png_destroy_write_struct(&write_ptr, &write_info_ptr);
fclose(fpin); fclose(fpin);
fclose(fpout); fclose(fpout);
free((png_byte *)near_row_buf); png_free(read_ptr, row_buf);
fpin = fopen(inname, "rb"); png_debug(0, "Opening files for comparison\n");
if ((fpin = fopen(inname, "rb")) == NULL)
if (!fpin)
{ {
fprintf(STDERR, "Could not find file %s\n", inname); fprintf(STDERR, "Could not find file %s\n", inname);
return 1; return 1;
} }
fpout = fopen(outname, "rb"); if ((fpout = fopen(outname, "rb")) == NULL)
if (!fpout)
{ {
fprintf(STDERR, "Could not find file %s\n", outname); fprintf(STDERR, "Could not find file %s\n", outname);
fclose(fpin); fclose(fpin);
return 1; return 1;
} }
while (1) while (1)
{ {
int num_in, num_out; png_size_t num_in, num_out;
num_in = fread(inbuf, 1, 1, fpin); num_in = fread(inbuf, 1, 1, fpin);
num_out = fread(outbuf, 1, 1, fpout); num_out = fread(outbuf, 1, 1, fpout);
@ -215,7 +359,7 @@ int main(int argc, char *argv[])
if (!num_in) if (!num_in)
break; break;
if (memcmp(inbuf, outbuf, num_in)) if (png_memcmp(inbuf, outbuf, num_in))
{ {
fprintf(STDERR, "Files %s and %s are different\n", inname, outname); fprintf(STDERR, "Files %s and %s are different\n", inname, outname);
fclose(fpin); fclose(fpin);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -1,11 +1,11 @@
/* pngtrans.c - transforms the data in a row /* pngtrans.c - transforms the data in a row (used by both readers and writers)
routines used by both readers and writers
libpng 1.0 beta 4 - version 0.90 libpng 1.0 beta 6 - version 0.96
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 10, 1997 Copyright (c) 1996, 1997 Andreas Dilger
May 12, 1997
*/ */
#define PNG_INTERNAL #define PNG_INTERNAL
@ -16,6 +16,7 @@
void void
png_set_bgr(png_structp png_ptr) png_set_bgr(png_structp png_ptr)
{ {
png_debug(1, "in png_set_bgr\n");
png_ptr->transformations |= PNG_BGR; png_ptr->transformations |= PNG_BGR;
} }
#endif #endif
@ -25,6 +26,7 @@ png_set_bgr(png_structp png_ptr)
void void
png_set_swap(png_structp png_ptr) png_set_swap(png_structp png_ptr)
{ {
png_debug(1, "in png_set_swap\n");
if (png_ptr->bit_depth == 16) if (png_ptr->bit_depth == 16)
png_ptr->transformations |= PNG_SWAP_BYTES; png_ptr->transformations |= PNG_SWAP_BYTES;
} }
@ -35,6 +37,7 @@ png_set_swap(png_structp png_ptr)
void void
png_set_packing(png_structp png_ptr) png_set_packing(png_structp png_ptr)
{ {
png_debug(1, "in png_set_packing\n");
if (png_ptr->bit_depth < 8) if (png_ptr->bit_depth < 8)
{ {
png_ptr->transformations |= PNG_PACK; png_ptr->transformations |= PNG_PACK;
@ -43,10 +46,22 @@ png_set_packing(png_structp png_ptr)
} }
#endif #endif
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
/* turn on packed pixel swapping */
void
png_set_packswap(png_structp png_ptr)
{
png_debug(1, "in png_set_packswap\n");
if (png_ptr->bit_depth < 8)
png_ptr->transformations |= PNG_PACKSWAP;
}
#endif
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
void void
png_set_shift(png_structp png_ptr, png_color_8p true_bits) png_set_shift(png_structp png_ptr, png_color_8p true_bits)
{ {
png_debug(1, "in png_set_shift\n");
png_ptr->transformations |= PNG_SHIFT; png_ptr->transformations |= PNG_SHIFT;
png_ptr->shift = *true_bits; png_ptr->shift = *true_bits;
} }
@ -56,6 +71,7 @@ png_set_shift(png_structp png_ptr, png_color_8p true_bits)
int int
png_set_interlace_handling(png_structp png_ptr) png_set_interlace_handling(png_structp png_ptr)
{ {
png_debug(1, "in png_set_interlace handling\n");
if (png_ptr->interlaced) if (png_ptr->interlaced)
{ {
png_ptr->transformations |= PNG_INTERLACE; png_ptr->transformations |= PNG_INTERLACE;
@ -67,35 +83,37 @@ png_set_interlace_handling(png_structp png_ptr)
#endif #endif
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
/* Add a filler byte on read, or remove a filler or alpha byte on write.
* The filler type has changed in v0.95 to allow future 2-byte fillers
* for 48-bit input data, as well as avoiding problems with some compilers
* which don't like bytes as parameters.
*/
void void
png_set_filler(png_structp png_ptr, png_byte filler, int filler_loc) png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
{ {
png_debug(1, "in png_set_filler\n");
png_ptr->transformations |= PNG_FILLER; png_ptr->transformations |= PNG_FILLER;
png_ptr->filler = filler; png_ptr->filler = (png_byte)filler;
if (filler_loc == PNG_FILLER_AFTER) if (filler_loc == PNG_FILLER_AFTER)
png_ptr->flags |= PNG_FLAG_FILLER_AFTER; png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
else else
png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER; png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
if (png_ptr->color_type == PNG_COLOR_TYPE_RGB && /* This should probably go in the "do_filler" routine */
png_ptr->bit_depth == 8) if (png_ptr->color_type == PNG_COLOR_TYPE_RGB && png_ptr->bit_depth == 8)
{
png_ptr->usr_channels = 4; png_ptr->usr_channels = 4;
}
} }
#endif
/* Old functions kept around for compatability purposes. They will be #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
* removed at some time in the future, so don't use them. You should defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
* use png_set_filler() above instead. We set filler bytes to 0xff in
* case they are mistakenly used as PNG alpha (0xff is fully opaque). */
void void
png_set_rgbx(png_structp png_ptr) png_set_swap_alpha(png_structp png_ptr)
{ {
png_set_filler(png_ptr, (png_byte)0xff, PNG_FILLER_AFTER); png_debug(1, "in png_set_swap_alpha\n");
} png_ptr->transformations |= PNG_SWAP_ALPHA;
void
png_set_xrgb(png_structp png_ptr)
{
png_set_filler(png_ptr, (png_byte)0xff, PNG_FILLER_BEFORE);
} }
#endif #endif
@ -103,6 +121,7 @@ png_set_xrgb(png_structp png_ptr)
void void
png_set_invert_mono(png_structp png_ptr) png_set_invert_mono(png_structp png_ptr)
{ {
png_debug(1, "in png_set_invert_mono\n");
png_ptr->transformations |= PNG_INVERT_MONO; png_ptr->transformations |= PNG_INVERT_MONO;
} }
@ -110,15 +129,17 @@ png_set_invert_mono(png_structp png_ptr)
void void
png_do_invert(png_row_infop row_info, png_bytep row) png_do_invert(png_row_infop row_info, png_bytep row)
{ {
if (row && row_info && row_info->bit_depth == 1 && png_debug(1, "in png_do_invert\n");
row_info->color_type == PNG_COLOR_TYPE_GRAY) if (row_info->bit_depth == 1 &&
#if defined(PNG_USELESS_TESTS_SUPPORTED)
row != NULL && row_info != NULL &&
#endif
row_info->color_type == PNG_COLOR_TYPE_GRAY)
{ {
png_bytep rp; png_bytep rp;
png_uint_32 i; png_uint_32 i;
for (i = 0, rp = row; for (i = 0, rp = row; i < row_info->rowbytes; i++, rp++)
i < row_info->rowbytes;
i++, rp++)
{ {
*rp = (png_byte)(~(*rp)); *rp = (png_byte)(~(*rp));
} }
@ -131,7 +152,12 @@ png_do_invert(png_row_infop row_info, png_bytep row)
void void
png_do_swap(png_row_infop row_info, png_bytep row) png_do_swap(png_row_infop row_info, png_bytep row)
{ {
if (row && row_info && row_info->bit_depth == 16) png_debug(1, "in png_do_swap\n");
if (
#if defined(PNG_USELESS_TESTS_SUPPORTED)
row != NULL && row_info != NULL &&
#endif
row_info->bit_depth == 16)
{ {
png_bytep rp; png_bytep rp;
png_byte t; png_byte t;
@ -149,80 +175,391 @@ png_do_swap(png_row_infop row_info, png_bytep row)
} }
#endif #endif
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
/* swaps red and blue */ static png_byte onebppswaptable[256] = {
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
};
static png_byte twobppswaptable[256] = {
0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
};
static png_byte fourbppswaptable[256] = {
0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
};
/* swaps pixel packing order within bytes */
void void
png_do_bgr(png_row_infop row_info, png_bytep row) png_do_packswap(png_row_infop row_info, png_bytep row)
{ {
if (row && row_info && (row_info->color_type & 2)) png_debug(1, "in png_do_packswap\n");
if (
#if defined(PNG_USELESS_TESTS_SUPPORTED)
row != NULL && row_info != NULL
#endif
row_info->bit_depth < 8)
{ {
if (row_info->color_type == 2 && row_info->bit_depth == 8) png_bytep rp, end, table;
{
png_bytep rp;
png_byte t;
png_uint_32 i;
for (i = 0, rp = row; end = row + row_info->rowbytes;
i < row_info->width;
i++, rp += 3) if (row_info->bit_depth == 1)
table = onebppswaptable;
else if (row_info->bit_depth == 2)
table = twobppswaptable;
else if (row_info->bit_depth == 4)
table = fourbppswaptable;
else
return;
for (rp = row; rp < end; rp++)
*rp = table[*rp];
}
}
#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
/* remove filler or alpha byte(s) */
void
png_do_strip_filler(png_row_infop row_info, png_bytep row, png_uint_32 flags)
{
png_debug(1, "in png_do_strip_filler\n");
#if defined(PNG_USELESS_TESTS_SUPPORTED)
if (row != NULL && row_info != NULL)
#endif
{
/*
if (row_info->color_type == PNG_COLOR_TYPE_RGB ||
row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
*/
if (row_info->channels == 4)
{
if (row_info->bit_depth == 8)
{ {
t = *rp; /* This converts from RGBX or RGBA to RGB */
*rp = *(rp + 2); if (flags & PNG_FLAG_FILLER_AFTER)
*(rp + 2) = t; {
png_bytep sp, dp;
png_uint_32 i;
for (i = 1, sp = row + 4, dp = row + 3; i < row_info->width; i++)
{
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
sp++;
}
}
/* This converts from XRGB or ARGB to RGB */
else
{
png_bytep sp, dp;
png_uint_32 i;
for (i = 0, sp = row, dp = row; i < row_info->width; i++)
{
sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
}
}
row_info->pixel_depth = 24;
row_info->rowbytes = row_info->width * 3;
} }
else /* if (row_info->bit_depth == 16) */
{
if (flags & PNG_FLAG_FILLER_AFTER)
{
png_bytep sp, dp;
png_uint_32 i;
/* This converts from RRGGBBXX or RRGGBBAA to RRGGBB */
for (i = 1, sp = row + 8, dp = row + 6; i < row_info->width; i++)
{
/* This could be (although memcpy is probably slower):
png_memcpy(dp, sp, 6);
sp += 8;
dp += 6;
*/
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
sp += 2;
}
}
else
{
png_bytep sp, dp;
png_uint_32 i;
/* This converts from XXRRGGBB or AARRGGBB to RRGGBB */
for (i = 0, sp = row + 2, dp = row; i < row_info->width; i++)
{
/* This could be (although memcpy is probably slower):
png_memcpy(dp, sp, 6);
sp += 8;
dp += 6;
*/
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
*dp++ = *sp++;
}
}
row_info->pixel_depth = 48;
row_info->rowbytes = row_info->width * 6;
}
row_info->channels = 3;
} }
else if (row_info->color_type == 6 && row_info->bit_depth == 8) /*
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY ||
row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
*/
else if (row_info->channels == 2)
{ {
png_bytep rp; if (row_info->bit_depth == 8)
png_byte t;
png_uint_32 i;
for (i = 0, rp = row;
i < row_info->width;
i++, rp += 4)
{ {
t = *rp; /* This converts from GX or GA to G */
*rp = *(rp + 2); if (flags & PNG_FLAG_FILLER_AFTER)
*(rp + 2) = t; {
} png_bytep sp, dp;
} png_uint_32 i;
else if (row_info->color_type == 2 && row_info->bit_depth == 16)
{
png_bytep rp;
png_byte t[2];
png_uint_32 i;
for (i = 0, rp = row; for (i = 1, sp = row + 2, dp = row + 1; i < row_info->width; i++)
i < row_info->width; {
i++, rp += 6) *dp++ = *sp++;
{ sp++;
t[0] = *rp; }
t[1] = *(rp + 1); }
*rp = *(rp + 4); /* This converts from XG or AG to G */
*(rp + 1) = *(rp + 5); else
*(rp + 4) = t[0]; {
*(rp + 5) = t[1]; png_bytep sp, dp;
} png_uint_32 i;
}
else if (row_info->color_type == 6 && row_info->bit_depth == 16)
{
png_bytep rp;
png_byte t[2];
png_uint_32 i;
for (i = 0, rp = row; for (i = 0, sp = row, dp = row; i < row_info->width; i++)
i < row_info->width; {
i++, rp += 8) sp++;
{ *dp++ = *sp++;
t[0] = *rp; }
t[1] = *(rp + 1); }
*rp = *(rp + 4); row_info->pixel_depth = 8;
*(rp + 1) = *(rp + 5); row_info->rowbytes = row_info->width;
*(rp + 4) = t[0];
*(rp + 5) = t[1];
} }
else /* if (row_info->bit_depth == 16) */
{
if (flags & PNG_FLAG_FILLER_AFTER)
{
png_bytep sp, dp;
png_uint_32 i;
/* This converts from GGXX or GGAA to GG */
for (i = 1, sp = row + 4, dp = row + 2; i < row_info->width; i++)
{
*dp++ = *sp++;
*dp++ = *sp++;
sp += 2;
}
}
else
{
png_bytep sp, dp;
png_uint_32 i;
/* This converts from XXGG or AAGG to GG */
for (i = 0, sp = row, dp = row; i < row_info->width; i++)
{
sp += 2;
*dp++ = *sp++;
*dp++ = *sp++;
}
}
row_info->pixel_depth = 16;
row_info->rowbytes = row_info->width * 2;
}
row_info->channels = 1;
} }
} }
} }
#endif #endif
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
/* swaps red and blue bytes within a pixel */
void
png_do_bgr(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_bgr\n");
if (
#if defined(PNG_USELESS_TESTS_SUPPORTED)
row != NULL && row_info != NULL &&
#endif
(row_info->color_type & PNG_COLOR_MASK_COLOR))
{
if (row_info->bit_depth == 8)
{
if (row_info->color_type == PNG_COLOR_TYPE_RGB)
{
png_bytep rp;
png_byte save;
png_uint_32 i;
for (i = 0, rp = row; i < row_info->width; i++, rp += 3)
{
save = *rp;
*rp = *(rp + 2);
*(rp + 2) = save;
}
}
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
{
png_bytep rp;
png_byte save;
png_uint_32 i;
for (i = 0, rp = row; i < row_info->width; i++, rp += 4)
{
save = *rp;
*rp = *(rp + 2);
*(rp + 2) = save;
}
}
}
else if (row_info->bit_depth == 16)
{
if (row_info->color_type == PNG_COLOR_TYPE_RGB)
{
png_bytep rp;
png_byte save[2];
png_uint_32 i;
for (i = 0, rp = row; i < row_info->width; i++, rp += 6)
{
save[0] = *rp;
save[1] = *(rp + 1);
*rp = *(rp + 4);
*(rp + 1) = *(rp + 5);
*(rp + 4) = save[0];
*(rp + 5) = save[1];
}
}
else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
{
png_bytep rp;
png_byte save[2];
png_uint_32 i;
for (i = 0, rp = row; i < row_info->width; i++, rp += 8)
{
save[0] = *rp;
save[1] = *(rp + 1);
*rp = *(rp + 4);
*(rp + 1) = *(rp + 5);
*(rp + 4) = save[0];
*(rp + 5) = save[1];
}
}
}
}
}
#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */

View File

@ -1,10 +1,11 @@
/* pngwio.c - functions for data output /* pngwio.c - functions for data output
libpng 1.0 beta 4 - version 0.90 libpng 1.0 beta 6 - version 0.96
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 10, 1997 Copyright (c) 1996, 1997 Andreas Dilger
May 12, 1997
This file provides a location for all output. Users which need This file provides a location for all output. Users which need
special handling are expected to write functions which have the same special handling are expected to write functions which have the same
@ -20,13 +21,12 @@
writes to a file pointer. Note that this routine sometimes gets called writes to a file pointer. Note that this routine sometimes gets called
with very small lengths, so you should implement some kind of simple with very small lengths, so you should implement some kind of simple
buffering if you are using unbuffered writes. This should never be asked buffering if you are using unbuffered writes. This should never be asked
to write more then 64K on a 16 bit machine. The cast to png_size_t is to write more then 64K on a 16 bit machine. */
there to quiet warnings of certain compilers. */
void void
png_write_data(png_structp png_ptr, png_bytep data, png_uint_32 length) png_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
{ {
if (png_ptr->write_data_fn) if (png_ptr->write_data_fn != NULL )
(*(png_ptr->write_data_fn))(png_ptr, data, length); (*(png_ptr->write_data_fn))(png_ptr, data, length);
else else
png_error(png_ptr, "Call to NULL write function"); png_error(png_ptr, "Call to NULL write function");
@ -38,11 +38,11 @@ png_write_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
than changing the library. */ than changing the library. */
#ifndef USE_FAR_KEYWORD #ifndef USE_FAR_KEYWORD
static void static void
png_default_write_data(png_structp png_ptr, png_bytep data, png_uint_32 length) png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
{ {
png_uint_32 check; png_uint_32 check;
check = fwrite(data, 1, (png_size_t)length, (FILE *)(png_ptr->io_ptr)); check = fwrite(data, 1, length, (FILE *)(png_ptr->io_ptr));
if (check != length) if (check != length)
{ {
png_error(png_ptr, "Write Error"); png_error(png_ptr, "Write Error");
@ -58,25 +58,25 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
#define MIN(a,b) (a <= b ? a : b) #define MIN(a,b) (a <= b ? a : b)
static void static void
png_default_write_data(png_structp png_ptr, png_bytep data, png_uint_32 length) png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
{ {
png_uint_32 check; png_uint_32 check;
png_byte *n_data; png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */
FILE *io_ptr; FILE *io_ptr;
/* Check if data really is near. If so, use usual code. */ /* Check if data really is near. If so, use usual code. */
n_data = (png_byte *)CVT_PTR_NOCHECK(data); near_data = (png_byte *)CVT_PTR_NOCHECK(data);
io_ptr = (FILE *)CVT_PTR(png_ptr->io_ptr); io_ptr = (FILE *)CVT_PTR(png_ptr->io_ptr);
if ((png_bytep)n_data == data) if ((png_bytep)near_data == data)
{ {
check = fwrite(n_data, 1, (png_size_t)length, io_ptr); check = fwrite(near_data, 1, length, io_ptr);
} }
else else
{ {
png_byte buf[NEAR_BUF_SIZE]; png_byte buf[NEAR_BUF_SIZE];
png_size_t written, remaining, err; png_size_t written, remaining, err;
check = 0; check = 0;
remaining = (png_size_t)length; remaining = length;
do do
{ {
written = MIN(NEAR_BUF_SIZE, remaining); written = MIN(NEAR_BUF_SIZE, remaining);
@ -106,7 +106,7 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
void void
png_flush(png_structp png_ptr) png_flush(png_structp png_ptr)
{ {
if (png_ptr->output_flush_fn) if (png_ptr->output_flush_fn != NULL)
(*(png_ptr->output_flush_fn))(png_ptr); (*(png_ptr->output_flush_fn))(png_ptr);
} }
@ -115,7 +115,7 @@ png_default_flush(png_structp png_ptr)
{ {
FILE *io_ptr; FILE *io_ptr;
io_ptr = (FILE *)CVT_PTR((png_ptr->io_ptr)); io_ptr = (FILE *)CVT_PTR((png_ptr->io_ptr));
if (io_ptr) if (io_ptr != NULL)
fflush(io_ptr); fflush(io_ptr);
} }
#endif #endif
@ -148,13 +148,13 @@ png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
{ {
png_ptr->io_ptr = io_ptr; png_ptr->io_ptr = io_ptr;
if (write_data_fn) if (write_data_fn != NULL)
png_ptr->write_data_fn = write_data_fn; png_ptr->write_data_fn = write_data_fn;
else else
png_ptr->write_data_fn = png_default_write_data; png_ptr->write_data_fn = png_default_write_data;
#if defined(PNG_WRITE_FLUSH_SUPPORTED) #if defined(PNG_WRITE_FLUSH_SUPPORTED)
if (output_flush_fn) if (output_flush_fn != NULL)
png_ptr->output_flush_fn = output_flush_fn; png_ptr->output_flush_fn = output_flush_fn;
else else
png_ptr->output_flush_fn = png_default_flush; png_ptr->output_flush_fn = png_default_flush;

View File

@ -1,28 +1,32 @@
/* pngwrite.c - general routines to write a PNG file
/* pngwrite.c - general routines to write a png file libpng 1.0 beta 6 - version 0.96
libpng 1.0 beta 4 - version 0.90
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 10, 1997 Copyright (c) 1996, 1997 Andreas Dilger
May 12, 1997
*/ */
/* get internal access to png.h */ /* get internal access to png.h */
#define PNG_INTERNAL #define PNG_INTERNAL
#include "png.h" #include "png.h"
/* Writes all the png information. This is the suggested way to use /* Writes all the PNG information. This is the suggested way to use the
the library. If you have a new chunk to add, make a function to * library. If you have a new chunk to add, make a function to write it,
write it, and put it in the correct location here. If you want * and put it in the correct location here. If you want the chunk written
the chunk written after the image data, put it in png_write_end(). * after the image data, put it in png_write_end(). I strongly encurage
I strongly encurage you to supply a PNG_INFO_ flag, and check * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
info_ptr->valid before writing the chunk, as that will keep the code * the chunk, as that will keep the code from breaking if you want to just
from breaking if you want to just write a plain png file. * write a plain PNG file. If you have long comments, I suggest writing
If you have long comments, I suggest writing them in png_write_end(), * them in png_write_end(), and compressing them.
and compressing them. */ */
void void
png_write_info(png_structp png_ptr, png_infop info_ptr) png_write_info(png_structp png_ptr, png_infop info_ptr)
{ {
int i;
png_debug(1, "in png_write_info\n");
png_write_sig(png_ptr); /* write PNG signature */ png_write_sig(png_ptr); /* write PNG signature */
/* write IHDR information. */ /* write IHDR information. */
png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
@ -47,7 +51,8 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
info_ptr->x_blue, info_ptr->y_blue); info_ptr->x_blue, info_ptr->y_blue);
#endif #endif
if (info_ptr->valid & PNG_INFO_PLTE) if (info_ptr->valid & PNG_INFO_PLTE)
png_write_PLTE(png_ptr, info_ptr->palette, info_ptr->num_palette); png_write_PLTE(png_ptr, info_ptr->palette,
(png_uint_32)info_ptr->num_palette);
else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
png_error(png_ptr, "Valid palette required for paletted images\n"); png_error(png_ptr, "Valid palette required for paletted images\n");
#if defined(PNG_WRITE_tRNS_SUPPORTED) #if defined(PNG_WRITE_tRNS_SUPPORTED)
@ -63,16 +68,22 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
if (info_ptr->valid & PNG_INFO_hIST) if (info_ptr->valid & PNG_INFO_hIST)
png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
#endif #endif
#if defined(PNG_WRITE_pHYs_SUPPORTED)
if (info_ptr->valid & PNG_INFO_pHYs)
png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
#endif
#if defined(PNG_WRITE_oFFs_SUPPORTED) #if defined(PNG_WRITE_oFFs_SUPPORTED)
if (info_ptr->valid & PNG_INFO_oFFs) if (info_ptr->valid & PNG_INFO_oFFs)
png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
info_ptr->offset_unit_type); info_ptr->offset_unit_type);
#endif #endif
#if defined(PNG_WRITE_pCAL_SUPPORTED)
if (info_ptr->valid & PNG_INFO_pCAL)
png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
info_ptr->pcal_units, info_ptr->pcal_params);
#endif
#if defined(PNG_WRITE_pHYs_SUPPORTED)
if (info_ptr->valid & PNG_INFO_pHYs)
png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
#endif
#if defined(PNG_WRITE_tIME_SUPPORTED) #if defined(PNG_WRITE_tIME_SUPPORTED)
if (info_ptr->valid & PNG_INFO_tIME) if (info_ptr->valid & PNG_INFO_tIME)
{ {
@ -82,15 +93,68 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
#endif #endif
#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED) #if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
/* Check to see if we need to write text chunks */ /* Check to see if we need to write text chunks */
if (info_ptr->num_text) for (i = 0; i < info_ptr->num_text; i++)
{ {
int i; /* local counter */ png_debug2(2, "Writing header text chunk %d, type %d\n", i,
info_ptr->text[i].compression);
/* If we want a compressed text chunk */
if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
{
#if defined(PNG_WRITE_zTXt_SUPPORTED)
/* write compressed chunk */
png_write_zTXt(png_ptr, info_ptr->text[i].key,
info_ptr->text[i].text, info_ptr->text[i].text_length,
info_ptr->text[i].compression);
#else
png_warning(png_ptr, "Unable to write compressed text\n");
#endif
/* Mark this chunk as written */
info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
}
else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
{
#if defined(PNG_WRITE_tEXt_SUPPORTED)
/* write uncompressed chunk */
png_write_tEXt(png_ptr, info_ptr->text[i].key,
info_ptr->text[i].text, info_ptr->text[i].text_length);
#else
png_warning(png_ptr, "Unable to write uncompressed text\n");
#endif
/* Mark this chunk as written */
info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
}
}
#endif
}
/* loop through the text chunks */ /* Writes the end of the PNG file. If you don't want to write comments or
time information, you can pass NULL for info. If you already wrote these
in png_write_info(), do not write them again here. If you have long
comments, I suggest writing them here, and compressing them. */
void
png_write_end(png_structp png_ptr, png_infop info_ptr)
{
png_debug(1, "in png_write_end\n");
if (!(png_ptr->mode & PNG_HAVE_IDAT))
png_error(png_ptr, "No IDATs written into file");
/* see if user wants us to write information chunks */
if (info_ptr != NULL)
{
int i; /* local index variable */
#if defined(PNG_WRITE_tIME_SUPPORTED)
/* check to see if user has supplied a time chunk */
if (info_ptr->valid & PNG_INFO_tIME &&
!(png_ptr->flags & PNG_FLAG_WROTE_tIME))
png_write_tIME(png_ptr, &(info_ptr->mod_time));
#endif
#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
/* loop through comment chunks */
for (i = 0; i < info_ptr->num_text; i++) for (i = 0; i < info_ptr->num_text; i++)
{ {
/* if chunk is compressed */ png_debug2(2, "Writing trailer text chunk %d, type %d\n", i,
if (info_ptr->text[i].compression >= 0) info_ptr->text[i].compression);
if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
{ {
#if defined(PNG_WRITE_zTXt_SUPPORTED) #if defined(PNG_WRITE_zTXt_SUPPORTED)
/* write compressed chunk */ /* write compressed chunk */
@ -100,8 +164,10 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
#else #else
png_warning(png_ptr, "Unable to write compressed text\n"); png_warning(png_ptr, "Unable to write compressed text\n");
#endif #endif
/* Mark this chunk as written */
info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
} }
else else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
{ {
#if defined(PNG_WRITE_tEXt_SUPPORTED) #if defined(PNG_WRITE_tEXt_SUPPORTED)
/* write uncompressed chunk */ /* write uncompressed chunk */
@ -110,60 +176,9 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
#else #else
png_warning(png_ptr, "Unable to write uncompressed text\n"); png_warning(png_ptr, "Unable to write uncompressed text\n");
#endif #endif
}
}
}
#endif
}
/* writes the end of the png file. If you don't want to write comments or /* Mark this chunk as written */
time information, you can pass NULL for info. If you already wrote these info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
in png_write_info(), do not write them again here. If you have long
comments, I suggest writing them here, and compressing them. */
void
png_write_end(png_structp png_ptr, png_infop info_ptr)
{
if (!(png_ptr->mode & PNG_HAVE_IDAT))
png_error(png_ptr, "No IDATs written into file");
/* see if user wants us to write information chunks */
if (info_ptr)
{
#if defined(PNG_WRITE_tIME_SUPPORTED)
/* check to see if user has supplied a time chunk */
if (info_ptr->valid & PNG_INFO_tIME &&
!(png_ptr->flags & PNG_FLAG_WROTE_tIME))
png_write_tIME(png_ptr, &(info_ptr->mod_time));
#endif
#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
/* check to see if we need to write comment chunks */
if (info_ptr->num_text)
{
int i; /* local index variable */
/* loop through comment chunks */
for (i = 0; i < info_ptr->num_text; i++)
{
#if defined(PNG_WRITE_zTXt_SUPPORTED)
/* check to see if comment is to be compressed */
if (info_ptr->text[i].compression >= 0)
{
/* write compressed chunk */
png_write_zTXt(png_ptr, info_ptr->text[i].key,
info_ptr->text[i].text, info_ptr->text[i].text_length,
info_ptr->text[i].compression);
}
#if defined(PNG_WRITE_tEXt_SUPPORTED)
else
#endif
#endif
#if defined(PNG_WRITE_tEXt_SUPPORTED)
{
/* write uncompressed chunk */
png_write_tEXt(png_ptr, info_ptr->text[i].key,
info_ptr->text[i].text, info_ptr->text[i].text_length);
}
#endif
} }
} }
#endif #endif
@ -171,7 +186,7 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
png_ptr->mode |= PNG_AFTER_IDAT; png_ptr->mode |= PNG_AFTER_IDAT;
/* write end of png file */ /* write end of PNG file */
png_write_IEND(png_ptr); png_write_IEND(png_ptr);
} }
@ -179,6 +194,7 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
void void
png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime) png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime)
{ {
png_debug(1, "in png_convert_from_struct_tm\n");
ptime->year = (png_uint_16)(1900 + ttime->tm_year); ptime->year = (png_uint_16)(1900 + ttime->tm_year);
ptime->month = (png_byte)(ttime->tm_mon + 1); ptime->month = (png_byte)(ttime->tm_mon + 1);
ptime->day = (png_byte)ttime->tm_mday; ptime->day = (png_byte)ttime->tm_mday;
@ -192,12 +208,13 @@ png_convert_from_time_t(png_timep ptime, time_t ttime)
{ {
struct tm *tbuf; struct tm *tbuf;
png_debug(1, "in png_convert_from_time_t\n");
tbuf = gmtime(&ttime); tbuf = gmtime(&ttime);
png_convert_from_struct_tm(ptime, tbuf); png_convert_from_struct_tm(ptime, tbuf);
} }
#endif #endif
/* initialize png structure, and allocate any memory needed */ /* Initialize png_ptr structure, and allocate any memory needed */
png_structp png_structp
png_create_write_struct(png_const_charp user_png_ver, voidp error_ptr, png_create_write_struct(png_const_charp user_png_ver, voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn) png_error_ptr error_fn, png_error_ptr warn_fn)
@ -206,6 +223,7 @@ png_create_write_struct(png_const_charp user_png_ver, voidp error_ptr,
#ifdef USE_FAR_KEYWORD #ifdef USE_FAR_KEYWORD
jmp_buf jmpbuf; jmp_buf jmpbuf;
#endif #endif
png_debug(1, "in png_create_write_struct\n");
if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL) if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
{ {
return (png_structp)NULL; return (png_structp)NULL;
@ -225,16 +243,16 @@ png_create_write_struct(png_const_charp user_png_ver, voidp error_ptr,
#endif #endif
png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
if (user_png_ver == NULL || png_strcmp(user_png_ver, png_libpng_ver)) /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
* we must recompile any applications that use any older library version.
* For versions after libpng 1.0, we will be compatible, so we need
* only check the first digit.
*/
if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
(png_libpng_ver[0] == '0' && user_png_ver[2] < '9'))
{ {
if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0]) png_error(png_ptr,
{ "Incompatible libpng version in application and library");
png_error(png_ptr, "Incompatible libpng versions");
}
else
{
png_warning(png_ptr, "Different libpng versions");
}
} }
/* initialize zbuf - compression buffer */ /* initialize zbuf - compression buffer */
@ -247,12 +265,13 @@ png_create_write_struct(png_const_charp user_png_ver, voidp error_ptr,
} }
/* initialize png structure, and allocate any memory needed */ /* Initialize png_ptr structure, and allocate any memory needed */
void void
png_write_init(png_structp png_ptr) png_write_init(png_structp png_ptr)
{ {
jmp_buf tmp_jmp; /* to save current jump buffer */ jmp_buf tmp_jmp; /* to save current jump buffer */
png_debug(1, "in png_write_init\n");
/* save jump buffer and error functions */ /* save jump buffer and error functions */
png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf)); png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
@ -266,6 +285,11 @@ png_write_init(png_structp png_ptr)
png_ptr->zbuf_size = PNG_ZBUF_SIZE; png_ptr->zbuf_size = PNG_ZBUF_SIZE;
png_ptr->zbuf = png_malloc(png_ptr, png_ptr->zbuf_size); png_ptr->zbuf = png_malloc(png_ptr, png_ptr->zbuf_size);
png_set_write_fn(png_ptr, NULL, NULL, NULL); png_set_write_fn(png_ptr, NULL, NULL, NULL);
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
png_set_filter_heuristics(png_ptr, PNG_FILTER_HEURISTIC_DEFAULT,
1, NULL, NULL);
#endif
} }
/* write a few rows of image data. If the image is interlaced, /* write a few rows of image data. If the image is interlaced,
@ -279,6 +303,7 @@ png_write_rows(png_structp png_ptr, png_bytepp row,
png_uint_32 i; /* row counter */ png_uint_32 i; /* row counter */
png_bytepp rp; /* row pointer */ png_bytepp rp; /* row pointer */
png_debug(1, "in png_write_rows\n");
/* loop through the rows */ /* loop through the rows */
for (i = 0, rp = row; i < num_rows; i++, rp++) for (i = 0, rp = row; i < num_rows; i++, rp++)
{ {
@ -295,6 +320,7 @@ png_write_image(png_structp png_ptr, png_bytepp image)
int pass, num_pass; /* pass variables */ int pass, num_pass; /* pass variables */
png_bytepp rp; /* points to current row */ png_bytepp rp; /* points to current row */
png_debug(1, "in png_write_image\n");
/* intialize interlace handling. If image is not interlaced, /* intialize interlace handling. If image is not interlaced,
this will set pass to 1 */ this will set pass to 1 */
num_pass = png_set_interlace_handling(png_ptr); num_pass = png_set_interlace_handling(png_ptr);
@ -313,6 +339,7 @@ png_write_image(png_structp png_ptr, png_bytepp image)
void void
png_write_row(png_structp png_ptr, png_bytep row) png_write_row(png_structp png_ptr, png_bytep row)
{ {
png_debug(1, "in png_write_row\n");
/* initialize transformations and other stuff if first time */ /* initialize transformations and other stuff if first time */
if (png_ptr->row_number == 0 && png_ptr->pass == 0) if (png_ptr->row_number == 0 && png_ptr->pass == 0)
{ {
@ -388,8 +415,15 @@ png_write_row(png_structp png_ptr, png_bytep row)
png_ptr->row_info.rowbytes = ((png_ptr->row_info.width * png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
(png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3); (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
/* copy users row into buffer, leaving room for filter byte */ png_debug1(4, "row_info->color_type = %d\n", png_ptr->row_info.color_type);
png_memcpy(png_ptr->row_buf + 1, row, (png_size_t)png_ptr->row_info.rowbytes); png_debug1(4, "row_info->width = %d\n", png_ptr->row_info.width);
png_debug1(4, "row_info->channels = %d\n", png_ptr->row_info.channels);
png_debug1(4, "row_info->bit_depth = %d\n", png_ptr->row_info.bit_depth);
png_debug1(4, "row_info->pixel_depth = %d\n", png_ptr->row_info.pixel_depth);
png_debug1(4, "row_info->rowbytes = %d\n", png_ptr->row_info.rowbytes);
/* Copy user's row into buffer, leaving room for filter byte. */
png_memcpy(png_ptr->row_buf + 1, row, png_ptr->row_info.rowbytes);
#if defined(PNG_WRITE_INTERLACING_SUPPORTED) #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
/* handle interlacing */ /* handle interlacing */
@ -411,7 +445,7 @@ png_write_row(png_structp png_ptr, png_bytep row)
if (png_ptr->transformations) if (png_ptr->transformations)
png_do_write_transformations(png_ptr); png_do_write_transformations(png_ptr);
/* find a filter if necessary, filter the row and write it out */ /* Find a filter if necessary, filter the row and write it out. */
png_write_find_filter(png_ptr, &(png_ptr->row_info)); png_write_find_filter(png_ptr, &(png_ptr->row_info));
} }
@ -420,6 +454,7 @@ png_write_row(png_structp png_ptr, png_bytep row)
void void
png_set_flush(png_structp png_ptr, int nrows) png_set_flush(png_structp png_ptr, int nrows)
{ {
png_debug(1, "in png_set_flush\n");
png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
} }
@ -429,6 +464,7 @@ png_write_flush(png_structp png_ptr)
{ {
int wrote_IDAT; int wrote_IDAT;
png_debug(1, "in png_write_flush\n");
/* We have already written out all of the data */ /* We have already written out all of the data */
if (png_ptr->row_number >= png_ptr->num_rows) if (png_ptr->row_number >= png_ptr->num_rows)
return; return;
@ -444,13 +480,13 @@ png_write_flush(png_structp png_ptr)
/* check for compression errors */ /* check for compression errors */
if (ret != Z_OK) if (ret != Z_OK)
{ {
if (png_ptr->zstream.msg) if (png_ptr->zstream.msg != NULL)
png_error(png_ptr, png_ptr->zstream.msg); png_error(png_ptr, png_ptr->zstream.msg);
else else
png_error(png_ptr, "zlib error"); png_error(png_ptr, "zlib error");
} }
if (!png_ptr->zstream.avail_out) if (!(png_ptr->zstream.avail_out))
{ {
/* write the IDAT and reset the zlib output buffer */ /* write the IDAT and reset the zlib output buffer */
png_write_IDAT(png_ptr, png_ptr->zbuf, png_write_IDAT(png_ptr, png_ptr->zbuf,
@ -482,19 +518,20 @@ png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
png_structp png_ptr = NULL; png_structp png_ptr = NULL;
png_infop info_ptr = NULL; png_infop info_ptr = NULL;
if (png_ptr_ptr) png_debug(1, "in png_destroy_write_struct\n");
if (png_ptr_ptr != NULL)
png_ptr = *png_ptr_ptr; png_ptr = *png_ptr_ptr;
if (info_ptr_ptr) if (info_ptr_ptr != NULL)
info_ptr = *info_ptr_ptr; info_ptr = *info_ptr_ptr;
if (info_ptr) if (info_ptr != NULL)
{ {
png_destroy_struct((png_voidp)info_ptr); png_destroy_struct((png_voidp)info_ptr);
*info_ptr_ptr = (png_infop)NULL; *info_ptr_ptr = (png_infop)NULL;
} }
if (png_ptr) if (png_ptr != NULL)
{ {
png_write_destroy(png_ptr); png_write_destroy(png_ptr);
png_destroy_struct((png_voidp)png_ptr); png_destroy_struct((png_voidp)png_ptr);
@ -503,7 +540,7 @@ png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
} }
/* free any memory used in png struct (old method) */ /* Free any memory used in png_ptr struct (old method) */
void void
png_write_destroy(png_structp png_ptr) png_write_destroy(png_structp png_ptr)
{ {
@ -512,6 +549,7 @@ png_write_destroy(png_structp png_ptr)
png_error_ptr warning_fn; png_error_ptr warning_fn;
png_voidp error_ptr; png_voidp error_ptr;
png_debug(1, "in png_write_destroy\n");
/* free any memory zlib uses */ /* free any memory zlib uses */
deflateEnd(&png_ptr->zstream); deflateEnd(&png_ptr->zstream);
@ -523,6 +561,13 @@ png_write_destroy(png_structp png_ptr)
png_free(png_ptr, png_ptr->up_row); png_free(png_ptr, png_ptr->up_row);
png_free(png_ptr, png_ptr->avg_row); png_free(png_ptr, png_ptr->avg_row);
png_free(png_ptr, png_ptr->paeth_row); png_free(png_ptr, png_ptr->paeth_row);
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
png_free(png_ptr, png_ptr->prev_filters);
png_free(png_ptr, png_ptr->filter_weights);
png_free(png_ptr, png_ptr->inv_filter_weights);
png_free(png_ptr, png_ptr->filter_costs);
png_free(png_ptr, png_ptr->inv_filter_costs);
#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
/* reset structure */ /* reset structure */
png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf)); png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
@ -540,71 +585,79 @@ png_write_destroy(png_structp png_ptr)
png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf)); png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
} }
/* Allow the application to select one or more filters to use */ /* Allow the application to select one or more row filters to use. */
void void
png_set_filter(png_structp png_ptr, int method, int filters) png_set_filter(png_structp png_ptr, int method, int filters)
{ {
/* We allow 'method' only for future expansion of the base filter method */ png_debug(1, "in png_set_filter\n");
if (method == 0) /* We allow 'method' only for future expansion of the base filter method. */
if (method == PNG_FILTER_TYPE_BASE)
{ {
switch (filters & (PNG_ALL_FILTERS | 0x07)) switch (filters & (PNG_ALL_FILTERS | 0x07))
{ {
case 5: case 5:
case 6: case 6:
case 7: png_warning(png_ptr, "Unknown custom row filter for method 0"); case 7: png_warning(png_ptr, "Unknown row filter for method 0");
case 0: png_ptr->do_filter = PNG_FILTER_NONE; break; case PNG_FILTER_VALUE_NONE: png_ptr->do_filter=PNG_FILTER_NONE; break;
case 1: png_ptr->do_filter = PNG_FILTER_SUB; break; case PNG_FILTER_VALUE_SUB: png_ptr->do_filter=PNG_FILTER_SUB; break;
case 2: png_ptr->do_filter = PNG_FILTER_UP; break; case PNG_FILTER_VALUE_UP: png_ptr->do_filter=PNG_FILTER_UP; break;
case 3: png_ptr->do_filter = PNG_FILTER_AVG; break; case PNG_FILTER_VALUE_AVG: png_ptr->do_filter=PNG_FILTER_AVG; break;
case 4: png_ptr->do_filter = PNG_FILTER_PAETH; break; case PNG_FILTER_VALUE_PAETH: png_ptr->do_filter=PNG_FILTER_PAETH;break;
default: png_ptr->do_filter = (png_byte)filters; break; default: png_ptr->do_filter = (png_byte)filters; break;
} }
/* If we have allocated the row_buf, then we should have also allocated /* If we have allocated the row_buf, this means we have already started
* all of the filter buffers that have been selected. * with the image and we should have allocated all of the filter buffers
* that have been selected. If prev_row isn't already allocated, then
* it is too late to start using the filters that need it, since we
* will be missing the data in the previous row. If an application
* wants to start and stop using particular filters during compression,
* it should start out with all of the filters, and then add and
* remove them after the start of compression.
*/ */
if (png_ptr->row_buf) if (png_ptr->row_buf != NULL)
{ {
if (png_ptr->do_filter & PNG_FILTER_SUB && !(png_ptr->sub_row)) if (png_ptr->do_filter & PNG_FILTER_SUB && png_ptr->sub_row == NULL)
{ {
png_ptr->sub_row = (png_bytep )png_malloc(png_ptr, png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
png_ptr->rowbytes + 1); png_ptr->rowbytes + 1);
png_ptr->sub_row[0] = 1; /* Set the row filter type */ png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
} }
if (png_ptr->do_filter & PNG_FILTER_UP && !(png_ptr->up_row)) if (png_ptr->do_filter & PNG_FILTER_UP && png_ptr->up_row == NULL)
{ {
if (!(png_ptr->prev_row)) if (png_ptr->prev_row == NULL)
{ {
png_warning(png_ptr, "Can't to add up filter after starting"); png_warning(png_ptr, "Can't add Up filter after starting");
png_ptr->do_filter &= ~PNG_FILTER_UP; png_ptr->do_filter &= ~PNG_FILTER_UP;
} }
else else
{ {
png_ptr->up_row = (png_bytep )png_malloc(png_ptr, png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
png_ptr->rowbytes + 1); png_ptr->rowbytes + 1);
png_ptr->up_row[0] = 2; /* Set the row filter type */ png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
} }
} }
if (png_ptr->do_filter & PNG_FILTER_AVG && !(png_ptr->avg_row)) if (png_ptr->do_filter & PNG_FILTER_AVG && png_ptr->avg_row == NULL)
{ {
if (!(png_ptr->prev_row)) if (png_ptr->prev_row == NULL)
{ {
png_warning(png_ptr, "Can't add average filter after starting"); png_warning(png_ptr, "Can't add Average filter after starting");
png_ptr->do_filter &= ~PNG_FILTER_AVG; png_ptr->do_filter &= ~PNG_FILTER_AVG;
} }
else else
{ {
png_ptr->up_row = (png_bytep )png_malloc(png_ptr, png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
png_ptr->rowbytes + 1); png_ptr->rowbytes + 1);
png_ptr->up_row[0] = 3; /* Set the row filter type */ png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
} }
} }
if (png_ptr->do_filter & PNG_FILTER_PAETH && !(png_ptr->paeth_row)) if (png_ptr->do_filter & PNG_FILTER_PAETH &&
png_ptr->paeth_row == NULL)
{ {
if (!(png_ptr->prev_row)) if (png_ptr->prev_row == NULL)
{ {
png_warning(png_ptr, "Can't add Paeth filter after starting"); png_warning(png_ptr, "Can't add Paeth filter after starting");
png_ptr->do_filter &= ~PNG_FILTER_PAETH; png_ptr->do_filter &= ~PNG_FILTER_PAETH;
@ -613,7 +666,7 @@ png_set_filter(png_structp png_ptr, int method, int filters)
{ {
png_ptr->paeth_row = (png_bytep )png_malloc(png_ptr, png_ptr->paeth_row = (png_bytep )png_malloc(png_ptr,
png_ptr->rowbytes + 1); png_ptr->rowbytes + 1);
png_ptr->paeth_row[0] = 4; /* Set the row filter type */ png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
} }
} }
@ -622,12 +675,137 @@ png_set_filter(png_structp png_ptr, int method, int filters)
} }
} }
else else
png_error(png_ptr, "Unknown custom filter method"); png_error(png_ptr, "Unknown custom filter method");
} }
/* This allows us to influence the way in which libpng chooses the "best"
* filter for the current scanline. While the "minimum-sum-of-absolute-
* differences metric is relatively fast and effective, there is some
* question as to whether it can be improved upon by trying to keep the
* filtered data going to zlib more consistent, hopefully resulting in
* better compression. */
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* GRR 970116 */
void
png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
int num_weights, png_doublep filter_weights,
png_doublep filter_costs)
{
int i;
png_debug(1, "in png_set_filter_heuristics\n");
if (heuristic_method >= PNG_FILTER_HEURISTIC_LAST)
{
png_warning(png_ptr, "Unknown filter heuristic method");
return;
}
if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT)
{
heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED;
}
if (num_weights < 0 || filter_weights == NULL ||
heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED)
{
num_weights = 0;
}
png_ptr->num_prev_filters = num_weights;
png_ptr->heuristic_method = heuristic_method;
if (num_weights > 0)
{
if (png_ptr->prev_filters == NULL)
{
png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
sizeof(png_byte) * num_weights);
/* To make sure that the weighting starts out fairly */
for (i = 0; i < num_weights; i++)
{
png_ptr->prev_filters[i] = 255;
}
}
if (png_ptr->filter_weights == NULL)
{
png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr,
sizeof(png_uint_16) * num_weights);
png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr,
sizeof(png_uint_16) * num_weights);
for (i = 0; i < num_weights; i++)
{
png_ptr->inv_filter_weights[i] =
png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
}
}
for (i = 0; i < num_weights; i++)
{
if (filter_weights[i] < 0.0)
{
png_ptr->inv_filter_weights[i] =
png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR;
}
else
{
png_ptr->inv_filter_weights[i] =
(png_uint_16)((double)PNG_WEIGHT_FACTOR*filter_weights[i]+0.5);
png_ptr->filter_weights[i] =
(png_uint_16)((double)PNG_WEIGHT_FACTOR/filter_weights[i]+0.5);
}
}
}
/* If, in the future, there are other filter methods, this would
* need to be based on png_ptr->filter.
*/
if (png_ptr->filter_costs == NULL)
{
png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr,
sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST);
png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr,
sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST);
for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
{
png_ptr->inv_filter_costs[i] =
png_ptr->filter_costs[i] = PNG_COST_FACTOR;
}
}
/* Here is where we set the relative costs of the different filters. We
* should take the desired compression level into account when setting
* the costs, so that Paeth, for instance, has a high relative cost at low
* compression levels, while it has a lower relative cost at higher
* compression settings. The filter types are in order of increasing
* relative cost, so it would be possible to do this with an algorithm.
*/
for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
{
if (filter_costs == NULL || filter_costs[i] < 0.0)
{
png_ptr->inv_filter_costs[i] =
png_ptr->filter_costs[i] = PNG_COST_FACTOR;
}
else if (filter_costs[i] >= 1.0)
{
png_ptr->inv_filter_costs[i] =
(png_uint_16)((double)PNG_COST_FACTOR / filter_costs[i] + 0.5);
png_ptr->filter_costs[i] =
(png_uint_16)((double)PNG_COST_FACTOR * filter_costs[i] + 0.5);
}
}
}
#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
void void
png_set_compression_level(png_structp png_ptr, int level) png_set_compression_level(png_structp png_ptr, int level)
{ {
png_debug(1, "in png_set_compression_level\n");
png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL; png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL;
png_ptr->zlib_level = level; png_ptr->zlib_level = level;
} }
@ -635,6 +813,7 @@ png_set_compression_level(png_structp png_ptr, int level)
void void
png_set_compression_mem_level(png_structp png_ptr, int mem_level) png_set_compression_mem_level(png_structp png_ptr, int mem_level)
{ {
png_debug(1, "in png_set_compression_mem_level\n");
png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL; png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL;
png_ptr->zlib_mem_level = mem_level; png_ptr->zlib_mem_level = mem_level;
} }
@ -642,6 +821,7 @@ png_set_compression_mem_level(png_structp png_ptr, int mem_level)
void void
png_set_compression_strategy(png_structp png_ptr, int strategy) png_set_compression_strategy(png_structp png_ptr, int strategy)
{ {
png_debug(1, "in png_set_compression_strategy\n");
png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
png_ptr->zlib_strategy = strategy; png_ptr->zlib_strategy = strategy;
} }
@ -658,6 +838,7 @@ png_set_compression_window_bits(png_structp png_ptr, int window_bits)
void void
png_set_compression_method(png_structp png_ptr, int method) png_set_compression_method(png_structp png_ptr, int method)
{ {
png_debug(1, "in png_set_compression_method\n");
if (method != 8) if (method != 8)
png_warning(png_ptr, "Only compression method 8 is supported by PNG"); png_warning(png_ptr, "Only compression method 8 is supported by PNG");
png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD; png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD;

View File

@ -1,10 +1,11 @@
/* pngwtran.c - transforms the data in a row for png writers /* pngwtran.c - transforms the data in a row for PNG writers
libpng 1.0 beta 4 - version 0.90 libpng 1.0 beta 6 - version 0.96
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 10, 1997 Copyright (c) 1996, 1997 Andreas Dilger
May 12, 1997
*/ */
#define PNG_INTERNAL #define PNG_INTERNAL
@ -15,15 +16,16 @@
void void
png_do_write_transformations(png_structp png_ptr) png_do_write_transformations(png_structp png_ptr)
{ {
png_debug(1, "in png_do_write_transformations\n");
#if defined(PNG_WRITE_FILLER_SUPPORTED) #if defined(PNG_WRITE_FILLER_SUPPORTED)
if (png_ptr->transformations & PNG_FILLER) if (png_ptr->transformations & PNG_FILLER)
png_do_write_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, png_do_strip_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
png_ptr->flags); png_ptr->flags);
#endif #endif
#if defined(PNG_WRITE_PACK_SUPPORTED) #if defined(PNG_WRITE_PACK_SUPPORTED)
if (png_ptr->transformations & PNG_PACK) if (png_ptr->transformations & PNG_PACK)
png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1, png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1,
png_ptr->bit_depth); (png_uint_32)png_ptr->bit_depth);
#endif #endif
#if defined(PNG_WRITE_SHIFT_SUPPORTED) #if defined(PNG_WRITE_SHIFT_SUPPORTED)
if (png_ptr->transformations & PNG_SHIFT) if (png_ptr->transformations & PNG_SHIFT)
@ -34,6 +36,10 @@ png_do_write_transformations(png_structp png_ptr)
if (png_ptr->transformations & PNG_SWAP_BYTES) if (png_ptr->transformations & PNG_SWAP_BYTES)
png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1); png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif #endif
#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
if (png_ptr->transformations & PNG_SWAP_ALPHA)
png_do_write_swap_alpha(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif
#if defined(PNG_WRITE_BGR_SUPPORTED) #if defined(PNG_WRITE_BGR_SUPPORTED)
if (png_ptr->transformations & PNG_BGR) if (png_ptr->transformations & PNG_BGR)
png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1); png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
@ -49,20 +55,22 @@ png_do_write_transformations(png_structp png_ptr)
row_info bit depth should be 8 (one pixel per byte). The channels row_info bit depth should be 8 (one pixel per byte). The channels
should be 1 (this only happens on grayscale and paletted images) */ should be 1 (this only happens on grayscale and paletted images) */
void void
png_do_pack(png_row_infop row_info, png_bytep row, png_byte bit_depth) png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
{ {
if (row_info && row && row_info->bit_depth == 8 && png_debug(1, "in png_do_pack\n");
if (row_info->bit_depth == 8 &&
#if defined(PNG_USELESS_TESTS_SUPPORTED)
row != NULL && row_info != NULL &&
#endif
row_info->channels == 1) row_info->channels == 1)
{ {
switch (bit_depth) switch ((int)bit_depth)
{ {
case 1: case 1:
{ {
png_bytep sp; png_bytep sp, dp;
png_bytep dp; int mask, v;
int mask; png_uint_32 i;
png_int_32 i;
int v;
sp = row; sp = row;
dp = row; dp = row;
@ -70,7 +78,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_byte bit_depth)
v = 0; v = 0;
for (i = 0; i < row_info->width; i++) for (i = 0; i < row_info->width; i++)
{ {
if (*sp) if (*sp != 0)
v |= mask; v |= mask;
sp++; sp++;
if (mask > 1) if (mask > 1)
@ -89,12 +97,9 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_byte bit_depth)
} }
case 2: case 2:
{ {
png_bytep sp; png_bytep sp, dp;
png_bytep dp; int shift, v;
int shift; png_uint_32 i;
png_int_32 i;
int v;
png_byte value;
sp = row; sp = row;
dp = row; dp = row;
@ -102,6 +107,8 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_byte bit_depth)
v = 0; v = 0;
for (i = 0; i < row_info->width; i++) for (i = 0; i < row_info->width; i++)
{ {
png_byte value;
value = (png_byte)(*sp & 0x3); value = (png_byte)(*sp & 0x3);
v |= (value << shift); v |= (value << shift);
if (shift == 0) if (shift == 0)
@ -121,12 +128,9 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_byte bit_depth)
} }
case 4: case 4:
{ {
png_bytep sp; png_bytep sp, dp;
png_bytep dp; int shift, v;
int shift; png_uint_32 i;
png_int_32 i;
int v;
png_byte value;
sp = row; sp = row;
dp = row; dp = row;
@ -134,6 +138,8 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_byte bit_depth)
v = 0; v = 0;
for (i = 0; i < row_info->width; i++) for (i = 0; i < row_info->width; i++)
{ {
png_byte value;
value = (png_byte)(*sp & 0xf); value = (png_byte)(*sp & 0xf);
v |= (value << shift); v |= (value << shift);
@ -154,8 +160,8 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_byte bit_depth)
break; break;
} }
} }
row_info->bit_depth = bit_depth; row_info->bit_depth = (png_byte)bit_depth;
row_info->pixel_depth = (png_uint_16)(bit_depth * row_info->channels); row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
row_info->rowbytes = row_info->rowbytes =
((row_info->width * row_info->pixel_depth + 7) >> 3); ((row_info->width * row_info->pixel_depth + 7) >> 3);
} }
@ -172,11 +178,16 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_byte bit_depth)
void void
png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth) png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
{ {
if (row && row_info && png_debug(1, "in png_do_shift\n");
#if defined(PNG_USELESS_TESTS_SUPPORTED)
if (row != NULL && row_info != NULL &&
#else
if (
#endif
row_info->color_type != PNG_COLOR_TYPE_PALETTE) row_info->color_type != PNG_COLOR_TYPE_PALETTE)
{ {
int shift_start[4], shift_dec[4]; int shift_start[4], shift_dec[4];
int channels; png_uint_32 channels;
channels = 0; channels = 0;
if (row_info->color_type & PNG_COLOR_MASK_COLOR) if (row_info->color_type & PNG_COLOR_MASK_COLOR)
@ -209,7 +220,6 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
{ {
png_bytep bp; png_bytep bp;
png_uint_32 i; png_uint_32 i;
int j;
png_byte mask; png_byte mask;
if (bit_depth->gray == 1 && row_info->bit_depth == 2) if (bit_depth->gray == 1 && row_info->bit_depth == 2)
@ -221,7 +231,8 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
for (bp = row, i = 0; i < row_info->rowbytes; i++, bp++) for (bp = row, i = 0; i < row_info->rowbytes; i++, bp++)
{ {
int v; png_uint_16 v;
int j;
v = *bp; v = *bp;
*bp = 0; *bp = 0;
@ -238,7 +249,6 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
{ {
png_bytep bp; png_bytep bp;
png_uint_32 i; png_uint_32 i;
int j;
for (bp = row, i = 0; i < row_info->width; i++) for (bp = row, i = 0; i < row_info->width; i++)
{ {
@ -246,7 +256,8 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
for (c = 0; c < channels; c++, bp++) for (c = 0; c < channels; c++, bp++)
{ {
int v; png_uint_16 v;
int j;
v = *bp; v = *bp;
*bp = 0; *bp = 0;
@ -264,20 +275,17 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
{ {
png_bytep bp; png_bytep bp;
png_uint_32 i; png_uint_32 i;
int j;
for (bp = row, i = 0; for (bp = row, i = 0; i < row_info->width * row_info->channels; i++)
i < row_info->width * row_info->channels;
i++)
{ {
int c; int c;
for (c = 0; c < channels; c++, bp += 2) for (c = 0; c < channels; c++, bp += 2)
{ {
png_uint_16 value, v; png_uint_16 value, v;
int j;
v = (png_uint_16)(((png_uint_16)(*bp) << 8) + v = ((png_uint_16)(*bp) << 8) + *(bp + 1);
(png_uint_16)(*(bp + 1)));
value = 0; value = 0;
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c]) for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
{ {
@ -295,51 +303,88 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
} }
#endif #endif
#ifdef PNG_WRITE_FILLER_SUPPORTED #if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
/* remove filler byte */
void void
png_do_write_filler(png_row_infop row_info, png_bytep row, png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
png_uint_32 flags)
{ {
if (row && row_info && row_info->color_type == PNG_COLOR_TYPE_RGB && png_debug(1, "in png_do_write_swap_alpha\n");
row_info->bit_depth == 8) #if defined(PNG_USELESS_TESTS_SUPPORTED)
if (row != NULL && row_info != NULL)
#endif
{ {
if (flags & PNG_FLAG_FILLER_AFTER) if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
{ {
png_bytep sp, dp; /* This converts from ARGB to RGBA */
if (row_info->bit_depth == 8)
png_uint_32 i;
for (i = 1, sp = row + 4, dp = row + 3;
i < row_info->width;
i++)
{ {
*dp++ = *sp++; png_bytep sp, dp;
*dp++ = *sp++; png_byte save;
*dp++ = *sp++; png_uint_32 i;
sp++;
for (i = 0, sp = dp = row; i < row_info->width; i++)
{
save = *(sp++);
*(dp++) = *(sp++);
*(dp++) = *(sp++);
*(dp++) = *(sp++);
*(dp++) = save;
}
}
/* This converts from AARRGGBB to RRGGBBAA */
else
{
png_bytep sp, dp;
png_byte save[2];
png_uint_32 i;
for (i = 0, sp = dp = row; i < row_info->width; i++)
{
save[0] = *(sp++);
save[1] = *(sp++);
*(dp++) = *(sp++);
*(dp++) = *(sp++);
*(dp++) = *(sp++);
*(dp++) = *(sp++);
*(dp++) = *(sp++);
*(dp++) = *(sp++);
*(dp++) = save[0];
*(dp++) = save[1];
}
} }
row_info->channels = 3;
row_info->pixel_depth = 24;
row_info->rowbytes = row_info->width * 3;
} }
else else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
{ {
png_bytep sp, dp; /* This converts from AG to GA */
png_uint_32 i; if (row_info->bit_depth == 8)
for (i = 0, sp = row, dp = row;
i < row_info->width;
i++)
{ {
sp++; png_bytep sp, dp;
*dp++ = *sp++; png_byte save;
*dp++ = *sp++; png_uint_32 i;
*dp++ = *sp++;
for (i = 0, sp = dp = row; i < row_info->width; i++)
{
save = *(sp++);
*(dp++) = *(sp++);
*(dp++) = save;
}
}
/* This converts from AAGG to GGAA */
else
{
png_bytep sp, dp;
png_byte save[2];
png_uint_32 i;
for (i = 0, sp = dp = row; i < row_info->width; i++)
{
save[0] = *(sp++);
save[1] = *(sp++);
*(dp++) = *(sp++);
*(dp++) = *(sp++);
*(dp++) = save[0];
*(dp++) = save[1];
}
} }
row_info->channels = 3;
row_info->pixel_depth = 24;
row_info->rowbytes = row_info->width * 3;
} }
} }
} }

1024
pngwutil.c

File diff suppressed because it is too large Load Diff