Imported from libpng-0.82.tar
This commit is contained in:
parent
51f0eb4584
commit
0f71645dfe
48
example.c
48
example.c
@ -79,9 +79,19 @@ void read_png(char *file_name)
|
||||
png_info_init(info_ptr);
|
||||
png_read_init(png_ptr);
|
||||
|
||||
/* set up the input control */
|
||||
/* set up the input control for the default input and message functions.
|
||||
* If we were to replace both the input and message functions we don't
|
||||
* need to call png_init_io first. */
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
/* if you are using replacement read functions, here you would call */
|
||||
io_ptr = (user_io_struct *)malloc(sizeof(user_io_struct));
|
||||
png_set_read_fn(png_ptr, (void *)io_ptr, user_read_fn);
|
||||
|
||||
/* if you are using replacement message functions, here you would call */
|
||||
msg_ptr = (user_msg_struct *)malloc(sizeof(user_msg_struct));
|
||||
png_set_read_fn(png_ptr, (void *)msg_ptr, user_error_fn, user_warning_fn);
|
||||
|
||||
/* read the file information */
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
@ -146,8 +156,7 @@ void read_png(char *file_name)
|
||||
png_set_invert(png_ptr);
|
||||
|
||||
/* shift the pixels down to their true bit depth */
|
||||
if (info_ptr->valid & PNG_INFO_sBIT &&
|
||||
info_ptr->bit_depth > info_ptr->sig_bit)
|
||||
if (info_ptr->valid & PNG_INFO_sBIT)
|
||||
png_set_shift(png_ptr, &(info_ptr->sig_bit));
|
||||
|
||||
/* pack pixels into bytes */
|
||||
@ -212,6 +221,11 @@ void read_png(char *file_name)
|
||||
in info_ptr */
|
||||
png_read_end(png_ptr, info_ptr);
|
||||
|
||||
/* if you had allocated any memory structures for custom input or
|
||||
messaging routines you need to free them before png_read_destroy */
|
||||
free(png_get_io_ptr(png_ptr));
|
||||
free(png_get_msg_ptr(png_ptr));
|
||||
|
||||
/* clean up after the read, and free any memory allocated */
|
||||
png_read_destroy(png_ptr, info_ptr, (png_info *)0);
|
||||
|
||||
@ -269,9 +283,19 @@ void write_png(char *file_name, ... other image information ...)
|
||||
png_info_init(info_ptr);
|
||||
png_write_init(png_ptr);
|
||||
|
||||
/* set up the output control */
|
||||
/* set up the output control for the default output and message functions.
|
||||
* If we were to replace both the output and message functions we don't
|
||||
* need to call png_init_io first. */
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
/* if you are using replacement write functions, here you would call */
|
||||
io_ptr = (user_io_struct *)malloc(sizeof(user_io_struct));
|
||||
png_set_write_fn(png_ptr, (void *)io_ptr, user_write_fn, user_flush_fn);
|
||||
|
||||
/* if you are using replacement message functions, here you would call */
|
||||
msg_ptr = (user_msg_struct *)malloc(sizeof(user_msg_struct));
|
||||
png_set_read_fn(png_ptr, (void *)msg_ptr, user_error_fn, user_warning_fn);
|
||||
|
||||
/* set the file information here */
|
||||
info_ptr->width = ;
|
||||
info_ptr->height = ;
|
||||
@ -285,9 +309,16 @@ void write_png(char *file_name, ... other image information ...)
|
||||
|
||||
/* optional significant bit chunk */
|
||||
info_ptr->valid |= PNG_INFO_sBIT;
|
||||
info_ptr->sig_bit = true_bit_depth;
|
||||
/* if we are dealing with a grayscale image then */
|
||||
info_ptr->sig_bit.gray = true_bit_depth;
|
||||
/* otherwise, if we are dealing with a color image then */
|
||||
info_ptr->sig_bit.red = true_red_bit_depth;
|
||||
info_ptr->sig_bit.green = true_green_bit_depth;
|
||||
info_ptr->sig_bit.blue = true_blue_bit_depth;
|
||||
/* if the image has an alpha channel then */
|
||||
info_ptr->sig_bit.alpha = true_alpha_bit_depth;
|
||||
|
||||
/* optional gamma chunk */
|
||||
/* optional gamma chunk is a good idea if you can write one */
|
||||
info_ptr->valid |= PNG_INFO_gAMA;
|
||||
info_ptr->gamma = gamma;
|
||||
|
||||
@ -347,6 +378,11 @@ void write_png(char *file_name, ... other image information ...)
|
||||
/* write the rest of the file */
|
||||
png_write_end(png_ptr, info_ptr);
|
||||
|
||||
/* if you had allocated any memory structures for custom output or
|
||||
messaging routines you need to free them before png_write_destroy */
|
||||
free(png_get_io_ptr(png_ptr));
|
||||
free(png_get_msg_ptr(png_ptr));
|
||||
|
||||
/* clean up after the write, and free any memory allocated */
|
||||
png_write_destroy(png_ptr);
|
||||
|
||||
|
250
libpng.txt
250
libpng.txt
@ -45,22 +45,22 @@ The structures:
|
||||
There are two main structures that are important to libpng, png_struct
|
||||
and png_info. The first, png_struct, is an internal structure that
|
||||
will not, for the most part, be used by the general user except as
|
||||
the first variable passed to every png function call.
|
||||
the first variable passed to every PNG function call.
|
||||
|
||||
The png_info structure is designed to provide information about the
|
||||
png file. All of it's fields are intended to be examined or modified
|
||||
by the user. See png.h for a good description of the png_info fields.
|
||||
|
||||
And while I'm on the topic, make sure you include the png header file:
|
||||
And while I'm on the topic, make sure you include the PNG header file:
|
||||
|
||||
#include <png.h>
|
||||
|
||||
Checking PNG files:
|
||||
|
||||
Libpng provides a simple check to see if a file is a png file. To
|
||||
Libpng provides a simple check to see if a file is a PNG file. To
|
||||
use it, pass in the first 1 to 8 bytes of the file, and it will return
|
||||
true or false (1 or 0) depending on whether the bytes could be part
|
||||
of a png file. Of course, the more bytes you pass in, the greater
|
||||
of a PNG file. Of course, the more bytes you pass in, the greater
|
||||
the accuracy of the prediction.
|
||||
|
||||
fread(header, 1, number, fp);
|
||||
@ -95,6 +95,11 @@ much to undo.
|
||||
return;
|
||||
}
|
||||
|
||||
If you are not using the standard IO functions to do input and
|
||||
output, and/or not using stderr for your output messages, you will
|
||||
have the ability to change the functions that libpng uses once
|
||||
you have allocated the libpng data structures below.
|
||||
|
||||
After you have these structures, you will need to set up the
|
||||
error handling. When libpng encounters an error, it expects to
|
||||
longjmp back to your routine. Therefore, you will need to call
|
||||
@ -103,10 +108,11 @@ read the file from different routines, you will need to update
|
||||
the jmpbuf field every time you enter a new routine that will
|
||||
call a png_ function. See your documentation of setjmp/longjmp
|
||||
for your compiler for more information on setjmp/longjmp. See
|
||||
the discussion on png error handling in the Customizing Libpng
|
||||
section below for more information on the png error handling.
|
||||
If an error occurs, and libpng longjmp's back to your setjmp,
|
||||
you will want to call png_read_destroy() to free any memory.
|
||||
the discussion on libpng error handling in the Customizing Libpng
|
||||
section below for more information on how to change the behaviour
|
||||
of libpng error handling. If an error occurs, and libpng longjmp's
|
||||
back to your setjmp, you will want to call png_read_destroy() to
|
||||
free any memory.
|
||||
|
||||
if (setjmp(png_ptr->jmpbuf))
|
||||
{
|
||||
@ -132,9 +138,8 @@ would be bad.
|
||||
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 valid FILE * in the function png_init_io(). Be sure that
|
||||
the file is opened in binary mode. If you wish to handle reading
|
||||
data in another way, see the discussion on png i/o handling in the
|
||||
Customizing Libpng section below.
|
||||
the file is opened in binary mode. Otherwise, you should see the
|
||||
section below on Customizing libpng I/O functions.
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
@ -159,7 +164,7 @@ to read the file. Some of the more important parts of the png_info are:
|
||||
PNG_INFO_<chunk name> define.
|
||||
palette and num_palette - the palette for the file
|
||||
gamma - the gamma the file is written at
|
||||
sig_bit and sig_bit_number - the number of significant bits
|
||||
sig_bit - the number of significant bits for red, green, blue, grey, alpha
|
||||
trans, trans_values, and number_trans - transparency info
|
||||
hist - histogram of palette
|
||||
text and num_text - text comments in the file.
|
||||
@ -174,14 +179,26 @@ suggested keywords, there is no requirement to restrict the use
|
||||
to these strings. There is a requirement to have at least one
|
||||
character for a keyword. It is strongly suggested that keywords
|
||||
be sensible to humans (that's the point), so don't use abbreviations.
|
||||
See the png specification for more details. There is no requirement
|
||||
to have text after the keyword on tEXt chunks. However, you must
|
||||
have text after the keyword on zTXt chunks, as only the text gets
|
||||
compressed, and compressing nothing will result in an error.
|
||||
Some suggested keywords for tEXT (or zTXt) chunks are:
|
||||
|
||||
There is no maximum length on the keyword, and nothing
|
||||
prevents you from duplicating the keyword. The text field is an
|
||||
array of png_text structures, each holding pointer to a keyword
|
||||
Title Short (one line) title or caption for image
|
||||
Author Name of image's creator
|
||||
Copyright Copyright notice (possibly long)
|
||||
Description Description of image (possibly long)
|
||||
Software Software used to create the image
|
||||
Disclaimer Legal disclaimer (possibly long)
|
||||
Warning Warning of nature of content
|
||||
Source Device used to create the image
|
||||
Comment Miscellaneous comment; conversion from GIF comment
|
||||
Created When the image or source file was created
|
||||
|
||||
There is no requirement to have text after the keyword on tEXt chunks.
|
||||
However, you must have text after the keyword on zTXt chunks, as only
|
||||
the text gets compressed, and compressing nothing will result in an error.
|
||||
|
||||
The maximum length of the keyword is limited to 80 characters. It is
|
||||
possible to use the same keyword any number of times. The text field
|
||||
is an array of png_text structures, each holding pointer to a keyword
|
||||
and a pointer to a text string. Only the text string may be null.
|
||||
The keyword/text pairs are put into the array in the order that
|
||||
they are received. However, some or all of the text chunks may be
|
||||
@ -200,7 +217,7 @@ check to see if it has data that it can do somthing with, you should
|
||||
make sure to only enable a transformation if it will be valid for
|
||||
the data. For example, don't swap red and blue on grayscale data.
|
||||
|
||||
This transforms bit depths of less then 8 to 8 bits, changes paletted
|
||||
This transforms bit depths of less than 8 to 8 bits, changes paletted
|
||||
images to rgb, and adds an alpha channel if there is transparency
|
||||
information in a tRNS chunk. This is probably most useful on grayscale
|
||||
images with bit depths of 2 or 4 and tRNS chunks.
|
||||
@ -239,7 +256,8 @@ This handles gamma transformations of the data. Pass both the file
|
||||
gamma and the desired screen gamma. If the file does not have a
|
||||
gamma value, you can pass one anyway if you wish. Note that file
|
||||
gammas are inverted from screen gammas. See the discussions on
|
||||
gamma in the PNG specification for more information.
|
||||
gamma in the PNG specification for more information. It is strongly
|
||||
reccommended that viewers support gamma correction.
|
||||
|
||||
if (info_ptr->valid & PNG_INFO_gAMA)
|
||||
png_set_gamma(png_ptr, screen_gamma, info_ptr->gamma);
|
||||
@ -506,9 +524,11 @@ setjmp and pass the jmpbuf field of your png_struct. If you
|
||||
write the file from different routines, you will need to update
|
||||
the jmpbuf field every time you enter a new routine that will
|
||||
call a png_ function. See your documentation of setjmp/longjmp
|
||||
for your compiler for more information on setjmp/longjmp. See
|
||||
the discussion on png error handling in the Customizing Libpng
|
||||
section below for more information on the png error handling.
|
||||
for your compiler for more information on setjmp/longjmp. If you
|
||||
don't want to use stderr for error output, or you want to use a
|
||||
method other than setjmp()/longjmp() to handle errors, see the
|
||||
Customizing Libpng section below for more information on libpng
|
||||
error handling.
|
||||
|
||||
if (setjmp(png_ptr->jmpbuf))
|
||||
{
|
||||
@ -535,7 +555,7 @@ Now you need to set up the input code. The default for libpng is
|
||||
to 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 opened in binary mode. If you wish to handle writing
|
||||
data in another way, see the discussion on png i/o handling in the
|
||||
data in another way, see the discussion on PNG I/O handling in the
|
||||
Customizing Libpng section below.
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
@ -543,7 +563,7 @@ Customizing Libpng section below.
|
||||
You now have the option of modifying how the compression library
|
||||
will run. The following functions are mainly for testing, but
|
||||
may be useful in certain special cases, like if you need to
|
||||
write png files extremely fast and are willing to give up some
|
||||
write PNG files extremely fast and are willing to give up some
|
||||
compression, or if you want to get the maximum possible compression
|
||||
at the expense of slower writing. If you have no special needs
|
||||
in this area, let the library do what it wants, as it has been
|
||||
@ -553,12 +573,34 @@ See the compression library for more details.
|
||||
/* turn on or off filtering (1 or 0) */
|
||||
png_set_filtering(png_struct *png_ptr, 1);
|
||||
|
||||
/* compression level (0 - none, 6 - default, 9 - maximum) */
|
||||
png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
|
||||
png_set_compression_mem_level(png_ptr, 8);
|
||||
png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
|
||||
png_set_compression_window_bits(png_ptr, 15);
|
||||
png_set_compression_method(png_ptr, 8);
|
||||
|
||||
It is possible to have libpng flush any pending output, either manually,
|
||||
or automatically after a certain number of lines have been written. To
|
||||
flush the output stream a single time call:
|
||||
|
||||
png_write_flush(png_ptr);
|
||||
|
||||
and to have libpng flush the output stream after a certain number of
|
||||
scanlines have been written, call:
|
||||
|
||||
png_set_flush(png_ptr, nrows);
|
||||
|
||||
Note that the distance between rows is from the last time png_write_flush
|
||||
was called, or the first row of the image if it has never been called.
|
||||
So if you write 50 lines, and then png_set_flush 25, it will flush the
|
||||
output on the next scanline, and on line 75, unless png_write_flush is
|
||||
called earlier. If nrows is too small (less than about 10 lines) the
|
||||
image compression may decrease dramatically (although this may be
|
||||
acceptable for real-time applications). Infrequent flushing will only
|
||||
degrade the compression performance by a few percent over images that
|
||||
do not use flushing.
|
||||
|
||||
You now need to fill in the png_info structure with all the data
|
||||
you wish to write before the actual image. Note that the only thing
|
||||
you are allowed to write after the image is the text chunks and the
|
||||
@ -581,7 +623,7 @@ parts of the png_info are:
|
||||
appropriate PNG_INFO_<chunk name> define.
|
||||
palette and num_palette - the palette for the file
|
||||
gamma - the gamma the file is written at
|
||||
sig_bit and sig_bit_number - the number of significant bits
|
||||
sig_bit - the number of significant bits for red, green, blue, grey, alpha
|
||||
trans, trans_values, and number_trans - transparency info
|
||||
hist - histogram of palette
|
||||
text and num_text - text comments in the file.
|
||||
@ -614,13 +656,20 @@ you can leave off the text string on non-compressed pairs.
|
||||
Compressed pairs must have a text string, as only the text string
|
||||
is compressed anyway, so the compression would be meaningless.
|
||||
|
||||
PNG supports modification time via the png_time structure. Two
|
||||
PNG supports MODIFICATION time via the png_time structure. Two
|
||||
conversion routines are proved, png_convert_from_time_t() for
|
||||
time_t and png_convert_from_struct_tm() for struct tm. The
|
||||
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,
|
||||
you should provide the time in universal time (GMT) if possible
|
||||
instead of your local time.
|
||||
instead of your local time. Note that the year number is the full
|
||||
year number (ie 1995 rather than 95).
|
||||
|
||||
Since the CREATION time of an image is somewhat ambiguous, it is not
|
||||
sensible to store an exact time like the tIME chunk above (ie when was
|
||||
a scanned photo of neanderthal art created?). However, a text chunk
|
||||
with a "Created" keyword can hold this information, in a form which is
|
||||
useful (ie "Painted circa 40000 BC, photographed 1971, scanned 1996").
|
||||
|
||||
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().
|
||||
@ -782,29 +831,43 @@ standard things like memory allocation, input/output, and error handling.
|
||||
The second deals with more complicated things like adding new chunks,
|
||||
adding new transformations, and generally changing how libpng works.
|
||||
|
||||
All of the memory allocation, input/output, and error handling in libpng
|
||||
goes through the routines in pngstub.c. The file as plenty of comments
|
||||
describing each function and how it expects to work, so I will just
|
||||
summarize here. See pngstub.c for more details.
|
||||
All of the memory allocation in libpng is done in pngmem.c. Memory
|
||||
allocation is done through the functions png_large_malloc(), png_malloc(),
|
||||
png_realloc(), png_large_free(), and png_free(). These currently just
|
||||
call the standard C functions. The large functions must handle at least
|
||||
64K, but they don't have to handle more then that. If your pointers can't
|
||||
access more then 64K at a time, you will want to set MAXSEG_64K in zlib.h.
|
||||
|
||||
Memory allocation is done through the functions png_large_malloc(),
|
||||
png_malloc(), png_realloc(), png_large_free(), and png_free().
|
||||
These currently just call the standard C functions. The large
|
||||
functions must handle exactly 64K, but they don't have to handle
|
||||
more then that. If your pointers can't access more then 64K at a
|
||||
time, you will want to set MAXSEG_64K in zlib.h.
|
||||
Since it is unlikely that the method of handling memory allocation on a
|
||||
platform will change between applications, these functions must be modified
|
||||
or replaced to change their behaviour. If you only need to add new tests or
|
||||
flags to have the compiler choose the correct function calls, please forward
|
||||
these changes to the libpng author, so they can be added into the library
|
||||
for the benefit of others.
|
||||
|
||||
Input/Output in libpng is done throught png_read() and png_write(), 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
|
||||
this, make the appropriate changes in pngstub.c and png.h. Make sure you
|
||||
change the function prototype for png_init_io() if you are no longer
|
||||
using a FILE *.
|
||||
All of the input/output, and error handling in libpng go through the
|
||||
routines in pngio.c by default. The file has plenty of comments describing
|
||||
each function and how it expects to work. It is possible to supply different
|
||||
I/O and error handling methods at run time with the png_set_msg_fn(),
|
||||
png_set_read_fn(), and png_set_write_fn() calls.
|
||||
|
||||
Error handling in libpng is done through png_error() and png_warning().
|
||||
Errors handled through png_error() are fatal, meaning that png_error()
|
||||
should never return to it's caller. Currently, this is handled via
|
||||
setjmp() and longjmp(), but you could change this to do things like
|
||||
Input/Output in libpng is done throught png_read_data() and png_write_data(),
|
||||
which currently just call fread() and fwrite(). The error and warning
|
||||
functions png_error() and png_warning() use stderr to output any messages,
|
||||
and png_error() uses longjmp to return from an error. These default
|
||||
functions are set by via png_init_io().
|
||||
|
||||
If you wish to change some or all of these functions, it is possible to
|
||||
do so at runtime, and without modifying the libpng library code. The
|
||||
application must supply replacement functions which have the same arguments
|
||||
and are functionally equivalent to the default functions. If you are
|
||||
replacing both the I/O and message functions, the call to png_init_io()
|
||||
is not needed.
|
||||
|
||||
Error handling in libpng is done through png_error() and png_warning() by
|
||||
default. Errors handled through png_error() are fatal, meaning that
|
||||
png_error() should never return to it's caller. Currently, this is handled
|
||||
via setjmp() and longjmp(), but you could change this to do things like
|
||||
exit() if you should wish. Similarly, both png_error() and png_warning()
|
||||
print a message on stderr, but that can also be changed. The motivation
|
||||
behind using setjmp() and longjmp() is the C++ throw and catch exception
|
||||
@ -815,6 +878,71 @@ a longjmp, so the user may want to be careful about doing anything after
|
||||
setjmp returns non zero besides returning itself. Consult your compiler
|
||||
documentation for more details.
|
||||
|
||||
The replacement message functions should have parameters as follows:
|
||||
|
||||
void user_error_fn(png_struct png_ptr, char *error_msg);
|
||||
void user_warning_fn(png_struct png_ptr, char *warning_msg);
|
||||
|
||||
These functions can be attached to a PNG stream with a call
|
||||
|
||||
png_set_msg_fn(png_ptr, msg_ptr, user_error_fn, user_warning_fn);
|
||||
|
||||
If NULL is supplied for user_error_fn, then the error function will not
|
||||
print any error messages, and will return via longjmp(png_ptr->jmpbuf,1) to
|
||||
the last location setjmp(png_ptr->jmpbuf) was previously called. If NULL is
|
||||
supplied for user_warning_fn then no warning messages will be printed.
|
||||
|
||||
In order to make it possible to have multiple PNG files open at the same
|
||||
time, the replacement message functions should not modify any global
|
||||
variables. In order to have any message information available to the
|
||||
libpng streams, there is a pointer available to for a user variable or
|
||||
structure. If more than one variable or structure of needs to be kept
|
||||
with each stream, then you must create a structure which holds all the
|
||||
relevant data. The pointer to this data is set in the initial png_set_msg_fn
|
||||
call, and can be accessed with:
|
||||
|
||||
msg_ptr = (user_msg_type *)png_get_msg_ptr(png_ptr);
|
||||
|
||||
The replacement I/O functions should have prototypes as follows:
|
||||
|
||||
void user_read_data(png_struct *png_ptr,png_bytef *data,png_uint_32 length);
|
||||
void user_write_data(png_struct *png_ptr,png_bytef *data,png_uint_32 length);
|
||||
|
||||
where the routine will read or write "length" bytes into or out of "data".
|
||||
If the routines are unable to read or write the correct number of bytes, they
|
||||
should call (*(png_ptr->error_fn))(png_ptr, "Error message"); to abort.
|
||||
|
||||
void user_output_flush(png_struct *png_ptr);
|
||||
|
||||
will flush any data from the buffer used by the output device. Note that
|
||||
the flush function is purely to output any data being stored by the write
|
||||
function, and has no control over any data buffered inside the compressor.
|
||||
|
||||
These functions can be attached to a PNG stream by calling one of
|
||||
|
||||
png_set_read_fn(png_ptr, io_ptr, user_read_data);
|
||||
png_set_write_fn(png_ptr, io_ptr, user_write_data, user_output_flush);
|
||||
|
||||
You should only call one of these two functions for a single PNG stream.
|
||||
It is a fatal error to read from a write stream, and vice-versa. If the
|
||||
output method you are using does not buffer any data, or you have chosen
|
||||
not to compile libpng with PNG_WRITE_FLUSH_SUPPORTED, NULL may be supplied
|
||||
instead of a function name for user_output_flush, and an empty function will
|
||||
be used. Note that even if the output method being used does not buffer
|
||||
output, during compression data is buffered by the compressor. If an
|
||||
application wants to guarantee that all pending output data has been written,
|
||||
it should call png_write_flush, which will flush the compression buffers,
|
||||
and in turn call the user_output_flush function.
|
||||
|
||||
As with the message functions, the replacement I/O functions should not
|
||||
modify any global variables. Therse is a separate pointer available to for
|
||||
an I/O variable or structure. If more than one variable or structure of
|
||||
needs to be kept with each stream, then you must create a structure which
|
||||
holds all the relevant data. The pointer to this data is set in the initial
|
||||
set_xxx_fn call, and can be accessed with:
|
||||
|
||||
io_ptr = (user_io_type *)png_get_io_ptr(png_ptr);
|
||||
|
||||
If you need to read or write custom chunks, you will need to get deeper
|
||||
into the libpng code. First, read the PNG specification, and have
|
||||
a first level of understanding of how it works. Pay particular
|
||||
@ -822,7 +950,9 @@ attention to the sections that describe chunk names, and look
|
||||
at how other chunks were designed, so you can do things similar.
|
||||
Second, check out the sections of libpng that read and write chunks.
|
||||
Try to find a chunk that is similar to yours, and copy off of it.
|
||||
More details can be found in the comments inside the code.
|
||||
More details can be found in the comments inside the code. If you are
|
||||
truly ambitious, you can modify the libpng code to handle unknown chunks
|
||||
in a general way and send the code to the libpng author.
|
||||
|
||||
If you wish to write your own transformation for the data, look
|
||||
through the part of the code that does the transformations, and check
|
||||
@ -833,8 +963,8 @@ itself.
|
||||
|
||||
Configuring for 16 bit platforms:
|
||||
|
||||
You will probably need to change the png__large_malloc() and
|
||||
png_large_free() routines in pngstub.c, as these are requred
|
||||
You will probably need to change the png_large_malloc() and
|
||||
png_large_free() routines in pngmem.c, as these are required
|
||||
to allocate 64K. Also, you will want to look into zconf.h to tell
|
||||
zlib (and thus libpng) that it cannot allocate more then 64K at a
|
||||
time. Even if you can, the memory won't be accessable. So limit zlib
|
||||
@ -842,11 +972,12 @@ and libpng to 64K by defining MAXSEG_64K.
|
||||
|
||||
Configuring for gui/windowing platforms:
|
||||
|
||||
You will need to change the error message display in png_error() and
|
||||
png_warning() to display a message instead of fprinting it to stderr.
|
||||
You may want to write a single function to do this and call it something
|
||||
like png_message(). On some compliers, you may have to change the
|
||||
memory allocators (png_malloc, etc.).
|
||||
You will need to supply new message display functions for png_error() and
|
||||
png_warning() (through png_set_message_fn() to display a message in a window
|
||||
instead of fprinting it to stderr. You may want to write a single function
|
||||
to do this and call it something like png_message() (although the error
|
||||
function should still call longjmp or otherwise handle the error without
|
||||
returning).
|
||||
|
||||
Configuring for compiler xxx:
|
||||
|
||||
@ -858,9 +989,9 @@ files in libpng proper only include png.h.
|
||||
|
||||
Removing unwanted object code:
|
||||
|
||||
There are a bunch of #define's in png.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
|
||||
not using an ability, you can change the #define to #undef and
|
||||
never going to use an ability, you can change the #define to #undef and
|
||||
save yourself code and data space. All the reading and writing
|
||||
specific code are in seperate files, so the linker should only grab
|
||||
the files it needs. However, if you want to make sure, or if you
|
||||
@ -868,4 +999,3 @@ are building a stand alone library, all the reading files start with
|
||||
pngr and all the writing files start with pngw. The files that
|
||||
don't match either (like png.c, pngtrans.c, etc.) are used for
|
||||
both reading and writing, and always need to be included.
|
||||
|
||||
|
190
lpfaq.txt
Normal file
190
lpfaq.txt
Normal file
@ -0,0 +1,190 @@
|
||||
libpng FAQ - August 20, 1995
|
||||
|
||||
Maintainer:
|
||||
|
||||
Guy Eric Schalnat: schalnat@group42.com CompuServe: 75501,1625
|
||||
|
||||
|
||||
Contents:
|
||||
|
||||
1) General Questions
|
||||
1.1) How official is this FAQ?
|
||||
1.2) How often is this FAQ posted?
|
||||
1.3) Where can I get this FAQ, libpng, zlib, the PNG
|
||||
specification, test images, etc.?
|
||||
1.4) How ready is libpng?
|
||||
1.5) How portable is libpng?
|
||||
1.6) When will libpng be out of Beta?
|
||||
1.7) What remains to be done in libpng for the 1.0 release?
|
||||
1.8) Can I help?
|
||||
1.9) Why don't you answer your mail?
|
||||
|
||||
2) Libpng questions
|
||||
2.1) Does the order of functions calls matter?
|
||||
2.2) When I try to read/write a png image, it doesn't work.
|
||||
2.3) Do I have to start with example.c?
|
||||
2.4) What things should I be careful of?
|
||||
2.5) Why doesn't example.c compile?
|
||||
|
||||
3) Critical Patches
|
||||
No known bugs (for now :-).
|
||||
|
||||
4) Non-critical patches
|
||||
No known bugs (for now :-).
|
||||
|
||||
|
||||
Questions:
|
||||
|
||||
1) General Questions
|
||||
|
||||
1.1) How official is this FAQ?
|
||||
|
||||
As it was written by the author of libpng (that's me :), it's
|
||||
about offical as one can get. However, it is not ready for
|
||||
prime time yet, as libpng is still in beta, and thus its
|
||||
users are of the sort that are willing to deal with beta
|
||||
software. Thus, I assume all of you reading this have a
|
||||
basic familiarity with PNG, libpng, and C programming. I'll
|
||||
write a basic section for libpng later, as well as some quick
|
||||
stuff on PNG itself (but this will not be the PNG FAQ. I just
|
||||
don't have that kind of time).
|
||||
|
||||
1.2) How often is this FAQ posted?
|
||||
|
||||
As often as events warrant. I doubt it'll get stale, and as
|
||||
it is not (and may never be) actually posted to a newsgroup,
|
||||
I feel no need to make monthy postings.
|
||||
|
||||
1.3) Where can I get this FAQ, libpng, zlib, the PNG
|
||||
specification, test images, etc.?
|
||||
|
||||
Everything should be at ftp://ftp.uu.net/graphics/png and
|
||||
mirror sites. On CompuServe, it should be at GO GRAPHSUPPORT
|
||||
in the Png Development library (lib 20). Failing that, try
|
||||
my ftp site at ftp://ftp.group42.com/pub/png or web site at
|
||||
http://www.group42.com/ If you have trouble getting to these,
|
||||
the numerical address is 204.94.158.25
|
||||
|
||||
1.4) How ready is libpng?
|
||||
|
||||
In its current incarnation (0.8), it still may have a few bugs.
|
||||
I think I got all of the bugs this time, but one never knows.
|
||||
Also, the dithering currently in libpng is horrid, so that
|
||||
needs work. Finally, I have yet to implement medium model
|
||||
support.
|
||||
|
||||
1.5) How portable is libpng?
|
||||
|
||||
As portable as I can make it. It needs int's of at least
|
||||
16 bits, and longs of at least 32 bits. It has not been
|
||||
tried for char's larger then 8 bits. It should support
|
||||
any reasonable K&R C compiler, as well as any ANSI C
|
||||
compiler. The most you should need to do is change the
|
||||
includes in pngconf.h. So far, I know of no compiler in use
|
||||
that libpng will not compile on.
|
||||
|
||||
1.6) When will libpng be out of Beta?
|
||||
|
||||
That depends on my workload here. I'm writing libpng for
|
||||
free, which generates tons of good will, but doesn't help
|
||||
put food on the table, so there are times I just can't do
|
||||
any real work on it. There is still some work to be done
|
||||
(see question 1.7), so don't expect the official version
|
||||
before September (and that may be pushing it). I'll try
|
||||
to get the next (last?) beta version out my early
|
||||
September. Be warned, I always seem to take twice as
|
||||
long as I think I will.
|
||||
|
||||
1.7) What remains to be done in libpng for the 1.0 release?
|
||||
|
||||
Add Tim Wegner's medium memory model support. (Thanks, Tim).
|
||||
Improve the dithering.
|
||||
Rewrite libpng.txt, and comment the code better.
|
||||
Test with a final zlib.
|
||||
|
||||
1.8) Can I help?
|
||||
|
||||
Sweet words. The most helpful thing you can do for the
|
||||
1.0 release is help testing on your compiler. After this
|
||||
release, though, there is a large list of things that ought
|
||||
to be done to make libpng be more full featured. We'll
|
||||
talk about this later, as I don't want to add tons of new
|
||||
code until after 1.0 gets out the door. Please send me
|
||||
any makefile changes and/or other changes needed to support
|
||||
your compiler (with a #ifdef for the code changes).
|
||||
|
||||
If any of you are good at technical writing, take a look at
|
||||
libpng.txt and correct it (or rewrite it) as necessary. I
|
||||
am not a writer, I'm a programmer. It shows.
|
||||
|
||||
1.9) Why don't you answer your mail?
|
||||
|
||||
I've been busy. I'm sorry about that, and I've got to get
|
||||
into the habit of at least replying that I got the message.
|
||||
Also, some of you have sent me problems that I haven't gotten
|
||||
back to you yet. If it is still a problem, you may want to
|
||||
give me a short message and remind me that I need to look into
|
||||
it. Libpng is being tested by more people than I dared hope
|
||||
(which is a good thing), and I was unprepared to deal with so
|
||||
many problems so soon.
|
||||
|
||||
|
||||
2) Libpng questions
|
||||
|
||||
2.1) Does the order of functions calls matter?
|
||||
|
||||
In general, yes. If you stick with the order I used in libpng.txt
|
||||
and example.c, you should be safe. Be warned, however, that I
|
||||
messed up the order of png_set_interlace_handling(). It needs
|
||||
to be called *before* png_start_read_image(), not after. Oops.
|
||||
The exceptions to this rule are all the png_set ... calls.
|
||||
They can be done in any order, but they all have to be done
|
||||
in the area indicated by libpng.txt/example.c.
|
||||
|
||||
2.2) When I try to read/write a png image, it doesn't work.
|
||||
|
||||
Does zlib's test program work (example.c)? Does libpng's test
|
||||
program work (testpng.c)? Have you installed the patches at
|
||||
the end of this FAQ? After all that, if the problem continues,
|
||||
e-mail me, and we'll try to fix it. If you don't have much
|
||||
programming experience, be patient about the fix. Code
|
||||
fragments help, as do *small* images (uuencoded please). If
|
||||
I don't get back to you right away, give me some time. Thanks.
|
||||
|
||||
2.3) Do I have to start with example.c?
|
||||
|
||||
No, but most people have had much better luck doing that. Seems
|
||||
I didn't explain things well in libpng.txt, so things are not
|
||||
intuitive to people (which could be an api design problem also).
|
||||
Sometime in the future, we'll revisit the api design, and try
|
||||
to make it easier to use. I'll rewrite libpng.txt before the
|
||||
1.0 release.
|
||||
|
||||
2.4) What things should I be careful of?
|
||||
|
||||
The main gotcha is calling png_read_init() before png_info_init().
|
||||
Also, always make sure you have a correct setjmp buffer. That's
|
||||
all I can think of for now.
|
||||
|
||||
2.5) Why doesn't example.c compile?
|
||||
|
||||
I wrote example.c as a staring point for using libpng. It doesn't
|
||||
compile because I don't know how you want to do things like allocating
|
||||
memory to hold the image, so I left that code out. If you go in and
|
||||
finish it up, it should work fine. The file pngtest.c gives a
|
||||
very simple example of reading and writing png files.
|
||||
|
||||
|
||||
3) Critical Patches
|
||||
|
||||
No known bugs (for now :-).
|
||||
|
||||
|
||||
4) Non-critical patches
|
||||
|
||||
No known bugs (for now :-).
|
||||
|
||||
|
||||
That's it so far as I know. If I missed something, yell.
|
||||
|
||||
-Guy
|
14
makefile
14
makefile
@ -2,25 +2,26 @@
|
||||
# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc.
|
||||
# For conditions of distribution and use, see copyright notice in png.h
|
||||
|
||||
CC=cc
|
||||
CFLAGS=-I../zlib -O
|
||||
CC=gcc
|
||||
CFLAGS=-I../zlib -O2 -Wall -ansi -pedantic
|
||||
LDFLAGS=-L. -L../zlib/ -lpng -lz -lm
|
||||
|
||||
#RANLIB=ranlib
|
||||
RANLIB=echo
|
||||
RANLIB=ranlib
|
||||
#RANLIB=echo
|
||||
|
||||
# where make install puts libpng.a and png.h
|
||||
prefix=/usr/local
|
||||
prefix=/home/munet-d2/sun/local
|
||||
|
||||
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \
|
||||
pngread.o pngio.o pngwrite.o pngrtran.o pngwtran.o \
|
||||
pngmem.o pngerror.o
|
||||
pngmem.o
|
||||
|
||||
all: libpng.a pngtest
|
||||
|
||||
libpng.a: $(OBJS)
|
||||
ar rc $@ $(OBJS)
|
||||
$(RANLIB) $@
|
||||
rcp libpng.a vlsi:bin/lib/libpng.a
|
||||
|
||||
pngtest: pngtest.o libpng.a
|
||||
$(CC) -o pngtest $(CCFLAGS) pngtest.o $(LDFLAGS)
|
||||
@ -44,7 +45,6 @@ clean:
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
png.o: png.h pngconf.h
|
||||
pngerror.o: png.h pngconf.h
|
||||
pngio.o: png.h pngconf.h
|
||||
pngmem.o: png.h pngconf.h
|
||||
pngrcb.o: png.h pngconf.h
|
||||
|
98
png.h
98
png.h
@ -267,7 +267,19 @@ typedef struct png_row_info_struct
|
||||
The only people who need to care about what is inside of this are the
|
||||
people who will be modifying the library for their own special needs.
|
||||
*/
|
||||
typedef struct png_struct_def
|
||||
typedef struct png_struct_def png_struct;
|
||||
typedef png_struct FAR png_structf;
|
||||
|
||||
/* These are the function types for the I/O functions, and the functions which
|
||||
* modify the default I/O functions to user I/O functions. The png_msg_ptr
|
||||
* type should match that of user supplied warning and error functions, while
|
||||
* the png_rw_ptr type should match that of the user read/write data functions.
|
||||
*/
|
||||
typedef void (*png_msg_ptr) PNGARG((png_struct *, char *));
|
||||
typedef void (*png_rw_ptr) PNGARG((png_struct *, png_bytef *, png_uint_32));
|
||||
typedef void (*png_flush_ptr) PNGARG((png_struct *));
|
||||
|
||||
struct png_struct_def
|
||||
{
|
||||
jmp_buf jmpbuf; /* used in png_error */
|
||||
png_byte mode; /* used to determine where we are in the png file */
|
||||
@ -314,6 +326,10 @@ typedef struct png_struct_def
|
||||
png_uint_32 width; /* width of file */
|
||||
png_uint_32 height; /* height of file */
|
||||
png_uint_32 num_rows; /* number of rows in current pass */
|
||||
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
|
||||
png_uint_32 flush_dist; /* how many rows apart to flush, 0 for no flush */
|
||||
png_uint_32 flush_rows; /* number of rows written since last flush */
|
||||
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
|
||||
png_uint_32 rowbytes; /* size of row in bytes */
|
||||
png_uint_32 usr_width; /* width of row at start of write */
|
||||
png_uint_32 iwidth; /* interlaced width */
|
||||
@ -322,13 +338,14 @@ typedef struct png_struct_def
|
||||
png_uint_32 idat_size; /* current idat size for read */
|
||||
png_uint_32 zbuf_size; /* size of zbuf */
|
||||
png_color *palette; /* files palette */
|
||||
png_uint_32 do_free; /* flags indicating if libpng should free memory */
|
||||
#if defined(PNG_READ_DITHER_SUPPORTED)
|
||||
png_bytef *palette_lookup; /* lookup table for dithering */
|
||||
#endif
|
||||
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
|
||||
png_byte *gamma_table; /* gamma table for 8 bit depth files */
|
||||
#endif
|
||||
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
|
||||
#if defined(PNG_READ_GAMMA_SUPPORTED)
|
||||
png_byte *gamma_from_1; /* converts from 1.0 to screen */
|
||||
png_byte *gamma_to_1; /* converts from file to 1.0 */
|
||||
#endif
|
||||
@ -363,7 +380,7 @@ typedef struct png_struct_def
|
||||
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
|
||||
png_color_8 shift; /* shift for significant bit tranformation */
|
||||
#endif
|
||||
#if defined(PNG_READ_GAMMA_SUPPORTED)
|
||||
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined (PNG_READ_sBIT_SUPPORTED)
|
||||
png_color_8 sig_bit; /* significant bits in file */
|
||||
#endif
|
||||
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
|
||||
@ -375,10 +392,17 @@ typedef struct png_struct_def
|
||||
#endif
|
||||
png_row_info row_info; /* used for transformation routines */
|
||||
z_stream zstream_struct; /* decompression structure */
|
||||
FILE *fp; /* used for png_read and png_write */
|
||||
} png_struct;
|
||||
|
||||
typedef png_struct FAR png_structf;
|
||||
FILE *fp; /* used for default png_read and png_write */
|
||||
png_msg_ptr error_fn; /* Function for printing errors and aborting */
|
||||
png_msg_ptr warning_fn; /* Function for printing warnings */
|
||||
png_rw_ptr write_data_fn; /* Function for writing output data */
|
||||
png_rw_ptr read_data_fn; /* Function for reading input data */
|
||||
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
|
||||
png_flush_ptr output_flush_fn;/* Function for flushing output */
|
||||
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
|
||||
void *io_ptr; /* Pointer to user supplied struct for I/O functions */
|
||||
void *msg_ptr; /* Pointer to user supplied struct for message functions */
|
||||
};
|
||||
|
||||
/* Here are the function definitions most commonly used. This is not
|
||||
the place to find out how to use libpng. See libpng.txt for the
|
||||
@ -403,7 +427,7 @@ extern void png_write_info PNGARG((png_struct *png_ptr, png_info *info));
|
||||
/* read the information before the actual image data. */
|
||||
extern void png_read_info PNGARG((png_struct *png_ptr, png_info *info));
|
||||
|
||||
#if defined(PNG_READ_tIME_SUPPORTED)
|
||||
#if defined(PNG_WRITE_tIME_SUPPORTED)
|
||||
/* convert from a struct tm to png_time */
|
||||
extern void png_convert_from_struct_tm PNGARG((png_time *ptime,
|
||||
struct tm *ttime));
|
||||
@ -500,6 +524,14 @@ extern void png_set_gamma PNGARG((png_struct *png_ptr, double screen_gamma,
|
||||
double default_file_gamma));
|
||||
#endif
|
||||
|
||||
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
|
||||
/* Set how many lines between output flushes - 0 for no flushing */
|
||||
extern void png_set_flush PNGARG((png_struct *png_ptr, int nrows));
|
||||
|
||||
/* Flush the current PNG output buffer */
|
||||
extern void png_write_flush PNGARG((png_struct *png_ptr));
|
||||
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
|
||||
|
||||
/* optional update palette with requested transformations */
|
||||
extern void png_start_read_image PNGARG((png_struct *png_ptr));
|
||||
|
||||
@ -570,21 +602,8 @@ extern void png_set_compression_window_bits PNGARG((png_struct *png_ptr,
|
||||
extern void png_set_compression_method PNGARG((png_struct *png_ptr,
|
||||
int method));
|
||||
|
||||
/* These next functions are stubs of typical c functions for input/output,
|
||||
memory, and error handling. They are in the file pngstub.c, and are
|
||||
set up to be easily modified for users that need to. See the file
|
||||
pngstub.c for more information */
|
||||
|
||||
/* Write the data to whatever output you are using. */
|
||||
extern void png_write_data PNGARG((png_struct *png_ptr, png_bytef *data,
|
||||
png_uint_32 length));
|
||||
|
||||
/* Read data from whatever input you are using */
|
||||
extern void png_read_data PNGARG((png_struct *png_ptr, png_bytef *data,
|
||||
png_uint_32 length));
|
||||
|
||||
/* Initialize the input/output for the png file. */
|
||||
extern void png_init_io PNGARG((png_struct *png_ptr, FILE *fp));
|
||||
/* These next functions are prototypes of the functions libpng uses for
|
||||
memory allocation. */
|
||||
|
||||
/* Allocate memory in larger chunks. */
|
||||
extern voidpf png_large_malloc PNGARG((png_structf *png_ptr, png_uint_32 size));
|
||||
@ -602,12 +621,32 @@ extern void *png_realloc PNGARG((png_struct *png_ptr, void *ptr,
|
||||
/* free's a pointer allocated by png_malloc() */
|
||||
extern void png_free PNGARG((png_struct *png_ptr, void *ptr));
|
||||
|
||||
/* Fatal error in libpng - can't continue */
|
||||
extern void png_error PNGARG((png_structf *png_ptr, char *error));
|
||||
/* Initialize the I/O and message handling for the png file to the defaults. */
|
||||
extern void png_init_io PNGARG((png_struct *png_ptr, FILE *fp));
|
||||
|
||||
/* Non-fatal error in libpng. Can continue, but may have a problem. */
|
||||
extern void png_warning PNGARG((png_struct *png_ptr, char *message));
|
||||
/* Replace the error message and abort, and warning functions with user
|
||||
supplied functions. If no messages are to be printed, NULL can be
|
||||
supplied for error_fn and warning_fn, although error_fn will still do
|
||||
a longjmp to the last setjmp location. */
|
||||
extern void png_set_msg_fn PNGARG((png_struct *png_ptr, void *msg_ptr,
|
||||
png_msg_ptr error_fn, png_msg_ptr warning_fn));
|
||||
|
||||
/* Return the user pointer associated with the message functions */
|
||||
extern void *png_get_msg_ptr PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* Replace the default data output functions with a user supplied one(s).
|
||||
If buffered output is not used, then output_flush_fn can be set to NULL.
|
||||
if PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time
|
||||
output_flush_fn will be ignored (but must be supplied for compatability). */
|
||||
extern void png_set_write_fn PNGARG((png_struct *png_ptr, void *io_ptr,
|
||||
png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn));
|
||||
|
||||
/* Replace the default data input function with a user supplied one. */
|
||||
extern void png_set_read_fn PNGARG((png_struct *png_ptr, void *io_ptr,
|
||||
png_rw_ptr read_data_fn));
|
||||
|
||||
/* Return the user pointer associated with the I/O functions */
|
||||
extern void *png_get_io_ptr PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* These next functions are used internally in the code. If you use
|
||||
them, make sure you read and understand the png spec. More information
|
||||
@ -646,6 +685,11 @@ extern void png_warning PNGARG((png_struct *png_ptr, char *message));
|
||||
#define PNG_GRAY_TO_RGB 0x2000
|
||||
#define PNG_FILLER 0x4000
|
||||
|
||||
/* defines for memory alloced by libpng which should be freed */
|
||||
#define PNG_FREE_TRANS 0x0001
|
||||
#define PNG_FREE_HIST 0x0002
|
||||
#define PNG_FREE_PALETTE 0x0004
|
||||
|
||||
/* save typing and make code easier to understand */
|
||||
#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \
|
||||
abs((int)((c1).green) - (int)((c2).green)) + \
|
||||
|
10
pngchang.txt
10
pngchang.txt
@ -55,6 +55,16 @@ version 0.8
|
||||
put all the configurable stuff in pngconf.h
|
||||
enabled png_set_shift to work with paletted images on read
|
||||
added png_read_update_info() - updates info structure with transformations
|
||||
version 0.81
|
||||
added support for medium memory model
|
||||
version 0.82
|
||||
added ability to flush output stream automatically or manually
|
||||
added ability to change I/O and error functions dynamically
|
||||
moved pngerror.c into pngio.c to make all the default functions static
|
||||
when freeing memory in png_read_destroy don't free memory we didn't allocate
|
||||
added warnings when reading blocks of incorrect length
|
||||
limit tEXt and zTXt keywords to 80 chars
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
Unless this gets smaller then the size of a row (compressed),
|
||||
it should not make much difference how big this is. */
|
||||
|
||||
#define PNG_ZBUF_SIZE 8192
|
||||
#define PNG_ZBUF_SIZE 32768
|
||||
|
||||
/* While libpng currently uses zlib for it's compression, it has been designed
|
||||
to stand on it's own. Towards this end, there are two defines that are
|
||||
@ -166,6 +166,7 @@
|
||||
#define PNG_WRITE_SWAP_SUPPORTED
|
||||
#define PNG_WRITE_INVERT_SUPPORTED
|
||||
#define PNG_WRITE_FILLER_SUPPORTED
|
||||
#define PNG_WRITE_FLUSH_SUPPORTED
|
||||
|
||||
/* any chunks you are not interested in, you can undef here. The
|
||||
ones that allocate memory may be expecially important (hIST,
|
||||
|
46
pngerror.c
46
pngerror.c
@ -1,46 +0,0 @@
|
||||
|
||||
/* pngstub.c - stub functions for i/o and memory allocation
|
||||
|
||||
libpng 1.0 beta 2 - version 0.81
|
||||
For conditions of distribution and use, see copyright notice in png.h
|
||||
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
|
||||
August 24, 1995
|
||||
|
||||
This file provides a location for all error handling. Users which
|
||||
need special error handling are expected to modify the code in this
|
||||
file to meet their needs. See the instructions at each function. */
|
||||
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
/* This function is called whenever there is an error. Replace with
|
||||
however you wish to handle the error. Note that this function
|
||||
MUST NOT return, or the program will crash */
|
||||
void
|
||||
png_error(png_structf *png_ptr, char *message)
|
||||
{
|
||||
fprintf(stderr, "libpng error: %s\n", message);
|
||||
#ifdef USE_FAR_KEYWORD
|
||||
{
|
||||
jmp_buf jmpbuf;
|
||||
png_memcpy(jmpbuf,png_ptr->jmpbuf,sizeof(jmp_buf));
|
||||
longjmp(jmpbuf, 1);
|
||||
}
|
||||
#else
|
||||
longjmp(png_ptr->jmpbuf, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This function is called when there is a warning, but the library
|
||||
thinks it can continue anyway. You don't have to do anything here
|
||||
if you don't want to. In the default configuration, png_ptr is
|
||||
not used, but it is passed in case it may be useful. */
|
||||
void
|
||||
png_warning(png_struct *png_ptr, char *message)
|
||||
{
|
||||
if (!png_ptr)
|
||||
return;
|
||||
|
||||
fprintf(stderr, "libpng warning: %s\n", message);
|
||||
}
|
||||
|
307
pngio.c
307
pngio.c
@ -1,32 +1,31 @@
|
||||
|
||||
/* pngstub.c - stub functions for i/o and memory allocation
|
||||
/* pngio.c - default functions for data I/O and error/warning messages
|
||||
|
||||
libpng 1.0 beta 2 - version 0.81
|
||||
libpng 1.0 beta 3 - version 0.82
|
||||
For conditions of distribution and use, see copyright notice in png.h
|
||||
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
|
||||
August 24, 1995
|
||||
Some portions Copyright (C) 1995 Andreas Dilger
|
||||
Sept 24, 1995
|
||||
|
||||
This file provides a location for all input/output. Users which need
|
||||
special handling are expected to modify the code in this file to meet
|
||||
their needs. See the instructions at each function. */
|
||||
special handling are expected to write functions which have the same
|
||||
arguments as these, and perform similar functions, but possibly have
|
||||
different I/O methods. Note that you shouldn't change these functions,
|
||||
but rather write replacement functions and then change them at run
|
||||
time with png_set_write_fn(...) or png_set_read_fn(...), etc */
|
||||
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
|
||||
/* Write the data to whatever output you are using. The default
|
||||
routine writes to a file pointer. If you need to write to something
|
||||
else, this is the place to do it. We suggest saving the old code
|
||||
for future use, possibly in a #define. Note that this routine sometimes
|
||||
gets called with very small lengths, so you should implement some kind
|
||||
of simple 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 there for insurance, but if you are having problems
|
||||
with it, you can take it out. Just be sure to cast length to whatever
|
||||
fwrite needs in that spot if you don't have a function prototype for
|
||||
it. */
|
||||
|
||||
else, this is a good example of how to do it. Note that this routine
|
||||
sometimes gets called with very small lengths, so you should implement
|
||||
some kind of simple 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 there for insurance. */
|
||||
#ifndef USE_FAR_KEYWORD
|
||||
void
|
||||
static void
|
||||
png_write_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length)
|
||||
{
|
||||
png_uint_32 check;
|
||||
@ -34,7 +33,7 @@ png_write_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length)
|
||||
check = fwrite(data, 1, (png_size_t)length, png_ptr->fp);
|
||||
if (check != length)
|
||||
{
|
||||
png_error(png_ptr, "Write Error");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Write error");
|
||||
}
|
||||
}
|
||||
#else
|
||||
@ -51,7 +50,7 @@ png_write_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length)
|
||||
#include <dos.h>
|
||||
#endif
|
||||
|
||||
void
|
||||
static void
|
||||
png_write_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length)
|
||||
{
|
||||
png_uint_32 check;
|
||||
@ -92,25 +91,22 @@ png_write_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length)
|
||||
}
|
||||
if (check != length)
|
||||
{
|
||||
png_error(png_ptr, "Write Error");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Write error");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Read the data from whatever input you are using. The default
|
||||
routine reads from a file pointer. If you need to read from something
|
||||
else, this is the place to do it. We suggest saving the old code
|
||||
for future use. Note that this routine sometimes gets called with
|
||||
very small lengths, so you should implement some kind of simple
|
||||
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 there for insurance, but if you are having problems
|
||||
with it, you can take it out. Just be sure to cast length to whatever
|
||||
fread needs in that spot if you don't have a function prototype for
|
||||
it. */
|
||||
else, this is a good example of how to do it. Note that this routine
|
||||
sometimes gets called with very small lengths, so you should implement
|
||||
some kind of simple 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 there for insurance. */
|
||||
#ifndef USE_FAR_KEYWORD
|
||||
void
|
||||
static void
|
||||
png_read_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length)
|
||||
{
|
||||
png_uint_32 check;
|
||||
@ -118,11 +114,11 @@ png_read_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length)
|
||||
check = fread(data, 1, (size_t)length, png_ptr->fp);
|
||||
if (check != length)
|
||||
{
|
||||
png_error(png_ptr, "Read Error");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Read error");
|
||||
}
|
||||
}
|
||||
#else
|
||||
void
|
||||
static void
|
||||
png_read_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length)
|
||||
{
|
||||
png_uint_32 check;
|
||||
@ -163,18 +159,253 @@ png_read_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length)
|
||||
}
|
||||
if (check != length)
|
||||
{
|
||||
png_error(png_ptr, "read Error");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Read error");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize the input/output for the png file. If you change
|
||||
the read and write routines, you will probably need to change
|
||||
this routine (or write your own). If you change the parameters
|
||||
of this routine, remember to change png.h also. */
|
||||
|
||||
/* This function does nothing, and is used for the write function on
|
||||
a read, and vice-versa. It is an error if this function is
|
||||
actually called. */
|
||||
static void
|
||||
png_empty_rw(png_struct *png_ptr, png_bytef *data, png_uint_32 length)
|
||||
{
|
||||
if (png_ptr->read_data_fn == png_empty_rw)
|
||||
{
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid read on a write device");
|
||||
}
|
||||
else /* if (png_ptr->write_data_fn == png_empty_rw) */
|
||||
{
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid write on a read device");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
|
||||
/* This function does nothing, and is supplied for user I/O functions which
|
||||
do not do any buffering. This function is set when NULL is supplied for
|
||||
the flush function pointer. */
|
||||
static void
|
||||
png_empty_flush(png_struct *png_ptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* Write out any remaining output that is stored in the output buffers.
|
||||
If you supply a new write routine, you will probably need to supply a
|
||||
replacement for this routine as well. */
|
||||
static void
|
||||
png_output_flush(png_struct *png_ptr)
|
||||
{
|
||||
fflush(png_ptr->fp);
|
||||
}
|
||||
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
|
||||
|
||||
|
||||
/* This function does nothing, and is called if the user supplies null
|
||||
when setting the error function. */
|
||||
static void
|
||||
png_empty_error(png_structf *png_ptr, char *message)
|
||||
{
|
||||
#ifdef USE_FAR_KEYWORD
|
||||
{
|
||||
jmp_buf jmpbuf;
|
||||
png_memcpy(jmpbuf,png_ptr->jmpbuf,sizeof(jmp_buf));
|
||||
longjmp(jmpbuf, 1);
|
||||
}
|
||||
#else
|
||||
longjmp(png_ptr->jmpbuf, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* This function is called whenever there is an error. Replace with a
|
||||
function you wish to handle the error. Note that this function
|
||||
MUST NOT return, or the program will crash. To be consistent with
|
||||
the examples for the library and this function, you could call
|
||||
longjmp(pnt_ptr->jmpbuf) to return to the program at the location of
|
||||
the last setjmp(png_ptr->jmpbuf) after an error. */
|
||||
static void
|
||||
png_error(png_structf *png_ptr, char *message)
|
||||
{
|
||||
fprintf(stderr, "libpng error: %s\n", message);
|
||||
|
||||
png_empty_error(png_ptr, message);
|
||||
}
|
||||
|
||||
|
||||
/* This function does nothing, and is called if the user supplies null
|
||||
when setting the warning function. */
|
||||
static void
|
||||
png_empty_warning(png_struct *png_ptr, char *message)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* This function is called when there is a warning, but the library
|
||||
thinks it can continue anyway. You don't have to do anything here
|
||||
if you don't want to. In the default configuration, png_ptr is
|
||||
not used, but it is passed in case it may be useful. */
|
||||
static void
|
||||
png_warning(png_struct *png_ptr, char *message)
|
||||
{
|
||||
fprintf(stderr, "libpng warning: %s\n", message);
|
||||
}
|
||||
|
||||
|
||||
/* This function allows the application to supply new output functions for
|
||||
libpng if standard C streams aren't being used. The new write function
|
||||
should call (*(png_ptr->error_fn))("Error message") to exit and output
|
||||
any fatal error messages if it cannot output the correct number of bytes.
|
||||
This function takes as its arguments:
|
||||
png_ptr - pointer to a png output data structure
|
||||
io_ptr - pointer to user supplied structure containing info about
|
||||
the output functions. May be NULL.
|
||||
write_data_fn - pointer to a new output function which takes as its
|
||||
arguments a pointer to a png_struct, a pointer to
|
||||
data to be written, and a 32-bit unsigned int which is
|
||||
the number of bytes to be written. The new write
|
||||
function should call (*(png_ptr->error_fn))("Error msg")
|
||||
to exit and output any fatal error messages.
|
||||
flush_data_fn - pointer to a new flush function which takes as its
|
||||
arguments a pointer to a png_struct. After a call to
|
||||
the flush function, there should be no data in any buffers
|
||||
or pending transmission. If the output method doesn't do
|
||||
any buffering of ouput, this parameter can be NULL. If
|
||||
PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng
|
||||
compile time, output_flush_fn will be ignored, although
|
||||
it must be supplied for compatibility. */
|
||||
void
|
||||
png_set_write_fn(png_struct *png_ptr, void *io_ptr, png_rw_ptr write_data_fn,
|
||||
png_flush_ptr output_flush_fn)
|
||||
{
|
||||
png_ptr->io_ptr = io_ptr;
|
||||
|
||||
if (write_data_fn == NULL)
|
||||
{
|
||||
(*(png_ptr->error_fn))(png_ptr, "NULL write function pointer given");
|
||||
}
|
||||
|
||||
png_ptr->write_data_fn = write_data_fn;
|
||||
|
||||
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
|
||||
if (output_flush_fn == NULL)
|
||||
{
|
||||
png_ptr->output_flush_fn = png_empty_flush;
|
||||
}
|
||||
else
|
||||
{
|
||||
png_ptr->output_flush_fn = output_flush_fn;
|
||||
}
|
||||
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
|
||||
|
||||
/* It is an error to write to a read device */
|
||||
png_ptr->read_data_fn = png_empty_rw;
|
||||
}
|
||||
|
||||
|
||||
/* This function allows the application to supply a new input function
|
||||
for libpng if standard C streams aren't being used. The new read function
|
||||
should call (*(png_ptr->error_fn))("Error message") to exit and output
|
||||
any fatal error messages if the desired number of bytes is not available.
|
||||
This function takes as its arguments:
|
||||
png_ptr - pointer to a png input data structure
|
||||
io_ptr - pointer to user supplied structure containing info about
|
||||
the input functions. May be NULL.
|
||||
read_data_fn - pointer to a new input function which takes as it's
|
||||
arguments a pointer to a png_struct, a pointer to
|
||||
a location where input data can be stored, and a 32-bit
|
||||
unsigned int which is the number of bytes to be read. */
|
||||
void
|
||||
png_set_read_fn(png_struct *png_ptr, void *io_ptr, png_rw_ptr read_data_fn)
|
||||
{
|
||||
png_ptr->io_ptr = io_ptr;
|
||||
|
||||
if (read_data_fn == NULL)
|
||||
{
|
||||
(*(png_ptr->error_fn))(png_ptr, "NULL read function pointer given");
|
||||
}
|
||||
png_ptr->read_data_fn = read_data_fn;
|
||||
|
||||
/* It is an error to write to a read device */
|
||||
png_ptr->write_data_fn = png_empty_rw;
|
||||
|
||||
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
|
||||
png_ptr->output_flush_fn = png_empty_flush;
|
||||
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
|
||||
}
|
||||
|
||||
|
||||
/* This function returns a pointer to the io_ptr associated with the user
|
||||
functions. The application should free any memory associated with this
|
||||
pointer before png_write_destroy and png_read_destroy are called. */
|
||||
void *
|
||||
png_get_io_ptr(png_struct *png_ptr)
|
||||
{
|
||||
return png_ptr->io_ptr;
|
||||
}
|
||||
|
||||
|
||||
/* This function is called when the application wants to use another
|
||||
method of handling errors and warnings. Note that the error function must
|
||||
NOT return to the calling routine or serious problems will occur. The
|
||||
error return method used in the default routine calls
|
||||
longjmp(png_ptr->jmpbuf, 1), or exits if setjmp(png_ptr->jmpbuf) has never
|
||||
been called. */
|
||||
void
|
||||
png_set_msg_fn(png_struct *png_ptr, void *msg_ptr, png_msg_ptr error_fn,
|
||||
png_msg_ptr warning_fn)
|
||||
{
|
||||
png_ptr->msg_ptr = msg_ptr;
|
||||
|
||||
if (error_fn == NULL)
|
||||
{
|
||||
png_ptr->error_fn = png_empty_error;
|
||||
}
|
||||
else
|
||||
{
|
||||
png_ptr->error_fn = error_fn;
|
||||
}
|
||||
|
||||
if (warning_fn == NULL)
|
||||
{
|
||||
png_ptr->warning_fn = png_empty_warning;
|
||||
}
|
||||
else
|
||||
{
|
||||
png_ptr->warning_fn = warning_fn;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* This function returns a pointer to the msg_ptr associated with the user
|
||||
functions. The application should free any memory associated with this
|
||||
pointer before png_write_destroy and png_read_destroy are called. */
|
||||
void *
|
||||
png_get_msg_ptr(png_struct *png_ptr)
|
||||
{
|
||||
return png_ptr->msg_ptr;
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the default input/output functions for the png file.
|
||||
If you change the read, write or message routines, can call
|
||||
either png_set_read_fn(...), png_set_write_fn(...), etc. to change
|
||||
individual functions after a call to png_init_io(...). You can also
|
||||
call one of png_set_read_fn(...) or png_set_write_fn(...), AND
|
||||
png_set_msg_fn(...) instead of png_init_io(...) if you aren't using
|
||||
any of the default libpng functions. */
|
||||
void
|
||||
png_init_io(png_struct *png_ptr, FILE *fp)
|
||||
{
|
||||
png_ptr->fp = fp;
|
||||
}
|
||||
png_ptr->error_fn = png_error;
|
||||
png_ptr->warning_fn = png_warning;
|
||||
png_ptr->write_data_fn = png_write_data;
|
||||
png_ptr->read_data_fn = png_read_data;
|
||||
|
||||
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
|
||||
png_ptr->output_flush_fn = png_output_flush;
|
||||
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
|
||||
}
|
||||
|
22
pngmem.c
22
pngmem.c
@ -1,5 +1,5 @@
|
||||
|
||||
/* pngstub.c - stub functions for i/o and memory allocation
|
||||
/* pngmem.c - stub functions for memory allocation
|
||||
|
||||
libpng 1.0 beta 2 - version 0.81
|
||||
For conditions of distribution and use, see copyright notice in png.h
|
||||
@ -61,7 +61,7 @@ png_large_malloc(png_structf *png_ptr, png_uint_32 size)
|
||||
|
||||
#ifdef PNG_MAX_MALLOC_64K
|
||||
if (size > (png_uint_32)65536L)
|
||||
png_error(png_ptr, "Cannot Allocate > 64K");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Cannot Allocate > 64K");
|
||||
#endif
|
||||
|
||||
#ifdef __TURBOC__
|
||||
@ -99,11 +99,11 @@ png_large_malloc(png_structf *png_ptr, png_uint_32 size)
|
||||
num_save_array = 1;
|
||||
save_array = malloc(num_save_array * sizeof (borland_seg));
|
||||
if (!save_array)
|
||||
png_error(png_ptr, "Out of Memory 1");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Memory 1");
|
||||
save_array->mem_ptr = farmalloc(
|
||||
(unsigned long)(NUM_SEG) * 65536L + 65532L);
|
||||
if (!save_array->mem_ptr)
|
||||
png_error(png_ptr, "Out of Memory 2");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Memory 2");
|
||||
offset = (unsigned long)(ret);
|
||||
offset &= 0xffffL;
|
||||
ptr = save_array->mem_ptr;
|
||||
@ -141,11 +141,11 @@ png_large_malloc(png_structf *png_ptr, png_uint_32 size)
|
||||
save_array = realloc(save_array,
|
||||
(num_save_array + 1) * sizeof (borland_seg));
|
||||
if (!save_array)
|
||||
png_error(png_ptr, "Out of Memory 3");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Memory 3");
|
||||
save_array[num_save_array].mem_ptr = farmalloc(
|
||||
(unsigned long)(NUM_SEG) * 65536L + 65532L);
|
||||
if (!save_array[num_save_array].mem_ptr)
|
||||
png_error(png_ptr, "Out of Memory 4");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Memory 4");
|
||||
offset = (unsigned long)(ret);
|
||||
offset &= 0xffffL;
|
||||
ptr = save_array[num_save_array].mem_ptr;
|
||||
@ -180,7 +180,7 @@ png_large_malloc(png_structf *png_ptr, png_uint_32 size)
|
||||
|
||||
if (ret == NULL)
|
||||
{
|
||||
png_error(png_ptr, "Out of Memory");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Memory");
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -259,14 +259,14 @@ png_malloc(png_struct *png_ptr, png_uint_32 size)
|
||||
|
||||
#ifdef PNG_MAX_MALLOC_64K
|
||||
if (size > (png_uint_32)65536L)
|
||||
png_error(png_ptr, "Cannot Allocate > 64K");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Cannot Allocate > 64K");
|
||||
#endif
|
||||
|
||||
ret = malloc((png_size_t)size);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
png_error(png_ptr, "Out of Memory 6");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Memory 6");
|
||||
}
|
||||
|
||||
return ret;
|
||||
@ -285,14 +285,14 @@ png_realloc(png_struct *png_ptr, void *ptr, png_uint_32 size,
|
||||
|
||||
#ifdef PNG_MAX_MALLOC_64K
|
||||
if (size > (png_uint_32)65536L)
|
||||
png_error(png_ptr, "Cannot Allocate > 64K");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Cannot Allocate > 64K");
|
||||
#endif
|
||||
|
||||
ret = realloc(ptr, (png_size_t)size);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
png_error(png_ptr, "Out of Memory 7");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Memory 7");
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
126
pngread.c
126
pngread.c
@ -38,22 +38,22 @@ png_read_info(png_struct *png_ptr, png_info *info)
|
||||
png_byte chunk_start[8];
|
||||
png_uint_32 length;
|
||||
|
||||
png_read_data(png_ptr, chunk_start, 8);
|
||||
(*(png_ptr->read_data_fn))(png_ptr, chunk_start, 8);
|
||||
if (memcmp(chunk_start, png_sig, 8))
|
||||
png_error(png_ptr, "Not a Png File");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Not a PNG File");
|
||||
|
||||
while (1)
|
||||
{
|
||||
png_uint_32 crc;
|
||||
|
||||
png_read_data(png_ptr, chunk_start, 8);
|
||||
(*(png_ptr->read_data_fn))(png_ptr, chunk_start, 8);
|
||||
length = png_get_uint_32(chunk_start);
|
||||
png_reset_crc(png_ptr);
|
||||
png_calculate_crc(png_ptr, chunk_start + 4, 4);
|
||||
if (!memcmp(chunk_start + 4, png_IHDR, 4))
|
||||
{
|
||||
if (png_ptr->mode != PNG_BEFORE_IHDR)
|
||||
png_error(png_ptr, "Out of Place IHDR");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Place IHDR");
|
||||
|
||||
png_handle_IHDR(png_ptr, info, length);
|
||||
png_ptr->mode = PNG_HAVE_IHDR;
|
||||
@ -61,7 +61,7 @@ png_read_info(png_struct *png_ptr, png_info *info)
|
||||
else if (!memcmp(chunk_start + 4, png_PLTE, 4))
|
||||
{
|
||||
if (png_ptr->mode != PNG_HAVE_IHDR)
|
||||
png_error(png_ptr, "Missing IHDR");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Missing IHDR");
|
||||
|
||||
#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
|
||||
if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
|
||||
@ -82,13 +82,13 @@ png_read_info(png_struct *png_ptr, png_info *info)
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_IEND, 4))
|
||||
{
|
||||
png_error(png_ptr, "No Image in File");
|
||||
(*(png_ptr->error_fn))(png_ptr, "No Image in File");
|
||||
}
|
||||
#if defined(PNG_READ_gAMA_SUPPORTED)
|
||||
else if (!memcmp(chunk_start + 4, png_gAMA, 4))
|
||||
{
|
||||
if (png_ptr->mode != PNG_HAVE_IHDR)
|
||||
png_error(png_ptr, "Out of Place PLTE");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Place PLTE");
|
||||
|
||||
png_handle_gAMA(png_ptr, info, length);
|
||||
}
|
||||
@ -97,7 +97,7 @@ png_read_info(png_struct *png_ptr, png_info *info)
|
||||
else if (!memcmp(chunk_start + 4, png_sBIT, 4))
|
||||
{
|
||||
if (png_ptr->mode != PNG_HAVE_IHDR)
|
||||
png_error(png_ptr, "Out of Place sBIT");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Place sBIT");
|
||||
|
||||
png_handle_sBIT(png_ptr, info, length);
|
||||
}
|
||||
@ -106,7 +106,7 @@ png_read_info(png_struct *png_ptr, png_info *info)
|
||||
else if (!memcmp(chunk_start + 4, png_cHRM, 4))
|
||||
{
|
||||
if (png_ptr->mode != PNG_HAVE_IHDR)
|
||||
png_error(png_ptr, "Out of Place cHRM");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Place cHRM");
|
||||
|
||||
png_handle_cHRM(png_ptr, info, length);
|
||||
}
|
||||
@ -116,7 +116,7 @@ png_read_info(png_struct *png_ptr, png_info *info)
|
||||
{
|
||||
if (png_ptr->mode != PNG_HAVE_IHDR &&
|
||||
png_ptr->mode != PNG_HAVE_PLTE)
|
||||
png_error(png_ptr, "Out of Place tRNS");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Place tRNS");
|
||||
|
||||
png_handle_tRNS(png_ptr, info, length);
|
||||
}
|
||||
@ -126,7 +126,7 @@ png_read_info(png_struct *png_ptr, png_info *info)
|
||||
{
|
||||
if (png_ptr->mode != PNG_HAVE_IHDR &&
|
||||
png_ptr->mode != PNG_HAVE_PLTE)
|
||||
png_error(png_ptr, "Out of Place bKGD");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Place bKGD");
|
||||
|
||||
png_handle_bKGD(png_ptr, info, length);
|
||||
}
|
||||
@ -135,7 +135,7 @@ png_read_info(png_struct *png_ptr, png_info *info)
|
||||
else if (!memcmp(chunk_start + 4, png_hIST, 4))
|
||||
{
|
||||
if (png_ptr->mode != PNG_HAVE_PLTE)
|
||||
png_error(png_ptr, "Out of Place hIST");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Place hIST");
|
||||
|
||||
png_handle_hIST(png_ptr, info, length);
|
||||
}
|
||||
@ -145,7 +145,7 @@ png_read_info(png_struct *png_ptr, png_info *info)
|
||||
{
|
||||
if (png_ptr->mode != PNG_HAVE_IHDR &&
|
||||
png_ptr->mode != PNG_HAVE_PLTE)
|
||||
png_error(png_ptr, "Out of Place pHYs");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Place pHYs");
|
||||
|
||||
png_handle_pHYs(png_ptr, info, length);
|
||||
}
|
||||
@ -155,7 +155,7 @@ png_read_info(png_struct *png_ptr, png_info *info)
|
||||
{
|
||||
if (png_ptr->mode != PNG_HAVE_IHDR &&
|
||||
png_ptr->mode != PNG_HAVE_PLTE)
|
||||
png_error(png_ptr, "Out of Place oFFs");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Place oFFs");
|
||||
|
||||
png_handle_oFFs(png_ptr, info, length);
|
||||
}
|
||||
@ -165,7 +165,7 @@ png_read_info(png_struct *png_ptr, png_info *info)
|
||||
{
|
||||
if (png_ptr->mode == PNG_BEFORE_IHDR ||
|
||||
png_ptr->mode == PNG_AFTER_IEND)
|
||||
png_error(png_ptr, "Out of Place tIME");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Place tIME");
|
||||
|
||||
png_handle_tIME(png_ptr, info, length);
|
||||
}
|
||||
@ -175,7 +175,7 @@ png_read_info(png_struct *png_ptr, png_info *info)
|
||||
{
|
||||
if (png_ptr->mode == PNG_BEFORE_IHDR ||
|
||||
png_ptr->mode == PNG_AFTER_IEND)
|
||||
png_error(png_ptr, "Out of Place tEXt");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Place tEXt");
|
||||
|
||||
png_handle_tEXt(png_ptr, info, length);
|
||||
}
|
||||
@ -185,7 +185,7 @@ png_read_info(png_struct *png_ptr, png_info *info)
|
||||
{
|
||||
if (png_ptr->mode == PNG_BEFORE_IHDR ||
|
||||
png_ptr->mode == PNG_AFTER_IEND)
|
||||
png_error(png_ptr, "Out of Place zTXt");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Place zTXt");
|
||||
|
||||
png_handle_zTXt(png_ptr, info, length);
|
||||
}
|
||||
@ -193,15 +193,15 @@ png_read_info(png_struct *png_ptr, png_info *info)
|
||||
else
|
||||
{
|
||||
if ((chunk_start[4] & 0x20) == 0)
|
||||
png_error(png_ptr, "Unknown Critical Chunk");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Unknown Critical Chunk");
|
||||
|
||||
png_crc_skip(png_ptr, length);
|
||||
}
|
||||
png_read_data(png_ptr, chunk_start, 4);
|
||||
(*(png_ptr->read_data_fn))(png_ptr, chunk_start, 4);
|
||||
crc = png_get_uint_32(chunk_start);
|
||||
if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
|
||||
(png_ptr->crc & 0xffffffffL))
|
||||
png_error(png_ptr, "Bad CRC value");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Bad CRC value");
|
||||
}
|
||||
}
|
||||
|
||||
@ -310,7 +310,7 @@ png_read_row(png_struct *png_ptr, png_bytef *row, png_byte *dsp_row)
|
||||
#endif
|
||||
|
||||
if (png_ptr->mode != PNG_HAVE_IDAT)
|
||||
png_error(png_ptr, "invalid attempt to read row data");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid attempt to read row data");
|
||||
|
||||
png_ptr->zstream->next_out = png_ptr->row_buf;
|
||||
png_ptr->zstream->avail_out = (uInt)png_ptr->irowbytes;
|
||||
@ -323,19 +323,19 @@ png_read_row(png_struct *png_ptr, png_bytef *row, png_byte *dsp_row)
|
||||
png_byte buf[4];
|
||||
png_uint_32 crc;
|
||||
|
||||
png_read_data(png_ptr, buf, 4);
|
||||
(*(png_ptr->read_data_fn))(png_ptr, buf, 4);
|
||||
crc = png_get_uint_32(buf);
|
||||
if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
|
||||
(png_ptr->crc & 0xffffffffL))
|
||||
png_error(png_ptr, "Bad CRC value");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Bad CRC value");
|
||||
|
||||
png_read_data(png_ptr, buf, 4);
|
||||
(*(png_ptr->read_data_fn))(png_ptr, buf, 4);
|
||||
png_ptr->idat_size = png_get_uint_32(buf);
|
||||
png_reset_crc(png_ptr);
|
||||
|
||||
png_crc_read(png_ptr, buf, 4);
|
||||
if (memcmp(buf, png_IDAT, 4))
|
||||
png_error(png_ptr, "Not enough image data");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Not enough image data");
|
||||
|
||||
}
|
||||
png_ptr->zstream->avail_in = (uInt)png_ptr->zbuf_size;
|
||||
@ -350,12 +350,12 @@ png_read_row(png_struct *png_ptr, png_bytef *row, png_byte *dsp_row)
|
||||
{
|
||||
if (png_ptr->zstream->avail_out || png_ptr->zstream->avail_in ||
|
||||
png_ptr->idat_size)
|
||||
png_error(png_ptr, "Extra compressed data");
|
||||
(*(png_ptr->warning_fn))(png_ptr, "Extra compressed data");
|
||||
png_ptr->mode = PNG_AT_LAST_IDAT;
|
||||
break;
|
||||
}
|
||||
if (ret != Z_OK)
|
||||
png_error(png_ptr, "Compression Error");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Compression Error");
|
||||
|
||||
} while (png_ptr->zstream->avail_out);
|
||||
|
||||
@ -448,6 +448,7 @@ png_read_rows(png_struct *png_ptr, png_bytef **row,
|
||||
dptr = *dp;
|
||||
else
|
||||
dptr = NULL;
|
||||
|
||||
png_read_row(png_ptr, rptr, dptr);
|
||||
if (row)
|
||||
rp++;
|
||||
@ -491,70 +492,70 @@ png_read_end(png_struct *png_ptr, png_info *info)
|
||||
png_uint_32 length;
|
||||
png_uint_32 crc;
|
||||
|
||||
png_read_data(png_ptr, chunk_start, 4);
|
||||
(*(png_ptr->read_data_fn))(png_ptr, chunk_start, 4);
|
||||
crc = png_get_uint_32(chunk_start);
|
||||
if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
|
||||
(png_ptr->crc & 0xffffffffL))
|
||||
png_error(png_ptr, "Bad CRC value");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Bad CRC value");
|
||||
|
||||
do
|
||||
{
|
||||
png_read_data(png_ptr, chunk_start, 8);
|
||||
(*(png_ptr->read_data_fn))(png_ptr, chunk_start, 8);
|
||||
length = png_get_uint_32(chunk_start);
|
||||
png_reset_crc(png_ptr);
|
||||
png_calculate_crc(png_ptr, chunk_start + 4, 4);
|
||||
|
||||
if (!memcmp(chunk_start + 4, png_IHDR, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_PLTE, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_gAMA, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_sBIT, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_cHRM, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_tRNS, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_bKGD, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_hIST, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_IDAT, 4))
|
||||
{
|
||||
if (length > 0 || png_ptr->mode != PNG_AT_LAST_IDAT)
|
||||
png_error(png_ptr, "too many IDAT's found");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Too many IDAT's found");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_pHYs, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_oFFs, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT");
|
||||
}
|
||||
#if defined(PNG_READ_tIME_SUPPORTED)
|
||||
else if (!memcmp(chunk_start + 4, png_tIME, 4))
|
||||
{
|
||||
if (png_ptr->mode == PNG_BEFORE_IHDR ||
|
||||
png_ptr->mode == PNG_AFTER_IEND)
|
||||
png_error(png_ptr, "Out of Place tIME");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Place tIME");
|
||||
|
||||
if (info)
|
||||
png_handle_tIME(png_ptr, info, length);
|
||||
@ -567,7 +568,7 @@ png_read_end(png_struct *png_ptr, png_info *info)
|
||||
{
|
||||
if (png_ptr->mode == PNG_BEFORE_IHDR ||
|
||||
png_ptr->mode == PNG_AFTER_IEND)
|
||||
png_error(png_ptr, "Out of Place tEXt");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Place tEXt");
|
||||
|
||||
if (info)
|
||||
png_handle_tEXt(png_ptr, info, length);
|
||||
@ -580,7 +581,7 @@ png_read_end(png_struct *png_ptr, png_info *info)
|
||||
{
|
||||
if (png_ptr->mode == PNG_BEFORE_IHDR ||
|
||||
png_ptr->mode == PNG_AFTER_IEND)
|
||||
png_error(png_ptr, "Out of Place zTXt");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Out of Place zTXt");
|
||||
|
||||
if (info)
|
||||
png_handle_zTXt(png_ptr, info, length);
|
||||
@ -594,16 +595,25 @@ png_read_end(png_struct *png_ptr, png_info *info)
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((chunk_start[4] & 0x20) == 0)
|
||||
png_error(png_ptr, "Unknown Critical Chunk");
|
||||
char msg[80];
|
||||
|
||||
if ((chunk_start[4] & 0x20) == 0)
|
||||
{
|
||||
png_strcpy(msg,"Unknown critical chunk ");
|
||||
png_memcpy(msg + strlen(msg), chunk_start + 4,4);
|
||||
(*(png_ptr->error_fn))(png_ptr, msg);
|
||||
}
|
||||
|
||||
png_strcpy(msg,"Unknown extension chunk ");
|
||||
png_memcpy(msg + strlen(msg), chunk_start + 4,4);
|
||||
(*(png_ptr->warning_fn))(png_ptr, msg);
|
||||
png_crc_skip(png_ptr, length);
|
||||
}
|
||||
png_read_data(png_ptr, chunk_start, 4);
|
||||
(*(png_ptr->read_data_fn))(png_ptr, chunk_start, 4);
|
||||
crc = png_get_uint_32(chunk_start);
|
||||
if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
|
||||
(png_ptr->crc & 0xffffffffL))
|
||||
png_error(png_ptr, "Bad CRC value");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Bad CRC value");
|
||||
if (png_ptr->mode == PNG_AT_LAST_IDAT)
|
||||
png_ptr->mode = PNG_AFTER_IDAT;
|
||||
} while (png_ptr->mode != PNG_AFTER_IEND);
|
||||
@ -618,19 +628,19 @@ png_read_destroy(png_struct *png_ptr, png_info *info, png_info *end_info)
|
||||
|
||||
if (info)
|
||||
{
|
||||
/* I'm not sure I should be freeing this */
|
||||
if (info->palette != png_ptr->palette)
|
||||
if (png_ptr->do_free & PNG_FREE_PALETTE)
|
||||
png_free(png_ptr, info->palette);
|
||||
/* I'm not sure I should be freeing this */
|
||||
|
||||
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_bKGD_SUPPORTED)
|
||||
if (info->trans != png_ptr->trans)
|
||||
if (png_ptr->do_free & PNG_FREE_TRANS)
|
||||
png_free(png_ptr, info->trans);
|
||||
#endif
|
||||
/* I'm not sure I should be freeing this */
|
||||
|
||||
#if defined(PNG_READ_hIST_SUPPORTED)
|
||||
if (info->hist != png_ptr->hist)
|
||||
if (png_ptr->do_free & PNG_FREE_HIST)
|
||||
png_free(png_ptr, info->hist);
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
|
||||
for (i = 0; i < info->num_text; i++)
|
||||
{
|
||||
@ -658,17 +668,21 @@ png_read_destroy(png_struct *png_ptr, png_info *info, png_info *end_info)
|
||||
png_large_free(png_ptr, png_ptr->zbuf);
|
||||
png_large_free(png_ptr, png_ptr->row_buf);
|
||||
png_large_free(png_ptr, png_ptr->prev_row);
|
||||
|
||||
#if defined(PNG_READ_DITHER_SUPPORTED)
|
||||
png_large_free(png_ptr, png_ptr->palette_lookup);
|
||||
png_free(png_ptr, png_ptr->dither_index);
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_GAMMA_SUPPORTED)
|
||||
png_free(png_ptr, png_ptr->gamma_table);
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
|
||||
png_free(png_ptr, png_ptr->gamma_from_1);
|
||||
png_free(png_ptr, png_ptr->gamma_to_1);
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_GAMMA_SUPPORTED)
|
||||
if (png_ptr->gamma_16_table)
|
||||
{
|
||||
@ -678,6 +692,7 @@ png_read_destroy(png_struct *png_ptr, png_info *info, png_info *end_info)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
|
||||
png_free(png_ptr, png_ptr->gamma_16_table);
|
||||
if (png_ptr->gamma_16_from_1)
|
||||
@ -697,12 +712,15 @@ png_read_destroy(png_struct *png_ptr, png_info *info, png_info *end_info)
|
||||
}
|
||||
png_free(png_ptr, png_ptr->gamma_16_to_1);
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
|
||||
png_free(png_ptr, png_ptr->trans);
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_DITHER_SUPPORTED)
|
||||
png_free(png_ptr, png_ptr->hist);
|
||||
#endif
|
||||
|
||||
if (!png_ptr->user_palette)
|
||||
png_free(png_ptr, png_ptr->palette);
|
||||
|
||||
|
49
pngrtran.c
49
pngrtran.c
@ -572,7 +572,7 @@ png_init_read_transformations(png_struct *png_ptr)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_READ_SHIFT_SUPPORTED)
|
||||
#if defined(PNG_READ_SHIFT_SUPPORTED) && defined(PNG_READ_sBIT_SUPPORTED)
|
||||
if ((png_ptr->transformations & PNG_SHIFT) &&
|
||||
png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
{
|
||||
@ -876,19 +876,33 @@ png_do_unshift(png_row_info *row_info, png_bytef *row,
|
||||
channels = 0;
|
||||
if (row_info->color_type & PNG_COLOR_MASK_COLOR)
|
||||
{
|
||||
shift[channels++] = row_info->bit_depth - sig_bits->red;
|
||||
shift[channels++] = row_info->bit_depth - sig_bits->green;
|
||||
shift[channels++] = row_info->bit_depth - sig_bits->blue;
|
||||
shift[channels++] = row_info->bit_depth - sig_bits->red < 0 ?
|
||||
0 : row_info->bit_depth - sig_bits->red;
|
||||
shift[channels++] = row_info->bit_depth - sig_bits->green < 0 ?
|
||||
0 : row_info->bit_depth - sig_bits->green;
|
||||
shift[channels++] = row_info->bit_depth - sig_bits->blue < 0 ?
|
||||
0 : row_info->bit_depth - sig_bits->blue;
|
||||
}
|
||||
else
|
||||
{
|
||||
shift[channels++] = row_info->bit_depth - sig_bits->gray;
|
||||
shift[channels++] = row_info->bit_depth - sig_bits->gray < 0 ?
|
||||
0 : row_info->bit_depth - sig_bits->gray;
|
||||
}
|
||||
if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
|
||||
{
|
||||
shift[channels++] = row_info->bit_depth - sig_bits->alpha;
|
||||
shift[channels++] = row_info->bit_depth - sig_bits->alpha < 0 ?
|
||||
0 : row_info->bit_depth - sig_bits->alpha;
|
||||
}
|
||||
|
||||
value = 1;
|
||||
|
||||
for (i = 0; i < channels; i++)
|
||||
{
|
||||
if (shift[i] != 0) value = 0;
|
||||
}
|
||||
|
||||
if (value == 1) return;
|
||||
|
||||
switch (row_info->bit_depth)
|
||||
{
|
||||
case 2:
|
||||
@ -905,6 +919,7 @@ png_do_unshift(png_row_info *row_info, png_bytef *row,
|
||||
case 4:
|
||||
{
|
||||
png_byte mask;
|
||||
|
||||
mask = (png_byte)(((int)0xf0 >> shift[0]) & (int)0xf0) |
|
||||
((int)0xf >> shift[0]);
|
||||
for (bp = row, i = 0;
|
||||
@ -957,17 +972,15 @@ png_do_unshift(png_row_info *row_info, png_bytef *row,
|
||||
void
|
||||
png_do_chop(png_row_info *row_info, png_bytef *row)
|
||||
{
|
||||
png_bytef *sp, *dp;
|
||||
png_uint_32 i;
|
||||
if (row && row_info && row_info->bit_depth == 16)
|
||||
{
|
||||
sp = row + 2;
|
||||
dp = row + 1;
|
||||
for (i = 1; i < row_info->width * row_info->channels; i++)
|
||||
png_bytef *sp = row, *dp = row;
|
||||
png_uint_32 i;
|
||||
|
||||
for (i = 0; i < row_info->width * row_info->channels; i++)
|
||||
{
|
||||
*dp = *sp;
|
||||
*dp++ = ((((*sp << 8 | *(sp + 1)) - *sp) + 0x7F) >> 8) & 0xFF;
|
||||
sp += 2;
|
||||
dp++;
|
||||
}
|
||||
row_info->bit_depth = 8;
|
||||
row_info->pixel_depth = 8 * row_info->channels;
|
||||
@ -1147,6 +1160,7 @@ png_build_grayscale_palette(int bit_depth, png_color *palette)
|
||||
break;
|
||||
default:
|
||||
num_palette = 0;
|
||||
color_inc = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -2002,7 +2016,7 @@ png_do_background(png_row_info *row_info, png_bytef *row,
|
||||
you do this after you deal with the trasparency issue on grayscale
|
||||
or rgb images. If your bit depth is 8, use gamma_table, if it is 16,
|
||||
use gamma_16_table and gamma_shift. Build these with
|
||||
build_gamma_table(). If your bit depth < 8, gamma correct a
|
||||
build_gamma_table(). If your bit depth <= 8, gamma correct a
|
||||
palette, not the data. */
|
||||
void
|
||||
png_do_gamma(png_row_info *row_info, png_bytef *row,
|
||||
@ -2623,8 +2637,9 @@ png_build_gamma_table(png_struct *png_ptr)
|
||||
{
|
||||
double g;
|
||||
int i, j, shift, num;
|
||||
int sig_bit;
|
||||
png_uint_32 ig;
|
||||
#if defined(PNG_READ_sBIT_SUPPORTED)
|
||||
int sig_bit;
|
||||
|
||||
if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
|
||||
{
|
||||
@ -2642,6 +2657,7 @@ png_build_gamma_table(png_struct *png_ptr)
|
||||
if (sig_bit > 0)
|
||||
shift = 16 - sig_bit;
|
||||
else
|
||||
#endif /* PNG_READ_sBIT_SUPPORTED */
|
||||
shift = 0;
|
||||
|
||||
if (png_ptr->transformations & PNG_16_TO_8)
|
||||
@ -2685,8 +2701,7 @@ png_build_gamma_table(png_struct *png_ptr)
|
||||
max = (png_uint_32)(fin * (double)(num << 8));
|
||||
while (last <= max)
|
||||
{
|
||||
png_ptr->gamma_16_table[(int)(last >> 8)]
|
||||
[(int)(last & 0xff)] =
|
||||
png_ptr->gamma_16_table[(int)(last >> 8)][(int)(last & 0xff)] =
|
||||
(png_uint_16)i | ((png_uint_16)i << 8);
|
||||
last++;
|
||||
}
|
||||
|
94
pngrutil.c
94
pngrutil.c
@ -40,7 +40,7 @@ png_get_uint_16(png_byte *buf)
|
||||
void
|
||||
png_crc_read(png_struct *png_ptr, png_bytef *buf, png_uint_32 length)
|
||||
{
|
||||
png_read_data(png_ptr, buf, length);
|
||||
(*(png_ptr->read_data_fn))(png_ptr, buf, length);
|
||||
png_calculate_crc(png_ptr, buf, length);
|
||||
}
|
||||
|
||||
@ -52,12 +52,12 @@ png_crc_skip(png_struct *png_ptr, png_uint_32 length)
|
||||
|
||||
for (i = length; i > png_ptr->zbuf_size; i -= png_ptr->zbuf_size)
|
||||
{
|
||||
png_read_data(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
|
||||
(*(png_ptr->read_data_fn))(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
|
||||
png_calculate_crc(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
|
||||
}
|
||||
if (i)
|
||||
{
|
||||
png_read_data(png_ptr, png_ptr->zbuf, i);
|
||||
(*(png_ptr->read_data_fn))(png_ptr, png_ptr->zbuf, i);
|
||||
png_calculate_crc(png_ptr, png_ptr->zbuf, i);
|
||||
}
|
||||
}
|
||||
@ -73,7 +73,7 @@ png_handle_IHDR(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
|
||||
/* check the length */
|
||||
if (length != 13)
|
||||
png_error(png_ptr, "Invalid IHDR chunk");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid IHDR chunk");
|
||||
|
||||
png_crc_read(png_ptr, buf, 13);
|
||||
|
||||
@ -87,36 +87,36 @@ png_handle_IHDR(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
|
||||
/* check for width and height valid values */
|
||||
if (width == 0 || height == 0)
|
||||
png_error(png_ptr, "Invalid Width or Height Found");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid Width or Height Found");
|
||||
|
||||
/* check other values */
|
||||
if (bit_depth != 1 && bit_depth != 2 &&
|
||||
bit_depth != 4 && bit_depth != 8 &&
|
||||
bit_depth != 16)
|
||||
png_error(png_ptr, "Invalid Bit Depth Found");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid Bit Depth Found");
|
||||
|
||||
if (color_type < 0 || color_type == 1 ||
|
||||
color_type == 5 || color_type > 6)
|
||||
png_error(png_ptr, "Invalid Color Type Found");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid Color Type Found");
|
||||
|
||||
if (color_type == PNG_COLOR_TYPE_PALETTE &&
|
||||
bit_depth == 16)
|
||||
png_error(png_ptr, "Found Invalid Color Type and Bit Depth Combination");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Found Invalid Color Type and Bit Depth Combination");
|
||||
|
||||
if ((color_type == PNG_COLOR_TYPE_RGB ||
|
||||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
|
||||
color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
|
||||
bit_depth < 8)
|
||||
png_error(png_ptr, "Found Invalid Color Type and Bit Depth Combination");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Found Invalid Color Type and Bit Depth Combination");
|
||||
|
||||
if (interlace_type > 1)
|
||||
png_error(png_ptr, "Found Invalid Interlace Value");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Found Unsupported Interlace Value");
|
||||
|
||||
if (compression_type > 0)
|
||||
png_error(png_ptr, "Found Invalid Compression Value");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Found Unsupported Compression Value");
|
||||
|
||||
if (filter_type > 0)
|
||||
png_error(png_ptr, "Found Invalid Filter Value");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Found Unsupported Filter Value");
|
||||
|
||||
/* set internal variables */
|
||||
png_ptr->width = width;
|
||||
@ -160,10 +160,12 @@ png_handle_PLTE(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
png_color *palette;
|
||||
|
||||
if (length % 3)
|
||||
png_error(png_ptr, "Invalid Palette Chunk");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid Palette Chunk");
|
||||
|
||||
num = (int)length / 3;
|
||||
palette = (png_color *)png_malloc(png_ptr, num * sizeof (png_color));
|
||||
png_ptr->do_free |= PNG_FREE_PALETTE;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
png_byte buf[3];
|
||||
@ -189,6 +191,7 @@ png_handle_gAMA(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
|
||||
if (length != 4)
|
||||
{
|
||||
(*(png_ptr->warning_fn))(png_ptr,"Incorrect gAMA chunk length");
|
||||
png_crc_skip(png_ptr, length);
|
||||
return;
|
||||
}
|
||||
@ -210,6 +213,7 @@ void
|
||||
png_handle_sBIT(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
{
|
||||
int slen;
|
||||
register int index = 0;
|
||||
png_byte buf[4];
|
||||
|
||||
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
@ -219,6 +223,7 @@ png_handle_sBIT(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
|
||||
if (length != (png_uint_32)slen)
|
||||
{
|
||||
(*(png_ptr->warning_fn))(png_ptr, "Incorrect sBIT chunk length");
|
||||
png_crc_skip(png_ptr, length);
|
||||
return;
|
||||
}
|
||||
@ -226,16 +231,28 @@ png_handle_sBIT(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
png_crc_read(png_ptr, buf, length);
|
||||
if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
|
||||
{
|
||||
png_ptr->sig_bit.red = buf[0];
|
||||
png_ptr->sig_bit.green = buf[1];
|
||||
png_ptr->sig_bit.blue = buf[2];
|
||||
png_ptr->sig_bit.alpha = buf[3];
|
||||
png_ptr->sig_bit.red = buf[index++];
|
||||
png_ptr->sig_bit.green = buf[index++];
|
||||
png_ptr->sig_bit.blue = buf[index++];
|
||||
png_ptr->sig_bit.gray = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
png_ptr->sig_bit.red = 0;
|
||||
png_ptr->sig_bit.green = 0;
|
||||
png_ptr->sig_bit.blue = 0;
|
||||
png_ptr->sig_bit.gray = buf[0];
|
||||
png_ptr->sig_bit.alpha = buf[1];
|
||||
}
|
||||
|
||||
if (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)
|
||||
{
|
||||
png_ptr->sig_bit.alpha = buf[index++];
|
||||
}
|
||||
else
|
||||
{
|
||||
png_ptr->sig_bit.alpha = 0;
|
||||
}
|
||||
|
||||
png_read_sBIT(png_ptr, info, &(png_ptr->sig_bit));
|
||||
}
|
||||
#endif
|
||||
@ -250,6 +267,7 @@ png_handle_cHRM(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
|
||||
if (length != 32)
|
||||
{
|
||||
(*(png_ptr->warning_fn))(png_ptr, "Incorrect cHRM chunk length");
|
||||
png_crc_skip(png_ptr, length);
|
||||
return;
|
||||
}
|
||||
@ -299,11 +317,13 @@ png_handle_tRNS(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
{
|
||||
if (length > png_ptr->num_palette)
|
||||
{
|
||||
(*(png_ptr->warning_fn))(png_ptr, "Incorrect tRNS chunk length");
|
||||
png_crc_skip(png_ptr, length);
|
||||
return;
|
||||
}
|
||||
|
||||
png_ptr->trans = png_malloc(png_ptr, length);
|
||||
png_ptr->do_free |= PNG_FREE_TRANS;
|
||||
png_crc_read(png_ptr, png_ptr->trans, length);
|
||||
png_ptr->num_trans = (int)length;
|
||||
}
|
||||
@ -313,6 +333,7 @@ png_handle_tRNS(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
|
||||
if (length != 6)
|
||||
{
|
||||
(*(png_ptr->warning_fn))(png_ptr, "Incorrect tRNS chunk length");
|
||||
png_crc_skip(png_ptr, length);
|
||||
return;
|
||||
}
|
||||
@ -329,6 +350,7 @@ png_handle_tRNS(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
|
||||
if (length != 2)
|
||||
{
|
||||
(*(png_ptr->warning_fn))(png_ptr, "Incorrect tRNS chunk length");
|
||||
png_crc_skip(png_ptr, length);
|
||||
return;
|
||||
}
|
||||
@ -338,7 +360,7 @@ png_handle_tRNS(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
png_ptr->trans_values.gray = png_get_uint_16(buf);
|
||||
}
|
||||
else
|
||||
png_error(png_ptr, "Invalid tRNS chunk");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Invalid tRNS chunk");
|
||||
|
||||
png_read_tRNS(png_ptr, info, png_ptr->trans, png_ptr->num_trans,
|
||||
&(png_ptr->trans_values));
|
||||
@ -361,6 +383,7 @@ png_handle_bKGD(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
|
||||
if (length != (png_uint_32)truelen)
|
||||
{
|
||||
(*(png_ptr->warning_fn))(png_ptr, "Incorrect bKGD chunk length");
|
||||
png_crc_skip(png_ptr, length);
|
||||
return;
|
||||
}
|
||||
@ -389,12 +412,15 @@ png_handle_hIST(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
|
||||
if (length != 2 * png_ptr->num_palette)
|
||||
{
|
||||
(*(png_ptr->warning_fn))(png_ptr, "Incorrect hIST chunk length");
|
||||
png_crc_skip(png_ptr, length);
|
||||
return;
|
||||
}
|
||||
|
||||
num = (int)length / 2;
|
||||
png_ptr->hist = png_malloc(png_ptr, num * sizeof (png_uint_16));
|
||||
png_ptr->do_free |= PNG_FREE_HIST;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
png_byte buf[2];
|
||||
@ -416,6 +442,7 @@ png_handle_pHYs(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
|
||||
if (length != 9)
|
||||
{
|
||||
(*(png_ptr->warning_fn))(png_ptr, "Incorrect pHYS chunk length");
|
||||
png_crc_skip(png_ptr, length);
|
||||
return;
|
||||
}
|
||||
@ -439,6 +466,7 @@ png_handle_oFFs(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
|
||||
if (length != 9)
|
||||
{
|
||||
(*(png_ptr->warning_fn))(png_ptr, "Incorrect oFFs chunk length");
|
||||
png_crc_skip(png_ptr, length);
|
||||
return;
|
||||
}
|
||||
@ -461,6 +489,7 @@ png_handle_tIME(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
|
||||
if (length != 7)
|
||||
{
|
||||
(*(png_ptr->warning_fn))(png_ptr, "Incorrect tIME chunk length");
|
||||
png_crc_skip(png_ptr, length);
|
||||
return;
|
||||
}
|
||||
@ -509,7 +538,7 @@ png_handle_zTXt(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
{
|
||||
charf *key;
|
||||
charf *text;
|
||||
int ret;
|
||||
int ret = Z_STREAM_END;
|
||||
png_uint_32 text_size, key_size;
|
||||
|
||||
text = NULL;
|
||||
@ -524,6 +553,7 @@ png_handle_zTXt(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
/* zTXt can't have zero text */
|
||||
if (text == key + (png_size_t)length)
|
||||
{
|
||||
(*(png_ptr->warning_fn))(png_ptr, "Zero length zTXt chunk");
|
||||
png_large_free(png_ptr, key);
|
||||
return;
|
||||
}
|
||||
@ -552,6 +582,10 @@ png_handle_zTXt(png_struct *png_ptr, png_info *info, png_uint_32 length)
|
||||
ret = inflate(png_ptr->zstream, Z_PARTIAL_FLUSH);
|
||||
if (ret != Z_OK && ret != Z_STREAM_END)
|
||||
{
|
||||
if (png_ptr->zstream->msg)
|
||||
(*(png_ptr->warning_fn))(png_ptr,png_ptr->zstream->msg);
|
||||
else
|
||||
(*(png_ptr->warning_fn))(png_ptr,"zTXt decompression error");
|
||||
inflateReset(png_ptr->zstream);
|
||||
png_ptr->zstream->avail_in = 0;
|
||||
png_large_free(png_ptr, key);
|
||||
@ -1104,19 +1138,19 @@ png_read_finish_row(png_struct *png_ptr)
|
||||
png_byte buf[4];
|
||||
png_uint_32 crc;
|
||||
|
||||
png_read_data(png_ptr, buf, 4);
|
||||
(*(png_ptr->read_data_fn))(png_ptr, buf, 4);
|
||||
crc = png_get_uint_32(buf);
|
||||
if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
|
||||
(png_ptr->crc & 0xffffffffL))
|
||||
png_error(png_ptr, "Bad CRC value");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Bad CRC value");
|
||||
|
||||
png_read_data(png_ptr, buf, 4);
|
||||
(*(png_ptr->read_data_fn))(png_ptr, buf, 4);
|
||||
png_ptr->idat_size = png_get_uint_32(buf);
|
||||
png_reset_crc(png_ptr);
|
||||
|
||||
png_crc_read(png_ptr, buf, 4);
|
||||
if (memcmp(buf, png_IDAT, 4))
|
||||
png_error(png_ptr, "Not enough image data");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Not enough image data");
|
||||
|
||||
}
|
||||
png_ptr->zstream->avail_in = (uInt)png_ptr->zbuf_size;
|
||||
@ -1131,22 +1165,22 @@ png_read_finish_row(png_struct *png_ptr)
|
||||
{
|
||||
if (!(png_ptr->zstream->avail_out) || png_ptr->zstream->avail_in ||
|
||||
png_ptr->idat_size)
|
||||
png_error(png_ptr, "Extra compressed data");
|
||||
(*(png_ptr->warning_fn))(png_ptr, "Extra compressed data");
|
||||
png_ptr->mode = PNG_AT_LAST_IDAT;
|
||||
break;
|
||||
}
|
||||
if (ret != Z_OK)
|
||||
png_error(png_ptr, "Compression Error");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Compression Error");
|
||||
|
||||
if (!(png_ptr->zstream->avail_out))
|
||||
png_error(png_ptr, "Extra compressed data");
|
||||
(*(png_ptr->error_fn))(png_ptr, "Extra compressed data");
|
||||
|
||||
} while (1);
|
||||
png_ptr->zstream->avail_out = 0;
|
||||
}
|
||||
|
||||
if (png_ptr->idat_size || png_ptr->zstream->avail_in)
|
||||
png_error(png_ptr, "Extra compression data");
|
||||
(*(png_ptr->warning_fn))(png_ptr, "Extra compression data");
|
||||
|
||||
inflateReset(png_ptr->zstream);
|
||||
|
||||
@ -1258,13 +1292,13 @@ png_read_start_row(png_struct *png_ptr)
|
||||
1 + ((max_pixel_depth + 7) >> 3);
|
||||
#ifdef PNG_MAX_MALLOC_64K
|
||||
if (rowbytes > 65536L)
|
||||
png_error(png_ptr, "This image requires a row greater then 64KB");
|
||||
(*(png_ptr->error_fn))(png_ptr, "This image requires a row greater then 64KB");
|
||||
#endif
|
||||
png_ptr->row_buf = (png_bytef *)png_large_malloc(png_ptr, rowbytes);
|
||||
|
||||
#ifdef PNG_MAX_MALLOC_64K
|
||||
if (png_ptr->rowbytes + 1 > 65536L)
|
||||
png_error(png_ptr, "This image requires a row greater then 64KB");
|
||||
(*(png_ptr->error_fn))(png_ptr, "This image requires a row greater then 64KB");
|
||||
#endif
|
||||
png_ptr->prev_row = png_large_malloc(png_ptr,
|
||||
png_ptr->rowbytes + 1);
|
||||
|
@ -19,7 +19,7 @@
|
||||
|
||||
/* input and output filenames */
|
||||
char inname[] = "pngtest.png";
|
||||
char outname[] = "pngout.png";
|
||||
char outname[] = "testout.png";
|
||||
|
||||
png_struct read_ptr;
|
||||
png_struct write_ptr;
|
||||
@ -79,10 +79,10 @@ int main()
|
||||
return 1;
|
||||
}
|
||||
|
||||
png_read_init(&read_ptr);
|
||||
png_write_init(&write_ptr);
|
||||
png_info_init(&info_ptr);
|
||||
png_info_init(&end_info);
|
||||
png_read_init(&read_ptr);
|
||||
png_write_init(&write_ptr);
|
||||
|
||||
png_init_io(&read_ptr, fpin);
|
||||
png_init_io(&write_ptr, fpout);
|
||||
@ -97,6 +97,9 @@ int main()
|
||||
if (info_ptr.color_type & 4)
|
||||
channels++;
|
||||
|
||||
png_set_flush(&write_ptr, 20);
|
||||
png_set_compression_level(&write_ptr, 9);
|
||||
|
||||
rowbytes = ((info_ptr.width * info_ptr.bit_depth * channels + 7) >> 3);
|
||||
row_buf = (png_byte *)malloc((size_t)rowbytes);
|
||||
if (!row_buf)
|
||||
|
107
pngwrite.c
107
pngwrite.c
@ -57,25 +57,30 @@ png_write_info(png_struct *png_ptr, png_info *info)
|
||||
if (info->valid & PNG_INFO_bKGD)
|
||||
png_write_bKGD(png_ptr, &(info->background), info->color_type);
|
||||
#endif
|
||||
|
||||
#if defined(PNG_WRITE_hIST_SUPPORTED)
|
||||
if (info->valid & PNG_INFO_hIST)
|
||||
png_write_hIST(png_ptr, info->hist, info->num_palette);
|
||||
#endif
|
||||
|
||||
#if defined(PNG_WRITE_pHYs_SUPPORTED)
|
||||
if (info->valid & PNG_INFO_pHYs)
|
||||
png_write_pHYs(png_ptr, info->x_pixels_per_unit,
|
||||
info->y_pixels_per_unit, info->phys_unit_type);
|
||||
#endif
|
||||
|
||||
#if defined(PNG_WRITE_oFFs_SUPPORTED)
|
||||
if (info->valid & PNG_INFO_oFFs)
|
||||
png_write_oFFs(png_ptr, info->x_offset, info->y_offset,
|
||||
info->offset_unit_type);
|
||||
#endif
|
||||
|
||||
#if defined(PNG_WRITE_tIME_SUPPORTED)
|
||||
if (info->valid & PNG_INFO_tIME)
|
||||
png_write_tIME(png_ptr, &(info->mod_time));
|
||||
/* Check to see if we need to write text chunks */
|
||||
#endif
|
||||
|
||||
#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
|
||||
if (info->num_text)
|
||||
{
|
||||
@ -84,6 +89,12 @@ png_write_info(png_struct *png_ptr, png_info *info)
|
||||
/* loop through the text chunks */
|
||||
for (i = 0; i < info->num_text; i++)
|
||||
{
|
||||
if (strlen(info->text[i].key) > 80)
|
||||
{
|
||||
(*(png_ptr->warning_fn))(png_ptr,"tEXt keyword more than 80 chars");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* if chunk is compressed */
|
||||
if (info->text[i].compression >= 0)
|
||||
{
|
||||
@ -104,7 +115,8 @@ png_write_info(png_struct *png_ptr, png_info *info)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* PNG_WRITE_tEXt_SUPPORTED || PNG_WRITE_zTXt_SUPPORTED */
|
||||
png_ptr->mode = PNG_HAVE_IHDR;
|
||||
}
|
||||
|
||||
/* writes the end of the png file. If you don't want to write comments or
|
||||
@ -114,6 +126,9 @@ png_write_info(png_struct *png_ptr, png_info *info)
|
||||
void
|
||||
png_write_end(png_struct *png_ptr, png_info *info)
|
||||
{
|
||||
if (info && png_ptr->mode == PNG_AFTER_IEND)
|
||||
return;
|
||||
|
||||
/* see if user wants us to write information chunks */
|
||||
if (info)
|
||||
{
|
||||
@ -122,6 +137,7 @@ png_write_end(png_struct *png_ptr, png_info *info)
|
||||
if (info->valid & PNG_INFO_tIME)
|
||||
png_write_tIME(png_ptr, &(info->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->num_text)
|
||||
@ -151,10 +167,12 @@ png_write_end(png_struct *png_ptr, png_info *info)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* PNG_WRITE_tEXt_SUPPORTED || PNG_WRITE_zTXt_SUPPORTED */
|
||||
}
|
||||
/* write end of png file */
|
||||
png_write_IEND(png_ptr);
|
||||
|
||||
png_ptr->mode = PNG_AFTER_IEND;
|
||||
}
|
||||
|
||||
#if defined(PNG_WRITE_tIME_SUPPORTED)
|
||||
@ -177,7 +195,7 @@ png_convert_from_time_t(png_time *ptime, time_t ttime)
|
||||
tbuf = gmtime(&ttime);
|
||||
png_convert_from_struct_tm(ptime, tbuf);
|
||||
}
|
||||
#endif
|
||||
#endif /* PNG_WRITE_tIME_SUPPORTED */
|
||||
|
||||
/* initialize png structure, and allocate any memory needed */
|
||||
void
|
||||
@ -243,11 +261,13 @@ void
|
||||
png_write_row(png_struct *png_ptr, png_bytef *row)
|
||||
{
|
||||
/* initialize transformations and other stuff if first time */
|
||||
if (png_ptr->row_number == 0 && png_ptr->pass == 0)
|
||||
if (png_ptr->mode < PNG_HAVE_IDAT)
|
||||
{
|
||||
png_write_start_row(png_ptr);
|
||||
}
|
||||
|
||||
png_ptr->mode = PNG_HAVE_IDAT;
|
||||
|
||||
#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
|
||||
/* if interlaced and not interested in row, return */
|
||||
if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
|
||||
@ -305,7 +325,7 @@ png_write_row(png_struct *png_ptr, png_bytef *row)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* PNG_WRITE_INTERLACE_SUPPORTED */
|
||||
|
||||
/* set up row info for transformations */
|
||||
png_ptr->row_info.color_type = png_ptr->color_type;
|
||||
@ -334,7 +354,7 @@ png_write_row(png_struct *png_ptr, png_bytef *row)
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif /* PNG_WRITE_INTERLACE_SUPPORTED */
|
||||
|
||||
/* handle other transformations */
|
||||
if (png_ptr->transformations)
|
||||
@ -367,6 +387,7 @@ png_write_row(png_struct *png_ptr, png_bytef *row)
|
||||
/* set up the zlib input buffer */
|
||||
png_ptr->zstream->next_in = png_ptr->row_buf;
|
||||
png_ptr->zstream->avail_in = (uInt)png_ptr->row_info.rowbytes + 1;
|
||||
|
||||
/* repeat until we have compressed all the data */
|
||||
do
|
||||
{
|
||||
@ -378,9 +399,9 @@ png_write_row(png_struct *png_ptr, png_bytef *row)
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
if (png_ptr->zstream->msg)
|
||||
png_error(png_ptr, png_ptr->zstream->msg);
|
||||
(*(png_ptr->error_fn))(png_ptr, png_ptr->zstream->msg);
|
||||
else
|
||||
png_error(png_ptr, "zlib error");
|
||||
(*(png_ptr->error_fn))(png_ptr, "zlib error");
|
||||
}
|
||||
|
||||
/* see if it is time to write another IDAT */
|
||||
@ -396,7 +417,76 @@ png_write_row(png_struct *png_ptr, png_bytef *row)
|
||||
|
||||
/* finish row - updates counters and flushes zlib if last row */
|
||||
png_write_finish_row(png_ptr);
|
||||
|
||||
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
|
||||
png_ptr->flush_rows++;
|
||||
|
||||
if (png_ptr->flush_dist > 0 &&
|
||||
png_ptr->flush_rows >= png_ptr->flush_dist)
|
||||
{
|
||||
png_write_flush(png_ptr);
|
||||
}
|
||||
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
|
||||
}
|
||||
|
||||
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
|
||||
/* Set the automatic flush interval or 0 to turn flushing off */
|
||||
void
|
||||
png_set_flush(png_struct *png_ptr, int nrows)
|
||||
{
|
||||
png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
|
||||
}
|
||||
|
||||
/* flush the current output buffers now */
|
||||
void
|
||||
png_write_flush(png_struct *png_ptr)
|
||||
{
|
||||
char wrote_IDAT;
|
||||
|
||||
if (png_ptr->mode != PNG_HAVE_IDAT)
|
||||
return;
|
||||
|
||||
do
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* compress the data */
|
||||
ret = deflate(png_ptr->zstream, Z_SYNC_FLUSH);
|
||||
wrote_IDAT = 0;
|
||||
|
||||
/* check for compression errors */
|
||||
if (ret != Z_OK)
|
||||
{
|
||||
if (png_ptr->zstream->msg)
|
||||
(*(png_ptr->error_fn))(png_ptr, png_ptr->zstream->msg);
|
||||
else
|
||||
(*(png_ptr->error_fn))(png_ptr, "zlib error");
|
||||
}
|
||||
|
||||
if (!png_ptr->zstream->avail_out)
|
||||
{
|
||||
/* write the IDAT and reset the zlib output buffer */
|
||||
png_write_IDAT(png_ptr, png_ptr->zbuf,
|
||||
png_ptr->zbuf_size);
|
||||
png_ptr->zstream->next_out = png_ptr->zbuf;
|
||||
png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
|
||||
wrote_IDAT = 1;
|
||||
}
|
||||
} while(wrote_IDAT == 1);
|
||||
|
||||
/* If there is any data left to be output, write it into a new IDAT */
|
||||
if (png_ptr->zbuf_size != png_ptr->zstream->avail_out)
|
||||
{
|
||||
/* write the IDAT and reset the zlib output buffer */
|
||||
png_write_IDAT(png_ptr, png_ptr->zbuf,
|
||||
png_ptr->zbuf_size - png_ptr->zstream->avail_out);
|
||||
png_ptr->zstream->next_out = png_ptr->zbuf;
|
||||
png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
|
||||
}
|
||||
png_ptr->flush_rows = 0;
|
||||
(*(png_ptr->output_flush_fn))(png_ptr);
|
||||
}
|
||||
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
|
||||
|
||||
/* free any memory used in png struct */
|
||||
void
|
||||
@ -416,6 +506,7 @@ png_write_destroy(png_struct *png_ptr)
|
||||
png_memset(png_ptr, 0, sizeof (png_struct));
|
||||
png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
|
||||
}
|
||||
|
||||
void
|
||||
png_set_filtering(png_struct *png_ptr, int filter)
|
||||
{
|
||||
|
29
pngwutil.c
29
pngwutil.c
@ -39,7 +39,7 @@ png_write_uint_32(png_struct *png_ptr, png_uint_32 i)
|
||||
buf[1] = (png_byte)((i >> 16) & 0xff);
|
||||
buf[2] = (png_byte)((i >> 8) & 0xff);
|
||||
buf[3] = (png_byte)(i & 0xff);
|
||||
png_write_data(png_ptr, buf, 4);
|
||||
(*(png_ptr->write_data_fn))(png_ptr, buf, 4);
|
||||
}
|
||||
|
||||
/* write a 16 bit number */
|
||||
@ -50,7 +50,7 @@ png_write_uint_16(png_struct *png_ptr, png_uint_16 i)
|
||||
|
||||
buf[0] = (png_byte)((i >> 8) & 0xff);
|
||||
buf[1] = (png_byte)(i & 0xff);
|
||||
png_write_data(png_ptr, buf, 2);
|
||||
(*(png_ptr->write_data_fn))(png_ptr, buf, 2);
|
||||
}
|
||||
|
||||
/* Write a png chunk all at once. The type is an array of ASCII characters
|
||||
@ -68,7 +68,7 @@ png_write_chunk(png_struct *png_ptr, png_byte *type,
|
||||
/* write length */
|
||||
png_write_uint_32(png_ptr, length);
|
||||
/* write chunk name */
|
||||
png_write_data(png_ptr, type, (png_uint_32)4);
|
||||
(*(png_ptr->write_data_fn))(png_ptr, type, (png_uint_32)4);
|
||||
/* reset the crc and run the chunk name over it */
|
||||
png_reset_crc(png_ptr);
|
||||
png_calculate_crc(png_ptr, type, (png_uint_32)4);
|
||||
@ -76,7 +76,7 @@ png_write_chunk(png_struct *png_ptr, png_byte *type,
|
||||
if (length)
|
||||
{
|
||||
png_calculate_crc(png_ptr, data, length);
|
||||
png_write_data(png_ptr, data, length);
|
||||
(*(png_ptr->write_data_fn))(png_ptr, data, length);
|
||||
}
|
||||
/* write the crc */
|
||||
png_write_uint_32(png_ptr, ~png_ptr->crc);
|
||||
@ -92,7 +92,7 @@ png_write_chunk_start(png_struct *png_ptr, png_byte *type,
|
||||
/* write the length */
|
||||
png_write_uint_32(png_ptr, total_length);
|
||||
/* write the chunk name */
|
||||
png_write_data(png_ptr, type, (png_uint_32)4);
|
||||
(*(png_ptr->write_data_fn))(png_ptr, type, (png_uint_32)4);
|
||||
/* reset the crc and run it over the chunk name */
|
||||
png_reset_crc(png_ptr);
|
||||
png_calculate_crc(png_ptr, type, (png_uint_32)4);
|
||||
@ -109,7 +109,7 @@ png_write_chunk_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length)
|
||||
if (length)
|
||||
{
|
||||
png_calculate_crc(png_ptr, data, length);
|
||||
png_write_data(png_ptr, data, length);
|
||||
(*(png_ptr->write_data_fn))(png_ptr, data, length);
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,7 +126,7 @@ void
|
||||
png_write_sig(png_struct *png_ptr)
|
||||
{
|
||||
/* write the 8 byte signature */
|
||||
png_write_data(png_ptr, png_sig, (png_uint_32)8);
|
||||
(*(png_ptr->write_data_fn))(png_ptr, png_sig, (png_uint_32)8);
|
||||
}
|
||||
|
||||
/* Write the IHDR chunk, and update the png_struct with the necessary
|
||||
@ -462,9 +462,9 @@ png_write_zTXt(png_struct *png_ptr, charf *key, charf *text,
|
||||
{
|
||||
/* error */
|
||||
if (png_ptr->zstream->msg)
|
||||
png_error(png_ptr, png_ptr->zstream->msg);
|
||||
(*(png_ptr->error_fn))(png_ptr, png_ptr->zstream->msg);
|
||||
else
|
||||
png_error(png_ptr, "zlib error");
|
||||
(*(png_ptr->error_fn))(png_ptr, "zlib error");
|
||||
}
|
||||
/* check to see if we need more room */
|
||||
if (!png_ptr->zstream->avail_out && png_ptr->zstream->avail_in)
|
||||
@ -508,9 +508,9 @@ png_write_zTXt(png_struct *png_ptr, charf *key, charf *text,
|
||||
{
|
||||
/* we got an error */
|
||||
if (png_ptr->zstream->msg)
|
||||
png_error(png_ptr, png_ptr->zstream->msg);
|
||||
(*(png_ptr->error_fn))(png_ptr, png_ptr->zstream->msg);
|
||||
else
|
||||
png_error(png_ptr, "zlib error");
|
||||
(*(png_ptr->error_fn))(png_ptr, "zlib error");
|
||||
}
|
||||
|
||||
/* check to see if we need more room */
|
||||
@ -689,7 +689,7 @@ png_write_finish_row(png_struct *png_ptr)
|
||||
/* next row */
|
||||
png_ptr->row_number++;
|
||||
/* see if we are done */
|
||||
if (png_ptr->row_number < png_ptr->num_rows)
|
||||
if (png_ptr->row_number < png_ptr->num_rows || png_ptr->mode > PNG_HAVE_IDAT)
|
||||
return;
|
||||
|
||||
/* if interlaced, go to next pass */
|
||||
@ -740,9 +740,9 @@ png_write_finish_row(png_struct *png_ptr)
|
||||
if (ret != Z_OK && ret != Z_STREAM_END)
|
||||
{
|
||||
if (png_ptr->zstream->msg)
|
||||
png_error(png_ptr, png_ptr->zstream->msg);
|
||||
(*(png_ptr->error_fn))(png_ptr, png_ptr->zstream->msg);
|
||||
else
|
||||
png_error(png_ptr, "zlib error");
|
||||
(*(png_ptr->error_fn))(png_ptr, "zlib error");
|
||||
}
|
||||
/* check to see if we need more room */
|
||||
if (!png_ptr->zstream->avail_out && ret == Z_OK)
|
||||
@ -761,6 +761,7 @@ png_write_finish_row(png_struct *png_ptr)
|
||||
}
|
||||
|
||||
deflateReset(png_ptr->zstream);
|
||||
png_ptr->mode = PNG_AFTER_IDAT;
|
||||
}
|
||||
|
||||
#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
|
||||
|
Reference in New Issue
Block a user