Imported from libpng-0.85.tar

This commit is contained in:
Guy Schalnat 1995-12-19 03:22:19 -06:00 committed by Glenn Randers-Pehrson
parent 0f71645dfe
commit 6d76471acd
24 changed files with 3505 additions and 2324 deletions

2
build.bat Normal file
View File

@ -0,0 +1,2 @@
make -fmakefile.bor -B -DMODEL=m %1 %2 %3 libpng >buildm.out
make -fmakefile.bor -B -DMODEL=l %1 %2 %3 libpng >buildl.out

193
example.c
View File

@ -15,7 +15,7 @@
#include <png.h> #include <png.h>
/* check to see if a file is a png file using png_check_sig() */ /* check to see if a file is a png file using png_check_sig() */
int check_png(char *file_name) int check_png(char * file_name)
{ {
FILE *fp; FILE *fp;
char buf[8]; char buf[8];
@ -40,8 +40,8 @@ int check_png(char *file_name)
void read_png(char *file_name) void read_png(char *file_name)
{ {
FILE *fp; FILE *fp;
png_struct *png_ptr; png_structp png_ptr;
png_info *info_ptr; png_infop info_ptr;
/* open the file */ /* open the file */
fp = fopen(file_name, "rb"); fp = fopen(file_name, "rb");
@ -79,19 +79,9 @@ void read_png(char *file_name)
png_info_init(info_ptr); png_info_init(info_ptr);
png_read_init(png_ptr); png_read_init(png_ptr);
/* set up the input control for the default input and message functions. /* set up the input control */
* 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); 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 */ /* read the file information */
png_read_info(png_ptr, info_ptr); png_read_info(png_ptr, info_ptr);
@ -117,10 +107,10 @@ void read_png(char *file_name)
if (info_ptr->valid & PNG_INFO_bKGD) if (info_ptr->valid & PNG_INFO_bKGD)
png_set_background(png_ptr, &(info_ptr->background), png_set_background(png_ptr, &(info_ptr->background),
PNG_GAMMA_FILE, 1, 1.0); PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
else else
png_set_background(png_ptr, &my_background, png_set_background(png_ptr, &my_background,
PNG_GAMMA_SCREEN, 0, 1.0); PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
/* tell libpng to handle the gamma conversion for you */ /* tell libpng to handle the gamma conversion for you */
if (info_ptr->valid & PNG_INFO_gAMA) if (info_ptr->valid & PNG_INFO_gAMA)
@ -156,7 +146,8 @@ void read_png(char *file_name)
png_set_invert(png_ptr); png_set_invert(png_ptr);
/* shift the pixels down to their true bit depth */ /* shift the pixels down to their true bit depth */
if (info_ptr->valid & PNG_INFO_sBIT) if (info_ptr->valid & PNG_INFO_sBIT &&
info_ptr->bit_depth > info_ptr->sig_bit)
png_set_shift(png_ptr, &(info_ptr->sig_bit)); png_set_shift(png_ptr, &(info_ptr->sig_bit));
/* pack pixels into bytes */ /* pack pixels into bytes */
@ -193,7 +184,7 @@ void read_png(char *file_name)
of png_info. */ of png_info. */
/* the easiest way to read the image */ /* the easiest way to read the image */
png_bytef *row_pointers[height]; png_bytep row_pointers[height];
png_read_image(png_ptr, row_pointers); png_read_image(png_ptr, row_pointers);
/* the other way to read images - deal with interlacing */ /* the other way to read images - deal with interlacing */
@ -206,7 +197,7 @@ void read_png(char *file_name)
/* If you are only reading on row at a time, this works */ /* If you are only reading on row at a time, this works */
for (y = 0; y < height; y++) for (y = 0; y < height; y++)
{ {
png_bytef *row_pointers = row[y]; png_bytep row_pointers = row[y];
png_read_rows(png_ptr, &row_pointers, NULL, 1); png_read_rows(png_ptr, &row_pointers, NULL, 1);
} }
@ -221,13 +212,8 @@ void read_png(char *file_name)
in info_ptr */ in info_ptr */
png_read_end(png_ptr, 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 */ /* clean up after the read, and free any memory allocated */
png_read_destroy(png_ptr, info_ptr, (png_info *)0); png_read_destroy(png_ptr, info_ptr, (png_infop)0);
/* free the structures */ /* free the structures */
free(png_ptr); free(png_ptr);
@ -240,12 +226,129 @@ void read_png(char *file_name)
return; return;
} }
/* progressively read a file */
/* these will normally not be global unless you are only
reading in one image at a time */
png_structp png_ptr;
png_infop info_ptr;
int
initialize_png_reader()
{
png_ptr = malloc(sizeof (png_struct));
if (!png_ptr)
return -1;
info_ptr = malloc(sizeof (png_info));
if (!info_ptr)
{
free(png_ptr);
return -1;
}
if (setjmp(png_ptr->jmpbuf))
{
png_read_destroy(png_ptr, info_ptr, (png_info *)0);
/* free pointers before returning, if necessary */
free(png_ptr);
free(info_ptr);
return -1;
}
png_info_init(info_ptr);
png_read_init(png_ptr);
/* this one's new. You will need to provide all three
function callbacks, even if you aren't using them all.
You can put a void pointer in place of the NULL, and
retrieve the pointer from inside the callbacks using
the function png_get_msg_ptr(png_ptr); */
png_set_progressive_read_fn(png_ptr, NULL,
info_callback, row_callback, end_callback);
return 0;
}
int
process_data(png_bytep buffer, png_uint_32 length)
{
if (setjmp(png_ptr->jmpbuf))
{
png_read_destroy(png_ptr, info_ptr, (png_info *)0);
free(png_ptr);
free(info_ptr);
return -1;
}
/* this one's new also. Simply give it a chunk of data
from the file stream (in order, of course). On Segmented
machines, don't give it any more then 64K. The library
seems to run fine with sizes of 4K, although you can give
it much less if necessary (I assume you can give it chunks
of 1 byte, but I haven't tried less then 256 bytes yet).
When this function returns, you may want to display any
rows that were generated in the row callback. */
png_process_data(png_ptr, info_ptr, buffer, length);
return 0;
}
info_callback(png_structp png_ptr, png_infop info)
{
/* do any setup here, including setting any of the transformations
mentioned in the Reading PNG files section. For now, you _must_
call either png_start_read_image() or png_read_update_info()
after all the transformations are set (even if you don't set
any). You may start getting rows before png_process_data()
returns, so this is your last chance to prepare for that. */
}
row_callback(png_structp png_ptr, png_bytep new_row,
png_uint_32 row_num, int pass)
{
/* this function is called for every row in the image. If the
image is interlacing, and you turned on the interlace handler,
this function will be called for every row in every pass.
Some of these rows will not be changed from the previous pass.
When the row is not changed, the new_row variable will be NULL.
The rows and passes are called in order, so you don't really
need the row_num and pass, but I'm supplying them because it
may make your life easier.
For the non-NULL rows of interlaced images, you must call
png_progressive_combine_row() passing in the row and the
old row. You can call this function for NULL rows (it will
just return) and for non-interlaced images (it just does the
memcpy for you) if it will make the code easier. Thus, you
can just do this for all cases: */
png_progressive_combine_row(png_ptr, old_row, new_row);
/* where old_row is what was displayed for previous rows. Note
that the first pass (pass == 0 really) will completely cover
the old row, so the rows do not have to be initialized. After
the first pass (and only for interlaced images), you will have
to pass the current row, and the function will combine the
old row and the new row. */
}
end_callback(png_structp png_ptr, png_infop info)
{
/* this function is called when the whole image has been read,
including any chunks after the image (up to and including
the IEND). You will usually have the same info chunk as you
had in the header, although some data may have been added
to the comments and time fields.
Most people won't do much here, perhaps setting a flag that
marks the image as finished. */
}
/* write a png file */ /* write a png file */
void write_png(char *file_name, ... other image information ...) void write_png(char *file_name, ... other image information ...)
{ {
FILE *fp; FILE *fp;
png_struct *png_ptr; png_structp png_ptr;
png_info *info_ptr; png_infop info_ptr;
/* open the file */ /* open the file */
fp = fopen(file_name, "wb"); fp = fopen(file_name, "wb");
@ -283,19 +386,9 @@ void write_png(char *file_name, ... other image information ...)
png_info_init(info_ptr); png_info_init(info_ptr);
png_write_init(png_ptr); png_write_init(png_ptr);
/* set up the output control for the default output and message functions. /* set up the output control */
* 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); 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 */ /* set the file information here */
info_ptr->width = ; info_ptr->width = ;
info_ptr->height = ; info_ptr->height = ;
@ -309,16 +402,9 @@ void write_png(char *file_name, ... other image information ...)
/* optional significant bit chunk */ /* optional significant bit chunk */
info_ptr->valid |= PNG_INFO_sBIT; info_ptr->valid |= PNG_INFO_sBIT;
/* if we are dealing with a grayscale image then */ info_ptr->sig_bit = true_bit_depth;
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 is a good idea if you can write one */ /* optional gamma chunk */
info_ptr->valid |= PNG_INFO_gAMA; info_ptr->valid |= PNG_INFO_gAMA;
info_ptr->gamma = gamma; info_ptr->gamma = gamma;
@ -357,7 +443,7 @@ void write_png(char *file_name, ... other image information ...)
number_passes = 1; number_passes = 1;
/* the easiest way to write the image */ /* the easiest way to write the image */
png_bytef *row_pointers[height]; png_bytep row_pointers[height];
png_write_image(png_ptr, row_pointers); png_write_image(png_ptr, row_pointers);
/* the other way to write the image - deal with interlacing */ /* the other way to write the image - deal with interlacing */
@ -370,7 +456,7 @@ void write_png(char *file_name, ... other image information ...)
/* If you are only writing one row at a time, this works */ /* If you are only writing one row at a time, this works */
for (y = 0; y < height; y++) for (y = 0; y < height; y++)
{ {
png_bytef *row_pointers = row[y]; png_bytep row_pointers = row[y];
png_write_rows(png_ptr, &row_pointers, 1); png_write_rows(png_ptr, &row_pointers, 1);
} }
} }
@ -378,11 +464,6 @@ void write_png(char *file_name, ... other image information ...)
/* write the rest of the file */ /* write the rest of the file */
png_write_end(png_ptr, info_ptr); 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 */ /* clean up after the write, and free any memory allocated */
png_write_destroy(png_ptr); png_write_destroy(png_ptr);

View File

@ -1,9 +1,9 @@
libpng.txt - a description on how to use and modify libpng libpng.txt - a description on how to use and modify libpng
libpng 1.0 beta 2 - version 0.8 libpng 1.0 beta 2 - version 0.85
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
August 20, 1995 December 19, 1995
This file describes how to use and modify the PNG reference library This file describes how to use and modify the PNG reference library
(known as libpng) for your own use. There are four sections to this (known as libpng) for your own use. There are four sections to this
@ -45,60 +45,60 @@ The structures:
There are two main structures that are important to libpng, png_struct There are two main structures that are important to libpng, png_struct
and png_info. The first, png_struct, is an internal structure that 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 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 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 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. 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> #include <png.h>
Checking PNG files: 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 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 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. the accuracy of the prediction. If you pass in more then eight bytes,
libpng will only look at the first eight bytes.
fread(header, 1, number, fp); fread(header, 1, number, fp);
is_png = png_check_sig(header, number); is_png = png_check_sig(header, number);
Reading PNG files: Reading PNG files:
This section covers reading png files row by row. Progressive reading
is covered in the next section (although you still need to read this
section, as much of the information is still needed).
The first thing you need to do while reading a PNG file is to allocate The first thing you need to do while reading a PNG file is to allocate
and initialize png_struct and png_info. As these are both large, you and initialize png_struct and png_info. As these are both large, you
may not want to store these on the stack, unless you have stack space may not want to store these on the stack, unless you have stack space
to spare. Of course, you will want to check if malloc returns NULL. to spare. Of course, you will want to check if malloc returns NULL.
png_struct *png_ptr = malloc(sizeof (png_struct)); png_structp png_ptr = malloc(sizeof (png_struct));
if (!png_ptr) if (!png_ptr)
return; return;
png_info *info_ptr = malloc(sizeof (png_info)); png_infop info_ptr = malloc(sizeof (png_info));
if (!info_ptr) if (!info_ptr)
{ {
free(png_ptr); free(png_ptr);
return; return;
} }
You may also want to do any i/o initialization here, before You may also want to do any i/o initialization here, before
you get into libpng, so if it doesn't work, you don't have you get into libpng, so if it doesn't work, you don't have
much to undo. much to undo.
FILE *fp = fopen(file_name, "rb"); FILE *fp = fopen(file_name, "rb");
if (!fp) if (!fp)
{ {
free(png_ptr); free(png_ptr);
free(info_ptr); free(info_ptr);
return; 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 After you have these structures, you will need to set up the
error handling. When libpng encounters an error, it expects to error handling. When libpng encounters an error, it expects to
@ -108,21 +108,20 @@ read the file from different routines, you will need to update
the jmpbuf field every time you enter a new routine that will the jmpbuf field every time you enter a new routine that will
call a png_ function. See your documentation of setjmp/longjmp call a png_ function. See your documentation of setjmp/longjmp
for your compiler for more information on setjmp/longjmp. See for your compiler for more information on setjmp/longjmp. See
the discussion on libpng error handling in the Customizing Libpng the discussion on png error handling in the Customizing Libpng
section below for more information on how to change the behaviour section below for more information on the png error handling.
of libpng error handling. If an error occurs, and libpng longjmp's If an error occurs, and libpng longjmp's back to your setjmp,
back to your setjmp, you will want to call png_read_destroy() to you will want to call png_read_destroy() to free any memory.
free any memory.
if (setjmp(png_ptr->jmpbuf)) if (setjmp(png_ptr->jmpbuf))
{ {
png_read_destroy(png_ptr, info_ptr, (png_info *)0); png_read_destroy(png_ptr, info_ptr, (png_info *)0);
/* free pointers before returning, if necessary */ /* free pointers before returning, if necessary */
free(png_ptr); free(png_ptr);
free(info_ptr); free(info_ptr);
fclose(fp); fclose(fp);
return; return;
} }
Next, you will need to call png_read_init() and png_info_init(). Next, you will need to call png_read_init() and png_info_init().
These functions make sure all the fields are initialized to useful These functions make sure all the fields are initialized to useful
@ -138,10 +137,11 @@ would be bad.
Now you need to set up the input code. The default for libpng is 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 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 pass a valid FILE * in the function png_init_io(). Be sure that
the file is opened in binary mode. Otherwise, you should see the the file is opened in binary mode. If you wish to handle reading
section below on Customizing libpng I/O functions. data in another way, see the discussion on png i/o handling in the
Customizing Libpng section below.
png_init_io(png_ptr, fp); png_init_io(png_ptr, fp);
You are now ready to read all the file information up to the actual You are now ready to read all the file information up to the actual
image data. You do this with a call to png_read_info(). image data. You do this with a call to png_read_info().
@ -150,7 +150,7 @@ image data. You do this with a call to png_read_info().
The png_info structure is now filled in with all the data necessary The png_info structure is now filled in with all the data necessary
to read the file. Some of the more important parts of the png_info are: to read the file. Some of the more important parts of the png_info are:
width - holds the width of the file width - holds the width of the file
height - holds the height of the file height - holds the height of the file
bit_depth - holds the bit depth of one of the image channels bit_depth - holds the bit depth of one of the image channels
color_type - describes the channels and what they mean color_type - describes the channels and what they mean
@ -158,13 +158,13 @@ to read the file. Some of the more important parts of the png_info are:
channels - number of channels of info for the color type channels - number of channels of info for the color type
pixel_depth - bits per pixel pixel_depth - bits per pixel
rowbytes - number of bytes needed to hold a row rowbytes - number of bytes needed to hold a row
interlace_type - currently 0 for none, 1 for interlaced interlace_type - currently 0 for none, 1 for interlaced
valid - this details which optional chunks were found in the file valid - this details which optional chunks were found in the file
to see if a chunk was present, OR valid with the appropriate to see if a chunk was present, OR valid with the appropriate
PNG_INFO_<chunk name> define. PNG_INFO_<chunk name> define.
palette and num_palette - the palette for the file palette and num_palette - the palette for the file
gamma - the gamma the file is written at gamma - the gamma the file is written at
sig_bit - the number of significant bits for red, green, blue, grey, alpha sig_bit and sig_bit_number - the number of significant bits
trans, trans_values, and number_trans - transparency info trans, trans_values, and number_trans - transparency info
hist - histogram of palette hist - histogram of palette
text and num_text - text comments in the file. text and num_text - text comments in the file.
@ -179,26 +179,13 @@ suggested keywords, there is no requirement to restrict the use
to these strings. There is a requirement to have at least one to these strings. There is a requirement to have at least one
character for a keyword. It is strongly suggested that keywords character for a keyword. It is strongly suggested that keywords
be sensible to humans (that's the point), so don't use abbreviations. be sensible to humans (that's the point), so don't use abbreviations.
Some suggested keywords for tEXT (or zTXt) chunks are: See the png specification for more details. There is no requirement
to have text after the keyword.
Title Short (one line) title or caption for image Keywords are restricted to 80 characters without leading or trailing
Author Name of image's creator spaces, but spaces are allowed within the keyword Nothing
Copyright Copyright notice (possibly long) prevents you from duplicating the keyword. The text field is an
Description Description of image (possibly long) array of png_text structures, each holding pointer to a keyword
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. 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 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 they are received. However, some or all of the text chunks may be
@ -217,16 +204,16 @@ 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 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. the data. For example, don't swap red and blue on grayscale data.
This transforms bit depths of less than 8 to 8 bits, changes paletted This transforms bit depths of less then 8 to 8 bits, changes paletted
images to rgb, and adds an alpha channel if there is transparency images to rgb, and adds an alpha channel if there is transparency
information in a tRNS chunk. This is probably most useful on grayscale information in a tRNS chunk. This is probably most useful on grayscale
images with bit depths of 2 or 4 and tRNS chunks. images with bit depths of 2 or 4 and tRNS chunks.
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE && if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
info_ptr->bit_depth < 8) info_ptr->bit_depth < 8)
png_set_expand(png_ptr); png_set_expand(png_ptr);
if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY && if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
info_ptr->bit_depth < 8) info_ptr->bit_depth < 8)
png_set_expand(png_ptr); png_set_expand(png_ptr);
@ -243,26 +230,25 @@ If you are modifying the color data with png_set_expand(), you must
indicate whether the background needs to be expanded. See the indicate whether the background needs to be expanded. See the
function definition in png.h for more details. function definition in png.h for more details.
png_color_16 my_background; png_color_16 my_background;
if (info_ptr->valid & PNG_INFO_bKGD) if (info_ptr->valid & PNG_INFO_bKGD)
png_set_backgrond(png_ptr, &(info_ptr->background), png_set_backgrond(png_ptr, &(info_ptr->background),
PNG_GAMMA_FILE, 1, 1.0); PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
else else
png_set_background(png_ptr, &my_background, png_set_background(png_ptr, &my_background,
PNG_GAMMA_SCREEN, 0, 1.0); PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
This handles gamma transformations of the data. Pass both the file 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 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 gamma value, you can pass one anyway if you wish. Note that file
gammas are inverted from screen gammas. See the discussions on gammas are inverted from screen gammas. See the discussions on
gamma in the PNG specification for more information. It is strongly gamma in the PNG specification for more information.
reccommended that viewers support gamma correction.
if (info_ptr->valid & PNG_INFO_gAMA) if (info_ptr->valid & PNG_INFO_gAMA)
png_set_gamma(png_ptr, screen_gamma, info_ptr->gamma); png_set_gamma(png_ptr, screen_gamma, info_ptr->gamma);
else else
png_set_gamma(png_ptr, screen_gamma, 0.45); png_set_gamma(png_ptr, screen_gamma, 0.45);
PNG can have files with 16 bits per channel. If you only can handle PNG can have files with 16 bits per channel. If you only can handle
8 bits per channel, this will strip the pixels down to 8 bit. 8 bits per channel, this will strip the pixels down to 8 bit.
@ -281,7 +267,7 @@ will fit into maximum_colors. If there is an histogram, it will
use it to make intelligent choises when reducing the palette. If use it to make intelligent choises when reducing the palette. If
there is no histogram, it may not do a good job. there is no histogram, it may not do a good job.
if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
{ {
if (info_ptr->valid & PNG_INFO_PLTE) if (info_ptr->valid & PNG_INFO_PLTE)
png_set_dither(png_ptr, info_ptr->palette, png_set_dither(png_ptr, info_ptr->palette,
@ -289,7 +275,7 @@ there is no histogram, it may not do a good job.
info_ptr->histogram); info_ptr->histogram);
else else
{ {
png_color std_color_cube[MAX_SCREEN_COLORS] = png_color std_color_cube[MAX_SCREEN_COLORS] =
{ ... colors ... }; { ... colors ... };
png_set_dither(png_ptr, std_color_cube, MAX_SCREEN_COLORS, png_set_dither(png_ptr, std_color_cube, MAX_SCREEN_COLORS,
@ -325,7 +311,7 @@ PNG files store 3 color pixels in red, green, blue order. If you would
rather have the pixels as blue, green, red, call this. rather have the pixels as blue, green, red, call this.
if (info_ptr->color_type == PNG_COLOR_TYPE_RGB || if (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA) info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
png_set_bgr(png_ptr); png_set_bgr(png_ptr);
For some uses, you may want a grayscale image to be represented as For some uses, you may want a grayscale image to be represented as
@ -333,7 +319,7 @@ rgb. If you need this, call this:
if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY || if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY ||
info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
png_set_gray_to_rgb(png_ptr); png_set_gray_to_rgb(png_ptr);
PNG files store 16 bit pixels in network byte order (most significant PNG files store 16 bit pixels in network byte order (most significant
bit first). If you would rather store them the other way, (the way bit first). If you would rather store them the other way, (the way
@ -365,7 +351,7 @@ who need an updated palette before they read the image data. If you
don't call this function, the library will automatically call it don't call this function, the library will automatically call it
before it reads the first row. before it reads the first row.
png_start_read_image(png_ptr); png_start_read_image(png_ptr);
If you want, libpng will update your png_info structure to reflect If you want, libpng will update your png_info structure to reflect
any transformations you've requested with this call. This is most any transformations you've requested with this call. This is most
@ -373,7 +359,7 @@ useful to update the info structures rowbytes field, so you can
use it to allocate your image memory. This function calls use it to allocate your image memory. This function calls
png_start_read_image(), so you don't have to call both of them. png_start_read_image(), so you don't have to call both of them.
png_read_update_info(png_ptr, info_ptr); png_read_update_info(png_ptr, info_ptr);
After you call png_read_update_info(), you can allocate any After you call png_read_update_info(), you can allocate any
memory you need to hold the image. As the actual allocation memory you need to hold the image. As the actual allocation
@ -397,7 +383,7 @@ times, or any of that other stuff necessary with png_read_rows().
where row_pointers is: where row_pointers is:
void *row_pointers[height]; png_bytep row_pointers[height];
You can point to void or char or whatever you use for pixels. You can point to void or char or whatever you use for pixels.
@ -412,7 +398,7 @@ row_pointers is the same as in the png_read_image() call.
If you are just calling one row at a time, you can do this for If you are just calling one row at a time, you can do this for
row_pointers: row_pointers:
char *row_pointers = row; png_bytep row_pointers = row;
png_read_rows(png_ptr, &row_pointers, NULL, 1); png_read_rows(png_ptr, &row_pointers, NULL, 1);
@ -460,7 +446,7 @@ rows between calls. You can change the locations of the data, just
not the data. Each pass only writes the pixels appropriate for that not the data. Each pass only writes the pixels appropriate for that
pass, and assumes the data from previous passes is still valid. pass, and assumes the data from previous passes is still valid.
png_read_rows(png_ptr, row_pointers, NULL, number_of_rows); png_read_rows(png_ptr, row_pointers, NULL, number_of_rows);
If you only want the first effect (the rectangles), do the same as If you only want the first effect (the rectangles), do the same as
before except pass the row buffer in the third parameter, and leave before except pass the row buffer in the third parameter, and leave
@ -484,6 +470,133 @@ read or write. For a more compact example of reading a PNG image,
see the file example.c. see the file example.c.
Reading PNG files progressively:
The progressive reader is slightly different then the non-progressive
reader. Instead of calling png_read_info(), png_read_rows(), and
png_read_end(), you make one call to png_process_data(), which calls
callbacks when it has the info, a row, or the end of the image. You
set up these callbacks with png_set_progressive_read_fn(). You don't
have to worry about the input/output functions of libpng, as you are
giving the library the data directly in png_process_data(). I will
assume that you have read the second on reading PNG files above,
so I will only highlight the differences (although I will show
all of the code).
png_structp png_ptr;
png_infop info_ptr;
int
initialize_png_reader()
{
png_ptr = malloc(sizeof (png_struct));
if (!png_ptr)
return -1;
info_ptr = malloc(sizeof (png_info));
if (!info_ptr)
{
free(png_ptr);
return -1;
}
if (setjmp(png_ptr->jmpbuf))
{
png_read_destroy(png_ptr, info_ptr, (png_info *)0);
/* free pointers before returning, if necessary */
free(png_ptr);
free(info_ptr);
return -1;
}
png_info_init(info_ptr);
png_read_init(png_ptr);
/* this one's new. You will need to provide all three
function callbacks, even if you aren't using them all.
You can put a void pointer in place of the NULL, and
retrieve the pointer from inside the callbacks using
the function png_get_progressive_ptr(png_ptr); */
png_set_progressive_read_fn(png_ptr, NULL,
info_callback, row_callback, end_callback);
return 0;
}
int
process_data(png_bytep buffer, png_uint_32 length)
{
if (setjmp(png_ptr->jmpbuf))
{
png_read_destroy(png_ptr, info_ptr, (png_info *)0);
free(png_ptr);
free(info_ptr);
return -1;
}
/* this one's new also. Simply give it a chunk of data
from the file stream (in order, of course). On Segmented
machines, don't give it any more then 64K. The library
seems to run fine with sizes of 4K, although you can give
it much less if necessary (I assume you can give it chunks
of 1 byte, but I haven't tried less then 256 bytes yet).
When this function returns, you may want to display any
rows that were generated in the row callback. */
png_process_data(png_ptr, info_ptr, buffer, length);
return 0;
}
info_callback(png_structp png_ptr, png_infop info)
{
do any setup here, including setting any of the transformations
mentioned in the Reading PNG files section. For now, you _must_
call either png_start_read_image() or png_read_update_info()
after all the transformations are set (even if you don't set
any). You may start getting rows before png_process_data()
returns, so this is your last chance to prepare for that.
}
row_callback(png_structp png_ptr, png_bytep new_row,
png_uint_32 row_num, int pass)
{
this function is called for every row in the image. If the
image is interlacing, and you turned on the interlace handler,
this function will be called for every row in every pass.
Some of these rows will not be changed from the previous pass.
When the row is not changed, the new_row variable will be NULL.
The rows and passes are called in order, so you don't really
need the row_num and pass, but I'm supplying them because it
may make your life easier.
For the non-NULL rows of interlaced images, you must call
png_progressive_combine_row() passing in the row and the
old row. You can call this function for NULL rows (it will
just return) and for non-interlaced images (it just does the
memcpy for you) if it will make the code easier. Thus, you
can just do this for all cases:
png_progressive_combine_row(png_ptr, old_row, new_row);
where old_row is what was displayed for previous rows. Note
that the first pass (pass == 0 really) will completely cover
the old row, so the rows do not have to be initialized. After
the first pass (and only for interlaced images), you will have
to pass the current row, and the function will combine the
old row and the new row.
}
end_callback(png_structp png_ptr, png_infop info)
{
this function is called when the whole image has been read,
including any chunks after the image (up to and including
the IEND). You will usually have the same info chunk as you
had in the header, although some data may have been added
to the comments and time fields.
Most people won't do much here, perhaps setting a flag that
marks the image as finished.
}
Writing PNG files: Writing PNG files:
Much of this is very similar to reading. However, everything of Much of this is very similar to reading. However, everything of
@ -495,11 +608,11 @@ and initialize png_struct and png_info. As these are both large, you
may not want to store these on the stack, unless you have stack space may not want to store these on the stack, unless you have stack space
to spare. to spare.
png_struct *png_ptr = malloc(sizeof (png_struct)); png_structp png_ptr = malloc(sizeof (png_struct));
if (!png_ptr) if (!png_ptr)
return; return;
png_info *info_ptr = malloc(sizeof (png_info)); png_infop info_ptr = malloc(sizeof (png_info));
if (!info_ptr) if (!info_ptr)
{ {
free(png_ptr); free(png_ptr);
return; return;
@ -513,7 +626,7 @@ much to undo.
if (!fp) if (!fp)
{ {
free(png_ptr); free(png_ptr);
free(info_ptr); free(info_ptr);
return; return;
} }
@ -524,20 +637,18 @@ setjmp and pass the jmpbuf field of your png_struct. If you
write the file from different routines, you will need to update write the file from different routines, you will need to update
the jmpbuf field every time you enter a new routine that will the jmpbuf field every time you enter a new routine that will
call a png_ function. See your documentation of setjmp/longjmp call a png_ function. See your documentation of setjmp/longjmp
for your compiler for more information on setjmp/longjmp. If you for your compiler for more information on setjmp/longjmp. See
don't want to use stderr for error output, or you want to use a the discussion on png error handling in the Customizing Libpng
method other than setjmp()/longjmp() to handle errors, see the section below for more information on the png error handling.
Customizing Libpng section below for more information on libpng
error handling.
if (setjmp(png_ptr->jmpbuf)) if (setjmp(png_ptr->jmpbuf))
{ {
png_write_destroy(png_ptr); png_write_destroy(png_ptr);
/* free pointers before returning. Make sure you clean up /* free pointers before returning. Make sure you clean up
anything else you've done. */ anything else you've done. */
free(png_ptr); free(png_ptr);
free(info_ptr); free(info_ptr);
fclose(fp); fclose(fp);
return; return;
} }
@ -555,7 +666,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 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 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 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. Customizing Libpng section below.
png_init_io(png_ptr, fp); png_init_io(png_ptr, fp);
@ -563,7 +674,7 @@ Customizing Libpng section below.
You now have the option of modifying how the compression library You now have the option of modifying how the compression library
will run. The following functions are mainly for testing, but will run. The following functions are mainly for testing, but
may be useful in certain special cases, like if you need to 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 compression, or if you want to get the maximum possible compression
at the expense of slower writing. If you have no special needs 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 in this area, let the library do what it wants, as it has been
@ -571,36 +682,14 @@ carefully tuned to deliver the best speed/compression ratio.
See the compression library for more details. See the compression library for more details.
/* turn on or off filtering (1 or 0) */ /* turn on or off filtering (1 or 0) */
png_set_filtering(png_struct *png_ptr, 1); png_set_filtering(png_ptr, 1);
/* compression level (0 - none, 6 - default, 9 - maximum) */ png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
png_set_compression_mem_level(png_ptr, 8); png_set_compression_mem_level(png_ptr, 8);
png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY); png_set_compression_strategy(png_ptr, Z_DEFAULT_STRATEGY);
png_set_compression_window_bits(png_ptr, 15); png_set_compression_window_bits(png_ptr, 15);
png_set_compression_method(png_ptr, 8); 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 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 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 you are allowed to write after the image is the text chunks and the
@ -613,7 +702,7 @@ parts of the png_info are:
width - holds the width of the file width - holds the width of the file
height - holds the height of the file height - holds the height of the file
bit_depth - holds the bit depth of one of the image channels bit_depth - holds the bit depth of one of the image channels
color_type - describes the channels and what they mean color_type - describes the channels and what they mean
see the PNG_COLOR_TYPE_ defines for more information see the PNG_COLOR_TYPE_ defines for more information
interlace_type - currently 0 for none, 1 for interlaced interlace_type - currently 0 for none, 1 for interlaced
valid - this describes which optional chunks to write to the valid - this describes which optional chunks to write to the
@ -623,7 +712,7 @@ parts of the png_info are:
appropriate PNG_INFO_<chunk name> define. appropriate PNG_INFO_<chunk name> define.
palette and num_palette - the palette for the file palette and num_palette - the palette for the file
gamma - the gamma the file is written at gamma - the gamma the file is written at
sig_bit - the number of significant bits for red, green, blue, grey, alpha sig_bit and sig_bit_number - the number of significant bits
trans, trans_values, and number_trans - transparency info trans, trans_values, and number_trans - transparency info
hist - histogram of palette hist - histogram of palette
text and num_text - text comments in the file. text and num_text - text comments in the file.
@ -656,25 +745,18 @@ you can leave off the text string on non-compressed pairs.
Compressed pairs must have a text string, as only the text string Compressed pairs must have a text string, as only the text string
is compressed anyway, so the compression would be meaningless. 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 conversion routines are proved, png_convert_from_time_t() for
time_t and png_convert_from_struct_tm() for struct tm. The 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 time_t routine uses gmtime(). You don't have to use either of
these, but if you wish to fill in the png_time structure directly, these, but if you wish to fill in the png_time structure directly,
you should provide the time in universal time (GMT) if possible you should provide the time in universal time (GMT) if possible
instead of your local time. Note that the year number is the full instead of your local time.
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 You are now ready to write all the file information up to the actual
image data. You do this with a call to png_write_info(). image data. You do this with a call to png_write_info().
png_write_info(png_ptr, info_ptr); png_write_info(png_ptr, info_ptr);
After you've read the file information, you can set up the library to After you've read the file information, you can set up the library to
handle any special transformations of the image data. The various handle any special transformations of the image data. The various
@ -746,7 +828,7 @@ PNG files describe moncrome as black is zero and white is one. If you
would rather supply the pixels with this reversed (black is one and would rather supply the pixels with this reversed (black is one and
white is zero), call this: white is zero), call this:
png_set_invert(png_ptr); png_set_invert(png_ptr);
That's it for the transformations. Now you can write the image data. That's it for the transformations. Now you can write the image data.
The simplest way to do this is in one function call. If have the The simplest way to do this is in one function call. If have the
@ -760,7 +842,7 @@ times, or any of that other stuff necessary with png_write_rows().
where row_pointers is: where row_pointers is:
void *row_pointers[height]; png_bytef *row_pointers[height];
You can point to void or char or whatever you use for pixels. You can point to void or char or whatever you use for pixels.
@ -775,7 +857,7 @@ row_pointers is the same as in the png_write_image() call.
If you are just calling one row at a time, you can do this for If you are just calling one row at a time, you can do this for
row_pointers: row_pointers:
char *row_pointers = row; png_bytep row_pointers = row;
png_write_rows(png_ptr, &row_pointers, 1); png_write_rows(png_ptr, &row_pointers, 1);
@ -811,7 +893,7 @@ pass the an appropriately filled png_info pointer. If you
are not interested, you can pass NULL. Be careful that you don't are not interested, you can pass NULL. Be careful that you don't
write the same text or time chunks here as you did in png_write_info(). write the same text or time chunks here as you did in png_write_info().
png_write_end(png_ptr, info_ptr); png_write_end(png_ptr, info_ptr);
When you are done, you can free all memory used by libpng like this: When you are done, you can free all memory used by libpng like this:
@ -831,43 +913,41 @@ standard things like memory allocation, input/output, and error handling.
The second deals with more complicated things like adding new chunks, The second deals with more complicated things like adding new chunks,
adding new transformations, and generally changing how libpng works. adding new transformations, and generally changing how libpng works.
All of the memory allocation in libpng is done in pngmem.c. Memory All of the memory allocation, input/output, and error handling in libpng
allocation is done through the functions png_large_malloc(), png_malloc(), goes through callbacks which are user setable. The default routines
png_realloc(), png_large_free(), and png_free(). These currently just are in pngerror.c, pngmem.c, and pngio.c. To change these functions,
call the standard C functions. The large functions must handle at least call the approprate fn function.
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 Memory allocation is done through the functions png_large_malloc(),
platform will change between applications, these functions must be modified png_malloc(), png_realloc(), png_large_free(), and png_free().
or replaced to change their behaviour. If you only need to add new tests or These currently just call the standard C functions. The large
flags to have the compiler choose the correct function calls, please forward functions must handle exactly 64K, but they don't have to handle
these changes to the libpng author, so they can be added into the library more then that. If your pointers can't access more then 64K at a
for the benefit of others. time, you will want to set MAXSEG_64K in zlib.h.
All of the input/output, and error handling in libpng go through the Input/Output in libpng is done throught png_read() and png_write(), which
routines in pngio.c by default. The file has plenty of comments describing currently just call fread() and fwrite(). The FILE * is stored in
each function and how it expects to work. It is possible to supply different png_struct, and is initialized via png_init_io(). If you wish to change
I/O and error handling methods at run time with the png_set_msg_fn(), this, the library supplies callbacks that you can set through the
png_set_read_fn(), and png_set_write_fn() calls. function png_set_read_fn() and png_set_write_fn(). These functions
also provide a void pointer that can be retrieved via the function
png_get_io_ptr(). For example:
Input/Output in libpng is done throught png_read_data() and png_write_data(), png_set_read_fn(png_structp png_ptr, voidp io_ptr,
which currently just call fread() and fwrite(). The error and warning png_rw_ptr read_data_fn)
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 png_set_write_fn(png_structp png_ptr, voidp io_ptr,
do so at runtime, and without modifying the libpng library code. The png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn);
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 voidp io_ptr = png_get_io_ptr(png_ptr);
default. Errors handled through png_error() are fatal, meaning that
png_error() should never return to it's caller. Currently, this is handled Note that you can pass NULL for the flush function if you are not doing
via setjmp() and longjmp(), but you could change this to do things like flushing.
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
exit() if you should wish. Similarly, both png_error() and png_warning() 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 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 behind using setjmp() and longjmp() is the C++ throw and catch exception
@ -876,72 +956,14 @@ is no need to check every return code of every function call. However,
there are some uncertainties about the status of local variables after there are some uncertainties about the status of local variables after
a longjmp, so the user may want to be careful about doing anything after a longjmp, so the user may want to be careful about doing anything after
setjmp returns non zero besides returning itself. Consult your compiler setjmp returns non zero besides returning itself. Consult your compiler
documentation for more details. documentation for more details. If you wish to change this behavior,
you will need to set up your own message callbacks. You do this like
the io callbacks above.
The replacement message functions should have parameters as follows: png_set_message_fn(png_structp png_ptr, png_voidp msg_ptr,
png_msg_ptr error_fn, png_msg_ptr warning_fn);
void user_error_fn(png_struct png_ptr, char *error_msg); png_voidp msg_ptr = png_get_msg_ptr(png_ptr);
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 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 into the libpng code. First, read the PNG specification, and have
@ -950,9 +972,7 @@ attention to the sections that describe chunk names, and look
at how other chunks were designed, so you can do things similar. at how other chunks were designed, so you can do things similar.
Second, check out the sections of libpng that read and write chunks. 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. 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. If you are More details can be found in the comments inside the code.
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 If you wish to write your own transformation for the data, look
through the part of the code that does the transformations, and check through the part of the code that does the transformations, and check
@ -963,21 +983,32 @@ itself.
Configuring for 16 bit platforms: Configuring for 16 bit platforms:
You will probably need to change the png_large_malloc() and You will may need to change the png_large_malloc() and
png_large_free() routines in pngmem.c, as these are required png_large_free() routines in pngmem.c, as these are requred
to allocate 64K. Also, you will want to look into zconf.h to tell 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 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 time. Even if you can, the memory won't be accessable. So limit zlib
and libpng to 64K by defining MAXSEG_64K. and libpng to 64K by defining MAXSEG_64K.
Configuring for Medium Model:
Libpng's support for medium model has been tested on most of the popular
complers. Make sure MAXSEG_64K get's defined, USE_FAR_KEYWORD get's
defined, and FAR get's defined to far in pngconf.h, and you should be
all set. Everything in the library (except for zlib's structure) is
expecting far data. You must use the typedefs with the p or pp on
the end for pointers (or at least look at them and be careful). Make
note that the row's of data are defined as png_bytepp which is a
unsigned char far * far *
Configuring for gui/windowing platforms: Configuring for gui/windowing platforms:
You will need to supply new message display functions for png_error() and You will need to change the error message display in png_error() and
png_warning() (through png_set_message_fn() to display a message in a window png_warning() to display a message instead of fprinting it to stderr.
instead of fprinting it to stderr. You may want to write a single function You may want to write a single function to do this and call it something
to do this and call it something like png_message() (although the error like png_message(). On some compliers, you may have to change the
function should still call longjmp or otherwise handle the error without memory allocators (png_malloc, etc.).
returning).
Configuring for compiler xxx: Configuring for compiler xxx:
@ -989,13 +1020,15 @@ files in libpng proper only include png.h.
Removing unwanted object code: Removing unwanted object code:
There are a bunch of #define's in pngconf.h that control what parts of There are a bunch of #define's in png.h that control what parts of
libpng are compiled. All the defines end in _SUPPORT. If you are libpng are compiled. All the defines end in _SUPPORT. If you are
never going to use an ability, you can change the #define to #undef and not using an ability, you can change the #define to #undef and
save yourself code and data space. All the reading and writing save yourself code and data space. All the reading and writing
specific code are in seperate files, so the linker should only grab 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 the files it needs. However, if you want to make sure, or if you
are building a stand alone library, all the reading files start with are building a stand alone library, all the reading files start with
pngr and all the writing files start with pngw. The files that 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 don't match either (like png.c, pngtrans.c, etc.) are used for
both reading and writing, and always need to be included. both reading and writing, and always need to be included. The
progressive reader is in pngpread.c

190
lpfaq.txt
View File

@ -1,190 +0,0 @@
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

View File

@ -2,26 +2,25 @@
# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc. # Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc.
# For conditions of distribution and use, see copyright notice in png.h # For conditions of distribution and use, see copyright notice in png.h
CC=gcc CC=cc
CFLAGS=-I../zlib -O2 -Wall -ansi -pedantic CFLAGS=-I../zlib -O
LDFLAGS=-L. -L../zlib/ -lpng -lz -lm LDFLAGS=-L. -L../zlib/ -lpng -lz -lm
RANLIB=ranlib #RANLIB=ranlib
#RANLIB=echo RANLIB=echo
# where make install puts libpng.a and png.h # where make install puts libpng.a and png.h
prefix=/home/munet-d2/sun/local prefix=/usr/local
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \ OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \
pngread.o pngio.o pngwrite.o pngrtran.o pngwtran.o \ pngread.o pngio.o pngwrite.o pngrtran.o pngwtran.o \
pngmem.o pngmem.o pngerror.o pngpread.o
all: libpng.a pngtest all: libpng.a pngtest
libpng.a: $(OBJS) libpng.a: $(OBJS)
ar rc $@ $(OBJS) ar rc $@ $(OBJS)
$(RANLIB) $@ $(RANLIB) $@
rcp libpng.a vlsi:bin/lib/libpng.a
pngtest: pngtest.o libpng.a pngtest: pngtest.o libpng.a
$(CC) -o pngtest $(CCFLAGS) pngtest.o $(LDFLAGS) $(CC) -o pngtest $(CCFLAGS) pngtest.o $(LDFLAGS)
@ -45,6 +44,7 @@ clean:
# DO NOT DELETE THIS LINE -- make depend depends on it. # DO NOT DELETE THIS LINE -- make depend depends on it.
png.o: png.h pngconf.h png.o: png.h pngconf.h
pngerror.o: png.h pngconf.h
pngio.o: png.h pngconf.h pngio.o: png.h pngconf.h
pngmem.o: png.h pngconf.h pngmem.o: png.h pngconf.h
pngrcb.o: png.h pngconf.h pngrcb.o: png.h pngconf.h
@ -56,3 +56,4 @@ pngtrans.o: png.h pngconf.h
pngwrite.o: png.h pngconf.h pngwrite.o: png.h pngconf.h
pngwtran.o: png.h pngconf.h pngwtran.o: png.h pngconf.h
pngwutil.o: png.h pngconf.h pngwutil.o: png.h pngconf.h
pngpread.o: png.h pngconf.h

88
png.c
View File

@ -1,10 +1,10 @@
/* png.c - location for general purpose png functions /* png.c - location for general purpose png functions
libpng 1.0 beta 2 - version 0.81 libpng 1.0 beta 2 - version 0.85
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
August 24, 1995 December 19, 1995
*/ */
#define PNG_INTERNAL #define PNG_INTERNAL
@ -13,123 +13,127 @@
/* version information for c files. This better match the version /* version information for c files. This better match the version
string defined in png.h */ string defined in png.h */
char png_libpng_ver[] = "0.81"; char FARDATA png_libpng_ver[] = "0.85";
/* place to hold the signiture string for a png file. */ /* place to hold the signiture string for a png file. */
png_byte png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10}; png_byte FARDATA png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
/* constant strings for known chunk types. If you need to add a chunk, /* constant strings for known chunk types. If you need to add a chunk,
add a string holding the name here. If you want to make the code add a string holding the name here. If you want to make the code
portable to EBCDIC machines, use ASCII numbers, not characters. */ portable to EBCDIC machines, use ASCII numbers, not characters. */
png_byte png_IHDR[4] = { 73, 72, 68, 82}; png_byte FARDATA png_IHDR[4] = { 73, 72, 68, 82};
png_byte png_IDAT[4] = { 73, 68, 65, 84}; png_byte FARDATA png_IDAT[4] = { 73, 68, 65, 84};
png_byte png_IEND[4] = { 73, 69, 78, 68}; png_byte FARDATA png_IEND[4] = { 73, 69, 78, 68};
png_byte png_PLTE[4] = { 80, 76, 84, 69}; png_byte FARDATA png_PLTE[4] = { 80, 76, 84, 69};
#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_WRITE_gAMA_SUPPORTED) #if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_WRITE_gAMA_SUPPORTED)
png_byte png_gAMA[4] = {103, 65, 77, 65}; png_byte FARDATA png_gAMA[4] = {103, 65, 77, 65};
#endif #endif
#if defined(PNG_READ_sBIT_SUPPORTED) || defined(PNG_WRITE_sBIT_SUPPORTED) #if defined(PNG_READ_sBIT_SUPPORTED) || defined(PNG_WRITE_sBIT_SUPPORTED)
png_byte png_sBIT[4] = {115, 66, 73, 84}; png_byte FARDATA png_sBIT[4] = {115, 66, 73, 84};
#endif #endif
#if defined(PNG_READ_cHRM_SUPPORTED) || defined(PNG_WRITE_cHRM_SUPPORTED) #if defined(PNG_READ_cHRM_SUPPORTED) || defined(PNG_WRITE_cHRM_SUPPORTED)
png_byte png_cHRM[4] = { 99, 72, 82, 77}; png_byte FARDATA png_cHRM[4] = { 99, 72, 82, 77};
#endif #endif
#if defined(PNG_READ_tRNS_SUPPORTED) || defined(PNG_WRITE_tRNS_SUPPORTED) #if defined(PNG_READ_tRNS_SUPPORTED) || defined(PNG_WRITE_tRNS_SUPPORTED)
png_byte png_tRNS[4] = {116, 82, 78, 83}; png_byte FARDATA png_tRNS[4] = {116, 82, 78, 83};
#endif #endif
#if defined(PNG_READ_bKGD_SUPPORTED) || defined(PNG_WRITE_bKGD_SUPPORTED) #if defined(PNG_READ_bKGD_SUPPORTED) || defined(PNG_WRITE_bKGD_SUPPORTED)
png_byte png_bKGD[4] = { 98, 75, 71, 68}; png_byte FARDATA png_bKGD[4] = { 98, 75, 71, 68};
#endif #endif
#if defined(PNG_READ_hIST_SUPPORTED) || defined(PNG_WRITE_hIST_SUPPORTED) #if defined(PNG_READ_hIST_SUPPORTED) || defined(PNG_WRITE_hIST_SUPPORTED)
png_byte png_hIST[4] = {104, 73, 83, 84}; png_byte FARDATA png_hIST[4] = {104, 73, 83, 84};
#endif #endif
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) #if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED)
png_byte png_tEXt[4] = {116, 69, 88, 116}; png_byte FARDATA png_tEXt[4] = {116, 69, 88, 116};
#endif #endif
#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED) #if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
png_byte png_zTXt[4] = {122, 84, 88, 116}; png_byte FARDATA png_zTXt[4] = {122, 84, 88, 116};
#endif #endif
#if defined(PNG_READ_pHYs_SUPPORTED) || defined(PNG_WRITE_pHYs_SUPPORTED) #if defined(PNG_READ_pHYs_SUPPORTED) || defined(PNG_WRITE_pHYs_SUPPORTED)
png_byte png_pHYs[4] = {112, 72, 89, 115}; png_byte FARDATA png_pHYs[4] = {112, 72, 89, 115};
#endif #endif
#if defined(PNG_READ_oFFs_SUPPORTED) || defined(PNG_WRITE_oFFs_SUPPORTED) #if defined(PNG_READ_oFFs_SUPPORTED) || defined(PNG_WRITE_oFFs_SUPPORTED)
png_byte png_oFFs[4] = {111, 70, 70, 115}; png_byte FARDATA png_oFFs[4] = {111, 70, 70, 115};
#endif #endif
#if defined(PNG_READ_tIME_SUPPORTED) || defined(PNG_WRITE_tIME_SUPPORTED) #if defined(PNG_READ_tIME_SUPPORTED) || defined(PNG_WRITE_tIME_SUPPORTED)
png_byte png_tIME[4] = {116, 73, 77, 69}; png_byte FARDATA png_tIME[4] = {116, 73, 77, 69};
#endif #endif
/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* start of interlace block */ /* start of interlace block */
int png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
/* offset to next interlace block */ /* offset to next interlace block */
int png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
/* start of interlace block in the y direction */ /* start of interlace block in the y direction */
int png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
/* offset to next interlace block in the y direction */ /* offset to next interlace block in the y direction */
int png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
/* width of interlace block */ /* width of interlace block */
/* this is not currently used - if you need it, uncomment it here and /* this is not currently used - if you need it, uncomment it here and
in png.h in png.h
int png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; int FARDATA png_pass_width[] = {8, 4, 4, 2, 2, 1, 1};
*/ */
/* height of interlace block */ /* height of interlace block */
/* this is not currently used - if you need it, uncomment it here and /* this is not currently used - if you need it, uncomment it here and
in png.h in png.h
int png_pass_height[] = {8, 8, 4, 4, 4, 2, 2, 1}; int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
*/ */
/* mask to determine which pixels are valid in a pass */ /* mask to determine which pixels are valid in a pass */
int png_pass_mask[] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; int FARDATA png_pass_mask[] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
/* mask to determine which pixels to overwrite while displaying */ /* mask to determine which pixels to overwrite while displaying */
int png_pass_dsp_mask[] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; int FARDATA png_pass_dsp_mask[] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
int int
png_check_sig(png_byte *sig, int num) png_check_sig(png_bytep sig, int num)
{ {
if (num > 8) if (num > 8)
num = 8; num = 8;
if (num < 1) if (num < 1)
return 0; return 0;
return (!memcmp(sig, png_sig, num)); return (!png_memcmp(sig, png_sig, num));
} }
/* Function to allocate memory for zlib. */ /* Function to allocate memory for zlib. */
voidpf voidpf
png_zalloc(voidpf png_ptr, uInt items, uInt size) png_zalloc(voidpf png_ptr, uInt items, uInt size)
{ {
return ((voidpf)png_large_malloc((png_struct FAR *)png_ptr, voidp * ptr;
(png_uint_32)items * (png_uint_32)size));
ptr = ((voidp)png_large_malloc((png_structp)png_ptr,
(png_uint_32)items * (png_uint_32)size));
png_memset(ptr, 0, (png_uint_32)items * (png_uint_32)size);
return (voidpf)(ptr);
} }
/* function to free memory for zlib */ /* function to free memory for zlib */
void void
png_zfree(voidpf png_ptr, voidpf ptr) png_zfree(voidpf png_ptr, voidpf ptr)
{ {
png_large_free((png_struct FAR *)png_ptr, (voidpf)ptr); png_large_free((png_structp)png_ptr, (voidp)ptr);
} }
/* reset the crc variable to 32 bits of 1's. Care must be taken /* reset the crc variable to 32 bits of 1's. Care must be taken
in case crc is > 32 bits to leave the top bits 0 */ in case crc is > 32 bits to leave the top bits 0 */
void void
png_reset_crc(png_struct *png_ptr) png_reset_crc(png_structp png_ptr)
{ {
/* set crc to all 1's */ /* set crc to all 1's */
png_ptr->crc = 0xffffffffL; png_ptr->crc = 0xffffffffL;
} }
/* Note: the crc code below was copied from the sample code in the /* Note: the crc code below was copied from the sample code in the
PNG spec, with appropriate modifications made to ensure the PNG spec, with appropriate modifications made to ensure the
variables are large enough */ variables are large enough */
/* table of crc's of all 8-bit messages. If you wish to png_malloc this /* table of crc's of all 8-bit messages. If you wish to png_malloc this
table, turn this into a pointer, and png_malloc it in make_crc_table(). table, turn this into a pointer, and png_malloc it in make_crc_table().
@ -161,10 +165,10 @@ make_crc_table(void)
initialized to all 1's, and the transmitted value is the 1's complement initialized to all 1's, and the transmitted value is the 1's complement
of the final running crc. */ of the final running crc. */
static png_uint_32 static png_uint_32
update_crc(png_uint_32 crc, png_bytef *buf, png_uint_32 len) update_crc(png_uint_32 crc, png_bytep buf, png_uint_32 len)
{ {
png_uint_32 c; png_uint_32 c;
png_bytef *p; png_bytep p;
png_uint_32 n; png_uint_32 n;
c = crc; c = crc;
@ -178,7 +182,7 @@ update_crc(png_uint_32 crc, png_bytef *buf, png_uint_32 len)
if (n > 0) do if (n > 0) do
{ {
c = crc_table[(png_byte)((c ^ (*p++)) & 0xff)] ^ (c >> 8); c = crc_table[(png_byte)((c ^ (*p++)) & 0xff)] ^ (c >> 8);
} while (--n); } while (--n);
return c; return c;
@ -189,15 +193,15 @@ update_crc(png_uint_32 crc, png_bytef *buf, png_uint_32 len)
would need to use huge pointers to access all that data. If you would need to use huge pointers to access all that data. If you
need this, put huge here and above. */ need this, put huge here and above. */
void void
png_calculate_crc(png_struct *png_ptr, png_bytef *ptr, png_calculate_crc(png_structp png_ptr, png_bytep ptr,
png_uint_32 length) png_uint_32 length)
{ {
png_ptr->crc = update_crc(png_ptr->crc, ptr, length); png_ptr->crc = update_crc(png_ptr->crc, ptr, length);
} }
void void
png_info_init(png_info *info) png_info_init(png_infop info)
{ {
/* set everything to 0 */ /* set everything to 0 */
memset(info, 0, sizeof (png_info)); png_memset(info, 0, sizeof (png_info));
} }

932
png.h

File diff suppressed because it is too large Load Diff

View File

@ -56,15 +56,11 @@ version 0.8
enabled png_set_shift to work with paletted images on read enabled png_set_shift to work with paletted images on read
added png_read_update_info() - updates info structure with transformations added png_read_update_info() - updates info structure with transformations
version 0.81 version 0.81
added support for medium memory model incorporated Tim Wegner's medium model code (thanks, Tim)
version 0.82 version 0.85
added ability to flush output stream automatically or manually added more medium model code (almost everythings a far)
added ability to change I/O and error functions dynamically added i/o, error, and memory callback functions
moved pngerror.c into pngio.c to make all the default functions static fixed some bugs (16 bit, 4 bit interlaced, etc.)
when freeing memory in png_read_destroy don't free memory we didn't allocate added first run progressive reader (barely tested)
added warnings when reading blocks of incorrect length
limit tEXt and zTXt keywords to 80 chars

118
pngconf.h
View File

@ -1,10 +1,10 @@
/* pngconf.c - machine configurable file for libpng /* pngconf.c - machine configurable file for libpng
libpng 1.0 beta 2 - version 0.81 libpng 1.0 beta 2 - version 0.85
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
August 24, 1995 December 19, 1995
*/ */
/* Any machine specific code is near the front of this file, so if you /* Any machine specific code is near the front of this file, so if you
@ -27,7 +27,7 @@
Unless this gets smaller then the size of a row (compressed), Unless this gets smaller then the size of a row (compressed),
it should not make much difference how big this is. */ it should not make much difference how big this is. */
#define PNG_ZBUF_SIZE 32768 #define PNG_ZBUF_SIZE 8192
/* While libpng currently uses zlib for it's compression, it has been designed /* 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 to stand on it's own. Towards this end, there are two defines that are
@ -48,6 +48,14 @@
#define PNG_MAX_ALLOC_64K #define PNG_MAX_ALLOC_64K
#endif #endif
/* this protects us against compilers which run on a windowing system
and thus don't have or would rather us not use the stdio types:
stdin, stdout, and stderr. The only one currently used is stderr
in png_error() and png_warning(). #defining PNG_NO_STDIO will
prevent these from being compiled and used. */
/* #define PNG_NO_STDIO */
/* this macro protects us against machines that don't have function /* this macro protects us against machines that don't have function
prototypes. If your compiler does not handle function prototypes, prototypes. If your compiler does not handle function prototypes,
define this macro. I've always been able to use _NO_PROTO as the define this macro. I've always been able to use _NO_PROTO as the
@ -60,7 +68,7 @@
#else #else
#ifdef _NO_PROTO #ifdef _NO_PROTO
#define PNGARG(arglist) #define PNGARG(arglist) ()
#else #else
#define PNGARG(arglist) arglist #define PNGARG(arglist) arglist
#endif /* _NO_PROTO */ #endif /* _NO_PROTO */
@ -129,6 +137,19 @@
#endif /* PNG_INTERNAL */ #endif /* PNG_INTERNAL */
/* the following uses const char * instead of char * for error
and warning message functions, so some compilers won't complain.
If you want to use const, define PNG_USE_CONST here. It is not
normally defined to make configuration easier, as it is not a
critical part of the code.
*/
#ifdef PNG_USE_CONST
# define PNG_CONST const
#else
# define PNG_CONST
#endif
/* The following defines give you the ability to remove code /* The following defines give you the ability to remove code
from the library that you will not be using. I wish I from the library that you will not be using. I wish I
could figure out how to automate this, but I can't do could figure out how to automate this, but I can't do
@ -144,7 +165,7 @@
*/ */
/* Any transformations you will not be using can be undef'ed here */ /* Any transformations you will not be using can be undef'ed here */
#define PNG_PROGRESSIVE_READ_SUPPORTED
#define PNG_READ_INTERLACING_SUPPORTED #define PNG_READ_INTERLACING_SUPPORTED
#define PNG_READ_EXPAND_SUPPORTED #define PNG_READ_EXPAND_SUPPORTED
#define PNG_READ_SHIFT_SUPPORTED #define PNG_READ_SHIFT_SUPPORTED
@ -223,16 +244,96 @@ typedef size_t png_size_t;
changes that are needed. Most of the far keyword changes are hidden changes that are needed. Most of the far keyword changes are hidden
inside typedefs with suffix "f". Tim Wegner */ inside typedefs with suffix "f". Tim Wegner */
#if defined(FAR) && defined(M_I86MM) /* MSC Medium model */ /* SJT: Separate compiler dependencies */
# define USE_FAR_KEYWORD /* SJT: problem here is that zlib.h always defines FAR */
#ifdef __BORLANDC__
#if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__)
#define LDATA 1
#else #else
#define LDATA 0
#endif
#if !defined(__WIN32__) && !defined(__FLAT__)
#define PNG_MAX_MALLOC_64K
#if (LDATA != 1)
#ifndef FAR
#define FAR __far
#endif
#define USE_FAR_KEYWORD
#endif /* LDATA != 1 */
/* SJT: Possibly useful for moving data out of default segment.
Uncomment it if you want. Could also define FARDATA as const
if your compiler supports it.
# define FARDATA FAR
*/
#endif /* __WIN32__, __FLAT__ */
#endif /* __BORLANDC__ */
/* SJT: Suggest testing for specific compiler first before
testing for FAR. The Watcom compiler defines both __MEDIUM__
and M_I86MM, making reliance oncertain keywords suspect
*/
/* MSC Medium model */
#if defined(FAR)
# if defined(M_I86MM)
# define USE_FAR_KEYWORD
# define FARDATA FAR /* SJT: added */
# endif
#endif
/* SJT: default case */
#ifndef FAR
# define FAR # define FAR
#endif #endif
/* SJT: At this point FAR is always defined */
/* not used anymore, but kept for compatability */
typedef unsigned char FAR png_bytef; typedef unsigned char FAR png_bytef;
/* SJT: */
#ifndef FARDATA
#define FARDATA
#endif
/* End medium model changes to be in zconf.h */ /* End medium model changes to be in zconf.h */
/* SJT: More typedefs */
typedef void FAR * png_voidp;
/* SJT: Add typedefs for pointers */
typedef png_byte FAR * png_bytep;
typedef png_uint_32 FAR * png_uint_32p;
typedef png_int_32 FAR * png_int_32p;
typedef png_uint_16 FAR * png_uint_16p;
typedef png_int_16 FAR * png_int_16p;
typedef PNG_CONST char FAR * png_const_charp;
typedef char FAR * png_charp;
/* SJT: Pointers to pointers; i.e. arrays */
typedef png_byte FAR * FAR * png_bytepp;
typedef png_uint_32 FAR * FAR * png_uint_32pp;
typedef png_int_32 FAR * FAR * png_int_32pp;
typedef png_uint_16 FAR * FAR * png_uint_16pp;
typedef png_int_16 FAR * FAR * png_int_16pp;
typedef PNG_CONST char FAR * FAR * png_const_charpp;
typedef char FAR * FAR * png_charpp;
/* SJT: libpng typedefs for types in zlib. If Zlib changes
or another compression library is used, then change these.
Eliminates need to change all the source files.
*/
typedef charf * png_zcharp;
typedef charf * FAR * png_zcharpp;
typedef z_stream * png_zstreamp; /* zlib won't accept far z_stream */
/* User may want to use these so not in PNG_INTERNAL. Any library functions /* User may want to use these so not in PNG_INTERNAL. Any library functions
that are passed far data must be model independent. */ that are passed far data must be model independent. */
#if defined(USE_FAR_KEYWORD) /* memory model independent fns */ #if defined(USE_FAR_KEYWORD) /* memory model independent fns */
@ -240,6 +341,7 @@ typedef unsigned char FAR png_bytef;
# define png_strcat _fstrcat # define png_strcat _fstrcat
# define png_strlen _fstrlen # define png_strlen _fstrlen
# define png_strcmp _fstrcmp # define png_strcmp _fstrcmp
# define png_memcmp _fmemcmp /* SJT: added */
# define png_memcpy _fmemcpy # define png_memcpy _fmemcpy
# define png_memset _fmemset # define png_memset _fmemset
#else /* use the usual functions */ #else /* use the usual functions */
@ -247,11 +349,11 @@ typedef unsigned char FAR png_bytef;
# define png_strcat strcat # define png_strcat strcat
# define png_strlen strlen # define png_strlen strlen
# define png_strcmp strcmp # define png_strcmp strcmp
# define png_memcmp memcmp /* SJT: added */
# define png_memcpy memcpy # define png_memcpy memcpy
# define png_memset memset # define png_memset memset
#endif #endif
/* End of memory model independent support */ /* End of memory model independent support */
#endif /* PNGCONF_H */ #endif /* PNGCONF_H */

99
pngerror.c Normal file
View File

@ -0,0 +1,99 @@
/* pngerror.c - stub functions for i/o and memory allocation
libpng 1.0 beta 2 - version 0.85
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
December 19, 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_structp png_ptr, png_const_charp message)
{
if (png_ptr->error_fn)
(*(png_ptr->error_fn))(png_ptr, message);
/* if the following returns or doesn't exist, use the default function,
which will not return */
png_default_error(png_ptr, message);
}
void
png_warning(png_structp png_ptr, png_const_charp message)
{
if (png_ptr->warning_fn)
(*(png_ptr->warning_fn))(png_ptr, message);
else
png_default_warning(png_ptr, message);
}
void
png_default_error(png_structp png_ptr, png_const_charp message)
{
#ifndef PNG_NO_STDIO
fprintf(stderr, "libpng error: %s\n", message);
#endif
#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_default_warning(png_structp png_ptr, png_const_charp message)
{
if (!png_ptr)
return;
#ifndef PNG_NO_STDIO
fprintf(stderr, "libpng warning: %s\n", message);
#endif
}
/* 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) */
void
png_set_message_fn(png_structp png_ptr, png_voidp msg_ptr, png_msg_ptr error_fn,
png_msg_ptr warning_fn)
{
png_ptr->msg_ptr = msg_ptr;
png_ptr->error_fn = error_fn;
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. */
png_voidp
png_get_msg_ptr(png_structp png_ptr)
{
return png_ptr->msg_ptr;
}

431
pngio.c
View File

@ -1,45 +1,54 @@
/* pngio.c - default functions for data I/O and error/warning messages /* pngstub.c - stub functions for i/o and memory allocation
libpng 1.0 beta 3 - version 0.82 libpng 1.0 beta 2 - version 0.85
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
Some portions Copyright (C) 1995 Andreas Dilger December 19, 1995
Sept 24, 1995
This file provides a location for all input/output. Users which need This file provides a location for all input/output. Users which need
special handling are expected to write functions which have the same special handling are expected to write functions which have the same
arguments as these, and perform similar functions, but possibly have arguments as these, and perform similar functions, but possibly have
different I/O methods. Note that you shouldn't change these functions, different I/O methods. Note that you shouldn't change these functions,
but rather write replacement functions and then change them at run but rather write replacement functions and then change them at run
time with png_set_write_fn(...) or png_set_read_fn(...), etc */ time with png_set_write_fn(...) or png_set_read_fn(...), etc */
#define PNG_INTERNAL
#include "png.h" #include "png.h"
/* Write the data to whatever output you are using. The default /* Write the data to whatever output you are using. The default
routine writes to a file pointer. If you need to write to something routine writes to a file pointer. If you need to write to something
else, this is a good example of how to do it. Note that this routine 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 sometimes gets called with very small lengths, so you should implement
some kind of simple buffering if you are using unbuffered writes. This 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 should never be asked to write more then 64K on a 16 bit machine. The
cast to png_size_t is there for insurance. */ cast to png_size_t is there for insurance. */
void
png_write_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
{
if (png_ptr->write_data_fn)
(*(png_ptr->write_data_fn))(png_ptr, data, length);
else
png_error(png_ptr, "Call to NULL write function");
}
#ifndef USE_FAR_KEYWORD #ifndef USE_FAR_KEYWORD
static void void
png_write_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length) png_default_write_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
{ {
png_uint_32 check; png_uint_32 check;
check = fwrite(data, 1, (png_size_t)length, png_ptr->fp); check = fwrite(data, 1, (png_size_t)length, png_ptr->fp);
if (check != length) if (check != length)
{ {
(*(png_ptr->error_fn))(png_ptr, "Write error"); png_error(png_ptr, "Write Error");
} }
} }
#else #else
/* this is the model-independent version. Since the standard I/O library /* this is the model-independent version. Since the standard I/O library
can't handle far buffers in the medium and small models, we have to copy can't handle far buffers in the medium and small models, we have to copy
the data. the data.
*/ */
#define NEAR_BUF_SIZE 1024 #define NEAR_BUF_SIZE 1024
@ -50,76 +59,97 @@ png_write_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length)
#include <dos.h> #include <dos.h>
#endif #endif
static void void
png_write_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length) png_default_write_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
{ {
png_uint_32 check; png_uint_32 check;
png_byte *n_data; png_byte *n_data;
/* Check if data really is near. If so, use usual code. */ /* Check if data really is near. If so, use usual code. */
#ifdef _MSC_VER #ifdef _MSC_VER
/* do it this way just to quiet warning */ /* do it this way just to quiet warning */
FP_OFF(n_data) = FP_OFF(data); FP_OFF(n_data) = FP_OFF(data);
if(FP_SEG(n_data) == FP_SEG(data)) if (FP_SEG(n_data) == FP_SEG(data))
#else #else
/* this works in MSC also but with lost segment warning */ /* this works in MSC also but with lost segment warning */
n_data = (png_byte *)data; n_data = (png_byte *)data;
if((png_bytef *)n_data == data) if ((png_bytep)n_data == data)
#endif #endif
{ {
check = fwrite(n_data, 1, (png_size_t)length, png_ptr->fp); check = fwrite(n_data, 1, (png_size_t)length, png_ptr->fp);
} }
else else
{ {
png_byte buf[NEAR_BUF_SIZE]; png_byte buf[NEAR_BUF_SIZE];
png_size_t written, remaining, err; png_size_t written, remaining, err;
check = 0; check = 0;
remaining = (png_size_t)length; remaining = (png_size_t)length;
do do
{ {
written = MIN(NEAR_BUF_SIZE,remaining); written = MIN(NEAR_BUF_SIZE, remaining);
png_memcpy(buf,data,written); /* copy far buffer to near buffer */ png_memcpy(buf, data, written); /* copy far buffer to near buffer */
err = fwrite(buf, 1, written, png_ptr->fp); err = fwrite(buf, 1, written, png_ptr->fp);
if(err != written) if (err != written)
break; break;
else else
check += err; check += err;
data += written; data += written;
remaining -= written; remaining -= written;
} }
while(remaining != 0); while (remaining != 0);
} }
if (check != length) if (check != length)
{ {
(*(png_ptr->error_fn))(png_ptr, "Write error"); png_error(png_ptr, "Write Error");
} }
} }
#endif #endif
/* Read the data from whatever input you are using. The default /* Read the data from whatever input you are using. The default
routine reads from a file pointer. If you need to read from something routine reads from a file pointer. If you need to read from something
else, this is a good example of how to do it. Note that this routine else, this is the place to do it. We suggest saving the old code
sometimes gets called with very small lengths, so you should implement for future use. Note that this routine sometimes gets called with
some kind of simple buffering if you are using unbuffered reads. This very small lengths, so you should implement some kind of simple
should never be asked to read more then 64K on a 16 bit machine. The buffering if you are using unbuffered reads. This should
cast to png_size_t is there for insurance. */ 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. */
void
png_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
{
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
if (png_ptr->read_mode == PNG_READ_PUSH_MODE)
{
png_push_fill_buffer(png_ptr, data, length);
}
else
#endif
{
if (png_ptr->read_data_fn)
(*(png_ptr->read_data_fn))(png_ptr, data, length);
else
png_error(png_ptr, "Call to NULL read function");
}
}
#ifndef USE_FAR_KEYWORD #ifndef USE_FAR_KEYWORD
static void void
png_read_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length) png_default_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
{ {
png_uint_32 check; png_uint_32 check;
check = fread(data, 1, (size_t)length, png_ptr->fp); check = fread(data, 1, (size_t)length, png_ptr->fp);
if (check != length) if (check != length)
{ {
(*(png_ptr->error_fn))(png_ptr, "Read error"); png_error(png_ptr, "Read Error");
} }
} }
#else #else
static void void
png_read_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length) png_default_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
{ {
png_uint_32 check; png_uint_32 check;
png_byte *n_data; png_byte *n_data;
@ -128,15 +158,15 @@ png_read_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length)
#ifdef _MSC_VER #ifdef _MSC_VER
/* do it this way just to quiet warning */ /* do it this way just to quiet warning */
FP_OFF(n_data) = FP_OFF(data); FP_OFF(n_data) = FP_OFF(data);
if(FP_SEG(n_data) == FP_SEG(data)) if (FP_SEG(n_data) == FP_SEG(data))
#else #else
/* this works in MSC also but with lost segment warning */ /* this works in MSC also but with lost segment warning */
n_data = (png_byte *)data; n_data = (png_byte *)data;
if((png_bytef *)n_data == data) if ((PNG_BYTEP )n_data == data)
#endif #endif
{ {
check = fread(n_data, 1, (size_t)length, png_ptr->fp); check = fread(n_data, 1, (size_t)length, png_ptr->fp);
} }
else else
{ {
png_byte buf[NEAR_BUF_SIZE]; png_byte buf[NEAR_BUF_SIZE];
@ -145,267 +175,136 @@ png_read_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length)
remaining = (png_size_t)length; remaining = (png_size_t)length;
do do
{ {
read = MIN(NEAR_BUF_SIZE,remaining); read = MIN(NEAR_BUF_SIZE, remaining);
err = fread(buf, 1, read, png_ptr->fp); err = fread(buf, 1, read, png_ptr->fp);
png_memcpy(data,buf,read); /* copy far buffer to near buffer */ png_memcpy(data, buf, read); /* copy far buffer to near buffer */
if(err != read) if(err != read)
break; break;
else else
check += err; check += err;
data += read; data += read;
remaining -= read; remaining -= read;
} }
while(remaining != 0); while (remaining != 0);
} }
if (check != length) if (check != length)
{ {
(*(png_ptr->error_fn))(png_ptr, "Read error"); png_error(png_ptr, "read Error");
} }
} }
#endif #endif
/* 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) #if defined(PNG_WRITE_FLUSH_SUPPORTED)
/* This function does nothing, and is supplied for user I/O functions which void
do not do any buffering. This function is set when NULL is supplied for png_flush(png_struct *png_ptr)
the flush function pointer. */
static void
png_empty_flush(png_struct *png_ptr)
{ {
if (png_ptr->output_flush_fn)
(*(png_ptr->output_flush_fn))(png_ptr);
} }
void
/* Write out any remaining output that is stored in the output buffers. png_default_flush(png_struct *png_ptr)
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); if (png_ptr->fp)
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 #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 /* This function allows the application to supply new output functions for
libpng if standard C streams aren't being used. The new write function libpng if standard C streams aren't being used.
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:
This function takes as its arguments: png_ptr - pointer to a png output data structure
png_ptr - pointer to a png output data structure io_ptr - pointer to user supplied structure containing info about
io_ptr - pointer to user supplied structure containing info about the output functions. May be NULL.
the output functions. May be NULL. write_data_fn - pointer to a new output function which takes as its
write_data_fn - pointer to a new output function which takes as its arguments a pointer to a png_struct, a pointer to
arguments a pointer to a png_struct, a pointer to data to be written, and a 32-bit unsigned int which is
data to be written, and a 32-bit unsigned int which is the number of bytes to be written. The new write
the number of bytes to be written. The new write function should call (*(png_ptr->error_fn))("Error msg")
function should call (*(png_ptr->error_fn))("Error msg") to exit and output any fatal error messages.
to exit and output any fatal error messages. flush_data_fn - pointer to a new flush function which takes as its
flush_data_fn - pointer to a new flush function which takes as its arguments a pointer to a png_struct. After a call to
arguments a pointer to a png_struct. After a call to the flush function, there should be no data in any buffers
the flush function, there should be no data in any buffers or pending transmission. If the output method doesn't do
or pending transmission. If the output method doesn't do any buffering of ouput, this parameter can be NULL. If
any buffering of ouput, this parameter can be NULL. If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng
PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time, output_flush_fn will be ignored, although
compile time, output_flush_fn will be ignored, although it must be supplied for compatibility. */
it must be supplied for compatibility. */
void void
png_set_write_fn(png_struct *png_ptr, void *io_ptr, png_rw_ptr write_data_fn, png_set_write_fn(png_structp png_ptr, png_voidp io_ptr, png_rw_ptr write_data_fn,
png_flush_ptr output_flush_fn) png_flush_ptr output_flush_fn)
{ {
png_ptr->io_ptr = io_ptr; png_ptr->io_ptr = io_ptr;
if (write_data_fn == NULL) if (write_data_fn)
{ png_ptr->write_data_fn = write_data_fn;
(*(png_ptr->error_fn))(png_ptr, "NULL write function pointer given"); else
} png_ptr->write_data_fn = png_default_write_data;
png_ptr->write_data_fn = write_data_fn;
#if defined(PNG_WRITE_FLUSH_SUPPORTED) #if defined(PNG_WRITE_FLUSH_SUPPORTED)
if (output_flush_fn == NULL) if (output_flush_fn == NULL)
{ png_ptr->output_flush_fn = png_default_flush;
png_ptr->output_flush_fn = png_empty_flush; else
} png_ptr->output_flush_fn = output_flush_fn;
else
{
png_ptr->output_flush_fn = output_flush_fn;
}
#endif /* PNG_WRITE_FLUSH_SUPPORTED */ #endif /* PNG_WRITE_FLUSH_SUPPORTED */
/* It is an error to write to a read device */ /* It is an error to read while writing a png file */
png_ptr->read_data_fn = png_empty_rw; png_ptr->read_data_fn = NULL;
} }
/* This function allows the application to supply a new input function /* 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 for libpng if standard C streams aren't being used.
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:
This function takes as its arguments: png_ptr - pointer to a png input data structure
png_ptr - pointer to a png input data structure io_ptr - pointer to user supplied structure containing info about
io_ptr - pointer to user supplied structure containing info about the input functions. May be NULL.
the input functions. May be NULL. read_data_fn - pointer to a new input function which takes as it's
read_data_fn - pointer to a new input function which takes as it's arguments a pointer to a png_struct, a pointer to
arguments a pointer to a png_struct, a pointer to a location where input data can be stored, and a 32-bit
a location where input data can be stored, and a 32-bit unsigned int which is the number of bytes to be read. */
unsigned int which is the number of bytes to be read. */
void void
png_set_read_fn(png_struct *png_ptr, void *io_ptr, png_rw_ptr read_data_fn) png_set_read_fn(png_struct *png_ptr, void *io_ptr, png_rw_ptr read_data_fn)
{ {
png_ptr->io_ptr = io_ptr; png_ptr->io_ptr = io_ptr;
if (read_data_fn == NULL) if (read_data_fn)
{ png_ptr->read_data_fn = read_data_fn;
(*(png_ptr->error_fn))(png_ptr, "NULL read function pointer given"); else
} png_ptr->read_data_fn = png_default_read_data;
png_ptr->read_data_fn = read_data_fn;
/* It is an error to write to a read device */ /* It is an error to write to a read device */
png_ptr->write_data_fn = png_empty_rw; png_ptr->write_data_fn = NULL;
#if defined(PNG_WRITE_FLUSH_SUPPORTED) #if defined(PNG_WRITE_FLUSH_SUPPORTED)
png_ptr->output_flush_fn = png_empty_flush; png_ptr->output_flush_fn = NULL;
#endif /* PNG_WRITE_FLUSH_SUPPORTED */ #endif /* PNG_WRITE_FLUSH_SUPPORTED */
} }
/* This function returns a pointer to the io_ptr associated with the user /* This function returns a pointer to the io_ptr associated with the user
functions. The application should free any memory associated with this functions. The application should free any memory associated with this
pointer before png_write_destroy and png_read_destroy are called. */ pointer before png_write_destroy and png_read_destroy are called. */
void * void *
png_get_io_ptr(png_struct *png_ptr) png_get_io_ptr(png_struct *png_ptr)
{ {
return png_ptr->io_ptr; return png_ptr->io_ptr;
} }
/* Initialize the input/output for the png file. If you change
/* This function is called when the application wants to use another the read and write routines, you will probably need to change
method of handling errors and warnings. Note that the error function must this routine (or write your own). If you change the parameters
NOT return to the calling routine or serious problems will occur. The of this routine, remember to change png.h also. */
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 void
png_set_msg_fn(png_struct *png_ptr, void *msg_ptr, png_msg_ptr error_fn, png_init_io(png_structp png_ptr, FILE *fp)
png_msg_ptr warning_fn)
{ {
png_ptr->msg_ptr = msg_ptr; png_ptr->fp = fp;
png_ptr->read_data_fn = png_default_read_data;
if (error_fn == NULL) png_ptr->write_data_fn = png_default_write_data;
{ #ifdef PNG_WRITE_FLUSH_SUPPORTED
png_ptr->error_fn = png_empty_error; png_ptr->output_flush_fn = png_default_flush;
} #endif
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 */
}

274
pngmem.c
View File

@ -1,13 +1,13 @@
/* pngmem.c - stub functions for memory allocation /* pngmem.c - stub functions for memory allocation
libpng 1.0 beta 2 - version 0.81 libpng 1.0 beta 2 - version 0.85
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
August 24, 1995 December 19, 1995
This file provides a location for all memory allocation. Users which This file provides a location for all memory allocation. Users which
need special memory handling are expected to modify the code in this file need special memory handling are expected to modify the code in this file
to meet their needs. See the instructions at each function. */ to meet their needs. See the instructions at each function. */
#define PNG_INTERNAL #define PNG_INTERNAL
@ -19,168 +19,28 @@
need to allocate exactly 64K, so whatever you call here must need to allocate exactly 64K, so whatever you call here must
have the ability to do that. */ have the ability to do that. */
/* Borland compilers have this habit of not giving you 64K chunks
that start on the segment in DOS mode. This has not been observed
in Windows, and of course it doesn't matter in 32 bit mode, as there
are no segments. Now libpng doesn't need that much memory normally,
but zlib does, so we have to normalize it, if necessary. It would be
better if zlib worked in less then 64K, but it doesn't, so we
have to deal with it. Truely, we are misusing farmalloc here,
as it is designed for use with huge pointers, which don't care
about segments. So we allocate a large amount of memory, and
divvy off segments when needed.
*/
#ifdef __TURBOC__
#ifndef __WIN32__
#ifndef __FLAT__
/* NUM_SEG is the number of segments allocated at once */ png_voidp
#define NUM_SEG 4 png_large_malloc(png_structp png_ptr, png_uint_32 size)
typedef struct borland_seg_struct
{ {
void *mem_ptr; png_voidp ret;
void *seg_ptr[NUM_SEG];
int seg_used[NUM_SEG];
int num_used;
} borland_seg;
borland_seg *save_array;
int num_save_array;
int max_save_array;
#endif
#endif
#endif
voidpf
png_large_malloc(png_structf *png_ptr, png_uint_32 size)
{
voidpf ret;
if (!png_ptr || !size) if (!png_ptr || !size)
return ((void *)0); return ((voidp)0);
#ifdef PNG_MAX_MALLOC_64K #ifdef PNG_MAX_MALLOC_64K
if (size > (png_uint_32)65536L) if (size > (png_uint_32)65536L)
(*(png_ptr->error_fn))(png_ptr, "Cannot Allocate > 64K"); png_error(png_ptr, "Cannot Allocate > 64K");
#endif #endif
#ifdef __TURBOC__ #if defined(__TURBOC__) && !defined(__FLAT__)
# if defined(__WIN32__) || defined(__FLAT__) ret = farmalloc(size);
ret = malloc(size); #else
# else ret = malloc(size);
if (size == 65536L)
{
unsigned long offset;
if (!save_array)
{
ret = farmalloc(size);
offset = (unsigned long)(ret);
offset &= 0xffffL;
}
else
{
ret = (void *)0;
}
if (save_array || offset)
{
int i, j;
if (ret)
farfree(ret);
ret = (void *)0;
if (!save_array)
{
unsigned long offset;
png_byte huge *ptr;
int i;
num_save_array = 1;
save_array = malloc(num_save_array * sizeof (borland_seg));
if (!save_array)
(*(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_ptr->error_fn))(png_ptr, "Out of Memory 2");
offset = (unsigned long)(ret);
offset &= 0xffffL;
ptr = save_array->mem_ptr;
if (offset)
ptr += 65536L - offset;
for (i = 0; i < NUM_SEG; i++, ptr += 65536L)
{
save_array->seg_ptr[i] = ptr;
save_array->seg_used[i] = 0;
}
save_array->num_used = 0;
}
for (i = 0; i < num_save_array; i++)
{
for (j = 0; j < NUM_SEG; j++)
{
if (!save_array[i].seg_used[j])
{
ret = save_array[i].seg_ptr[j];
save_array[i].seg_used[j] = 1;
save_array[i].num_used++;
break;
}
}
if (ret)
break;
}
if (!ret)
{
unsigned long offset;
png_byte huge *ptr;
save_array = realloc(save_array,
(num_save_array + 1) * sizeof (borland_seg));
if (!save_array)
(*(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_ptr->error_fn))(png_ptr, "Out of Memory 4");
offset = (unsigned long)(ret);
offset &= 0xffffL;
ptr = save_array[num_save_array].mem_ptr;
if (offset)
ptr += 65536L - offset;
for (i = 0; i < NUM_SEG; i++, ptr += 65536L)
{
save_array[num_save_array].seg_ptr[i] = ptr;
save_array[num_save_array].seg_used[i] = 0;
}
ret = save_array[num_save_array].seg_ptr[0];
save_array[num_save_array].seg_used[0] = 1;
save_array[num_save_array].num_used = 1;
num_save_array++;
}
}
}
else
{
ret = farmalloc(size);
}
# endif /* __WIN32__ */
#else /* __TURBOC__ */
# ifdef _MSC_VER
ret = halloc(size, 1);
# else
/* everybody else, so normal malloc should do it. */
ret = malloc(size);
# endif
#endif #endif
if (ret == NULL) if (ret == NULL)
{ {
(*(png_ptr->error_fn))(png_ptr, "Out of Memory"); png_error(png_ptr, "Out of Memory");
} }
return ret; return ret;
@ -190,124 +50,88 @@ png_large_malloc(png_structf *png_ptr, png_uint_32 size)
configuration, png_ptr is not used, but is passed in case it configuration, png_ptr is not used, but is passed in case it
is needed. If ptr is NULL, return without taking any action. */ is needed. If ptr is NULL, return without taking any action. */
void void
png_large_free(png_structf *png_ptr, voidpf ptr) png_large_free(png_structp png_ptr, png_voidp ptr)
{ {
if (!png_ptr) if (!png_ptr)
return; return;
if (ptr != (void *)0) if (ptr != NULL)
{ {
#ifdef __TURBOC__ #if defined(__TURBOC__) && !defined(__FLAT__)
# if defined(__WIN32__) || defined(__FLAT__) farfree(ptr);
if (ptr)
free(ptr);
# else
int i, j;
for (i = 0; i < num_save_array; i++)
{
for (j = 0; j < NUM_SEG; j++)
{
if (ptr == save_array[i].seg_ptr[j])
{
save_array[i].seg_used[j] = 0;
ptr = 0;
save_array[i].num_used--;
if (!save_array[i].num_used)
{
int k;
num_save_array--;
farfree(save_array[i].mem_ptr);
for (k = i; k < num_save_array; k++)
save_array[k] = save_array[k + 1];
if (!num_save_array)
{
free(save_array);
save_array = 0;
}
}
break;
}
}
if (!ptr)
break;
}
if (ptr)
farfree(ptr);
# endif
#else #else
# ifdef _MSC_VER free(ptr);
hfree(ptr);
# else
free(ptr);
# endif
#endif #endif
} }
} }
/* Allocate memory. This is called for smallish blocks only It /* Allocate memory. This is called for smallish blocks only It
should not get anywhere near 64K. */ should not get anywhere near 64K. On segmented machines, this
must come from the local heap (for zlib). */
void * void *
png_malloc(png_struct *png_ptr, png_uint_32 size) png_malloc(png_structp png_ptr, png_uint_32 size)
{ {
void *ret; void *ret;
if (!png_ptr || !size) if (!png_ptr || !size)
{
return ((void *)0); return ((void *)0);
}
#ifdef PNG_MAX_MALLOC_64K #ifdef PNG_MAX_MALLOC_64K
if (size > (png_uint_32)65536L) if (size > (png_uint_32)65536L)
(*(png_ptr->error_fn))(png_ptr, "Cannot Allocate > 64K"); png_error(png_ptr, "Cannot Allocate > 64K");
#endif #endif
ret = malloc((png_size_t)size); ret = malloc((png_size_t)size);
if (!ret) if (!ret)
{ {
(*(png_ptr->error_fn))(png_ptr, "Out of Memory 6"); png_error(png_ptr, "Out of Memory");
} }
return ret; return ret;
} }
/* Reallocate memory. This will not get near 64K on a /* Reallocate memory. This will not get near 64K on a
even marginally reasonable file. */ even marginally reasonable file. */
void * void *
png_realloc(png_struct *png_ptr, void *ptr, png_uint_32 size, png_realloc(png_structp png_ptr, void * ptr, png_uint_32 size,
png_uint_32 old_size) png_uint_32 old_size)
{ {
void *ret; void *ret;
if (!png_ptr || !old_size || !ptr || !size) if (!png_ptr || !old_size || !ptr || !size)
return ((void *)0); return ((void *)0);
#ifdef PNG_MAX_MALLOC_64K #ifdef PNG_MAX_MALLOC_64K
if (size > (png_uint_32)65536L) if (size > (png_uint_32)65536L)
(*(png_ptr->error_fn))(png_ptr, "Cannot Allocate > 64K"); png_error(png_ptr, "Cannot Allocate > 64K");
#endif #endif
ret = realloc(ptr, (png_size_t)size); ret = realloc(ptr, (png_size_t)size);
if (!ret) if (!ret)
{ {
(*(png_ptr->error_fn))(png_ptr, "Out of Memory 7"); png_error(png_ptr, "Out of Memory 7");
} }
return ret; return ret;
} }
/* free a pointer allocated by png_malloc(). In the default /* free a pointer allocated by png_malloc(). In the default
configuration, png_ptr is not used, but is passed incase it configuration, png_ptr is not used, but is passed incase it
is needed. If ptr is NULL, return without taking any action. */ is needed. If ptr is NULL, return without taking any action. */
void void
png_free(png_struct *png_ptr, void *ptr) png_free(png_structp png_ptr, void * ptr)
{ {
if (!png_ptr) if (!png_ptr)
return; return;
if (ptr != (void *)0) if (ptr != (void *)0)
free(ptr); free(ptr);
} }

1214
pngpread.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,16 @@
/* pngrcb.c - callbacks while reading a png file /* pngrcb.c - callbacks while reading a png file
libpng 1.0 beta 2 - version 0.81 libpng 1.0 beta 2 - version 0.85
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
August 24, 1995 December 19, 1995
*/ */
#define PNG_INTERNAL #define PNG_INTERNAL
#include "png.h" #include "png.h"
void void
png_read_IHDR(png_struct *png_ptr, png_info *info, png_read_IHDR(png_structp png_ptr, png_infop info,
png_uint_32 width, png_uint_32 height, int bit_depth, png_uint_32 width, png_uint_32 height, int bit_depth,
int color_type, int compression_type, int filter_type, int color_type, int compression_type, int filter_type,
int interlace_type) int interlace_type)
@ -24,7 +24,7 @@ png_read_IHDR(png_struct *png_ptr, png_info *info,
info->color_type = color_type; info->color_type = color_type;
info->compression_type = compression_type; info->compression_type = compression_type;
info->filter_type = filter_type; info->filter_type = filter_type;
info->interlace_type = interlace_type; info->interlace_type = interlace_type;
if (info->color_type == PNG_COLOR_TYPE_PALETTE) if (info->color_type == PNG_COLOR_TYPE_PALETTE)
info->channels = 1; info->channels = 1;
else if (info->color_type & PNG_COLOR_MASK_COLOR) else if (info->color_type & PNG_COLOR_MASK_COLOR)
@ -38,8 +38,8 @@ png_read_IHDR(png_struct *png_ptr, png_info *info,
} }
void void
png_read_PLTE(png_struct *png_ptr, png_info *info, png_read_PLTE(png_structp png_ptr, png_infop info,
png_color *palette, int num) png_colorp palette, int num)
{ {
if (!png_ptr || !info) if (!png_ptr || !info)
return; return;
@ -51,7 +51,7 @@ png_read_PLTE(png_struct *png_ptr, png_info *info,
#if defined(PNG_READ_gAMA_SUPPORTED) #if defined(PNG_READ_gAMA_SUPPORTED)
void void
png_read_gAMA(png_struct *png_ptr, png_info *info, float gamma) png_read_gAMA(png_structp png_ptr, png_infop info, double gamma)
{ {
if (!png_ptr || !info) if (!png_ptr || !info)
return; return;
@ -63,22 +63,22 @@ png_read_gAMA(png_struct *png_ptr, png_info *info, float gamma)
#if defined(PNG_READ_sBIT_SUPPORTED) #if defined(PNG_READ_sBIT_SUPPORTED)
void void
png_read_sBIT(png_struct *png_ptr, png_info *info, png_read_sBIT(png_structp png_ptr, png_infop info,
png_color_8 *sig_bit) png_color_8p sig_bit)
{ {
if (!png_ptr || !info) if (!png_ptr || !info)
return; return;
memcpy(&(info->sig_bit), sig_bit, sizeof (png_color_8)); png_memcpy(&(info->sig_bit), sig_bit, sizeof (png_color_8));
info->valid |= PNG_INFO_sBIT; info->valid |= PNG_INFO_sBIT;
} }
#endif #endif
#if defined(PNG_READ_cHRM_SUPPORTED) #if defined(PNG_READ_cHRM_SUPPORTED)
void void
png_read_cHRM(png_struct *png_ptr, png_info *info, png_read_cHRM(png_structp png_ptr, png_infop info,
float white_x, float white_y, float red_x, float red_y, double white_x, double white_y, double red_x, double red_y,
float green_x, float green_y, float blue_x, float blue_y) double green_x, double green_y, double blue_x, double blue_y)
{ {
if (!png_ptr || !info) if (!png_ptr || !info)
return; return;
@ -97,8 +97,8 @@ png_read_cHRM(png_struct *png_ptr, png_info *info,
#if defined(PNG_READ_tRNS_SUPPORTED) #if defined(PNG_READ_tRNS_SUPPORTED)
void void
png_read_tRNS(png_struct *png_ptr, png_info *info, png_read_tRNS(png_structp png_ptr, png_infop info,
png_byte *trans, int num_trans, png_color_16 *trans_values) png_bytep trans, int num_trans, png_color_16p trans_values)
{ {
if (!png_ptr || !info) if (!png_ptr || !info)
return; return;
@ -109,7 +109,7 @@ png_read_tRNS(png_struct *png_ptr, png_info *info,
} }
else else
{ {
memcpy(&(info->trans_values), trans_values, png_memcpy(&(info->trans_values), trans_values,
sizeof(png_color_16)); sizeof(png_color_16));
} }
info->num_trans = num_trans; info->num_trans = num_trans;
@ -119,20 +119,20 @@ png_read_tRNS(png_struct *png_ptr, png_info *info,
#if defined(PNG_READ_bKGD_SUPPORTED) #if defined(PNG_READ_bKGD_SUPPORTED)
void void
png_read_bKGD(png_struct *png_ptr, png_info *info, png_read_bKGD(png_structp png_ptr, png_infop info,
png_color_16 *background) png_color_16p background)
{ {
if (!png_ptr || !info) if (!png_ptr || !info)
return; return;
memcpy(&(info->background), background, sizeof(png_color_16)); png_memcpy(&(info->background), background, sizeof(png_color_16));
info->valid |= PNG_INFO_bKGD; info->valid |= PNG_INFO_bKGD;
} }
#endif #endif
#if defined(PNG_READ_hIST_SUPPORTED) #if defined(PNG_READ_hIST_SUPPORTED)
void void
png_read_hIST(png_struct *png_ptr, png_info *info, png_uint_16 *hist) png_read_hIST(png_structp png_ptr, png_infop info, png_uint_16p hist)
{ {
if (!png_ptr || !info) if (!png_ptr || !info)
return; return;
@ -144,7 +144,7 @@ png_read_hIST(png_struct *png_ptr, png_info *info, png_uint_16 *hist)
#if defined(PNG_READ_pHYs_SUPPORTED) #if defined(PNG_READ_pHYs_SUPPORTED)
void void
png_read_pHYs(png_struct *png_ptr, png_info *info, png_read_pHYs(png_structp png_ptr, png_infop info,
png_uint_32 res_x, png_uint_32 res_y, int unit_type) png_uint_32 res_x, png_uint_32 res_y, int unit_type)
{ {
if (!png_ptr || !info) if (!png_ptr || !info)
@ -159,7 +159,7 @@ png_read_pHYs(png_struct *png_ptr, png_info *info,
#if defined(PNG_READ_oFFs_SUPPORTED) #if defined(PNG_READ_oFFs_SUPPORTED)
void void
png_read_oFFs(png_struct *png_ptr, png_info *info, png_read_oFFs(png_structp png_ptr, png_infop info,
png_uint_32 offset_x, png_uint_32 offset_y, int unit_type) png_uint_32 offset_x, png_uint_32 offset_y, int unit_type)
{ {
if (!png_ptr || !info) if (!png_ptr || !info)
@ -174,26 +174,26 @@ png_read_oFFs(png_struct *png_ptr, png_info *info,
#if defined(PNG_READ_tIME_SUPPORTED) #if defined(PNG_READ_tIME_SUPPORTED)
void void
png_read_tIME(png_struct *png_ptr, png_info *info, png_read_tIME(png_structp png_ptr, png_infop info,
png_time *mod_time) png_timep mod_time)
{ {
if (!png_ptr || !info) if (!png_ptr || !info)
return; return;
memcpy(&(info->mod_time), mod_time, sizeof (png_time)); png_memcpy(&(info->mod_time), mod_time, sizeof (png_time));
info->valid |= PNG_INFO_tIME; info->valid |= PNG_INFO_tIME;
} }
#endif #endif
#if defined(PNG_READ_zTXt_SUPPORTED) #if defined(PNG_READ_zTXt_SUPPORTED)
void void
png_read_zTXt(png_struct *png_ptr, png_info *info, png_read_zTXt(png_structp png_ptr, png_infop info,
charf *key, charf *text, png_uint_32 text_len, int compression) png_charp key, png_charp text, png_uint_32 text_len, int compression)
{ {
if (!png_ptr || !info) if (!png_ptr || !info)
return; return;
if (info->max_text <= info->num_text) if (info->max_text <= info->num_text)
{ {
if (info->text) if (info->text)
{ {
@ -201,15 +201,15 @@ png_read_zTXt(png_struct *png_ptr, png_info *info,
old_max = info->max_text; old_max = info->max_text;
info->max_text = info->num_text + 16; info->max_text = info->num_text + 16;
info->text = (png_text *)png_realloc(png_ptr, info->text = (png_textp)png_realloc(png_ptr,
info->text, info->text,
info->max_text * sizeof (png_text), info->max_text * sizeof (png_text),
old_max * sizeof (png_text)); old_max * sizeof (png_text));
} }
else else
{ {
info->max_text = info->num_text + 16; info->max_text = info->num_text + 16;
info->text = (png_text *)png_malloc(png_ptr, info->text = (png_textp)png_malloc(png_ptr,
info->max_text * sizeof (png_text)); info->max_text * sizeof (png_text));
info->num_text = 0; info->num_text = 0;
} }
@ -225,13 +225,13 @@ png_read_zTXt(png_struct *png_ptr, png_info *info,
#if defined(PNG_READ_tEXt_SUPPORTED) #if defined(PNG_READ_tEXt_SUPPORTED)
void void
png_read_tEXt(png_struct *png_ptr, png_info *info, png_read_tEXt(png_structp png_ptr, png_infop info,
charf *key, charf *text, png_uint_32 text_len) png_charp key, png_charp text, png_uint_32 text_len)
{ {
if (!png_ptr || !info) if (!png_ptr || !info)
return; return;
png_read_zTXt(png_ptr, info, key, text, text_len, -1); png_read_zTXt(png_ptr, info, key, text, text_len, -1);
} }
#endif #endif

346
pngread.c
View File

@ -1,10 +1,10 @@
/* pngread.c - read a png file /* pngread.c - read a png file
libpng 1.0 beta 2 - version 0.81 libpng 1.0 beta 2 - version 0.85
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
August 24, 1995 December 19, 1995
*/ */
#define PNG_INTERNAL #define PNG_INTERNAL
@ -12,56 +12,67 @@
/* initialize png structure for reading, and allocate any memory needed */ /* initialize png structure for reading, and allocate any memory needed */
void void
png_read_init(png_struct *png_ptr) png_read_init(png_structp png_ptr)
{ {
jmp_buf tmp_jmp; jmp_buf tmp_jmp;
png_msg_ptr error_fn;
png_msg_ptr warning_fn;
png_voidp msg_ptr;
png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf)); png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
png_memset(png_ptr, 0, sizeof (png_struct)); error_fn = png_ptr->error_fn;
png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf)); warning_fn = png_ptr->warning_fn;
msg_ptr = png_ptr->msg_ptr;
png_memset(png_ptr, 0, sizeof (png_struct));
png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
png_ptr->error_fn = error_fn;
png_ptr->warning_fn = warning_fn;
png_ptr->msg_ptr = msg_ptr;
png_ptr->zbuf_size = PNG_ZBUF_SIZE; png_ptr->zbuf_size = PNG_ZBUF_SIZE;
png_ptr->zbuf = png_large_malloc(png_ptr, png_ptr->zbuf_size); png_ptr->zbuf = png_large_malloc(png_ptr, png_ptr->zbuf_size);
png_ptr->zstream = &(png_ptr->zstream_struct); png_ptr->zstream = (z_stream *)png_malloc(png_ptr, sizeof (z_stream));
png_ptr->zstream->zalloc = png_zalloc; png_ptr->zstream->zalloc = png_zalloc;
png_ptr->zstream->zfree = png_zfree; png_ptr->zstream->zfree = png_zfree;
png_ptr->zstream->opaque = (voidp)png_ptr; png_ptr->zstream->opaque = (voidp)png_ptr;
inflateInit(png_ptr->zstream); inflateInit(png_ptr->zstream);
png_ptr->zstream->next_out = png_ptr->zbuf; png_ptr->zstream->next_out = png_ptr->zbuf;
png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size; png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
} }
/* read the information before the actual image data. */ /* read the information before the actual image data. */
void void
png_read_info(png_struct *png_ptr, png_info *info) png_read_info(png_structp png_ptr, png_infop info)
{ {
png_byte chunk_start[8]; png_byte chunk_start[8];
png_uint_32 length; png_uint_32 length;
(*(png_ptr->read_data_fn))(png_ptr, chunk_start, 8); png_read_data(png_ptr, chunk_start, 8);
if (memcmp(chunk_start, png_sig, 8)) if (png_memcmp(chunk_start, png_sig, 8))
(*(png_ptr->error_fn))(png_ptr, "Not a PNG File"); png_error(png_ptr, "Not a Png File");
while (1) while (1)
{ {
png_uint_32 crc; png_uint_32 crc;
(*(png_ptr->read_data_fn))(png_ptr, chunk_start, 8); png_read_data(png_ptr, chunk_start, 8);
length = png_get_uint_32(chunk_start); length = png_get_uint_32(chunk_start);
png_reset_crc(png_ptr); png_reset_crc(png_ptr);
png_calculate_crc(png_ptr, chunk_start + 4, 4); png_calculate_crc(png_ptr, chunk_start + 4, 4);
if (!memcmp(chunk_start + 4, png_IHDR, 4)) if (!png_memcmp(chunk_start + 4, png_IHDR, 4))
{ {
if (png_ptr->mode != PNG_BEFORE_IHDR) if (png_ptr->mode != PNG_BEFORE_IHDR)
(*(png_ptr->error_fn))(png_ptr, "Out of Place IHDR"); png_error(png_ptr, "Out of Place IHDR");
png_handle_IHDR(png_ptr, info, length); png_handle_IHDR(png_ptr, info, length);
png_ptr->mode = PNG_HAVE_IHDR; png_ptr->mode = PNG_HAVE_IHDR;
} }
else if (!memcmp(chunk_start + 4, png_PLTE, 4)) else if (!png_memcmp(chunk_start + 4, png_PLTE, 4))
{ {
if (png_ptr->mode != PNG_HAVE_IHDR) if (png_ptr->mode != PNG_HAVE_IHDR)
(*(png_ptr->error_fn))(png_ptr, "Missing IHDR"); png_error(png_ptr, "Missing IHDR");
#if !defined(PNG_READ_OPT_PLTE_SUPPORTED) #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
@ -70,122 +81,122 @@ png_read_info(png_struct *png_ptr, png_info *info)
#else #else
{ {
png_handle_PLTE(png_ptr, info, length); png_handle_PLTE(png_ptr, info, length);
} }
#endif #endif
png_ptr->mode = PNG_HAVE_PLTE; png_ptr->mode = PNG_HAVE_PLTE;
} }
else if (!memcmp(chunk_start + 4, png_IDAT, 4)) else if (!png_memcmp(chunk_start + 4, png_IDAT, 4))
{ {
png_ptr->idat_size = length; png_ptr->idat_size = length;
png_ptr->mode = PNG_HAVE_IDAT; png_ptr->mode = PNG_HAVE_IDAT;
break; break;
} }
else if (!memcmp(chunk_start + 4, png_IEND, 4)) else if (!png_memcmp(chunk_start + 4, png_IEND, 4))
{ {
(*(png_ptr->error_fn))(png_ptr, "No Image in File"); png_error(png_ptr, "No Image in File");
} }
#if defined(PNG_READ_gAMA_SUPPORTED) #if defined(PNG_READ_gAMA_SUPPORTED)
else if (!memcmp(chunk_start + 4, png_gAMA, 4)) else if (!png_memcmp(chunk_start + 4, png_gAMA, 4))
{ {
if (png_ptr->mode != PNG_HAVE_IHDR) if (png_ptr->mode != PNG_HAVE_IHDR)
(*(png_ptr->error_fn))(png_ptr, "Out of Place PLTE"); png_error(png_ptr, "Out of Place PLTE");
png_handle_gAMA(png_ptr, info, length); png_handle_gAMA(png_ptr, info, length);
} }
#endif #endif
#if defined(PNG_READ_sBIT_SUPPORTED) #if defined(PNG_READ_sBIT_SUPPORTED)
else if (!memcmp(chunk_start + 4, png_sBIT, 4)) else if (!png_memcmp(chunk_start + 4, png_sBIT, 4))
{ {
if (png_ptr->mode != PNG_HAVE_IHDR) if (png_ptr->mode != PNG_HAVE_IHDR)
(*(png_ptr->error_fn))(png_ptr, "Out of Place sBIT"); png_error(png_ptr, "Out of Place sBIT");
png_handle_sBIT(png_ptr, info, length); png_handle_sBIT(png_ptr, info, length);
} }
#endif #endif
#if defined(PNG_READ_cHRM_SUPPORTED) #if defined(PNG_READ_cHRM_SUPPORTED)
else if (!memcmp(chunk_start + 4, png_cHRM, 4)) else if (!png_memcmp(chunk_start + 4, png_cHRM, 4))
{ {
if (png_ptr->mode != PNG_HAVE_IHDR) if (png_ptr->mode != PNG_HAVE_IHDR)
(*(png_ptr->error_fn))(png_ptr, "Out of Place cHRM"); png_error(png_ptr, "Out of Place cHRM");
png_handle_cHRM(png_ptr, info, length); png_handle_cHRM(png_ptr, info, length);
} }
#endif #endif
#if defined(PNG_READ_tRNS_SUPPORTED) #if defined(PNG_READ_tRNS_SUPPORTED)
else if (!memcmp(chunk_start + 4, png_tRNS, 4)) else if (!png_memcmp(chunk_start + 4, png_tRNS, 4))
{ {
if (png_ptr->mode != PNG_HAVE_IHDR && if (png_ptr->mode != PNG_HAVE_IHDR &&
png_ptr->mode != PNG_HAVE_PLTE) png_ptr->mode != PNG_HAVE_PLTE)
(*(png_ptr->error_fn))(png_ptr, "Out of Place tRNS"); png_error(png_ptr, "Out of Place tRNS");
png_handle_tRNS(png_ptr, info, length); png_handle_tRNS(png_ptr, info, length);
} }
#endif #endif
#if defined(PNG_READ_bKGD_SUPPORTED) #if defined(PNG_READ_bKGD_SUPPORTED)
else if (!memcmp(chunk_start + 4, png_bKGD, 4)) else if (!png_memcmp(chunk_start + 4, png_bKGD, 4))
{ {
if (png_ptr->mode != PNG_HAVE_IHDR && if (png_ptr->mode != PNG_HAVE_IHDR &&
png_ptr->mode != PNG_HAVE_PLTE) png_ptr->mode != PNG_HAVE_PLTE)
(*(png_ptr->error_fn))(png_ptr, "Out of Place bKGD"); png_error(png_ptr, "Out of Place bKGD");
png_handle_bKGD(png_ptr, info, length); png_handle_bKGD(png_ptr, info, length);
} }
#endif #endif
#if defined(PNG_READ_hIST_SUPPORTED) #if defined(PNG_READ_hIST_SUPPORTED)
else if (!memcmp(chunk_start + 4, png_hIST, 4)) else if (!png_memcmp(chunk_start + 4, png_hIST, 4))
{ {
if (png_ptr->mode != PNG_HAVE_PLTE) if (png_ptr->mode != PNG_HAVE_PLTE)
(*(png_ptr->error_fn))(png_ptr, "Out of Place hIST"); png_error(png_ptr, "Out of Place hIST");
png_handle_hIST(png_ptr, info, length); png_handle_hIST(png_ptr, info, length);
} }
#endif #endif
#if defined(PNG_READ_pHYs_SUPPORTED) #if defined(PNG_READ_pHYs_SUPPORTED)
else if (!memcmp(chunk_start + 4, png_pHYs, 4)) else if (!png_memcmp(chunk_start + 4, png_pHYs, 4))
{ {
if (png_ptr->mode != PNG_HAVE_IHDR && if (png_ptr->mode != PNG_HAVE_IHDR &&
png_ptr->mode != PNG_HAVE_PLTE) png_ptr->mode != PNG_HAVE_PLTE)
(*(png_ptr->error_fn))(png_ptr, "Out of Place pHYs"); png_error(png_ptr, "Out of Place pHYs");
png_handle_pHYs(png_ptr, info, length); png_handle_pHYs(png_ptr, info, length);
} }
#endif #endif
#if defined(PNG_READ_oFFs_SUPPORTED) #if defined(PNG_READ_oFFs_SUPPORTED)
else if (!memcmp(chunk_start + 4, png_oFFs, 4)) else if (!png_memcmp(chunk_start + 4, png_oFFs, 4))
{ {
if (png_ptr->mode != PNG_HAVE_IHDR && if (png_ptr->mode != PNG_HAVE_IHDR &&
png_ptr->mode != PNG_HAVE_PLTE) png_ptr->mode != PNG_HAVE_PLTE)
(*(png_ptr->error_fn))(png_ptr, "Out of Place oFFs"); png_error(png_ptr, "Out of Place oFFs");
png_handle_oFFs(png_ptr, info, length); png_handle_oFFs(png_ptr, info, length);
} }
#endif #endif
#if defined(PNG_READ_tIME_SUPPORTED) #if defined(PNG_READ_tIME_SUPPORTED)
else if (!memcmp(chunk_start + 4, png_tIME, 4)) else if (!png_memcmp(chunk_start + 4, png_tIME, 4))
{ {
if (png_ptr->mode == PNG_BEFORE_IHDR || if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND) png_ptr->mode == PNG_AFTER_IEND)
(*(png_ptr->error_fn))(png_ptr, "Out of Place tIME"); png_error(png_ptr, "Out of Place tIME");
png_handle_tIME(png_ptr, info, length); png_handle_tIME(png_ptr, info, length);
} }
#endif #endif
#if defined(PNG_READ_tEXt_SUPPORTED) #if defined(PNG_READ_tEXt_SUPPORTED)
else if (!memcmp(chunk_start + 4, png_tEXt, 4)) else if (!png_memcmp(chunk_start + 4, png_tEXt, 4))
{ {
if (png_ptr->mode == PNG_BEFORE_IHDR || if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND) png_ptr->mode == PNG_AFTER_IEND)
(*(png_ptr->error_fn))(png_ptr, "Out of Place tEXt"); png_error(png_ptr, "Out of Place tEXt");
png_handle_tEXt(png_ptr, info, length); png_handle_tEXt(png_ptr, info, length);
} }
#endif #endif
#if defined(PNG_READ_zTXt_SUPPORTED) #if defined(PNG_READ_zTXt_SUPPORTED)
else if (!memcmp(chunk_start + 4, png_zTXt, 4)) else if (!png_memcmp(chunk_start + 4, png_zTXt, 4))
{ {
if (png_ptr->mode == PNG_BEFORE_IHDR || if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND) png_ptr->mode == PNG_AFTER_IEND)
(*(png_ptr->error_fn))(png_ptr, "Out of Place zTXt"); png_error(png_ptr, "Out of Place zTXt");
png_handle_zTXt(png_ptr, info, length); png_handle_zTXt(png_ptr, info, length);
} }
@ -193,21 +204,21 @@ png_read_info(png_struct *png_ptr, png_info *info)
else else
{ {
if ((chunk_start[4] & 0x20) == 0) if ((chunk_start[4] & 0x20) == 0)
(*(png_ptr->error_fn))(png_ptr, "Unknown Critical Chunk"); png_error(png_ptr, "Unknown Critical Chunk");
png_crc_skip(png_ptr, length); png_crc_skip(png_ptr, length);
} }
(*(png_ptr->read_data_fn))(png_ptr, chunk_start, 4); png_read_data(png_ptr, chunk_start, 4);
crc = png_get_uint_32(chunk_start); crc = png_get_uint_32(chunk_start);
if (((crc ^ 0xffffffffL) & 0xffffffffL) != if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
(png_ptr->crc & 0xffffffffL)) (png_ptr->crc & 0xffffffffL))
(*(png_ptr->error_fn))(png_ptr, "Bad CRC value"); png_error(png_ptr, "Bad CRC value");
} }
} }
/* optional call to update the users info structure */ /* optional call to update the users info structure */
void void
png_read_update_info(png_struct *png_ptr, png_info *info_ptr) png_read_update_info(png_structp png_ptr, png_infop info_ptr)
{ {
if (!(png_ptr->row_init)) if (!(png_ptr->row_init))
png_read_start_row(png_ptr); png_read_start_row(png_ptr);
@ -219,14 +230,14 @@ png_read_update_info(png_struct *png_ptr, png_info *info_ptr)
the user to obtail a gamma corrected palette, for example. the user to obtail a gamma corrected palette, for example.
If the user doesn't call this, we will do it ourselves. */ If the user doesn't call this, we will do it ourselves. */
void void
png_start_read_image(png_struct *png_ptr) png_start_read_image(png_structp png_ptr)
{ {
if (!(png_ptr->row_init)) if (!(png_ptr->row_init))
png_read_start_row(png_ptr); png_read_start_row(png_ptr);
} }
void void
png_read_row(png_struct *png_ptr, png_bytef *row, png_byte *dsp_row) png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
{ {
int ret; int ret;
if (!(png_ptr->row_init)) if (!(png_ptr->row_init))
@ -244,7 +255,7 @@ png_read_row(png_struct *png_ptr, png_bytef *row, png_byte *dsp_row)
if (dsp_row) if (dsp_row)
png_combine_row(png_ptr, dsp_row, png_combine_row(png_ptr, dsp_row,
png_pass_dsp_mask[png_ptr->pass]); png_pass_dsp_mask[png_ptr->pass]);
png_read_finish_row(png_ptr); png_read_finish_row(png_ptr);
return; return;
} }
break; break;
@ -262,7 +273,7 @@ png_read_row(png_struct *png_ptr, png_bytef *row, png_byte *dsp_row)
if ((png_ptr->row_number & 7) != 4) if ((png_ptr->row_number & 7) != 4)
{ {
if (dsp_row && (png_ptr->row_number & 4)) if (dsp_row && (png_ptr->row_number & 4))
png_combine_row(png_ptr, dsp_row, png_combine_row(png_ptr, dsp_row,
png_pass_dsp_mask[png_ptr->pass]); png_pass_dsp_mask[png_ptr->pass]);
png_read_finish_row(png_ptr); png_read_finish_row(png_ptr);
return; return;
@ -280,7 +291,7 @@ png_read_row(png_struct *png_ptr, png_bytef *row, png_byte *dsp_row)
break; break;
case 4: case 4:
if ((png_ptr->row_number & 3) != 2) if ((png_ptr->row_number & 3) != 2)
{ {
if (dsp_row && (png_ptr->row_number & 2)) if (dsp_row && (png_ptr->row_number & 2))
png_combine_row(png_ptr, dsp_row, png_combine_row(png_ptr, dsp_row,
png_pass_dsp_mask[png_ptr->pass]); png_pass_dsp_mask[png_ptr->pass]);
@ -298,7 +309,7 @@ png_read_row(png_struct *png_ptr, png_bytef *row, png_byte *dsp_row)
return; return;
} }
break; break;
case 6: case 6:
if (!(png_ptr->row_number & 1)) if (!(png_ptr->row_number & 1))
{ {
png_read_finish_row(png_ptr); png_read_finish_row(png_ptr);
@ -310,32 +321,32 @@ png_read_row(png_struct *png_ptr, png_bytef *row, png_byte *dsp_row)
#endif #endif
if (png_ptr->mode != PNG_HAVE_IDAT) if (png_ptr->mode != PNG_HAVE_IDAT)
(*(png_ptr->error_fn))(png_ptr, "Invalid attempt to read row data"); png_error(png_ptr, "invalid attempt to read row data");
png_ptr->zstream->next_out = png_ptr->row_buf; png_ptr->zstream->next_out = png_ptr->row_buf;
png_ptr->zstream->avail_out = (uInt)png_ptr->irowbytes; png_ptr->zstream->avail_out = (uInt)png_ptr->irowbytes;
do do
{ {
if (!(png_ptr->zstream->avail_in)) if (!(png_ptr->zstream->avail_in))
{ {
while (!png_ptr->idat_size) while (!png_ptr->idat_size)
{ {
png_byte buf[4]; png_byte buf[4];
png_uint_32 crc; png_uint_32 crc;
(*(png_ptr->read_data_fn))(png_ptr, buf, 4); png_read_data(png_ptr, buf, 4);
crc = png_get_uint_32(buf); crc = png_get_uint_32(buf);
if (((crc ^ 0xffffffffL) & 0xffffffffL) != if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
(png_ptr->crc & 0xffffffffL)) (png_ptr->crc & 0xffffffffL))
(*(png_ptr->error_fn))(png_ptr, "Bad CRC value"); png_error(png_ptr, "Bad CRC value");
(*(png_ptr->read_data_fn))(png_ptr, buf, 4); png_read_data(png_ptr, buf, 4);
png_ptr->idat_size = png_get_uint_32(buf); png_ptr->idat_size = png_get_uint_32(buf);
png_reset_crc(png_ptr); png_reset_crc(png_ptr);
png_crc_read(png_ptr, buf, 4); png_crc_read(png_ptr, buf, 4);
if (memcmp(buf, png_IDAT, 4)) if (png_memcmp(buf, png_IDAT, 4))
(*(png_ptr->error_fn))(png_ptr, "Not enough image data"); png_error(png_ptr, "Not enough image data");
} }
png_ptr->zstream->avail_in = (uInt)png_ptr->zbuf_size; png_ptr->zstream->avail_in = (uInt)png_ptr->zbuf_size;
@ -345,17 +356,17 @@ png_read_row(png_struct *png_ptr, png_bytef *row, png_byte *dsp_row)
png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream->avail_in); png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream->avail_in);
png_ptr->idat_size -= png_ptr->zstream->avail_in; png_ptr->idat_size -= png_ptr->zstream->avail_in;
} }
ret = inflate(png_ptr->zstream, Z_PARTIAL_FLUSH); ret = inflate(png_ptr->zstream, Z_PARTIAL_FLUSH);
if (ret == Z_STREAM_END) if (ret == Z_STREAM_END)
{ {
if (png_ptr->zstream->avail_out || png_ptr->zstream->avail_in || if (png_ptr->zstream->avail_out || png_ptr->zstream->avail_in ||
png_ptr->idat_size) png_ptr->idat_size)
(*(png_ptr->warning_fn))(png_ptr, "Extra compressed data"); png_error(png_ptr, "Extra compressed data");
png_ptr->mode = PNG_AT_LAST_IDAT; png_ptr->mode = PNG_AT_LAST_IDAT;
break; break;
} }
if (ret != Z_OK) if (ret != Z_OK)
(*(png_ptr->error_fn))(png_ptr, "Compression Error"); png_error(png_ptr, "Compression Error");
} while (png_ptr->zstream->avail_out); } while (png_ptr->zstream->avail_out);
@ -370,7 +381,7 @@ png_read_row(png_struct *png_ptr, png_bytef *row, png_byte *dsp_row)
png_ptr->row_info.rowbytes = ((png_ptr->row_info.width * png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
(png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3); (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
if (png_ptr->row_buf[0]) if (png_ptr->row_buf[0])
png_read_filter_row(&(png_ptr->row_info), png_read_filter_row(&(png_ptr->row_info),
png_ptr->row_buf + 1, png_ptr->prev_row + 1, png_ptr->row_buf + 1, png_ptr->prev_row + 1,
(int)(png_ptr->row_buf[0])); (int)(png_ptr->row_buf[0]));
@ -410,7 +421,7 @@ png_read_row(png_struct *png_ptr, png_bytef *row, png_byte *dsp_row)
/* read a one or more rows of image data. If the image is interlaced, /* read a one or more rows of image data. If the image is interlaced,
and png_set_interlace_handling() has been called, the rows need to and png_set_interlace_handling() has been called, the rows need to
to contain the contents of the rows from the previous pass. If to contain the contents of the rows from the previous pass. If
the image has alpha or transparency, and png_handle_alpha() has been the image has alpha or transparency, and png_handle_alpha() has been
called, the rows contents must be initialized to the contents of the called, the rows contents must be initialized to the contents of the
screen. row holds the actual image, and pixels are placed in it screen. row holds the actual image, and pixels are placed in it
as they arrive. If the image is displayed after each pass, it will as they arrive. If the image is displayed after each pass, it will
@ -424,21 +435,22 @@ png_read_row(png_struct *png_ptr, png_bytef *row, png_byte *dsp_row)
rows. In this case, you do not have to provide a display_rows buffer rows. In this case, you do not have to provide a display_rows buffer
also, but you may. If the image is not interlaced, or if you have also, but you may. If the image is not interlaced, or if you have
not called png_set_interlace_handling(), the display_row buffer will not called png_set_interlace_handling(), the display_row buffer will
be ignored, so pass NULL to it. */ be ignored, so pass NULL to it. */
void void
png_read_rows(png_struct *png_ptr, png_bytef **row, png_read_rows(png_structp png_ptr, png_bytepp row,
png_byte **display_row, png_uint_32 num_rows) png_bytepp display_row, png_uint_32 num_rows)
{ {
png_uint_32 i; png_uint_32 i;
png_bytef **rp; png_bytepp rp;
png_byte **dp; png_bytepp dp;
rp = row; rp = row;
dp = display_row; dp = display_row;
for (i = 0; i < num_rows; i++) for (i = 0; i < num_rows; i++)
{ {
png_bytef *rptr; png_bytep rptr;
png_byte *dptr; png_bytep dptr;
if (rp) if (rp)
rptr = *rp; rptr = *rp;
@ -448,10 +460,9 @@ png_read_rows(png_struct *png_ptr, png_bytef **row,
dptr = *dp; dptr = *dp;
else else
dptr = NULL; dptr = NULL;
png_read_row(png_ptr, rptr, dptr); png_read_row(png_ptr, rptr, dptr);
if (row) if (row)
rp++; rp++;
if (display_row) if (display_row)
dp++; dp++;
} }
@ -464,11 +475,11 @@ png_read_rows(png_struct *png_ptr, png_bytef **row,
You only need to call this function once. If you desire to have You only need to call this function once. If you desire to have
an image for each pass of a interlaced image, use png_read_rows() */ an image for each pass of a interlaced image, use png_read_rows() */
void void
png_read_image(png_struct *png_ptr, png_bytef **image) png_read_image(png_structp png_ptr, png_bytepp image)
{ {
png_uint_32 i; png_uint_32 i;
int pass, j; int pass, j;
png_bytef **rp; png_bytepp rp;
pass = png_set_interlace_handling(png_ptr); pass = png_set_interlace_handling(png_ptr);
for (j = 0; j < pass; j++) for (j = 0; j < pass; j++)
@ -486,89 +497,89 @@ png_read_image(png_struct *png_ptr, png_bytef **image)
file, will verify the end is accurate, and will read any comments file, will verify the end is accurate, and will read any comments
or time information at the end of the file, if info is not NULL. */ or time information at the end of the file, if info is not NULL. */
void void
png_read_end(png_struct *png_ptr, png_info *info) png_read_end(png_structp png_ptr, png_infop info)
{ {
png_byte chunk_start[8]; png_byte chunk_start[8];
png_uint_32 length; png_uint_32 length;
png_uint_32 crc; png_uint_32 crc;
(*(png_ptr->read_data_fn))(png_ptr, chunk_start, 4); png_read_data(png_ptr, chunk_start, 4);
crc = png_get_uint_32(chunk_start); crc = png_get_uint_32(chunk_start);
if (((crc ^ 0xffffffffL) & 0xffffffffL) != if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
(png_ptr->crc & 0xffffffffL)) (png_ptr->crc & 0xffffffffL))
(*(png_ptr->error_fn))(png_ptr, "Bad CRC value"); png_error(png_ptr, "Bad CRC value");
do do
{ {
(*(png_ptr->read_data_fn))(png_ptr, chunk_start, 8); png_read_data(png_ptr, chunk_start, 8);
length = png_get_uint_32(chunk_start); length = png_get_uint_32(chunk_start);
png_reset_crc(png_ptr); png_reset_crc(png_ptr);
png_calculate_crc(png_ptr, chunk_start + 4, 4); png_calculate_crc(png_ptr, chunk_start + 4, 4);
if (!memcmp(chunk_start + 4, png_IHDR, 4)) if (!png_memcmp(chunk_start + 4, png_IHDR, 4))
{ {
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT"); png_error(png_ptr, "invalid chunk after IDAT");
} }
else if (!memcmp(chunk_start + 4, png_PLTE, 4)) else if (!png_memcmp(chunk_start + 4, png_PLTE, 4))
{ {
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT"); png_error(png_ptr, "invalid chunk after IDAT");
} }
else if (!memcmp(chunk_start + 4, png_gAMA, 4)) else if (!png_memcmp(chunk_start + 4, png_gAMA, 4))
{ {
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT"); png_error(png_ptr, "invalid chunk after IDAT");
} }
else if (!memcmp(chunk_start + 4, png_sBIT, 4)) else if (!png_memcmp(chunk_start + 4, png_sBIT, 4))
{ {
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT"); png_error(png_ptr, "invalid chunk after IDAT");
} }
else if (!memcmp(chunk_start + 4, png_cHRM, 4)) else if (!png_memcmp(chunk_start + 4, png_cHRM, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
}
else if (!png_memcmp(chunk_start + 4, png_tRNS, 4))
{ {
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT"); png_error(png_ptr, "invalid chunk after IDAT");
} }
else if (!memcmp(chunk_start + 4, png_tRNS, 4)) else if (!png_memcmp(chunk_start + 4, png_bKGD, 4))
{ {
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT"); png_error(png_ptr, "invalid chunk after IDAT");
} }
else if (!memcmp(chunk_start + 4, png_bKGD, 4)) else if (!png_memcmp(chunk_start + 4, png_hIST, 4))
{ {
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT"); png_error(png_ptr, "invalid chunk after IDAT");
} }
else if (!memcmp(chunk_start + 4, png_hIST, 4)) else if (!png_memcmp(chunk_start + 4, png_IDAT, 4))
{
(*(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) if (length > 0 || png_ptr->mode != PNG_AT_LAST_IDAT)
(*(png_ptr->error_fn))(png_ptr, "Too many IDAT's found"); png_error(png_ptr, "too many IDAT's found");
} }
else if (!memcmp(chunk_start + 4, png_pHYs, 4)) else if (!png_memcmp(chunk_start + 4, png_pHYs, 4))
{ {
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT"); png_error(png_ptr, "invalid chunk after IDAT");
} }
else if (!memcmp(chunk_start + 4, png_oFFs, 4)) else if (!png_memcmp(chunk_start + 4, png_oFFs, 4))
{ {
(*(png_ptr->error_fn))(png_ptr, "Invalid chunk after IDAT"); png_error(png_ptr, "invalid chunk after IDAT");
} }
#if defined(PNG_READ_tIME_SUPPORTED) #if defined(PNG_READ_tIME_SUPPORTED)
else if (!memcmp(chunk_start + 4, png_tIME, 4)) else if (!png_memcmp(chunk_start + 4, png_tIME, 4))
{ {
if (png_ptr->mode == PNG_BEFORE_IHDR || if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND) png_ptr->mode == PNG_AFTER_IEND)
(*(png_ptr->error_fn))(png_ptr, "Out of Place tIME"); png_error(png_ptr, "Out of Place tIME");
if (info) if (info)
png_handle_tIME(png_ptr, info, length); png_handle_tIME(png_ptr, info, length);
else else
png_crc_skip(png_ptr, length); png_crc_skip(png_ptr, length);
} }
#endif #endif
#if defined(PNG_READ_tEXt_SUPPORTED) #if defined(PNG_READ_tEXt_SUPPORTED)
else if (!memcmp(chunk_start + 4, png_tEXt, 4)) else if (!png_memcmp(chunk_start + 4, png_tEXt, 4))
{ {
if (png_ptr->mode == PNG_BEFORE_IHDR || if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND) png_ptr->mode == PNG_AFTER_IEND)
(*(png_ptr->error_fn))(png_ptr, "Out of Place tEXt"); png_error(png_ptr, "Out of Place tEXt");
if (info) if (info)
png_handle_tEXt(png_ptr, info, length); png_handle_tEXt(png_ptr, info, length);
@ -577,11 +588,11 @@ png_read_end(png_struct *png_ptr, png_info *info)
} }
#endif #endif
#if defined(PNG_READ_zTXt_SUPPORTED) #if defined(PNG_READ_zTXt_SUPPORTED)
else if (!memcmp(chunk_start + 4, png_zTXt, 4)) else if (!png_memcmp(chunk_start + 4, png_zTXt, 4))
{ {
if (png_ptr->mode == PNG_BEFORE_IHDR || if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND) png_ptr->mode == PNG_AFTER_IEND)
(*(png_ptr->error_fn))(png_ptr, "Out of Place zTXt"); png_error(png_ptr, "Out of Place zTXt");
if (info) if (info)
png_handle_zTXt(png_ptr, info, length); png_handle_zTXt(png_ptr, info, length);
@ -589,75 +600,63 @@ png_read_end(png_struct *png_ptr, png_info *info)
png_crc_skip(png_ptr, length); png_crc_skip(png_ptr, length);
} }
#endif #endif
else if (!memcmp(chunk_start + 4, png_IEND, 4)) else if (!png_memcmp(chunk_start + 4, png_IEND, 4))
{ {
png_ptr->mode = PNG_AFTER_IEND; png_ptr->mode = PNG_AFTER_IEND;
} }
else else
{ {
char msg[80];
if ((chunk_start[4] & 0x20) == 0) if ((chunk_start[4] & 0x20) == 0)
{ png_error(png_ptr, "Unknown Critical Chunk");
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_crc_skip(png_ptr, length);
} }
(*(png_ptr->read_data_fn))(png_ptr, chunk_start, 4); png_read_data(png_ptr, chunk_start, 4);
crc = png_get_uint_32(chunk_start); crc = png_get_uint_32(chunk_start);
if (((crc ^ 0xffffffffL) & 0xffffffffL) != if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
(png_ptr->crc & 0xffffffffL)) (png_ptr->crc & 0xffffffffL))
(*(png_ptr->error_fn))(png_ptr, "Bad CRC value"); png_error(png_ptr, "Bad CRC value");
if (png_ptr->mode == PNG_AT_LAST_IDAT) if (png_ptr->mode == PNG_AT_LAST_IDAT)
png_ptr->mode = PNG_AFTER_IDAT; png_ptr->mode = PNG_AFTER_IDAT;
} while (png_ptr->mode != PNG_AFTER_IEND); } while (png_ptr->mode != PNG_AFTER_IEND);
} }
/* free all memory used by the read */ /* free all memory used by the read */
void void
png_read_destroy(png_struct *png_ptr, png_info *info, png_info *end_info) png_read_destroy(png_structp png_ptr, png_infop info, png_infop end_info)
{ {
int i; int i;
jmp_buf tmp_jmp; jmp_buf tmp_jmp;
if (info) if (info)
{ {
if (png_ptr->do_free & PNG_FREE_PALETTE) if (png_ptr->do_free & PNG_FREE_PALETTE)
png_free(png_ptr, info->palette); png_free(png_ptr, info->palette);
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_bKGD_SUPPORTED) #if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_bKGD_SUPPORTED)
if (png_ptr->do_free & PNG_FREE_TRANS) if (png_ptr->do_free & PNG_FREE_PALETTE)
png_free(png_ptr, info->trans); png_free(png_ptr, info->trans);
#endif #endif
#if defined(PNG_READ_hIST_SUPPORTED) #if defined(PNG_READ_hIST_SUPPORTED)
if (png_ptr->do_free & PNG_FREE_HIST) if (png_ptr->do_free & PNG_FREE_HIST)
png_free(png_ptr, info->hist); png_free(png_ptr, info->hist);
#endif #endif
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED) #if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
for (i = 0; i < info->num_text; i++) for (i = 0; i < info->num_text; i++)
{ {
png_large_free(png_ptr, info->text[i].key); png_large_free(png_ptr, info->text[i].key);
} }
png_free(png_ptr, info->text); png_free(png_ptr, info->text);
#endif #endif
png_memset(info, 0, sizeof(png_info)); png_memset(info, 0, sizeof(png_info));
} }
if (end_info) if (end_info)
{ {
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED) #if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
for (i = 0; i < end_info->num_text; i++) for (i = 0; i < end_info->num_text; i++)
{ {
png_large_free(png_ptr, end_info->text[i].key); png_large_free(png_ptr, end_info->text[i].key);
} }
png_free(png_ptr, end_info->text); png_free(png_ptr, end_info->text);
@ -668,21 +667,17 @@ 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->zbuf);
png_large_free(png_ptr, png_ptr->row_buf); png_large_free(png_ptr, png_ptr->row_buf);
png_large_free(png_ptr, png_ptr->prev_row); png_large_free(png_ptr, png_ptr->prev_row);
#if defined(PNG_READ_DITHER_SUPPORTED) #if defined(PNG_READ_DITHER_SUPPORTED)
png_large_free(png_ptr, png_ptr->palette_lookup); png_large_free(png_ptr, png_ptr->palette_lookup);
png_free(png_ptr, png_ptr->dither_index); png_free(png_ptr, png_ptr->dither_index);
#endif #endif
#if defined(PNG_READ_GAMMA_SUPPORTED) #if defined(PNG_READ_GAMMA_SUPPORTED)
png_free(png_ptr, png_ptr->gamma_table); png_free(png_ptr, png_ptr->gamma_table);
#endif #endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED) #if defined(PNG_READ_BACKGROUND_SUPPORTED)
png_free(png_ptr, png_ptr->gamma_from_1); png_free(png_ptr, png_ptr->gamma_from_1);
png_free(png_ptr, png_ptr->gamma_to_1); png_free(png_ptr, png_ptr->gamma_to_1);
#endif #endif
#if defined(PNG_READ_GAMMA_SUPPORTED) #if defined(PNG_READ_GAMMA_SUPPORTED)
if (png_ptr->gamma_16_table) if (png_ptr->gamma_16_table)
{ {
@ -690,15 +685,14 @@ png_read_destroy(png_struct *png_ptr, png_info *info, png_info *end_info)
{ {
png_free(png_ptr, png_ptr->gamma_16_table[i]); png_free(png_ptr, png_ptr->gamma_16_table[i]);
} }
} }
#endif #endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED) #if defined(PNG_READ_BACKGROUND_SUPPORTED)
png_free(png_ptr, png_ptr->gamma_16_table); png_free(png_ptr, png_ptr->gamma_16_table);
if (png_ptr->gamma_16_from_1) if (png_ptr->gamma_16_from_1)
{ {
for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++) for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
{ {
png_free(png_ptr, png_ptr->gamma_16_from_1[i]); png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
} }
} }
@ -709,25 +703,25 @@ png_read_destroy(png_struct *png_ptr, png_info *info, png_info *end_info)
{ {
png_free(png_ptr, png_ptr->gamma_16_to_1[i]); png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
} }
} }
png_free(png_ptr, png_ptr->gamma_16_to_1); png_free(png_ptr, png_ptr->gamma_16_to_1);
#endif #endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED) #if defined(PNG_READ_BACKGROUND_SUPPORTED)
png_free(png_ptr, png_ptr->trans); png_free(png_ptr, png_ptr->trans);
#endif #endif
#if defined(PNG_READ_DITHER_SUPPORTED) #if defined(PNG_READ_DITHER_SUPPORTED)
png_free(png_ptr, png_ptr->hist); png_free(png_ptr, png_ptr->hist);
#endif #endif
if (!png_ptr->user_palette)
png_free(png_ptr, png_ptr->palette);
if (!png_ptr->user_palette) inflateEnd(png_ptr->zstream);
png_free(png_ptr, png_ptr->palette); png_free(png_ptr, png_ptr->zstream);
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
inflateEnd(png_ptr->zstream); png_free(png_ptr, png_ptr->save_buffer);
#endif
png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf)); png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
png_memset(png_ptr, 0, sizeof (png_struct)); png_memset(png_ptr, 0, sizeof (png_struct));
png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf)); png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
} }

View File

@ -1,10 +1,10 @@
/* pngrtran.c - transforms the data in a row for png readers /* pngrtran.c - transforms the data in a row for png readers
libpng 1.0 beta 2 - version 0.8 libpng 1.0 beta 2 - version 0.85
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
August 20, 1995 December 19, 1995
*/ */
#define PNG_INTERNAL #define PNG_INTERNAL
@ -13,8 +13,8 @@
#if defined(PNG_READ_BACKGROUND_SUPPORTED) #if defined(PNG_READ_BACKGROUND_SUPPORTED)
/* handle alpha and tRNS via a background color */ /* handle alpha and tRNS via a background color */
void void
png_set_background(png_struct *png_ptr, png_set_background(png_structp png_ptr,
png_color_16 *background_color, int background_gamma_code, png_color_16p background_color, int background_gamma_code,
int need_expand, double background_gamma) int need_expand, double background_gamma)
{ {
png_ptr->transformations |= PNG_BACKGROUND; png_ptr->transformations |= PNG_BACKGROUND;
@ -29,7 +29,7 @@ png_set_background(png_struct *png_ptr,
#if defined(PNG_READ_16_TO_8_SUPPORTED) #if defined(PNG_READ_16_TO_8_SUPPORTED)
/* strip 16 bit depth files to 8 bit depth */ /* strip 16 bit depth files to 8 bit depth */
void void
png_set_strip_16(png_struct *png_ptr) png_set_strip_16(png_structp png_ptr)
{ {
png_ptr->transformations |= PNG_16_TO_8; png_ptr->transformations |= PNG_16_TO_8;
} }
@ -42,16 +42,19 @@ png_set_strip_16(png_struct *png_ptr)
is greater then the maximum number, the palette will be is greater then the maximum number, the palette will be
modified to fit in the maximum number */ modified to fit in the maximum number */
typedef struct dsort_struct
typedef struct png_dsort_struct
{ {
struct dsort_struct *next; struct png_dsort_struct FAR * next;
png_byte left; png_byte left;
png_byte right; png_byte right;
} dsort; } png_dsort;
typedef png_dsort FAR * png_dsortp;
typedef png_dsort FAR * FAR * png_dsortpp;
void void
png_set_dither(png_struct *png_ptr, png_color *palette, png_set_dither(png_structp png_ptr, png_colorp palette,
int num_palette, int maximum_colors, png_uint_16 *histogram, int num_palette, int maximum_colors, png_uint_16p histogram,
int full_dither) int full_dither)
{ {
png_ptr->transformations |= PNG_DITHER; png_ptr->transformations |= PNG_DITHER;
@ -60,7 +63,7 @@ png_set_dither(png_struct *png_ptr, png_color *palette,
{ {
int i; int i;
png_ptr->dither_index = png_malloc(png_ptr, png_ptr->dither_index = (png_bytep)png_malloc(png_ptr,
num_palette * sizeof (png_byte)); num_palette * sizeof (png_byte));
for (i = 0; i < num_palette; i++) for (i = 0; i < num_palette; i++)
png_ptr->dither_index[i] = i; png_ptr->dither_index[i] = i;
@ -74,10 +77,10 @@ png_set_dither(png_struct *png_ptr, png_color *palette,
perhaps not the best solution, but good enough */ perhaps not the best solution, but good enough */
int i; int i;
png_byte *sort; png_bytep sort;
/* initialize an array to sort colors */ /* initialize an array to sort colors */
sort = (png_byte *)png_malloc(png_ptr, num_palette * sizeof (png_byte)); sort = (png_bytep)png_malloc(png_ptr, num_palette * sizeof (png_byte));
/* initialize the sort array */ /* initialize the sort array */
for (i = 0; i < num_palette; i++) for (i = 0; i < num_palette; i++)
@ -200,16 +203,16 @@ png_set_dither(png_struct *png_ptr, png_color *palette,
int i; int i;
int max_d; int max_d;
int num_new_palette; int num_new_palette;
dsort **hash; png_dsortpp hash;
png_byte *index_to_palette; png_bytep index_to_palette;
/* where the original index currently is in the palette */ /* where the original index currently is in the palette */
png_byte *palette_to_index; png_bytep palette_to_index;
/* which original index points to this palette color */ /* which original index points to this palette color */
/* initialize palette index arrays */ /* initialize palette index arrays */
index_to_palette = (png_byte *)png_malloc(png_ptr, index_to_palette = (png_bytep)png_malloc(png_ptr,
num_palette * sizeof (png_byte)); num_palette * sizeof (png_byte));
palette_to_index = (png_byte *)png_malloc(png_ptr, palette_to_index = (png_bytep)png_malloc(png_ptr,
num_palette * sizeof (png_byte)); num_palette * sizeof (png_byte));
/* initialize the sort array */ /* initialize the sort array */
@ -219,10 +222,10 @@ png_set_dither(png_struct *png_ptr, png_color *palette,
palette_to_index[i] = i; palette_to_index[i] = i;
} }
hash = (dsort **)png_malloc(png_ptr, 769 * sizeof (dsort *)); hash = (png_dsortpp)png_malloc(png_ptr, 769 * sizeof (png_dsortp));
for (i = 0; i < 769; i++) for (i = 0; i < 769; i++)
hash[i] = (dsort *)0; hash[i] = (png_dsortp)0;
/* png_memset(hash, 0, 769 * sizeof (dsort *)); */ /* png_memset(hash, 0, 769 * sizeof (png_dsortp)); */
num_new_palette = num_palette; num_new_palette = num_palette;
@ -246,13 +249,13 @@ png_set_dither(png_struct *png_ptr, png_color *palette,
{ {
int d; int d;
d = PNG_COLOR_DIST(palette[i], palette[j]); d = PNG_COLOR_DIST(palette[i], palette[j]);
if (d <= max_d) if (d <= max_d)
{ {
dsort *t; png_dsortp t;
t = png_malloc(png_ptr, sizeof (dsort)); t = png_malloc(png_ptr, sizeof (png_dsort));
t->next = hash[d]; t->next = hash[d];
t->left = i; t->left = i;
t->right = j; t->right = j;
@ -265,7 +268,7 @@ png_set_dither(png_struct *png_ptr, png_color *palette,
{ {
if (hash[i]) if (hash[i])
{ {
dsort *p; png_dsortp p;
for (p = hash[i]; p; p = p->next) for (p = hash[i]; p; p = p->next)
{ {
@ -325,12 +328,12 @@ png_set_dither(png_struct *png_ptr, png_color *palette,
{ {
if (hash[i]) if (hash[i])
{ {
dsort *p; png_dsortp p;
p = hash[i]; p = hash[i];
while (p) while (p)
{ {
dsort *t; png_dsortp t;
t = p->next; t = p->next;
png_free(png_ptr, p); png_free(png_ptr, p);
@ -348,7 +351,7 @@ png_set_dither(png_struct *png_ptr, png_color *palette,
num_palette = maximum_colors; num_palette = maximum_colors;
} }
if (!(png_ptr->palette)) if (!(png_ptr->palette))
{ {
png_ptr->palette = palette; png_ptr->palette = palette;
png_ptr->user_palette = 1; png_ptr->user_palette = 1;
} }
@ -359,22 +362,22 @@ png_set_dither(png_struct *png_ptr, png_color *palette,
int i; int i;
int total_bits, num_red, num_green, num_blue; int total_bits, num_red, num_green, num_blue;
png_uint_32 num_entries; png_uint_32 num_entries;
png_bytef *distance; png_bytep distance;
total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS + total_bits = PNG_DITHER_RED_BITS + PNG_DITHER_GREEN_BITS +
PNG_DITHER_BLUE_BITS; PNG_DITHER_BLUE_BITS;
num_red = (1 << PNG_DITHER_RED_BITS); num_red = (1 << PNG_DITHER_RED_BITS);
num_green = (1 << PNG_DITHER_GREEN_BITS); num_green = (1 << PNG_DITHER_GREEN_BITS);
num_blue = (1 << PNG_DITHER_BLUE_BITS); num_blue = (1 << PNG_DITHER_BLUE_BITS);
num_entries = ((png_uint_32)1 << total_bits); num_entries = ((png_uint_32)1 << total_bits);
png_ptr->palette_lookup = (png_bytef *)png_large_malloc(png_ptr, png_ptr->palette_lookup = (png_bytep )png_large_malloc(png_ptr,
(png_size_t)num_entries * sizeof (png_byte)); (png_size_t)num_entries * sizeof (png_byte));
png_memset(png_ptr->palette_lookup, 0, (png_size_t)num_entries * sizeof (png_byte)); png_memset(png_ptr->palette_lookup, 0, (png_size_t)num_entries * sizeof (png_byte));
distance = (png_bytef *)png_large_malloc(png_ptr, distance = (png_bytep )png_large_malloc(png_ptr,
(png_size_t)num_entries * sizeof (png_byte)); (png_size_t)num_entries * sizeof (png_byte));
png_memset(distance, 0xff, (png_size_t)num_entries * sizeof (png_byte)); png_memset(distance, 0xff, (png_size_t)num_entries * sizeof (png_byte));
@ -384,7 +387,7 @@ png_set_dither(png_struct *png_ptr, png_color *palette,
int r, g, b, ir, ig, ib; int r, g, b, ir, ig, ib;
r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS)); r = (palette[i].red >> (8 - PNG_DITHER_RED_BITS));
g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS)); g = (palette[i].green >> (8 - PNG_DITHER_GREEN_BITS));
b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS)); b = (palette[i].blue >> (8 - PNG_DITHER_BLUE_BITS));
for (ir = 0; ir < num_red; ir++) for (ir = 0; ir < num_red; ir++)
@ -402,7 +405,7 @@ png_set_dither(png_struct *png_ptr, png_color *palette,
dm = ((dr > dg) ? dr : dg); dm = ((dr > dg) ? dr : dg);
index_g = index_r | (ig << PNG_DITHER_BLUE_BITS); index_g = index_r | (ig << PNG_DITHER_BLUE_BITS);
for (ib = 0; ib < num_blue; ib++) for (ib = 0; ib < num_blue; ib++)
{ {
int index, db, dmax, d; int index, db, dmax, d;
index = index_g | ib; index = index_g | ib;
@ -420,7 +423,7 @@ png_set_dither(png_struct *png_ptr, png_color *palette,
} }
} }
png_large_free(png_ptr, distance); png_large_free(png_ptr, distance);
} }
} }
#endif #endif
@ -428,7 +431,7 @@ png_set_dither(png_struct *png_ptr, png_color *palette,
#if defined(PNG_READ_GAMMA_SUPPORTED) #if defined(PNG_READ_GAMMA_SUPPORTED)
/* transform the image from the file_gamma to the screen_gamma */ /* transform the image from the file_gamma to the screen_gamma */
void void
png_set_gamma(png_struct *png_ptr, double screen_gamma, png_set_gamma(png_structp png_ptr, double screen_gamma,
double file_gamma) double file_gamma)
{ {
png_ptr->transformations |= PNG_GAMMA; png_ptr->transformations |= PNG_GAMMA;
@ -442,7 +445,7 @@ png_set_gamma(png_struct *png_ptr, double screen_gamma,
less then 8 bit depth to 8 bit depth, and expand tRNS chunks less then 8 bit depth to 8 bit depth, and expand tRNS chunks
to alpha channels */ to alpha channels */
void void
png_set_expand(png_struct *png_ptr) png_set_expand(png_structp png_ptr)
{ {
png_ptr->transformations |= PNG_EXPAND; png_ptr->transformations |= PNG_EXPAND;
} }
@ -450,7 +453,7 @@ png_set_expand(png_struct *png_ptr)
#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
void void
png_set_gray_to_rgb(png_struct *png_ptr) png_set_gray_to_rgb(png_structp png_ptr)
{ {
png_ptr->transformations |= PNG_GRAY_TO_RGB; png_ptr->transformations |= PNG_GRAY_TO_RGB;
} }
@ -459,7 +462,7 @@ png_set_gray_to_rgb(png_struct *png_ptr)
/* initialize everything needed for the read. This includes modifying /* initialize everything needed for the read. This includes modifying
the palette */ the palette */
void void
png_init_read_transformations(png_struct *png_ptr) png_init_read_transformations(png_structp png_ptr)
{ {
int color_type; int color_type;
@ -474,7 +477,7 @@ png_init_read_transformations(png_struct *png_ptr)
(png_ptr->transformations & PNG_BACKGROUND) && (png_ptr->transformations & PNG_BACKGROUND) &&
png_ptr->background_expand) png_ptr->background_expand)
/* (!(png_ptr->transformations & PNG_BACKGROUND) || /* (!(png_ptr->transformations & PNG_BACKGROUND) ||
png_ptr->background_expand)) */ png_ptr->background_expand)) */
{ {
/* expand background chunk. While this may not be /* expand background chunk. While this may not be
the fastest way to do this, it only happens once the fastest way to do this, it only happens once
@ -492,7 +495,7 @@ png_init_read_transformations(png_struct *png_ptr)
break; break;
} }
} }
if (color_type == PNG_COLOR_TYPE_PALETTE && if (color_type == PNG_COLOR_TYPE_PALETTE &&
(png_ptr->transformations & PNG_BACKGROUND) && (png_ptr->transformations & PNG_BACKGROUND) &&
png_ptr->background_expand) png_ptr->background_expand)
{ {
@ -523,12 +526,12 @@ png_init_read_transformations(png_struct *png_ptr)
{ {
double g, gs, m; double g, gs, m;
m = (double)((png_uint_32)1 << png_ptr->bit_depth); m = (double)(((png_uint_32)1 << png_ptr->bit_depth) - 1);
g = 1.0; g = 1.0;
gs = 1.0; gs = 1.0;
switch (png_ptr->background_gamma_type) switch (png_ptr->background_gamma_type)
{ {
case PNG_BACKGROUND_GAMMA_SCREEN: case PNG_BACKGROUND_GAMMA_SCREEN:
g = (png_ptr->display_gamma); g = (png_ptr->display_gamma);
gs = 1.0; gs = 1.0;
@ -544,9 +547,9 @@ png_init_read_transformations(png_struct *png_ptr)
break; break;
} }
if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) if (color_type & PNG_COLOR_MASK_COLOR)
{ {
png_ptr->background_1.red = (png_uint_16)(pow( png_ptr->background_1.red = (png_uint_16)(pow(
(double)png_ptr->background.red / m, g) * m + .5); (double)png_ptr->background.red / m, g) * m + .5);
png_ptr->background_1.green = (png_uint_16)(pow( png_ptr->background_1.green = (png_uint_16)(pow(
(double)png_ptr->background.green / m, g) * m + .5); (double)png_ptr->background.green / m, g) * m + .5);
@ -562,9 +565,9 @@ png_init_read_transformations(png_struct *png_ptr)
else else
{ {
png_ptr->background_1.gray = (png_uint_16)(pow( png_ptr->background_1.gray = (png_uint_16)(pow(
(double)png_ptr->background.gray / m, g) * m + .5); (double)png_ptr->background.gray / m, g) * m + .5);
png_ptr->background.gray = (png_uint_16)(pow( png_ptr->background.gray = (png_uint_16)(pow(
(double)png_ptr->background.gray / m, gs) * m + .5); (double)png_ptr->background.gray / m, gs) * m + .5);
} }
} }
} }
@ -572,9 +575,9 @@ png_init_read_transformations(png_struct *png_ptr)
} }
#endif #endif
#if defined(PNG_READ_SHIFT_SUPPORTED) && defined(PNG_READ_sBIT_SUPPORTED) #if defined(PNG_READ_SHIFT_SUPPORTED)
if ((png_ptr->transformations & PNG_SHIFT) && if ((png_ptr->transformations & PNG_SHIFT) &&
png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) color_type == PNG_COLOR_TYPE_PALETTE)
{ {
png_uint_16 i; png_uint_16 i;
int sr, sg, sb; int sr, sg, sb;
@ -582,7 +585,7 @@ png_init_read_transformations(png_struct *png_ptr)
sr = 8 - png_ptr->sig_bit.red; sr = 8 - png_ptr->sig_bit.red;
if (sr < 0 || sr > 8) if (sr < 0 || sr > 8)
sr = 0; sr = 0;
sg = 8 - png_ptr->sig_bit.green; sg = 8 - png_ptr->sig_bit.green;
if (sg < 0 || sg > 8) if (sg < 0 || sg > 8)
sg = 0; sg = 0;
sb = 8 - png_ptr->sig_bit.blue; sb = 8 - png_ptr->sig_bit.blue;
@ -600,9 +603,9 @@ png_init_read_transformations(png_struct *png_ptr)
/* modify the info structure to reflect the transformations. The /* modify the info structure to reflect the transformations. The
info should be updated so a png file could be written with it, info should be updated so a png file could be written with it,
assuming the transformations result in valid png data */ assuming the transformations result in valid png data */
void void
png_read_transform_info(png_struct *png_ptr, png_info *info_ptr) png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
{ {
#if defined(PNG_READ_EXPAND_SUPPORTED) #if defined(PNG_READ_EXPAND_SUPPORTED)
if ((png_ptr->transformations & PNG_EXPAND) && if ((png_ptr->transformations & PNG_EXPAND) &&
@ -618,7 +621,7 @@ png_read_transform_info(png_struct *png_ptr, png_info *info_ptr)
else if (png_ptr->transformations & PNG_EXPAND) else if (png_ptr->transformations & PNG_EXPAND)
{ {
if (png_ptr->num_trans) if (png_ptr->num_trans)
info_ptr->color_type |= PNG_COLOR_MASK_ALPHA; info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
if (info_ptr->bit_depth < 8) if (info_ptr->bit_depth < 8)
info_ptr->bit_depth = 8; info_ptr->bit_depth = 8;
info_ptr->num_trans = 0; info_ptr->num_trans = 0;
@ -636,7 +639,7 @@ png_read_transform_info(png_struct *png_ptr, png_info *info_ptr)
#if defined(PNG_READ_16_TO_8_SUPPORTED) #if defined(PNG_READ_16_TO_8_SUPPORTED)
if ((png_ptr->transformations & PNG_16_TO_8) && info_ptr->bit_depth == 16) if ((png_ptr->transformations & PNG_16_TO_8) && info_ptr->bit_depth == 16)
info_ptr->bit_depth = 8; info_ptr->bit_depth = 8;
#endif #endif
#if defined(PNG_READ_DITHER_SUPPORTED) #if defined(PNG_READ_DITHER_SUPPORTED)
@ -661,7 +664,7 @@ png_read_transform_info(png_struct *png_ptr, png_info *info_ptr)
!(info_ptr->color_type & PNG_COLOR_MASK_COLOR)) !(info_ptr->color_type & PNG_COLOR_MASK_COLOR))
info_ptr->color_type |= PNG_COLOR_MASK_COLOR; info_ptr->color_type |= PNG_COLOR_MASK_COLOR;
#endif #endif
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
info_ptr->channels = 1; info_ptr->channels = 1;
else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
info_ptr->channels = 3; info_ptr->channels = 3;
@ -677,7 +680,7 @@ png_read_transform_info(png_struct *png_ptr, png_info *info_ptr)
and is very touchy. If you add a transformation, take care to and is very touchy. If you add a transformation, take care to
decide how it fits in with the other transformations here */ decide how it fits in with the other transformations here */
void void
png_do_read_transformations(png_struct *png_ptr) png_do_read_transformations(png_structp png_ptr)
{ {
#if defined(PNG_READ_EXPAND_SUPPORTED) #if defined(PNG_READ_EXPAND_SUPPORTED)
if ((png_ptr->transformations & PNG_EXPAND) && if ((png_ptr->transformations & PNG_EXPAND) &&
@ -690,7 +693,7 @@ png_do_read_transformations(png_struct *png_ptr)
{ {
if (png_ptr->num_trans) if (png_ptr->num_trans)
png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
&(png_ptr->trans_values)); &(png_ptr->trans_values));
else else
png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1, png_do_expand(&(png_ptr->row_info), png_ptr->row_buf + 1,
NULL); NULL);
@ -724,16 +727,16 @@ png_do_read_transformations(png_struct *png_ptr)
#if defined(PNG_READ_DITHER_SUPPORTED) #if defined(PNG_READ_DITHER_SUPPORTED)
if (png_ptr->transformations & PNG_DITHER) if (png_ptr->transformations & PNG_DITHER)
{ {
png_do_dither((png_row_info *)&(png_ptr->row_info), png_do_dither((png_row_infop)&(png_ptr->row_info),
png_ptr->row_buf + 1, png_ptr->row_buf + 1,
png_ptr->palette_lookup, png_ptr->palette_lookup,
png_ptr->dither_index); png_ptr->dither_index);
} }
#endif #endif
#if defined(PNG_READ_INVERT_SUPPORTED) #if defined(PNG_READ_INVERT_SUPPORTED)
if (png_ptr->transformations & PNG_INVERT_MONO) if (png_ptr->transformations & PNG_INVERT_MONO)
png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1); png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif #endif
#if defined(PNG_READ_SHIFT_SUPPORTED) #if defined(PNG_READ_SHIFT_SUPPORTED)
@ -744,7 +747,7 @@ png_do_read_transformations(png_struct *png_ptr)
#if defined(PNG_READ_PACK_SUPPORTED) #if defined(PNG_READ_PACK_SUPPORTED)
if (png_ptr->transformations & PNG_PACK) if (png_ptr->transformations & PNG_PACK)
png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1); png_do_unpack(&(png_ptr->row_info), png_ptr->row_buf + 1);
#endif #endif
#if defined(PNG_READ_BGR_SUPPORTED) #if defined(PNG_READ_BGR_SUPPORTED)
@ -776,11 +779,11 @@ png_do_read_transformations(png_struct *png_ptr)
the numbers 0 or 1. If you would rather they contain 0 and 255, use the numbers 0 or 1. If you would rather they contain 0 and 255, use
png_do_shift() after this. */ png_do_shift() after this. */
void void
png_do_unpack(png_row_info *row_info, png_bytef *row) png_do_unpack(png_row_infop row_info, png_bytep row)
{ {
int shift; int shift;
png_bytef *sp, *dp; png_bytep sp, dp;
png_uint_32 i; png_uint_32 i;
if (row && row_info && row_info->bit_depth < 8) if (row && row_info && row_info->bit_depth < 8)
{ {
@ -798,7 +801,7 @@ png_do_unpack(png_row_info *row_info, png_bytef *row)
{ {
shift = 0; shift = 0;
sp--; sp--;
} }
else else
shift++; shift++;
@ -831,7 +834,7 @@ png_do_unpack(png_row_info *row_info, png_bytef *row)
{ {
sp = row + (png_size_t)((row_info->width - 1) >> 1); sp = row + (png_size_t)((row_info->width - 1) >> 1);
dp = row + (png_size_t)row_info->width - 1; dp = row + (png_size_t)row_info->width - 1;
shift = (int)((1 - ((row_info->width + 1) & 1)) << 4); shift = (int)((1 - ((row_info->width + 1) & 1)) << 2);
for (i = 0; i < row_info->width; i++) for (i = 0; i < row_info->width; i++)
{ {
*dp = (*sp >> shift) & 0xf; *dp = (*sp >> shift) & 0xf;
@ -861,10 +864,10 @@ png_do_unpack(png_row_info *row_info, png_bytef *row)
a row of bit depth 8, but only 5 are significant, this will shift a row of bit depth 8, but only 5 are significant, this will shift
the values back to 0 through 31 */ the values back to 0 through 31 */
void void
png_do_unshift(png_row_info *row_info, png_bytef *row, png_do_unshift(png_row_infop row_info, png_bytep row,
png_color_8 *sig_bits) png_color_8p sig_bits)
{ {
png_bytef *bp; png_bytep bp;
png_uint_16 value; png_uint_16 value;
png_uint_32 i; png_uint_32 i;
if (row && row_info && sig_bits && if (row && row_info && sig_bits &&
@ -876,34 +879,33 @@ png_do_unshift(png_row_info *row_info, png_bytef *row,
channels = 0; channels = 0;
if (row_info->color_type & PNG_COLOR_MASK_COLOR) if (row_info->color_type & PNG_COLOR_MASK_COLOR)
{ {
shift[channels++] = row_info->bit_depth - sig_bits->red < 0 ? shift[channels++] = row_info->bit_depth - sig_bits->red;
0 : row_info->bit_depth - sig_bits->red; shift[channels++] = row_info->bit_depth - sig_bits->green;
shift[channels++] = row_info->bit_depth - sig_bits->green < 0 ? shift[channels++] = row_info->bit_depth - sig_bits->blue;
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 else
{ {
shift[channels++] = row_info->bit_depth - sig_bits->gray < 0 ? shift[channels++] = row_info->bit_depth - sig_bits->gray;
0 : row_info->bit_depth - sig_bits->gray;
} }
if (row_info->color_type & PNG_COLOR_MASK_ALPHA) if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
{ {
shift[channels++] = row_info->bit_depth - sig_bits->alpha < 0 ? shift[channels++] = row_info->bit_depth - sig_bits->alpha;
0 : row_info->bit_depth - sig_bits->alpha; }
}
value = 1; value = 0;
for (i = 0; i < channels; i++) for (i = 0; i < channels; i++)
{ {
if (shift[i] != 0) value = 0; if (shift[i] <= 0)
} shift[i] = 0;
else
value = 1;
}
if (value == 1) return; if (!value)
return;
switch (row_info->bit_depth) switch (row_info->bit_depth)
{ {
case 2: case 2:
{ {
@ -919,8 +921,7 @@ png_do_unshift(png_row_info *row_info, png_bytef *row,
case 4: case 4:
{ {
png_byte mask; png_byte mask;
mask = (png_byte)(((int)0xf0 >> shift[0]) & (int)0xf0) |
mask = (png_byte)(((int)0xf0 >> shift[0]) & (int)0xf0) |
((int)0xf >> shift[0]); ((int)0xf >> shift[0]);
for (bp = row, i = 0; for (bp = row, i = 0;
i < row_info->rowbytes; i < row_info->rowbytes;
@ -938,7 +939,7 @@ png_do_unshift(png_row_info *row_info, png_bytef *row,
{ {
int c; int c;
for (c = 0; c < row_info->channels; c++, bp++) for (c = 0; c < row_info->channels; c++, bp++)
{ {
*bp >>= shift[c]; *bp >>= shift[c];
} }
@ -956,7 +957,7 @@ png_do_unshift(png_row_info *row_info, png_bytef *row,
{ {
value = (*bp << 8) + *(bp + 1); value = (*bp << 8) + *(bp + 1);
value >>= shift[c]; value >>= shift[c];
*bp = value >> 8; *bp = value >> 8;
*(bp + 1) = value & 0xff; *(bp + 1) = value & 0xff;
} }
} }
@ -970,17 +971,24 @@ png_do_unshift(png_row_info *row_info, png_bytef *row,
#if defined(PNG_READ_16_TO_8_SUPPORTED) #if defined(PNG_READ_16_TO_8_SUPPORTED)
/* chop rows of bit depth 16 down to 8 */ /* chop rows of bit depth 16 down to 8 */
void void
png_do_chop(png_row_info *row_info, png_bytef *row) png_do_chop(png_row_infop row_info, png_bytep row)
{ {
if (row && row_info && row_info->bit_depth == 16) png_bytep sp, dp;
png_uint_32 i;
if (row && row_info && row_info->bit_depth == 16)
{ {
png_bytef *sp = row, *dp = row; sp = row;
png_uint_32 i; dp = row;
for (i = 0; i < row_info->width * row_info->channels; i++) for (i = 0; i < row_info->width * row_info->channels; i++)
{ {
*dp++ = ((((*sp << 8 | *(sp + 1)) - *sp) + 0x7F) >> 8) & 0xFF; *dp = *sp;
sp += 2; /* not yet, as I'm afraid of overflow here
*dp = ((((((png_uint_16)(*sp) << 8)) |
(png_uint_16)((*(sp + 1) - *sp) & 0xff) +
0x7f) >> 8) & 0xff);
*/
sp += 2;
dp++;
} }
row_info->bit_depth = 8; row_info->bit_depth = 8;
row_info->pixel_depth = 8 * row_info->channels; row_info->pixel_depth = 8 * row_info->channels;
@ -992,10 +1000,10 @@ png_do_chop(png_row_info *row_info, png_bytef *row)
#if defined(PNG_READ_FILLER_SUPPORTED) #if defined(PNG_READ_FILLER_SUPPORTED)
/* add filler byte */ /* add filler byte */
void void
png_do_read_filler(png_row_info *row_info, png_bytef *row, png_do_read_filler(png_row_infop row_info, png_bytep row,
png_byte filler, png_byte filler_loc) png_byte filler, png_byte filler_loc)
{ {
png_bytef *sp, *dp; png_bytep sp, dp;
png_uint_32 i; png_uint_32 i;
if (row && row_info && row_info->color_type == 2 && if (row && row_info && row_info->color_type == 2 &&
row_info->bit_depth == 8) row_info->bit_depth == 8)
@ -1040,10 +1048,11 @@ png_do_read_filler(png_row_info *row_info, png_bytef *row,
#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED) #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
/* expand grayscale files to rgb, with or without alpha */ /* expand grayscale files to rgb, with or without alpha */
void void
png_do_gray_to_rgb(png_row_info *row_info, png_bytef *row) png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
{ {
png_bytef *sp, *dp; png_bytep sp, dp;
png_uint_32 i; png_uint_32 i;
if (row && row_info && row_info->bit_depth >= 8 && if (row && row_info && row_info->bit_depth >= 8 &&
!(row_info->color_type & PNG_COLOR_MASK_COLOR)) !(row_info->color_type & PNG_COLOR_MASK_COLOR))
{ {
@ -1130,7 +1139,7 @@ png_do_gray_to_rgb(png_row_info *row_info, png_bytef *row)
paletted. Most useful for gamma correction and simplification paletted. Most useful for gamma correction and simplification
of code. */ of code. */
void void
png_build_grayscale_palette(int bit_depth, png_color *palette) png_build_grayscale_palette(int bit_depth, png_colorp palette)
{ {
int num_palette; int num_palette;
int color_inc; int color_inc;
@ -1160,7 +1169,6 @@ png_build_grayscale_palette(int bit_depth, png_color *palette)
break; break;
default: default:
num_palette = 0; num_palette = 0;
color_inc = 0;
break; break;
} }
@ -1174,7 +1182,7 @@ png_build_grayscale_palette(int bit_depth, png_color *palette)
#if defined(PNG_READ_DITHER_SUPPORTED) #if defined(PNG_READ_DITHER_SUPPORTED)
void void
png_correct_palette(png_struct *png_ptr, png_color *palette, png_correct_palette(png_structp png_ptr, png_colorp palette,
int num_palette) int num_palette)
{ {
if ((png_ptr->transformations & (PNG_GAMMA)) && if ((png_ptr->transformations & (PNG_GAMMA)) &&
@ -1344,15 +1352,16 @@ png_correct_palette(png_struct *png_ptr, png_color *palette,
background is the color (in rgb or grey or palette index, as background is the color (in rgb or grey or palette index, as
appropriate). note that paletted files are taken care of elsewhere */ appropriate). note that paletted files are taken care of elsewhere */
void void
png_do_background(png_row_info *row_info, png_bytef *row, png_do_background(png_row_infop row_info, png_bytep row,
png_color_16 *trans_values, png_color_16 *background, png_color_16p trans_values, png_color_16p background,
png_color_16 *background_1, png_color_16p background_1,
png_byte *gamma_table, png_byte *gamma_from_1, png_byte *gamma_to_1, png_bytep gamma_table, png_bytep gamma_from_1, png_bytep gamma_to_1,
png_uint_16 **gamma_16, png_uint_16 **gamma_16_from_1, png_uint_16pp gamma_16, png_uint_16pp gamma_16_from_1,
png_uint_16 **gamma_16_to_1, int gamma_shift) png_uint_16pp gamma_16_to_1, int gamma_shift)
{ {
png_bytef *sp, *dp; png_bytep sp, dp;
png_uint_32 i; png_uint_32 i;
int shift; int shift;
if (row && row_info && background && if (row && row_info && background &&
(!(row_info->color_type & PNG_COLOR_MASK_ALPHA) || (!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
@ -2016,15 +2025,16 @@ png_do_background(png_row_info *row_info, png_bytef *row,
you do this after you deal with the trasparency issue on grayscale 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, 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 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. */ palette, not the data. */
void void
png_do_gamma(png_row_info *row_info, png_bytef *row, png_do_gamma(png_row_infop row_info, png_bytep row,
png_byte *gamma_table, png_uint_16 **gamma_16_table, png_bytep gamma_table, png_uint_16pp gamma_16_table,
int gamma_shift) int gamma_shift)
{ {
png_bytef *sp; png_bytep sp;
png_uint_32 i; png_uint_32 i;
if (row && row_info && ((row_info->bit_depth <= 8 && gamma_table) || if (row && row_info && ((row_info->bit_depth <= 8 && gamma_table) ||
(row_info->bit_depth == 16 && gamma_16_table))) (row_info->bit_depth == 16 && gamma_16_table)))
{ {
@ -2177,13 +2187,14 @@ png_do_gamma(png_row_info *row_info, png_bytef *row,
/* expands a palette row to an rgb or rgba row depending /* expands a palette row to an rgb or rgba row depending
upon whether you supply trans and num_trans */ upon whether you supply trans and num_trans */
void void
png_do_expand_palette(png_row_info *row_info, png_bytef *row, png_do_expand_palette(png_row_infop row_info, png_bytep row,
png_color *palette, png_colorp palette,
png_byte *trans, int num_trans) png_bytep trans, int num_trans)
{ {
int shift, value; int shift, value;
png_bytef *sp, *dp; png_bytep sp, dp;
png_uint_32 i; png_uint_32 i;
if (row && row_info && row_info->color_type == PNG_COLOR_TYPE_PALETTE) if (row && row_info && row_info->color_type == PNG_COLOR_TYPE_PALETTE)
{ {
if (row_info->bit_depth < 8) if (row_info->bit_depth < 8)
@ -2311,14 +2322,15 @@ png_do_expand_palette(png_row_info *row_info, png_bytef *row,
} }
/* if the bit depth < 8, it is expanded to 8. Also, if the /* if the bit depth < 8, it is expanded to 8. Also, if the
transparency value is supplied, an alpha channel is built. */ transparency value is supplied, an alpha channel is built. */
void void
png_do_expand(png_row_info *row_info, png_bytef *row, png_do_expand(png_row_infop row_info, png_bytep row,
png_color_16 *trans_value) png_color_16p trans_value)
{ {
int shift, value; int shift, value;
png_bytef *sp, *dp; png_bytep sp, dp;
png_uint_32 i; png_uint_32 i;
if (row && row_info) if (row && row_info)
{ {
if (row_info->color_type == PNG_COLOR_TYPE_GRAY && if (row_info->color_type == PNG_COLOR_TYPE_GRAY &&
@ -2411,7 +2423,7 @@ png_do_expand(png_row_info *row_info, png_bytef *row,
*dp-- = 0xff; *dp-- = 0xff;
*dp-- = *sp--; *dp-- = *sp--;
} }
} }
else if (row_info->bit_depth == 16) else if (row_info->bit_depth == 16)
{ {
sp = row + (png_size_t)row_info->rowbytes - 1; sp = row + (png_size_t)row_info->rowbytes - 1;
@ -2429,7 +2441,7 @@ png_do_expand(png_row_info *row_info, png_bytef *row,
*dp-- = 0xff; *dp-- = 0xff;
*dp-- = 0xff; *dp-- = 0xff;
} }
*dp-- = *sp--; *dp-- = *sp--;
*dp-- = *sp--; *dp-- = *sp--;
} }
} }
@ -2447,7 +2459,7 @@ png_do_expand(png_row_info *row_info, png_bytef *row,
dp = row + (png_size_t)(row_info->width << 2) - 1; dp = row + (png_size_t)(row_info->width << 2) - 1;
for (i = 0; i < row_info->width; i++) for (i = 0; i < row_info->width; i++)
{ {
if (*(sp - 2) == trans_value->red && if (*(sp - 2) == trans_value->red &&
*(sp - 1) == trans_value->green && *(sp - 1) == trans_value->green &&
*(sp - 0) == trans_value->blue) *(sp - 0) == trans_value->blue)
*dp-- = 0; *dp-- = 0;
@ -2465,7 +2477,7 @@ png_do_expand(png_row_info *row_info, png_bytef *row,
for (i = 0; i < row_info->width; i++) for (i = 0; i < row_info->width; i++)
{ {
if ((((png_uint_16)*(sp - 4) | if ((((png_uint_16)*(sp - 4) |
((png_uint_16)*(sp - 5) << 8)) == trans_value->red) && ((png_uint_16)*(sp - 5) << 8)) == trans_value->red) &&
(((png_uint_16)*(sp - 2) | (((png_uint_16)*(sp - 2) |
((png_uint_16)*(sp - 3) << 8)) == trans_value->green) && ((png_uint_16)*(sp - 3) << 8)) == trans_value->green) &&
(((png_uint_16)*(sp - 0) | (((png_uint_16)*(sp - 0) |
@ -2483,7 +2495,7 @@ png_do_expand(png_row_info *row_info, png_bytef *row,
*dp-- = *sp--; *dp-- = *sp--;
*dp-- = *sp--; *dp-- = *sp--;
*dp-- = *sp--; *dp-- = *sp--;
*dp-- = *sp--; *dp-- = *sp--;
*dp-- = *sp--; *dp-- = *sp--;
} }
} }
@ -2499,11 +2511,12 @@ png_do_expand(png_row_info *row_info, png_bytef *row,
#if defined(PNG_READ_DITHER_SUPPORTED) #if defined(PNG_READ_DITHER_SUPPORTED)
void void
png_do_dither(png_row_info *row_info, png_bytef *row, png_do_dither(png_row_infop row_info, png_bytep row,
png_byte *palette_lookup, png_byte *dither_lookup) png_bytep palette_lookup, png_bytep dither_lookup)
{ {
png_bytef *sp, *dp; png_bytep sp, dp;
png_uint_32 i; png_uint_32 i;
if (row && row_info) if (row && row_info)
{ {
if (row_info->color_type == PNG_COLOR_TYPE_RGB && if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
@ -2529,7 +2542,7 @@ png_do_dither(png_row_info *row_info, png_bytef *row,
((1 << PNG_DITHER_RED_BITS) - 1)) << ((1 << PNG_DITHER_RED_BITS) - 1)) <<
(PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
(((g >> (8 - PNG_DITHER_GREEN_BITS)) & (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
((1 << PNG_DITHER_GREEN_BITS) - 1)) << ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
(PNG_DITHER_BLUE_BITS)) | (PNG_DITHER_BLUE_BITS)) |
((b >> (8 - PNG_DITHER_BLUE_BITS)) & ((b >> (8 - PNG_DITHER_BLUE_BITS)) &
((1 << PNG_DITHER_BLUE_BITS) - 1)); ((1 << PNG_DITHER_BLUE_BITS) - 1));
@ -2556,7 +2569,7 @@ png_do_dither(png_row_info *row_info, png_bytef *row,
sp++; sp++;
p = (((r >> (8 - PNG_DITHER_RED_BITS)) & p = (((r >> (8 - PNG_DITHER_RED_BITS)) &
((1 << PNG_DITHER_RED_BITS) - 1)) << ((1 << PNG_DITHER_RED_BITS) - 1)) <<
(PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) | (PNG_DITHER_GREEN_BITS + PNG_DITHER_BLUE_BITS)) |
(((g >> (8 - PNG_DITHER_GREEN_BITS)) & (((g >> (8 - PNG_DITHER_GREEN_BITS)) &
((1 << PNG_DITHER_GREEN_BITS) - 1)) << ((1 << PNG_DITHER_GREEN_BITS) - 1)) <<
@ -2574,7 +2587,7 @@ png_do_dither(png_row_info *row_info, png_bytef *row,
} }
else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
dither_lookup && row_info->bit_depth == 8) dither_lookup && row_info->bit_depth == 8)
{ {
sp = row; sp = row;
for (i = 0; i < row_info->width; i++, sp++) for (i = 0; i < row_info->width; i++, sp++)
{ {
@ -2590,7 +2603,7 @@ static int png_gamma_shift[] =
{0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0}; {0x10, 0x21, 0x42, 0x84, 0x110, 0x248, 0x550, 0xff0};
void void
png_build_gamma_table(png_struct *png_ptr) png_build_gamma_table(png_structp png_ptr)
{ {
if (png_ptr->bit_depth <= 8) if (png_ptr->bit_depth <= 8)
{ {
@ -2599,7 +2612,7 @@ png_build_gamma_table(png_struct *png_ptr)
g = 1.0 / (png_ptr->gamma * png_ptr->display_gamma); g = 1.0 / (png_ptr->gamma * png_ptr->display_gamma);
png_ptr->gamma_table = (png_byte *)png_malloc(png_ptr, png_ptr->gamma_table = (png_bytep)png_malloc(png_ptr,
(png_uint_32)256); (png_uint_32)256);
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
@ -2612,7 +2625,7 @@ png_build_gamma_table(png_struct *png_ptr)
{ {
g = 1.0 / (png_ptr->gamma); g = 1.0 / (png_ptr->gamma);
png_ptr->gamma_to_1 = (png_byte *)png_malloc(png_ptr, png_ptr->gamma_to_1 = (png_bytep)png_malloc(png_ptr,
(png_uint_32)256); (png_uint_32)256);
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
@ -2623,7 +2636,7 @@ png_build_gamma_table(png_struct *png_ptr)
g = 1.0 / (png_ptr->display_gamma); g = 1.0 / (png_ptr->display_gamma);
png_ptr->gamma_from_1 = (png_byte *)png_malloc(png_ptr, png_ptr->gamma_from_1 = (png_bytep)png_malloc(png_ptr,
(png_uint_32)256); (png_uint_32)256);
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
@ -2633,16 +2646,15 @@ png_build_gamma_table(png_struct *png_ptr)
} }
} }
} }
else else
{ {
double g; double g;
int i, j, shift, num; int i, j, shift, num;
png_uint_32 ig; int sig_bit;
#if defined(PNG_READ_sBIT_SUPPORTED) png_uint_32 ig;
int sig_bit;
if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
{ {
sig_bit = (int)png_ptr->sig_bit.red; sig_bit = (int)png_ptr->sig_bit.red;
if ((int)png_ptr->sig_bit.green > sig_bit) if ((int)png_ptr->sig_bit.green > sig_bit)
sig_bit = png_ptr->sig_bit.green; sig_bit = png_ptr->sig_bit.green;
@ -2652,13 +2664,12 @@ png_build_gamma_table(png_struct *png_ptr)
else else
{ {
sig_bit = (int)png_ptr->sig_bit.gray; sig_bit = (int)png_ptr->sig_bit.gray;
} }
if (sig_bit > 0) if (sig_bit > 0)
shift = 16 - sig_bit; shift = 16 - sig_bit;
else else
#endif /* PNG_READ_sBIT_SUPPORTED */ shift = 0;
shift = 0;
if (png_ptr->transformations & PNG_16_TO_8) if (png_ptr->transformations & PNG_16_TO_8)
{ {
@ -2666,58 +2677,60 @@ png_build_gamma_table(png_struct *png_ptr)
shift = (16 - PNG_MAX_GAMMA_8); shift = (16 - PNG_MAX_GAMMA_8);
} }
if (shift > 8) if (shift > 8)
shift = 8; shift = 8;
if (shift < 0) if (shift < 0)
shift = 0; shift = 0;
png_ptr->gamma_shift = shift; png_ptr->gamma_shift = shift;
num = (1 << (8 - shift)); num = (1 << (8 - shift));
g = 1.0 / (png_ptr->gamma * png_ptr->display_gamma); g = 1.0 / (png_ptr->gamma * png_ptr->display_gamma);
png_ptr->gamma_16_table = (png_uint_16 **)png_malloc(png_ptr, png_ptr->gamma_16_table = (png_uint_16pp)png_malloc(png_ptr,
num * sizeof (png_uint_16 *)); num * sizeof (png_uint_16p ));
if ((png_ptr->transformations & PNG_16_TO_8) && if ((png_ptr->transformations & PNG_16_TO_8) &&
!(png_ptr->transformations & PNG_BACKGROUND)) !(png_ptr->transformations & PNG_BACKGROUND))
{ {
double fin, fout; double fin, fout;
png_uint_32 last, max; png_uint_32 last, max;
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
{ {
png_ptr->gamma_16_table[i] = (png_uint_16 *)png_malloc(png_ptr, png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
256 * sizeof (png_uint_16)); 256 * sizeof (png_uint_16));
} }
g = 1.0 / g; g = 1.0 / g;
last = 0; last = 0;
for (i = 0; i < 256; i++) for (i = 0; i < 256; i++)
{ {
fout = ((double)i + 0.5) / 256.0; fout = ((double)i + 0.5) / 256.0;
fin = pow(fout, g); fin = pow(fout, g);
max = (png_uint_32)(fin * (double)(num << 8)); max = (png_uint_32)(fin * (double)(num << 8));
while (last <= max) while (last <= max)
{ {
png_ptr->gamma_16_table[(int)(last >> 8)][(int)(last & 0xff)] = png_ptr->gamma_16_table[(int)(last & 0xff) >> shift]
(png_uint_16)i | ((png_uint_16)i << 8); [(int)(last >> (8 - shift))] =
(png_uint_16)i | ((png_uint_16)i << 8);
last++; last++;
} }
} }
while (last < (num << 8)) while (last < ((png_uint_32)num << 8))
{ {
png_ptr->gamma_16_table[(int)(last >> 8)][(int)(last & 0xff)] = png_ptr->gamma_16_table[(int)(last & 0xff) >> shift]
(png_uint_16)65535L; [(int)(last >> (8 - shift))] =
last++; (png_uint_16)65535L;
} last++;
}
} }
else else
{ {
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
{ {
png_ptr->gamma_16_table[i] = (png_uint_16 *)png_malloc(png_ptr, png_ptr->gamma_16_table[i] = (png_uint_16p)png_malloc(png_ptr,
256 * sizeof (png_uint_16)); 256 * sizeof (png_uint_16));
ig = (((png_uint_32)i * ig = (((png_uint_32)i *
@ -2735,12 +2748,12 @@ png_build_gamma_table(png_struct *png_ptr)
{ {
g = 1.0 / (png_ptr->gamma); g = 1.0 / (png_ptr->gamma);
png_ptr->gamma_16_to_1 = (png_uint_16 **)png_malloc(png_ptr, png_ptr->gamma_16_to_1 = (png_uint_16pp)png_malloc(png_ptr,
num * sizeof (png_uint_16 *)); num * sizeof (png_uint_16p ));
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
{ {
png_ptr->gamma_16_to_1[i] = (png_uint_16 *)png_malloc(png_ptr, png_ptr->gamma_16_to_1[i] = (png_uint_16p)png_malloc(png_ptr,
256 * sizeof (png_uint_16)); 256 * sizeof (png_uint_16));
ig = (((png_uint_32)i * ig = (((png_uint_32)i *
@ -2754,12 +2767,12 @@ png_build_gamma_table(png_struct *png_ptr)
} }
g = 1.0 / (png_ptr->display_gamma); g = 1.0 / (png_ptr->display_gamma);
png_ptr->gamma_16_from_1 = (png_uint_16 **)png_malloc(png_ptr, png_ptr->gamma_16_from_1 = (png_uint_16pp)png_malloc(png_ptr,
num * sizeof (png_uint_16 *)); num * sizeof (png_uint_16p));
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
{ {
png_ptr->gamma_16_from_1[i] = (png_uint_16 *)png_malloc(png_ptr, png_ptr->gamma_16_from_1[i] = (png_uint_16p)png_malloc(png_ptr,
256 * sizeof (png_uint_16)); 256 * sizeof (png_uint_16));
ig = (((png_uint_32)i * ig = (((png_uint_32)i *

View File

@ -1,10 +1,10 @@
/* pngrutil.c - utilities to read a png file /* pngrutil.c - utilities to read a png file
libpng 1.0 beta 2 - version 0.81 libpng 1.0 beta 2 - version 0.85
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
August 24, 1995 December 19, 1995
*/ */
#define PNG_INTERNAL #define PNG_INTERNAL
@ -12,7 +12,7 @@
/* grab an uint 32 from a buffer */ /* grab an uint 32 from a buffer */
png_uint_32 png_uint_32
png_get_uint_32(png_byte *buf) png_get_uint_32(png_bytep buf)
{ {
png_uint_32 i; png_uint_32 i;
@ -26,11 +26,11 @@ png_get_uint_32(png_byte *buf)
/* grab an uint 16 from a buffer */ /* grab an uint 16 from a buffer */
png_uint_16 png_uint_16
png_get_uint_16(png_byte *buf) png_get_uint_16(png_bytep buf)
{ {
png_uint_16 i; png_uint_16 i;
i = ((png_uint_16)(*buf) << 8) + i = ((png_uint_16)(*buf) << 8) +
(png_uint_16)(*(buf + 1)); (png_uint_16)(*(buf + 1));
return i; return i;
@ -38,33 +38,33 @@ png_get_uint_16(png_byte *buf)
/* read data, and run it through the crc */ /* read data, and run it through the crc */
void void
png_crc_read(png_struct *png_ptr, png_bytef *buf, png_uint_32 length) png_crc_read(png_structp png_ptr, png_bytep buf, png_uint_32 length)
{ {
(*(png_ptr->read_data_fn))(png_ptr, buf, length); png_read_data(png_ptr, buf, length);
png_calculate_crc(png_ptr, buf, length); png_calculate_crc(png_ptr, buf, length);
} }
/* skip data, but calcuate the crc anyway */ /* skip data, but calcuate the crc anyway */
void void
png_crc_skip(png_struct *png_ptr, png_uint_32 length) png_crc_skip(png_structp png_ptr, png_uint_32 length)
{ {
png_uint_32 i; png_uint_32 i;
for (i = length; i > png_ptr->zbuf_size; i -= png_ptr->zbuf_size) for (i = length; i > png_ptr->zbuf_size; i -= png_ptr->zbuf_size)
{ {
(*(png_ptr->read_data_fn))(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); png_read_data(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
png_calculate_crc(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); png_calculate_crc(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
} }
if (i) if (i)
{ {
(*(png_ptr->read_data_fn))(png_ptr, png_ptr->zbuf, i); png_read_data(png_ptr, png_ptr->zbuf, i);
png_calculate_crc(png_ptr, png_ptr->zbuf, i); png_calculate_crc(png_ptr, png_ptr->zbuf, i);
} }
} }
/* read and check the IDHR chunk */ /* read and check the IDHR chunk */
void void
png_handle_IHDR(png_struct *png_ptr, png_info *info, png_uint_32 length) png_handle_IHDR(png_structp png_ptr, png_infop info, png_uint_32 length)
{ {
png_byte buf[13]; png_byte buf[13];
png_uint_32 width, height; png_uint_32 width, height;
@ -73,7 +73,7 @@ png_handle_IHDR(png_struct *png_ptr, png_info *info, png_uint_32 length)
/* check the length */ /* check the length */
if (length != 13) if (length != 13)
(*(png_ptr->error_fn))(png_ptr, "Invalid IHDR chunk"); png_error(png_ptr, "Invalid IHDR chunk");
png_crc_read(png_ptr, buf, 13); 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 */ /* check for width and height valid values */
if (width == 0 || height == 0) if (width == 0 || height == 0)
(*(png_ptr->error_fn))(png_ptr, "Invalid Width or Height Found"); png_error(png_ptr, "Invalid Width or Height Found");
/* check other values */ /* check other values */
if (bit_depth != 1 && bit_depth != 2 && if (bit_depth != 1 && bit_depth != 2 &&
bit_depth != 4 && bit_depth != 8 && bit_depth != 4 && bit_depth != 8 &&
bit_depth != 16) bit_depth != 16)
(*(png_ptr->error_fn))(png_ptr, "Invalid Bit Depth Found"); png_error(png_ptr, "Invalid Bit Depth Found");
if (color_type < 0 || color_type == 1 || if (color_type < 0 || color_type == 1 ||
color_type == 5 || color_type > 6) color_type == 5 || color_type > 6)
(*(png_ptr->error_fn))(png_ptr, "Invalid Color Type Found"); png_error(png_ptr, "Invalid Color Type Found");
if (color_type == PNG_COLOR_TYPE_PALETTE && if (color_type == PNG_COLOR_TYPE_PALETTE &&
bit_depth == 16) bit_depth == 16)
(*(png_ptr->error_fn))(png_ptr, "Found Invalid Color Type and Bit Depth Combination"); png_error(png_ptr, "Found Invalid Color Type and Bit Depth Combination");
if ((color_type == PNG_COLOR_TYPE_RGB || if ((color_type == PNG_COLOR_TYPE_RGB ||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA || color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
color_type == PNG_COLOR_TYPE_RGB_ALPHA) && color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
bit_depth < 8) bit_depth < 8)
(*(png_ptr->error_fn))(png_ptr, "Found Invalid Color Type and Bit Depth Combination"); png_error(png_ptr, "Found Invalid Color Type and Bit Depth Combination");
if (interlace_type > 1) if (interlace_type > 1)
(*(png_ptr->error_fn))(png_ptr, "Found Unsupported Interlace Value"); png_error(png_ptr, "Found Invalid Interlace Value");
if (compression_type > 0) if (compression_type > 0)
(*(png_ptr->error_fn))(png_ptr, "Found Unsupported Compression Value"); png_error(png_ptr, "Found Invalid Compression Value");
if (filter_type > 0) if (filter_type > 0)
(*(png_ptr->error_fn))(png_ptr, "Found Unsupported Filter Value"); png_error(png_ptr, "Found Invalid Filter Value");
/* set internal variables */ /* set internal variables */
png_ptr->width = width; png_ptr->width = width;
@ -154,18 +154,16 @@ png_handle_IHDR(png_struct *png_ptr, png_info *info, png_uint_32 length)
/* read and check the palette */ /* read and check the palette */
void void
png_handle_PLTE(png_struct *png_ptr, png_info *info, png_uint_32 length) png_handle_PLTE(png_structp png_ptr, png_infop info, png_uint_32 length)
{ {
int num, i; int num, i;
png_color *palette; png_colorp palette;
if (length % 3) if (length % 3)
(*(png_ptr->error_fn))(png_ptr, "Invalid Palette Chunk"); png_error(png_ptr, "Invalid Palette Chunk");
num = (int)length / 3; num = (int)length / 3;
palette = (png_color *)png_malloc(png_ptr, num * sizeof (png_color)); palette = (png_colorp)png_malloc(png_ptr, num * sizeof (png_color));
png_ptr->do_free |= PNG_FREE_PALETTE;
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
{ {
png_byte buf[3]; png_byte buf[3];
@ -183,7 +181,7 @@ png_handle_PLTE(png_struct *png_ptr, png_info *info, png_uint_32 length)
#if defined(PNG_READ_gAMA_SUPPORTED) #if defined(PNG_READ_gAMA_SUPPORTED)
void void
png_handle_gAMA(png_struct *png_ptr, png_info *info, png_uint_32 length) png_handle_gAMA(png_structp png_ptr, png_infop info, png_uint_32 length)
{ {
png_uint_32 igamma; png_uint_32 igamma;
float gamma; float gamma;
@ -191,7 +189,6 @@ png_handle_gAMA(png_struct *png_ptr, png_info *info, png_uint_32 length)
if (length != 4) if (length != 4)
{ {
(*(png_ptr->warning_fn))(png_ptr,"Incorrect gAMA chunk length");
png_crc_skip(png_ptr, length); png_crc_skip(png_ptr, length);
return; return;
} }
@ -200,7 +197,7 @@ png_handle_gAMA(png_struct *png_ptr, png_info *info, png_uint_32 length)
igamma = png_get_uint_32(buf); igamma = png_get_uint_32(buf);
/* check for zero gamma */ /* check for zero gamma */
if (!igamma) if (!igamma)
return; return;
gamma = (float)igamma / (float)100000.0; gamma = (float)igamma / (float)100000.0;
png_read_gAMA(png_ptr, info, gamma); png_read_gAMA(png_ptr, info, gamma);
@ -210,20 +207,18 @@ png_handle_gAMA(png_struct *png_ptr, png_info *info, png_uint_32 length)
#if defined(PNG_READ_sBIT_SUPPORTED) #if defined(PNG_READ_sBIT_SUPPORTED)
void void
png_handle_sBIT(png_struct *png_ptr, png_info *info, png_uint_32 length) png_handle_sBIT(png_structp png_ptr, png_infop info, png_uint_32 length)
{ {
int slen; int slen;
register int index = 0;
png_byte buf[4]; png_byte buf[4];
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
slen = 3; slen = 3;
else else
slen = png_ptr->channels; slen = png_ptr->channels;
if (length != (png_uint_32)slen) if (length != (png_uint_32)slen)
{ {
(*(png_ptr->warning_fn))(png_ptr, "Incorrect sBIT chunk length");
png_crc_skip(png_ptr, length); png_crc_skip(png_ptr, length);
return; return;
} }
@ -231,35 +226,23 @@ png_handle_sBIT(png_struct *png_ptr, png_info *info, png_uint_32 length)
png_crc_read(png_ptr, buf, length); png_crc_read(png_ptr, buf, length);
if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
{ {
png_ptr->sig_bit.red = buf[index++]; png_ptr->sig_bit.red = buf[0];
png_ptr->sig_bit.green = buf[index++]; png_ptr->sig_bit.green = buf[1];
png_ptr->sig_bit.blue = buf[index++]; png_ptr->sig_bit.blue = buf[2];
png_ptr->sig_bit.gray = 0; png_ptr->sig_bit.alpha = buf[3];
} }
else else
{ {
png_ptr->sig_bit.red = 0; png_ptr->sig_bit.gray = buf[0];
png_ptr->sig_bit.green = 0; png_ptr->sig_bit.alpha = buf[1];
png_ptr->sig_bit.blue = 0;
png_ptr->sig_bit.gray = buf[0];
} }
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)); png_read_sBIT(png_ptr, info, &(png_ptr->sig_bit));
} }
#endif #endif
#if defined(PNG_READ_cHRM_SUPPORTED) #if defined(PNG_READ_cHRM_SUPPORTED)
void void
png_handle_cHRM(png_struct *png_ptr, png_info *info, png_uint_32 length) png_handle_cHRM(png_structp png_ptr, png_infop info, png_uint_32 length)
{ {
png_byte buf[4]; png_byte buf[4];
png_uint_32 v; png_uint_32 v;
@ -267,9 +250,8 @@ png_handle_cHRM(png_struct *png_ptr, png_info *info, png_uint_32 length)
if (length != 32) if (length != 32)
{ {
(*(png_ptr->warning_fn))(png_ptr, "Incorrect cHRM chunk length");
png_crc_skip(png_ptr, length); png_crc_skip(png_ptr, length);
return; return;
} }
png_crc_read(png_ptr, buf, 4); png_crc_read(png_ptr, buf, 4);
@ -305,27 +287,25 @@ png_handle_cHRM(png_struct *png_ptr, png_info *info, png_uint_32 length)
blue_y = (float)v / (float)100000.0; blue_y = (float)v / (float)100000.0;
png_read_cHRM(png_ptr, info, png_read_cHRM(png_ptr, info,
white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
} }
#endif #endif
#if defined(PNG_READ_tRNS_SUPPORTED) #if defined(PNG_READ_tRNS_SUPPORTED)
void void
png_handle_tRNS(png_struct *png_ptr, png_info *info, png_uint_32 length) png_handle_tRNS(png_structp png_ptr, png_infop info, png_uint_32 length)
{ {
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{ {
if (length > png_ptr->num_palette) if (length > png_ptr->num_palette)
{ {
(*(png_ptr->warning_fn))(png_ptr, "Incorrect tRNS chunk length");
png_crc_skip(png_ptr, length); png_crc_skip(png_ptr, length);
return; return;
} }
png_ptr->trans = png_malloc(png_ptr, length); png_ptr->trans = (png_bytep)png_malloc(png_ptr, length);
png_ptr->do_free |= PNG_FREE_TRANS;
png_crc_read(png_ptr, png_ptr->trans, length); png_crc_read(png_ptr, png_ptr->trans, length);
png_ptr->num_trans = (int)length; png_ptr->num_trans = (int)length;
} }
else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
{ {
@ -333,7 +313,6 @@ png_handle_tRNS(png_struct *png_ptr, png_info *info, png_uint_32 length)
if (length != 6) if (length != 6)
{ {
(*(png_ptr->warning_fn))(png_ptr, "Incorrect tRNS chunk length");
png_crc_skip(png_ptr, length); png_crc_skip(png_ptr, length);
return; return;
} }
@ -350,7 +329,6 @@ png_handle_tRNS(png_struct *png_ptr, png_info *info, png_uint_32 length)
if (length != 2) if (length != 2)
{ {
(*(png_ptr->warning_fn))(png_ptr, "Incorrect tRNS chunk length");
png_crc_skip(png_ptr, length); png_crc_skip(png_ptr, length);
return; return;
} }
@ -360,7 +338,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); png_ptr->trans_values.gray = png_get_uint_16(buf);
} }
else else
(*(png_ptr->error_fn))(png_ptr, "Invalid tRNS chunk"); png_error(png_ptr, "Invalid tRNS chunk");
png_read_tRNS(png_ptr, info, png_ptr->trans, png_ptr->num_trans, png_read_tRNS(png_ptr, info, png_ptr->trans, png_ptr->num_trans,
&(png_ptr->trans_values)); &(png_ptr->trans_values));
@ -369,7 +347,7 @@ png_handle_tRNS(png_struct *png_ptr, png_info *info, png_uint_32 length)
#if defined(PNG_READ_bKGD_SUPPORTED) #if defined(PNG_READ_bKGD_SUPPORTED)
void void
png_handle_bKGD(png_struct *png_ptr, png_info *info, png_uint_32 length) png_handle_bKGD(png_structp png_ptr, png_infop info, png_uint_32 length)
{ {
int truelen; int truelen;
png_byte buf[6]; png_byte buf[6];
@ -383,7 +361,6 @@ png_handle_bKGD(png_struct *png_ptr, png_info *info, png_uint_32 length)
if (length != (png_uint_32)truelen) if (length != (png_uint_32)truelen)
{ {
(*(png_ptr->warning_fn))(png_ptr, "Incorrect bKGD chunk length");
png_crc_skip(png_ptr, length); png_crc_skip(png_ptr, length);
return; return;
} }
@ -406,21 +383,19 @@ png_handle_bKGD(png_struct *png_ptr, png_info *info, png_uint_32 length)
#if defined(PNG_READ_hIST_SUPPORTED) #if defined(PNG_READ_hIST_SUPPORTED)
void void
png_handle_hIST(png_struct *png_ptr, png_info *info, png_uint_32 length) png_handle_hIST(png_structp png_ptr, png_infop info, png_uint_32 length)
{ {
int num, i; int num, i;
if (length != 2 * png_ptr->num_palette) if (length != 2 * png_ptr->num_palette)
{ {
(*(png_ptr->warning_fn))(png_ptr, "Incorrect hIST chunk length");
png_crc_skip(png_ptr, length); png_crc_skip(png_ptr, length);
return; return;
} }
num = (int)length / 2; num = (int)length / 2;
png_ptr->hist = png_malloc(png_ptr, num * sizeof (png_uint_16)); png_ptr->hist = (png_uint_16p)png_malloc(png_ptr,
png_ptr->do_free |= PNG_FREE_HIST; num * sizeof (png_uint_16));
for (i = 0; i < num; i++) for (i = 0; i < num; i++)
{ {
png_byte buf[2]; png_byte buf[2];
@ -434,7 +409,7 @@ png_handle_hIST(png_struct *png_ptr, png_info *info, png_uint_32 length)
#if defined(PNG_READ_pHYs_SUPPORTED) #if defined(PNG_READ_pHYs_SUPPORTED)
void void
png_handle_pHYs(png_struct *png_ptr, png_info *info, png_uint_32 length) png_handle_pHYs(png_structp png_ptr, png_infop info, png_uint_32 length)
{ {
png_byte buf[9]; png_byte buf[9];
png_uint_32 res_x, res_y; png_uint_32 res_x, res_y;
@ -442,10 +417,9 @@ png_handle_pHYs(png_struct *png_ptr, png_info *info, png_uint_32 length)
if (length != 9) if (length != 9)
{ {
(*(png_ptr->warning_fn))(png_ptr, "Incorrect pHYS chunk length");
png_crc_skip(png_ptr, length); png_crc_skip(png_ptr, length);
return; return;
} }
png_crc_read(png_ptr, buf, 9); png_crc_read(png_ptr, buf, 9);
@ -458,7 +432,7 @@ png_handle_pHYs(png_struct *png_ptr, png_info *info, png_uint_32 length)
#if defined(PNG_READ_oFFs_SUPPORTED) #if defined(PNG_READ_oFFs_SUPPORTED)
void void
png_handle_oFFs(png_struct *png_ptr, png_info *info, png_uint_32 length) png_handle_oFFs(png_structp png_ptr, png_infop info, png_uint_32 length)
{ {
png_byte buf[9]; png_byte buf[9];
png_uint_32 offset_x, offset_y; png_uint_32 offset_x, offset_y;
@ -466,7 +440,6 @@ png_handle_oFFs(png_struct *png_ptr, png_info *info, png_uint_32 length)
if (length != 9) if (length != 9)
{ {
(*(png_ptr->warning_fn))(png_ptr, "Incorrect oFFs chunk length");
png_crc_skip(png_ptr, length); png_crc_skip(png_ptr, length);
return; return;
} }
@ -482,14 +455,13 @@ png_handle_oFFs(png_struct *png_ptr, png_info *info, png_uint_32 length)
#if defined(PNG_READ_tIME_SUPPORTED) #if defined(PNG_READ_tIME_SUPPORTED)
void void
png_handle_tIME(png_struct *png_ptr, png_info *info, png_uint_32 length) png_handle_tIME(png_structp png_ptr, png_infop info, png_uint_32 length)
{ {
png_byte buf[7]; png_byte buf[7];
png_time mod_time; png_time mod_time;
if (length != 7) if (length != 7)
{ {
(*(png_ptr->warning_fn))(png_ptr, "Incorrect tIME chunk length");
png_crc_skip(png_ptr, length); png_crc_skip(png_ptr, length);
return; return;
} }
@ -501,7 +473,7 @@ png_handle_tIME(png_struct *png_ptr, png_info *info, png_uint_32 length)
mod_time.hour = buf[4]; mod_time.hour = buf[4];
mod_time.day = buf[3]; mod_time.day = buf[3];
mod_time.month = buf[2]; mod_time.month = buf[2];
mod_time.year = png_get_uint_16(buf); mod_time.year = png_get_uint_16(buf);
png_read_tIME(png_ptr, info, &mod_time); png_read_tIME(png_ptr, info, &mod_time);
} }
@ -510,16 +482,16 @@ png_handle_tIME(png_struct *png_ptr, png_info *info, png_uint_32 length)
#if defined(PNG_READ_tEXt_SUPPORTED) #if defined(PNG_READ_tEXt_SUPPORTED)
/* note: this does not correctly handle chunks that are > 64K */ /* note: this does not correctly handle chunks that are > 64K */
void void
png_handle_tEXt(png_struct *png_ptr, png_info *info, png_uint_32 length) png_handle_tEXt(png_structp png_ptr, png_infop info, png_uint_32 length)
{ {
charf *key; png_charp key;
charf *text; png_charp text;
text = NULL; text = NULL;
key = (charf *)png_large_malloc(png_ptr, length + 1); key = (png_charp )png_large_malloc(png_ptr, length + 1);
png_crc_read(png_ptr, (png_bytef *)key, length); png_crc_read(png_ptr, (png_bytep )key, length);
key[(png_size_t)length] = '\0'; key[(png_size_t)length] = '\0';
for (text = key; *text; text++) for (text = key; *text; text++)
/* empty loop */ ; /* empty loop */ ;
@ -534,17 +506,17 @@ png_handle_tEXt(png_struct *png_ptr, png_info *info, png_uint_32 length)
#if defined(PNG_READ_zTXt_SUPPORTED) #if defined(PNG_READ_zTXt_SUPPORTED)
/* note: this does not correctly handle chunks that are > 64K compressed */ /* note: this does not correctly handle chunks that are > 64K compressed */
void void
png_handle_zTXt(png_struct *png_ptr, png_info *info, png_uint_32 length) png_handle_zTXt(png_structp png_ptr, png_infop info, png_uint_32 length)
{ {
charf *key; png_charp key;
charf *text; png_charp text;
int ret = Z_STREAM_END; int ret;
png_uint_32 text_size, key_size; png_uint_32 text_size, key_size;
text = NULL; text = NULL;
key = png_large_malloc(png_ptr, length + 1); key = png_large_malloc(png_ptr, length + 1);
png_crc_read(png_ptr, (png_bytef *)key, length); png_crc_read(png_ptr, (png_bytep )key, length);
key[(png_size_t)length] = '\0'; key[(png_size_t)length] = '\0';
for (text = key; *text; text++) for (text = key; *text; text++)
@ -553,7 +525,6 @@ png_handle_zTXt(png_struct *png_ptr, png_info *info, png_uint_32 length)
/* zTXt can't have zero text */ /* zTXt can't have zero text */
if (text == key + (png_size_t)length) if (text == key + (png_size_t)length)
{ {
(*(png_ptr->warning_fn))(png_ptr, "Zero length zTXt chunk");
png_large_free(png_ptr, key); png_large_free(png_ptr, key);
return; return;
} }
@ -568,7 +539,7 @@ png_handle_zTXt(png_struct *png_ptr, png_info *info, png_uint_32 length)
text++; text++;
png_ptr->zstream->next_in = (png_bytef *)text; png_ptr->zstream->next_in = (png_bytep )text;
png_ptr->zstream->avail_in = (uInt)(length - (text - key)); png_ptr->zstream->avail_in = (uInt)(length - (text - key));
png_ptr->zstream->next_out = png_ptr->zbuf; png_ptr->zstream->next_out = png_ptr->zbuf;
png_ptr->zstream->avail_out = (png_size_t)png_ptr->zbuf_size; png_ptr->zstream->avail_out = (png_size_t)png_ptr->zbuf_size;
@ -579,14 +550,10 @@ png_handle_zTXt(png_struct *png_ptr, png_info *info, png_uint_32 length)
while (png_ptr->zstream->avail_in) while (png_ptr->zstream->avail_in)
{ {
ret = inflate(png_ptr->zstream, Z_PARTIAL_FLUSH); ret = inflate(png_ptr->zstream, Z_PARTIAL_FLUSH);
if (ret != Z_OK && ret != Z_STREAM_END) if (ret != Z_OK && ret != Z_STREAM_END)
{ {
if (png_ptr->zstream->msg) inflateReset(png_ptr->zstream);
(*(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_ptr->zstream->avail_in = 0;
png_large_free(png_ptr, key); png_large_free(png_ptr, key);
png_large_free(png_ptr, text); png_large_free(png_ptr, text);
@ -596,7 +563,7 @@ png_handle_zTXt(png_struct *png_ptr, png_info *info, png_uint_32 length)
{ {
if (!text) if (!text)
{ {
text = png_malloc(png_ptr, text = (png_charp)png_malloc(png_ptr,
png_ptr->zbuf_size - png_ptr->zstream->avail_out + png_ptr->zbuf_size - png_ptr->zstream->avail_out +
key_size + 1); key_size + 1);
png_memcpy(text + (png_size_t)key_size, png_ptr->zbuf, png_memcpy(text + (png_size_t)key_size, png_ptr->zbuf,
@ -608,7 +575,7 @@ png_handle_zTXt(png_struct *png_ptr, png_info *info, png_uint_32 length)
} }
else else
{ {
charf *tmp; png_charp tmp;
tmp = text; tmp = text;
text = png_large_malloc(png_ptr, text_size + text = png_large_malloc(png_ptr, text_size +
@ -635,7 +602,7 @@ png_handle_zTXt(png_struct *png_ptr, png_info *info, png_uint_32 length)
break; break;
} }
inflateReset(png_ptr->zstream); inflateReset(png_ptr->zstream);
png_ptr->zstream->avail_in = 0; png_ptr->zstream->avail_in = 0;
if (ret != Z_STREAM_END) if (ret != Z_STREAM_END)
@ -666,7 +633,7 @@ png_handle_zTXt(png_struct *png_ptr, png_info *info, png_uint_32 length)
you want all pixels to be combined, pass 0xff (255) in mask. you want all pixels to be combined, pass 0xff (255) in mask.
*/ */
void void
png_combine_row(png_struct *png_ptr, png_bytef *row, png_combine_row(png_structp png_ptr, png_bytep row,
int mask) int mask)
{ {
if (mask == 0xff) if (mask == 0xff)
@ -681,8 +648,8 @@ png_combine_row(png_struct *png_ptr, png_bytef *row,
{ {
case 1: case 1:
{ {
png_bytef *sp; png_bytep sp;
png_bytef *dp; png_bytep dp;
int m; int m;
int shift; int shift;
png_uint_32 i; png_uint_32 i;
@ -719,8 +686,8 @@ png_combine_row(png_struct *png_ptr, png_bytef *row,
} }
case 2: case 2:
{ {
png_bytef *sp; png_bytep sp;
png_bytef *dp; png_bytep dp;
int m; int m;
int shift; int shift;
png_uint_32 i; png_uint_32 i;
@ -756,8 +723,8 @@ png_combine_row(png_struct *png_ptr, png_bytef *row,
} }
case 4: case 4:
{ {
png_bytef *sp; png_bytep sp;
png_bytef *dp; png_bytep dp;
int m; int m;
int shift; int shift;
png_uint_32 i; png_uint_32 i;
@ -793,8 +760,8 @@ png_combine_row(png_struct *png_ptr, png_bytef *row,
} }
default: default:
{ {
png_bytef *sp; png_bytep sp;
png_bytef *dp; png_bytep dp;
png_uint_32 i; png_uint_32 i;
int pixel_bytes, m; int pixel_bytes, m;
@ -826,7 +793,7 @@ png_combine_row(png_struct *png_ptr, png_bytef *row,
#if defined(PNG_READ_INTERLACING_SUPPORTED) #if defined(PNG_READ_INTERLACING_SUPPORTED)
void void
png_do_read_interlace(png_row_info *row_info, png_bytef *row, int pass) png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass)
{ {
if (row && row_info) if (row && row_info)
{ {
@ -838,7 +805,7 @@ png_do_read_interlace(png_row_info *row_info, png_bytef *row, int pass)
{ {
case 1: case 1:
{ {
png_bytef *sp, *dp; png_bytep sp, dp;
int sshift, dshift; int sshift, dshift;
png_byte v; png_byte v;
png_uint_32 i; png_uint_32 i;
@ -875,7 +842,7 @@ png_do_read_interlace(png_row_info *row_info, png_bytef *row, int pass)
} }
case 2: case 2:
{ {
png_bytef *sp, *dp; png_bytep sp, dp;
int sshift, dshift; int sshift, dshift;
png_byte v; png_byte v;
png_uint_32 i, j; png_uint_32 i, j;
@ -911,7 +878,7 @@ png_do_read_interlace(png_row_info *row_info, png_bytef *row, int pass)
} }
case 4: case 4:
{ {
png_bytef *sp, *dp; png_bytep sp, dp;
int sshift, dshift; int sshift, dshift;
png_byte v; png_byte v;
png_uint_32 i; png_uint_32 i;
@ -948,7 +915,7 @@ png_do_read_interlace(png_row_info *row_info, png_bytef *row, int pass)
} }
default: default:
{ {
png_bytef *sp, *dp; png_bytep sp, dp;
png_byte v[8]; png_byte v[8];
png_uint_32 i; png_uint_32 i;
int j; int j;
@ -979,8 +946,8 @@ png_do_read_interlace(png_row_info *row_info, png_bytef *row, int pass)
#endif #endif
void void
png_read_filter_row(png_row_info *row_info, png_bytef *row, png_read_filter_row(png_row_infop row_info, png_bytep row,
png_bytef *prev_row, int filter) png_bytep prev_row, int filter)
{ {
switch (filter) switch (filter)
{ {
@ -990,8 +957,8 @@ png_read_filter_row(png_row_info *row_info, png_bytef *row,
{ {
png_uint_32 i; png_uint_32 i;
int bpp; int bpp;
png_bytef *rp; png_bytep rp;
png_bytef *lp; png_bytep lp;
bpp = (row_info->pixel_depth + 7) / 8; bpp = (row_info->pixel_depth + 7) / 8;
for (i = (png_uint_32)bpp, rp = row + bpp, lp = row; for (i = (png_uint_32)bpp, rp = row + bpp, lp = row;
@ -1004,8 +971,8 @@ png_read_filter_row(png_row_info *row_info, png_bytef *row,
case 2: case 2:
{ {
png_uint_32 i; png_uint_32 i;
png_bytef *rp; png_bytep rp;
png_bytef *pp; png_bytep pp;
for (i = 0, rp = row, pp = prev_row; for (i = 0, rp = row, pp = prev_row;
i < row_info->rowbytes; i++, rp++, pp++) i < row_info->rowbytes; i++, rp++, pp++)
@ -1018,9 +985,9 @@ png_read_filter_row(png_row_info *row_info, png_bytef *row,
{ {
png_uint_32 i; png_uint_32 i;
int bpp; int bpp;
png_bytef *rp; png_bytep rp;
png_bytef *pp; png_bytep pp;
png_bytef *lp; png_bytep lp;
bpp = (row_info->pixel_depth + 7) / 8; bpp = (row_info->pixel_depth + 7) / 8;
for (i = 0, rp = row, pp = prev_row; for (i = 0, rp = row, pp = prev_row;
@ -1040,10 +1007,10 @@ png_read_filter_row(png_row_info *row_info, png_bytef *row,
{ {
int bpp; int bpp;
png_uint_32 i; png_uint_32 i;
png_bytef *rp; png_bytep rp;
png_bytef *pp; png_bytep pp;
png_bytef *lp; png_bytep lp;
png_bytef *cp; png_bytep cp;
bpp = (row_info->pixel_depth + 7) / 8; bpp = (row_info->pixel_depth + 7) / 8;
for (i = 0, rp = row, pp = prev_row, for (i = 0, rp = row, pp = prev_row,
@ -1084,7 +1051,7 @@ png_read_filter_row(png_row_info *row_info, png_bytef *row,
} }
void void
png_read_finish_row(png_struct *png_ptr) png_read_finish_row(png_structp png_ptr)
{ {
png_ptr->row_number++; png_ptr->row_number++;
if (png_ptr->row_number < png_ptr->num_rows) if (png_ptr->row_number < png_ptr->num_rows)
@ -1138,19 +1105,19 @@ png_read_finish_row(png_struct *png_ptr)
png_byte buf[4]; png_byte buf[4];
png_uint_32 crc; png_uint_32 crc;
(*(png_ptr->read_data_fn))(png_ptr, buf, 4); png_read_data(png_ptr, buf, 4);
crc = png_get_uint_32(buf); crc = png_get_uint_32(buf);
if (((crc ^ 0xffffffffL) & 0xffffffffL) != if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
(png_ptr->crc & 0xffffffffL)) (png_ptr->crc & 0xffffffffL))
(*(png_ptr->error_fn))(png_ptr, "Bad CRC value"); png_error(png_ptr, "Bad CRC value");
(*(png_ptr->read_data_fn))(png_ptr, buf, 4); png_read_data(png_ptr, buf, 4);
png_ptr->idat_size = png_get_uint_32(buf); png_ptr->idat_size = png_get_uint_32(buf);
png_reset_crc(png_ptr); png_reset_crc(png_ptr);
png_crc_read(png_ptr, buf, 4); png_crc_read(png_ptr, buf, 4);
if (memcmp(buf, png_IDAT, 4)) if (png_memcmp(buf, png_IDAT, 4))
(*(png_ptr->error_fn))(png_ptr, "Not enough image data"); png_error(png_ptr, "Not enough image data");
} }
png_ptr->zstream->avail_in = (uInt)png_ptr->zbuf_size; png_ptr->zstream->avail_in = (uInt)png_ptr->zbuf_size;
@ -1160,27 +1127,27 @@ png_read_finish_row(png_struct *png_ptr)
png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream->avail_in); png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream->avail_in);
png_ptr->idat_size -= png_ptr->zstream->avail_in; png_ptr->idat_size -= png_ptr->zstream->avail_in;
} }
ret = inflate(png_ptr->zstream, Z_PARTIAL_FLUSH); ret = inflate(png_ptr->zstream, Z_PARTIAL_FLUSH);
if (ret == Z_STREAM_END) if (ret == Z_STREAM_END)
{ {
if (!(png_ptr->zstream->avail_out) || png_ptr->zstream->avail_in || if (!(png_ptr->zstream->avail_out) || png_ptr->zstream->avail_in ||
png_ptr->idat_size) png_ptr->idat_size)
(*(png_ptr->warning_fn))(png_ptr, "Extra compressed data"); png_error(png_ptr, "Extra compressed data");
png_ptr->mode = PNG_AT_LAST_IDAT; png_ptr->mode = PNG_AT_LAST_IDAT;
break; break;
} }
if (ret != Z_OK) if (ret != Z_OK)
(*(png_ptr->error_fn))(png_ptr, "Compression Error"); png_error(png_ptr, "Compression Error");
if (!(png_ptr->zstream->avail_out)) if (!(png_ptr->zstream->avail_out))
(*(png_ptr->error_fn))(png_ptr, "Extra compressed data"); png_error(png_ptr, "Extra compressed data");
} while (1); } while (1);
png_ptr->zstream->avail_out = 0; png_ptr->zstream->avail_out = 0;
} }
if (png_ptr->idat_size || png_ptr->zstream->avail_in) if (png_ptr->idat_size || png_ptr->zstream->avail_in)
(*(png_ptr->warning_fn))(png_ptr, "Extra compression data"); png_error(png_ptr, "Extra compression data");
inflateReset(png_ptr->zstream); inflateReset(png_ptr->zstream);
@ -1188,7 +1155,7 @@ png_read_finish_row(png_struct *png_ptr)
} }
void void
png_read_start_row(png_struct *png_ptr) png_read_start_row(png_structp png_ptr)
{ {
int max_pixel_depth; int max_pixel_depth;
png_uint_32 rowbytes; png_uint_32 rowbytes;
@ -1292,13 +1259,13 @@ png_read_start_row(png_struct *png_ptr)
1 + ((max_pixel_depth + 7) >> 3); 1 + ((max_pixel_depth + 7) >> 3);
#ifdef PNG_MAX_MALLOC_64K #ifdef PNG_MAX_MALLOC_64K
if (rowbytes > 65536L) if (rowbytes > 65536L)
(*(png_ptr->error_fn))(png_ptr, "This image requires a row greater then 64KB"); png_error(png_ptr, "This image requires a row greater then 64KB");
#endif #endif
png_ptr->row_buf = (png_bytef *)png_large_malloc(png_ptr, rowbytes); png_ptr->row_buf = (png_bytep )png_large_malloc(png_ptr, rowbytes);
#ifdef PNG_MAX_MALLOC_64K #ifdef PNG_MAX_MALLOC_64K
if (png_ptr->rowbytes + 1 > 65536L) if (png_ptr->rowbytes + 1 > 65536L)
(*(png_ptr->error_fn))(png_ptr, "This image requires a row greater then 64KB"); png_error(png_ptr, "This image requires a row greater then 64KB");
#endif #endif
png_ptr->prev_row = png_large_malloc(png_ptr, png_ptr->prev_row = png_large_malloc(png_ptr,
png_ptr->rowbytes + 1); png_ptr->rowbytes + 1);

View File

@ -15,11 +15,12 @@
#endif #endif
/* defined so I can write to a file on gui/windowing platforms */ /* defined so I can write to a file on gui/windowing platforms */
#define STDERR stderr /* #define STDERR stderr */
#define STDERR stdout /* for DOS */
/* input and output filenames */ /* input and output filenames */
char inname[] = "pngtest.png"; char inname[] = "pngtest.png";
char outname[] = "testout.png"; char outname[] = "pngout.png";
png_struct read_ptr; png_struct read_ptr;
png_struct write_ptr; png_struct write_ptr;
@ -31,12 +32,12 @@ char inbuf[256], outbuf[256];
int main() int main()
{ {
FILE *fpin, *fpout; FILE *fpin, *fpout;
png_byte *row_buf; png_bytep row_buf;
png_uint_32 rowbytes; png_uint_32 rowbytes;
png_uint_32 y; png_uint_32 y;
int channels, num_pass, pass; int channels, num_pass, pass;
row_buf = (png_byte *)0; row_buf = (png_bytep )0;
fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING); fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
@ -79,10 +80,10 @@ int main()
return 1; return 1;
} }
png_info_init(&info_ptr);
png_info_init(&end_info);
png_read_init(&read_ptr); png_read_init(&read_ptr);
png_write_init(&write_ptr); png_write_init(&write_ptr);
png_info_init(&info_ptr);
png_info_init(&end_info);
png_init_io(&read_ptr, fpin); png_init_io(&read_ptr, fpin);
png_init_io(&write_ptr, fpout); png_init_io(&write_ptr, fpout);
@ -97,15 +98,12 @@ int main()
if (info_ptr.color_type & 4) if (info_ptr.color_type & 4)
channels++; 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); rowbytes = ((info_ptr.width * info_ptr.bit_depth * channels + 7) >> 3);
row_buf = (png_byte *)malloc((size_t)rowbytes); row_buf = (png_bytep )malloc((size_t)rowbytes);
if (!row_buf) if (!row_buf)
{ {
fprintf(STDERR, "no memory to allocate row buffer\n"); fprintf(STDERR, "no memory to allocate row buffer\n");
png_read_destroy(&read_ptr, &info_ptr, (png_info *)0); png_read_destroy(&read_ptr, &info_ptr, (png_infop )0);
png_write_destroy(&write_ptr); png_write_destroy(&write_ptr);
fclose(fpin); fclose(fpin);
fclose(fpout); fclose(fpout);
@ -126,8 +124,8 @@ int main()
{ {
for (y = 0; y < info_ptr.height; y++) for (y = 0; y < info_ptr.height; y++)
{ {
png_read_rows(&read_ptr, (png_bytef **)&row_buf, (png_bytef **)0, 1); png_read_rows(&read_ptr, (png_bytepp )&row_buf, (png_bytepp )0, 1);
png_write_rows(&write_ptr, (png_bytef **)&row_buf, 1); png_write_rows(&write_ptr, (png_bytepp )&row_buf, 1);
} }
} }
@ -140,7 +138,7 @@ int main()
fclose(fpin); fclose(fpin);
fclose(fpout); fclose(fpout);
free(row_buf); free((void *)row_buf);
fpin = fopen(inname, "rb"); fpin = fopen(inname, "rb");

View File

@ -1,18 +1,15 @@
pngtodo.txt - list of things to do for libpng pngtodo.txt - list of things to do for libpng
for 0.9 for 0.9
medium memory model improved dithering
improved dithering? final bug fixes
cHRM transformation
for 1.1 after 1.0
push reader
for 1.1 or later
overlaying one image on top of another overlaying one image on top of another
optional palette creation optional palette creation
histogram creation histogram creation
text conversion between different code types text conversion between different code types
cHRM transformation
support for other chunks being defined (sCAl, the gIF series, support for other chunks being defined (sCAl, the gIF series,
and others that people come up with). and others that people come up with).
pull writer pull writer

View File

@ -2,10 +2,10 @@
/* pngtrans.c - transforms the data in a row /* pngtrans.c - transforms the data in a row
routines used by both readers and writers routines used by both readers and writers
libpng 1.0 beta 2 - version 0.81 libpng 1.0 beta 2 - version 0.85
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
August 24, 1995 December 19, 1995
*/ */
#define PNG_INTERNAL #define PNG_INTERNAL
@ -14,7 +14,7 @@
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
/* turn on bgr to rgb mapping */ /* turn on bgr to rgb mapping */
void void
png_set_bgr(png_struct *png_ptr) png_set_bgr(png_structp png_ptr)
{ {
png_ptr->transformations |= PNG_BGR; png_ptr->transformations |= PNG_BGR;
} }
@ -23,7 +23,7 @@ png_set_bgr(png_struct *png_ptr)
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
/* turn on 16 bit byte swapping */ /* turn on 16 bit byte swapping */
void void
png_set_swap(png_struct *png_ptr) png_set_swap(png_structp png_ptr)
{ {
if (png_ptr->bit_depth == 16) if (png_ptr->bit_depth == 16)
png_ptr->transformations |= PNG_SWAP_BYTES; png_ptr->transformations |= PNG_SWAP_BYTES;
@ -33,7 +33,7 @@ png_set_swap(png_struct *png_ptr)
#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
/* turn on pixel packing */ /* turn on pixel packing */
void void
png_set_packing(png_struct *png_ptr) png_set_packing(png_structp png_ptr)
{ {
if (png_ptr->bit_depth < 8) if (png_ptr->bit_depth < 8)
{ {
@ -45,7 +45,7 @@ png_set_packing(png_struct *png_ptr)
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
void void
png_set_shift(png_struct *png_ptr, png_color_8 *true_bits) png_set_shift(png_structp png_ptr, png_color_8p true_bits)
{ {
png_ptr->transformations |= PNG_SHIFT; png_ptr->transformations |= PNG_SHIFT;
png_ptr->shift = *true_bits; png_ptr->shift = *true_bits;
@ -54,7 +54,7 @@ png_set_shift(png_struct *png_ptr, png_color_8 *true_bits)
#if defined(PNG_READ_INTERLACING_SUPPORTED) || defined(PNG_WRITE_INTERLACING_SUPPORTED) #if defined(PNG_READ_INTERLACING_SUPPORTED) || defined(PNG_WRITE_INTERLACING_SUPPORTED)
int int
png_set_interlace_handling(png_struct *png_ptr) png_set_interlace_handling(png_structp png_ptr)
{ {
if (png_ptr->interlaced) if (png_ptr->interlaced)
{ {
@ -68,7 +68,7 @@ png_set_interlace_handling(png_struct *png_ptr)
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
void void
png_set_filler(png_struct *png_ptr, int filler, int filler_loc) png_set_filler(png_structp png_ptr, int filler, int filler_loc)
{ {
png_ptr->transformations |= PNG_FILLER; png_ptr->transformations |= PNG_FILLER;
png_ptr->filler = (png_byte)filler; png_ptr->filler = (png_byte)filler;
@ -80,13 +80,13 @@ png_set_filler(png_struct *png_ptr, int filler, int filler_loc)
/* old functions kept around for compatability purposes */ /* old functions kept around for compatability purposes */
void void
png_set_rgbx(png_struct *png_ptr) png_set_rgbx(png_structp png_ptr)
{ {
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
} }
void void
png_set_xrgb(png_struct *png_ptr) png_set_xrgb(png_structp png_ptr)
{ {
png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE); png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
} }
@ -94,19 +94,19 @@ png_set_xrgb(png_struct *png_ptr)
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
void void
png_set_invert_mono(png_struct *png_ptr) png_set_invert_mono(png_structp png_ptr)
{ {
png_ptr->transformations |= PNG_INVERT_MONO; png_ptr->transformations |= PNG_INVERT_MONO;
} }
/* invert monocrome grayscale data */ /* invert monocrome grayscale data */
void void
png_do_invert(png_row_info *row_info, png_bytef *row) png_do_invert(png_row_infop row_info, png_bytep row)
{ {
if (row && row_info && row_info->bit_depth == 1 && if (row && row_info && row_info->bit_depth == 1 &&
row_info->color_type == PNG_COLOR_TYPE_GRAY) row_info->color_type == PNG_COLOR_TYPE_GRAY)
{ {
png_bytef *rp; png_bytep rp;
png_uint_32 i; png_uint_32 i;
for (i = 0, rp = row; for (i = 0, rp = row;
@ -122,11 +122,11 @@ png_do_invert(png_row_info *row_info, png_bytef *row)
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
/* swaps byte order on 16 bit depth images */ /* swaps byte order on 16 bit depth images */
void void
png_do_swap(png_row_info *row_info, png_bytef *row) png_do_swap(png_row_infop row_info, png_bytep row)
{ {
if (row && row_info && row_info->bit_depth == 16) if (row && row_info && row_info->bit_depth == 16)
{ {
png_bytef *rp; png_bytep rp;
png_byte t; png_byte t;
png_uint_32 i; png_uint_32 i;
@ -145,13 +145,13 @@ png_do_swap(png_row_info *row_info, png_bytef *row)
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
/* swaps red and blue */ /* swaps red and blue */
void void
png_do_bgr(png_row_info *row_info, png_bytef *row) png_do_bgr(png_row_infop row_info, png_bytep row)
{ {
if (row && row_info && (row_info->color_type & 2)) if (row && row_info && (row_info->color_type & 2))
{ {
if (row_info->color_type == 2 && row_info->bit_depth == 8) if (row_info->color_type == 2 && row_info->bit_depth == 8)
{ {
png_bytef *rp; png_bytep rp;
png_byte t; png_byte t;
png_uint_32 i; png_uint_32 i;
@ -166,7 +166,7 @@ png_do_bgr(png_row_info *row_info, png_bytef *row)
} }
else if (row_info->color_type == 6 && row_info->bit_depth == 8) else if (row_info->color_type == 6 && row_info->bit_depth == 8)
{ {
png_bytef *rp; png_bytep rp;
png_byte t; png_byte t;
png_uint_32 i; png_uint_32 i;
@ -181,7 +181,7 @@ png_do_bgr(png_row_info *row_info, png_bytef *row)
} }
else if (row_info->color_type == 2 && row_info->bit_depth == 16) else if (row_info->color_type == 2 && row_info->bit_depth == 16)
{ {
png_bytef *rp; png_bytep rp;
png_byte t[2]; png_byte t[2];
png_uint_32 i; png_uint_32 i;
@ -199,7 +199,7 @@ png_do_bgr(png_row_info *row_info, png_bytef *row)
} }
else if (row_info->color_type == 6 && row_info->bit_depth == 16) else if (row_info->color_type == 6 && row_info->bit_depth == 16)
{ {
png_bytef *rp; png_bytep rp;
png_byte t[2]; png_byte t[2];
png_uint_32 i; png_uint_32 i;

View File

@ -1,10 +1,10 @@
/* pngwrite.c - general routines to write a png file /* pngwrite.c - general routines to write a png file
libpng 1.0 beta 2 - version 0.81 libpng 1.0 beta 2 - version 0.85
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
August 24, 1995 December 19, 1995
*/ */
/* get internal access to png.h */ /* get internal access to png.h */
@ -16,12 +16,12 @@
write it, and put it in the correct location here. If you want write it, and put it in the correct location here. If you want
the chunk written after the image data, put it in png_write_end(). the chunk written after the image data, put it in png_write_end().
I strongly encurage you to supply a PNG_INFO_ flag, and check I strongly encurage you to supply a PNG_INFO_ flag, and check
info->valid before writing the chunk, as that will keep the code info->valid before writing the chunk, as that will keep the code
from breaking if you want to just write a plain png file. from breaking if you want to just write a plain png file.
If you have long comments, I suggest writing them in png_write_end(), If you have long comments, I suggest writing them in png_write_end(),
and compressing them. */ and compressing them. */
void void
png_write_info(png_struct *png_ptr, png_info *info) png_write_info(png_structp png_ptr, png_infop info)
{ {
png_write_sig(png_ptr); /* write PNG signature */ png_write_sig(png_ptr); /* write PNG signature */
/* write IHDR information. */ /* write IHDR information. */
@ -57,30 +57,25 @@ png_write_info(png_struct *png_ptr, png_info *info)
if (info->valid & PNG_INFO_bKGD) if (info->valid & PNG_INFO_bKGD)
png_write_bKGD(png_ptr, &(info->background), info->color_type); png_write_bKGD(png_ptr, &(info->background), info->color_type);
#endif #endif
#if defined(PNG_WRITE_hIST_SUPPORTED) #if defined(PNG_WRITE_hIST_SUPPORTED)
if (info->valid & PNG_INFO_hIST) if (info->valid & PNG_INFO_hIST)
png_write_hIST(png_ptr, info->hist, info->num_palette); png_write_hIST(png_ptr, info->hist, info->num_palette);
#endif #endif
#if defined(PNG_WRITE_pHYs_SUPPORTED) #if defined(PNG_WRITE_pHYs_SUPPORTED)
if (info->valid & PNG_INFO_pHYs) if (info->valid & PNG_INFO_pHYs)
png_write_pHYs(png_ptr, info->x_pixels_per_unit, png_write_pHYs(png_ptr, info->x_pixels_per_unit,
info->y_pixels_per_unit, info->phys_unit_type); info->y_pixels_per_unit, info->phys_unit_type);
#endif #endif
#if defined(PNG_WRITE_oFFs_SUPPORTED) #if defined(PNG_WRITE_oFFs_SUPPORTED)
if (info->valid & PNG_INFO_oFFs) if (info->valid & PNG_INFO_oFFs)
png_write_oFFs(png_ptr, info->x_offset, info->y_offset, png_write_oFFs(png_ptr, info->x_offset, info->y_offset,
info->offset_unit_type); info->offset_unit_type);
#endif #endif
#if defined(PNG_WRITE_tIME_SUPPORTED) #if defined(PNG_WRITE_tIME_SUPPORTED)
if (info->valid & PNG_INFO_tIME) if (info->valid & PNG_INFO_tIME)
png_write_tIME(png_ptr, &(info->mod_time)); png_write_tIME(png_ptr, &(info->mod_time));
/* Check to see if we need to write text chunks */ /* Check to see if we need to write text chunks */
#endif #endif
#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED) #if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
if (info->num_text) if (info->num_text)
{ {
@ -89,17 +84,11 @@ png_write_info(png_struct *png_ptr, png_info *info)
/* loop through the text chunks */ /* loop through the text chunks */
for (i = 0; i < info->num_text; i++) 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 chunk is compressed */
if (info->text[i].compression >= 0) if (info->text[i].compression >= 0)
{ {
#if defined(PNG_WRITE_zTXt_SUPPORTED) #if defined(PNG_WRITE_zTXt_SUPPORTED)
/* write compressed chunk */ /* write compressed chunk */
png_write_zTXt(png_ptr, info->text[i].key, png_write_zTXt(png_ptr, info->text[i].key,
info->text[i].text, info->text[i].text_length, info->text[i].text, info->text[i].text_length,
info->text[i].compression); info->text[i].compression);
@ -110,13 +99,12 @@ png_write_info(png_struct *png_ptr, png_info *info)
#if defined(PNG_WRITE_tEXt_SUPPORTED) #if defined(PNG_WRITE_tEXt_SUPPORTED)
/* write uncompressed chunk */ /* write uncompressed chunk */
png_write_tEXt(png_ptr, info->text[i].key, png_write_tEXt(png_ptr, info->text[i].key,
info->text[i].text, info->text[i].text_length); info->text[i].text, info->text[i].text_length);
#endif #endif
} }
} }
} }
#endif /* PNG_WRITE_tEXt_SUPPORTED || PNG_WRITE_zTXt_SUPPORTED */ #endif
png_ptr->mode = PNG_HAVE_IHDR;
} }
/* writes the end of the png file. If you don't want to write comments or /* writes the end of the png file. If you don't want to write comments or
@ -124,11 +112,8 @@ png_write_info(png_struct *png_ptr, png_info *info)
in png_write_info(), do not write them again here. If you have long in png_write_info(), do not write them again here. If you have long
comments, I suggest writing them here, and compressing them. */ comments, I suggest writing them here, and compressing them. */
void void
png_write_end(png_struct *png_ptr, png_info *info) png_write_end(png_structp png_ptr, png_infop info)
{ {
if (info && png_ptr->mode == PNG_AFTER_IEND)
return;
/* see if user wants us to write information chunks */ /* see if user wants us to write information chunks */
if (info) if (info)
{ {
@ -137,7 +122,6 @@ png_write_end(png_struct *png_ptr, png_info *info)
if (info->valid & PNG_INFO_tIME) if (info->valid & PNG_INFO_tIME)
png_write_tIME(png_ptr, &(info->mod_time)); png_write_tIME(png_ptr, &(info->mod_time));
#endif #endif
#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED) #if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
/* check to see if we need to write comment chunks */ /* check to see if we need to write comment chunks */
if (info->num_text) if (info->num_text)
@ -146,7 +130,7 @@ png_write_end(png_struct *png_ptr, png_info *info)
/* loop through comment chunks */ /* loop through comment chunks */
for (i = 0; i < info->num_text; i++) for (i = 0; i < info->num_text; i++)
{ {
/* check to see if comment is to be compressed */ /* check to see if comment is to be compressed */
if (info->text[i].compression >= 0) if (info->text[i].compression >= 0)
{ {
@ -164,51 +148,59 @@ png_write_end(png_struct *png_ptr, png_info *info)
png_write_tEXt(png_ptr, info->text[i].key, png_write_tEXt(png_ptr, info->text[i].key,
info->text[i].text, info->text[i].text_length); info->text[i].text, info->text[i].text_length);
#endif #endif
} }
} }
} }
#endif /* PNG_WRITE_tEXt_SUPPORTED || PNG_WRITE_zTXt_SUPPORTED */ #endif
} }
/* write end of png file */ /* write end of png file */
png_write_IEND(png_ptr); png_write_IEND(png_ptr);
png_ptr->mode = PNG_AFTER_IEND;
} }
#if defined(PNG_WRITE_tIME_SUPPORTED) #if defined(PNG_WRITE_tIME_SUPPORTED)
void void
png_convert_from_struct_tm(png_time *ptime, struct tm *ttime) png_convert_from_struct_tm(png_timep ptime, struct tm FAR * ttime)
{ {
ptime->year = 1900 + ttime->tm_year; ptime->year = 1900 + ttime->tm_year;
ptime->month = ttime->tm_mon + 1; ptime->month = ttime->tm_mon + 1;
ptime->day = ttime->tm_mday; ptime->day = ttime->tm_mday;
ptime->hour = ttime->tm_hour; ptime->hour = ttime->tm_hour;
ptime->minute = ttime->tm_min; ptime->minute = ttime->tm_min;
ptime->second = ttime->tm_sec; ptime->second = ttime->tm_sec;
} }
void void
png_convert_from_time_t(png_time *ptime, time_t ttime) png_convert_from_time_t(png_timep ptime, time_t ttime)
{ {
struct tm *tbuf; struct tm *tbuf;
tbuf = gmtime(&ttime); tbuf = gmtime(&ttime);
png_convert_from_struct_tm(ptime, tbuf); png_convert_from_struct_tm(ptime, tbuf);
} }
#endif /* PNG_WRITE_tIME_SUPPORTED */ #endif
/* initialize png structure, and allocate any memory needed */ /* initialize png structure, and allocate any memory needed */
void void
png_write_init(png_struct *png_ptr) png_write_init(png_structp png_ptr)
{ {
jmp_buf tmp_jmp; /* to save current jump buffer */ jmp_buf tmp_jmp; /* to save current jump buffer */
png_msg_ptr error_fn;
png_msg_ptr warning_fn;
png_voidp msg_ptr;
/* save jump buffer */ /* save jump buffer and error functions */
png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf)); png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
/* reset all variables to 0 */ error_fn = png_ptr->error_fn;
png_memset(png_ptr, 0, sizeof (png_struct)); warning_fn = png_ptr->warning_fn;
/* restore jump buffer */ msg_ptr = png_ptr->msg_ptr;
/* reset all variables to 0 */
png_memset(png_ptr, 0, sizeof (png_struct));
/* restore jump buffer and error functions */
png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf)); png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
png_ptr->error_fn = error_fn;
png_ptr->warning_fn = warning_fn;
png_ptr->msg_ptr = msg_ptr;
/* initialize zbuf - compression buffer */ /* initialize zbuf - compression buffer */
png_ptr->zbuf_size = PNG_ZBUF_SIZE; png_ptr->zbuf_size = PNG_ZBUF_SIZE;
@ -218,13 +210,13 @@ png_write_init(png_struct *png_ptr)
/* write a few rows of image data. If the image is interlaced, /* write a few rows of image data. If the image is interlaced,
either you will have to write the 7 sub images, or, if you either you will have to write the 7 sub images, or, if you
have called png_set_interlace_handling(), you will have to have called png_set_interlace_handling(), you will have to
"write" the image seven times */ "write" the image seven times */
void void
png_write_rows(png_struct *png_ptr, png_bytef **row, png_write_rows(png_structp png_ptr, png_bytepp row,
png_uint_32 num_rows) png_uint_32 num_rows)
{ {
png_uint_32 i; /* row counter */ png_uint_32 i; /* row counter */
png_bytef **rp; /* row pointer */ png_bytepp rp; /* row pointer */
/* loop through the rows */ /* loop through the rows */
for (i = 0, rp = row; i < num_rows; i++, rp++) for (i = 0, rp = row; i < num_rows; i++, rp++)
@ -236,11 +228,11 @@ png_write_rows(png_struct *png_ptr, png_bytef **row,
/* write the image. You only need to call this function once, even /* write the image. You only need to call this function once, even
if you are writing an interlaced image. */ if you are writing an interlaced image. */
void void
png_write_image(png_struct *png_ptr, png_bytef **image) png_write_image(png_structp png_ptr, png_bytepp image)
{ {
png_uint_32 i; /* row index */ png_uint_32 i; /* row index */
int pass, num_pass; /* pass variables */ int pass, num_pass; /* pass variables */
png_bytef **rp; /* points to current row */ png_bytepp rp; /* points to current row */
/* intialize interlace handling. If image is not interlaced, /* intialize interlace handling. If image is not interlaced,
this will set pass to 1 */ this will set pass to 1 */
@ -258,23 +250,21 @@ png_write_image(png_struct *png_ptr, png_bytef **image)
/* write a row of image data */ /* write a row of image data */
void void
png_write_row(png_struct *png_ptr, png_bytef *row) png_write_row(png_structp png_ptr, png_bytep row)
{ {
/* initialize transformations and other stuff if first time */ /* initialize transformations and other stuff if first time */
if (png_ptr->mode < PNG_HAVE_IDAT) if (png_ptr->row_number == 0 && png_ptr->pass == 0)
{ {
png_write_start_row(png_ptr); png_write_start_row(png_ptr);
} }
png_ptr->mode = PNG_HAVE_IDAT;
#if defined(PNG_WRITE_INTERLACING_SUPPORTED) #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
/* if interlaced and not interested in row, return */ /* if interlaced and not interested in row, return */
if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
{ {
switch (png_ptr->pass) switch (png_ptr->pass)
{ {
case 0: case 0:
if (png_ptr->row_number & 7) if (png_ptr->row_number & 7)
{ {
png_write_finish_row(png_ptr); png_write_finish_row(png_ptr);
@ -292,7 +282,7 @@ png_write_row(png_struct *png_ptr, png_bytef *row)
if ((png_ptr->row_number & 7) != 4) if ((png_ptr->row_number & 7) != 4)
{ {
png_write_finish_row(png_ptr); png_write_finish_row(png_ptr);
return; return;
} }
break; break;
case 3: case 3:
@ -310,7 +300,7 @@ png_write_row(png_struct *png_ptr, png_bytef *row)
} }
break; break;
case 5: case 5:
if ((png_ptr->row_number & 1) || png_ptr->width < 2) if ((png_ptr->row_number & 1) || png_ptr->width < 2)
{ {
png_write_finish_row(png_ptr); png_write_finish_row(png_ptr);
return; return;
@ -325,10 +315,10 @@ png_write_row(png_struct *png_ptr, png_bytef *row)
break; break;
} }
} }
#endif /* PNG_WRITE_INTERLACE_SUPPORTED */ #endif
/* set up row info for transformations */ /* set up row info for transformations */
png_ptr->row_info.color_type = png_ptr->color_type; png_ptr->row_info.color_type = png_ptr->color_type;
png_ptr->row_info.width = png_ptr->usr_width; png_ptr->row_info.width = png_ptr->usr_width;
png_ptr->row_info.channels = png_ptr->usr_channels; png_ptr->row_info.channels = png_ptr->usr_channels;
png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth; png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth;
@ -346,7 +336,7 @@ png_write_row(png_struct *png_ptr, png_bytef *row)
(png_ptr->transformations & PNG_INTERLACE)) (png_ptr->transformations & PNG_INTERLACE))
{ {
png_do_write_interlace(&(png_ptr->row_info), png_do_write_interlace(&(png_ptr->row_info),
png_ptr->row_buf + 1, png_ptr->pass); png_ptr->row_buf + 1, png_ptr->pass);
/* this should always get caught above, but still ... */ /* this should always get caught above, but still ... */
if (!(png_ptr->row_info.width)) if (!(png_ptr->row_info.width))
{ {
@ -354,7 +344,7 @@ png_write_row(png_struct *png_ptr, png_bytef *row)
return; return;
} }
} }
#endif /* PNG_WRITE_INTERLACE_SUPPORTED */ #endif
/* handle other transformations */ /* handle other transformations */
if (png_ptr->transformations) if (png_ptr->transformations)
@ -364,7 +354,7 @@ png_write_row(png_struct *png_ptr, png_bytef *row)
if (png_ptr->do_filter) if (png_ptr->do_filter)
{ {
/* save row to previous row */ /* save row to previous row */
png_memcpy(png_ptr->save_row, png_ptr->row_buf, png_memcpy(png_ptr->save_row, png_ptr->row_buf,
(png_size_t)png_ptr->row_info.rowbytes + 1); (png_size_t)png_ptr->row_info.rowbytes + 1);
/* filter row */ /* filter row */
@ -373,7 +363,7 @@ png_write_row(png_struct *png_ptr, png_bytef *row)
/* trade saved pointer and prev pointer so next row references are correctly */ /* trade saved pointer and prev pointer so next row references are correctly */
{ /* scope limiter */ { /* scope limiter */
png_bytef *tptr; png_bytep tptr;
tptr = png_ptr->prev_row; tptr = png_ptr->prev_row;
png_ptr->prev_row = png_ptr->save_row; png_ptr->prev_row = png_ptr->save_row;
@ -382,12 +372,11 @@ png_write_row(png_struct *png_ptr, png_bytef *row)
} }
else else
/* set filter row to "none" */ /* set filter row to "none" */
png_ptr->row_buf[0] = 0; png_ptr->row_buf[0] = 0;
/* set up the zlib input buffer */ /* set up the zlib input buffer */
png_ptr->zstream->next_in = png_ptr->row_buf; png_ptr->zstream->next_in = png_ptr->row_buf;
png_ptr->zstream->avail_in = (uInt)png_ptr->row_info.rowbytes + 1; png_ptr->zstream->avail_in = (uInt)png_ptr->row_info.rowbytes + 1;
/* repeat until we have compressed all the data */ /* repeat until we have compressed all the data */
do do
{ {
@ -399,9 +388,9 @@ png_write_row(png_struct *png_ptr, png_bytef *row)
if (ret != Z_OK) if (ret != Z_OK)
{ {
if (png_ptr->zstream->msg) if (png_ptr->zstream->msg)
(*(png_ptr->error_fn))(png_ptr, png_ptr->zstream->msg); png_error(png_ptr, png_ptr->zstream->msg);
else else
(*(png_ptr->error_fn))(png_ptr, "zlib error"); png_error(png_ptr, "zlib error");
} }
/* see if it is time to write another IDAT */ /* see if it is time to write another IDAT */
@ -415,17 +404,17 @@ png_write_row(png_struct *png_ptr, png_bytef *row)
/* repeat until all data has been compressed */ /* repeat until all data has been compressed */
} while (png_ptr->zstream->avail_in); } while (png_ptr->zstream->avail_in);
/* finish row - updates counters and flushes zlib if last row */ /* finish row - updates counters and flushes zlib if last row */
png_write_finish_row(png_ptr); png_write_finish_row(png_ptr);
#if defined(PNG_WRITE_FLUSH_SUPPORTED) #if defined(PNG_WRITE_FLUSH_SUPPORTED)
png_ptr->flush_rows++; png_ptr->flush_rows++;
if (png_ptr->flush_dist > 0 && if (png_ptr->flush_dist > 0 &&
png_ptr->flush_rows >= png_ptr->flush_dist) png_ptr->flush_rows >= png_ptr->flush_dist)
{ {
png_write_flush(png_ptr); png_write_flush(png_ptr);
} }
#endif /* PNG_WRITE_FLUSH_SUPPORTED */ #endif /* PNG_WRITE_FLUSH_SUPPORTED */
} }
@ -434,68 +423,70 @@ png_write_row(png_struct *png_ptr, png_bytef *row)
void void
png_set_flush(png_struct *png_ptr, int nrows) png_set_flush(png_struct *png_ptr, int nrows)
{ {
png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); png_ptr->flush_dist = (nrows < 0 ? 0 : nrows);
} }
/* flush the current output buffers now */ /* flush the current output buffers now */
void void
png_write_flush(png_struct *png_ptr) png_write_flush(png_struct *png_ptr)
{ {
char wrote_IDAT; int wrote_IDAT;
if (png_ptr->mode != PNG_HAVE_IDAT) if (png_ptr->mode != PNG_HAVE_IDAT)
return; return;
do do
{ {
int ret; int ret;
/* compress the data */ /* compress the data */
ret = deflate(png_ptr->zstream, Z_SYNC_FLUSH); ret = deflate(png_ptr->zstream, Z_SYNC_FLUSH);
wrote_IDAT = 0; wrote_IDAT = 0;
/* check for compression errors */ /* check for compression errors */
if (ret != Z_OK) if (ret != Z_OK)
{ {
if (png_ptr->zstream->msg) if (png_ptr->zstream->msg)
(*(png_ptr->error_fn))(png_ptr, png_ptr->zstream->msg); png_error(png_ptr, png_ptr->zstream->msg);
else else
(*(png_ptr->error_fn))(png_ptr, "zlib error"); png_error(png_ptr, "zlib error");
} }
if (!png_ptr->zstream->avail_out) if (!png_ptr->zstream->avail_out)
{ {
/* write the IDAT and reset the zlib output buffer */ /* write the IDAT and reset the zlib output buffer */
png_write_IDAT(png_ptr, png_ptr->zbuf, png_write_IDAT(png_ptr, png_ptr->zbuf,
png_ptr->zbuf_size); png_ptr->zbuf_size);
png_ptr->zstream->next_out = png_ptr->zbuf; png_ptr->zstream->next_out = png_ptr->zbuf;
png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size; png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
wrote_IDAT = 1; wrote_IDAT = 1;
} }
} while(wrote_IDAT == 1); } while(wrote_IDAT == 1);
/* If there is any data left to be output, write it into a new IDAT */ /* 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) if (png_ptr->zbuf_size != png_ptr->zstream->avail_out)
{ {
/* write the IDAT and reset the zlib output buffer */ /* write the IDAT and reset the zlib output buffer */
png_write_IDAT(png_ptr, png_ptr->zbuf, png_write_IDAT(png_ptr, png_ptr->zbuf,
png_ptr->zbuf_size - png_ptr->zstream->avail_out); png_ptr->zbuf_size - png_ptr->zstream->avail_out);
png_ptr->zstream->next_out = png_ptr->zbuf; png_ptr->zstream->next_out = png_ptr->zbuf;
png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size; png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
} }
png_ptr->flush_rows = 0; png_ptr->flush_rows = 0;
(*(png_ptr->output_flush_fn))(png_ptr); png_flush(png_ptr);
} }
#endif /* PNG_WRITE_FLUSH_SUPPORTED */ #endif /* PNG_WRITE_FLUSH_SUPPORTED */
/* free any memory used in png struct */ /* free any memory used in png struct */
void void
png_write_destroy(png_struct *png_ptr) png_write_destroy(png_structp png_ptr)
{ {
jmp_buf tmp_jmp; /* save jump buffer */ jmp_buf tmp_jmp; /* save jump buffer */
/* free any memory zlib uses */ /* free any memory zlib uses */
deflateEnd(png_ptr->zstream); deflateEnd(png_ptr->zstream);
png_free(png_ptr, png_ptr->zstream);
/* free our memory. png_free checks NULL for us. */ /* free our memory. png_free checks NULL for us. */
png_large_free(png_ptr, png_ptr->zbuf); png_large_free(png_ptr, png_ptr->zbuf);
png_large_free(png_ptr, png_ptr->row_buf); png_large_free(png_ptr, png_ptr->row_buf);
@ -506,44 +497,43 @@ png_write_destroy(png_struct *png_ptr)
png_memset(png_ptr, 0, sizeof (png_struct)); png_memset(png_ptr, 0, sizeof (png_struct));
png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf)); png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
} }
void void
png_set_filtering(png_struct *png_ptr, int filter) png_set_filtering(png_structp png_ptr, int filter)
{ {
png_ptr->do_custom_filter = 1; png_ptr->do_custom_filter = 1;
png_ptr->do_filter = filter; png_ptr->do_filter = filter;
} }
void void
png_set_compression_level(png_struct *png_ptr, int level) png_set_compression_level(png_structp png_ptr, int level)
{ {
png_ptr->zlib_custom_level = 1; png_ptr->zlib_custom_level = 1;
png_ptr->zlib_level = level; png_ptr->zlib_level = level;
} }
void void
png_set_compression_mem_level(png_struct *png_ptr, int mem_level) png_set_compression_mem_level(png_structp png_ptr, int mem_level)
{ {
png_ptr->zlib_custom_mem_level = 1; png_ptr->zlib_custom_mem_level = 1;
png_ptr->zlib_mem_level = mem_level; png_ptr->zlib_mem_level = mem_level;
} }
void void
png_set_compression_strategy(png_struct *png_ptr, int strategy) png_set_compression_strategy(png_structp png_ptr, int strategy)
{ {
png_ptr->zlib_custom_strategy = 1; png_ptr->zlib_custom_strategy = 1;
png_ptr->zlib_strategy = strategy; png_ptr->zlib_strategy = strategy;
} }
void void
png_set_compression_window_bits(png_struct *png_ptr, int window_bits) png_set_compression_window_bits(png_structp png_ptr, int window_bits)
{ {
png_ptr->zlib_custom_window_bits = 1; png_ptr->zlib_custom_window_bits = 1;
png_ptr->zlib_window_bits = window_bits; png_ptr->zlib_window_bits = window_bits;
} }
void void
png_set_compression_method(png_struct *png_ptr, int method) png_set_compression_method(png_structp png_ptr, int method)
{ {
png_ptr->zlib_custom_method = 1; png_ptr->zlib_custom_method = 1;
png_ptr->zlib_method = method; png_ptr->zlib_method = method;

View File

@ -1,10 +1,10 @@
/* pngwtran.c - transforms the data in a row for png writers /* pngwtran.c - transforms the data in a row for png writers
libpng 1.0 beta 2 - version 0.81 libpng 1.0 beta 2 - version 0.85
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
August 24, 1995 December 19, 1995
*/ */
#define PNG_INTERNAL #define PNG_INTERNAL
@ -13,10 +13,10 @@
/* transform the data according to the users wishes. The order of /* transform the data according to the users wishes. The order of
transformations is significant. */ transformations is significant. */
void void
png_do_write_transformations(png_struct *png_ptr) png_do_write_transformations(png_structp png_ptr)
{ {
#if defined(PNG_WRITE_FILLER_SUPPORTED) #if defined(PNG_WRITE_FILLER_SUPPORTED)
if (png_ptr->transformations & PNG_RGBA) if (png_ptr->transformations & PNG_FILLER)
png_do_write_filler(&(png_ptr->row_info), png_ptr->row_buf + 1, png_do_write_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
png_ptr->filler_loc); png_ptr->filler_loc);
#endif #endif
@ -49,7 +49,7 @@ png_do_write_transformations(png_struct *png_ptr)
row_info bit depth should be 8 (one pixel per byte). The channels row_info bit depth should be 8 (one pixel per byte). The channels
should be 1 (this only happens on grayscale and paletted images) */ should be 1 (this only happens on grayscale and paletted images) */
void void
png_do_pack(png_row_info *row_info, png_bytef *row, png_byte bit_depth) png_do_pack(png_row_infop row_info, png_bytep row, png_byte bit_depth)
{ {
if (row_info && row && row_info->bit_depth == 8 && if (row_info && row && row_info->bit_depth == 8 &&
row_info->channels == 1) row_info->channels == 1)
@ -58,10 +58,10 @@ png_do_pack(png_row_info *row_info, png_bytef *row, png_byte bit_depth)
{ {
case 1: case 1:
{ {
png_bytef *sp; png_bytep sp;
png_bytef *dp; png_bytep dp;
int mask; int mask;
png_int_32 i; png_int_32 i;
int v; int v;
sp = row; sp = row;
@ -79,7 +79,7 @@ png_do_pack(png_row_info *row_info, png_bytef *row, png_byte bit_depth)
{ {
mask = 0x80; mask = 0x80;
*dp = v; *dp = v;
dp++; dp++;
v = 0; v = 0;
} }
} }
@ -89,8 +89,8 @@ png_do_pack(png_row_info *row_info, png_bytef *row, png_byte bit_depth)
} }
case 2: case 2:
{ {
png_bytef *sp; png_bytep sp;
png_bytef *dp; png_bytep dp;
int shift; int shift;
png_int_32 i; png_int_32 i;
int v; int v;
@ -121,8 +121,8 @@ png_do_pack(png_row_info *row_info, png_bytef *row, png_byte bit_depth)
} }
case 4: case 4:
{ {
png_bytef *sp; png_bytep sp;
png_bytef *dp; png_bytep dp;
int shift; int shift;
png_int_32 i; png_int_32 i;
int v; int v;
@ -170,7 +170,7 @@ png_do_pack(png_row_info *row_info, png_bytef *row, png_byte bit_depth)
would pass 3 as bit_depth, and this routine would translate the would pass 3 as bit_depth, and this routine would translate the
data to 0 to 15. */ data to 0 to 15. */
void void
png_do_shift(png_row_info *row_info, png_bytef *row, png_color_8 *bit_depth) png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
{ {
if (row && row_info && if (row && row_info &&
row_info->color_type != PNG_COLOR_TYPE_PALETTE) row_info->color_type != PNG_COLOR_TYPE_PALETTE)
@ -207,7 +207,7 @@ png_do_shift(png_row_info *row_info, png_bytef *row, png_color_8 *bit_depth)
/* with low row dephts, could only be grayscale, so one channel */ /* with low row dephts, could only be grayscale, so one channel */
if (row_info->bit_depth < 8) if (row_info->bit_depth < 8)
{ {
png_bytef *bp; png_bytep bp;
png_uint_32 i; png_uint_32 i;
int j; int j;
png_byte mask; png_byte mask;
@ -236,7 +236,7 @@ png_do_shift(png_row_info *row_info, png_bytef *row, png_color_8 *bit_depth)
} }
else if (row_info->bit_depth == 8) else if (row_info->bit_depth == 8)
{ {
png_bytef *bp; png_bytep bp;
png_uint_32 i; png_uint_32 i;
int j; int j;
@ -262,7 +262,7 @@ png_do_shift(png_row_info *row_info, png_bytef *row, png_color_8 *bit_depth)
} }
else else
{ {
png_bytef *bp; png_bytep bp;
png_uint_32 i; png_uint_32 i;
int j; int j;
@ -297,7 +297,7 @@ png_do_shift(png_row_info *row_info, png_bytef *row, png_color_8 *bit_depth)
#ifdef PNG_WRITE_FILLER_SUPPORTED #ifdef PNG_WRITE_FILLER_SUPPORTED
/* remove filler byte */ /* remove filler byte */
void void
png_do_write_filler(png_row_info *row_info, png_bytef *row, png_do_write_filler(png_row_infop row_info, png_bytep row,
png_byte filler_loc) png_byte filler_loc)
{ {
if (row && row_info && row_info->color_type == PNG_COLOR_TYPE_RGB && if (row && row_info && row_info->color_type == PNG_COLOR_TYPE_RGB &&
@ -305,7 +305,8 @@ png_do_write_filler(png_row_info *row_info, png_bytef *row,
{ {
if (filler_loc == PNG_FILLER_AFTER) if (filler_loc == PNG_FILLER_AFTER)
{ {
png_bytef *sp, *dp; png_bytep sp, dp;
png_uint_32 i; png_uint_32 i;
for (i = 1, sp = row + 4, dp = row + 3; for (i = 1, sp = row + 4, dp = row + 3;
@ -323,10 +324,10 @@ png_do_write_filler(png_row_info *row_info, png_bytef *row,
} }
else else
{ {
png_bytef *sp, *dp; png_bytep sp, dp;
png_uint_32 i; png_uint_32 i;
for (i = 1, sp = row + 4, dp = row + 3; for (i = 0, sp = row, dp = row;
i < row_info->width; i < row_info->width;
i++) i++)
{ {

View File

@ -1,10 +1,10 @@
/* pngwutil.c - utilities to write a png file /* pngwutil.c - utilities to write a png file
libpng 1.0 beta 2 - version 0.81 libpng 1.0 beta 2 - version 0.85
For conditions of distribution and use, see copyright notice in png.h For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc. Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
August 24, 1995 December 19, 1995
*/ */
#define PNG_INTERNAL #define PNG_INTERNAL
#include "png.h" #include "png.h"
@ -13,7 +13,7 @@
with unsigned numbers for convenience, you may have to cast with unsigned numbers for convenience, you may have to cast
signed numbers (if you use any, most png data is unsigned). */ signed numbers (if you use any, most png data is unsigned). */
void void
png_save_uint_32(png_byte *buf, png_uint_32 i) png_save_uint_32(png_bytep buf, png_uint_32 i)
{ {
buf[0] = (png_byte)((i >> 24) & 0xff); buf[0] = (png_byte)((i >> 24) & 0xff);
buf[1] = (png_byte)((i >> 16) & 0xff); buf[1] = (png_byte)((i >> 16) & 0xff);
@ -23,7 +23,7 @@ png_save_uint_32(png_byte *buf, png_uint_32 i)
/* place a 16 bit number into a buffer in png byte order */ /* place a 16 bit number into a buffer in png byte order */
void void
png_save_uint_16(png_byte *buf, png_uint_16 i) png_save_uint_16(png_bytep buf, png_uint_16 i)
{ {
buf[0] = (png_byte)((i >> 8) & 0xff); buf[0] = (png_byte)((i >> 8) & 0xff);
buf[1] = (png_byte)(i & 0xff); buf[1] = (png_byte)(i & 0xff);
@ -31,7 +31,7 @@ png_save_uint_16(png_byte *buf, png_uint_16 i)
/* write a 32 bit number */ /* write a 32 bit number */
void void
png_write_uint_32(png_struct *png_ptr, png_uint_32 i) png_write_uint_32(png_structp png_ptr, png_uint_32 i)
{ {
png_byte buf[4]; png_byte buf[4];
@ -39,18 +39,18 @@ png_write_uint_32(png_struct *png_ptr, png_uint_32 i)
buf[1] = (png_byte)((i >> 16) & 0xff); buf[1] = (png_byte)((i >> 16) & 0xff);
buf[2] = (png_byte)((i >> 8) & 0xff); buf[2] = (png_byte)((i >> 8) & 0xff);
buf[3] = (png_byte)(i & 0xff); buf[3] = (png_byte)(i & 0xff);
(*(png_ptr->write_data_fn))(png_ptr, buf, 4); png_write_data(png_ptr, buf, 4);
} }
/* write a 16 bit number */ /* write a 16 bit number */
void void
png_write_uint_16(png_struct *png_ptr, png_uint_16 i) png_write_uint_16(png_structp png_ptr, png_uint_16 i)
{ {
png_byte buf[2]; png_byte buf[2];
buf[0] = (png_byte)((i >> 8) & 0xff); buf[0] = (png_byte)((i >> 8) & 0xff);
buf[1] = (png_byte)(i & 0xff); buf[1] = (png_byte)(i & 0xff);
(*(png_ptr->write_data_fn))(png_ptr, buf, 2); png_write_data(png_ptr, buf, 2);
} }
/* Write a png chunk all at once. The type is an array of ASCII characters /* Write a png chunk all at once. The type is an array of ASCII characters
@ -62,13 +62,13 @@ png_write_uint_16(png_struct *png_ptr, png_uint_16 i)
png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
functions instead. */ functions instead. */
void void
png_write_chunk(png_struct *png_ptr, png_byte *type, png_write_chunk(png_structp png_ptr, png_bytep type,
png_bytef *data, png_uint_32 length) png_bytep data, png_uint_32 length)
{ {
/* write length */ /* write length */
png_write_uint_32(png_ptr, length); png_write_uint_32(png_ptr, length);
/* write chunk name */ /* write chunk name */
(*(png_ptr->write_data_fn))(png_ptr, type, (png_uint_32)4); png_write_data(png_ptr, type, (png_uint_32)4);
/* reset the crc and run the chunk name over it */ /* reset the crc and run the chunk name over it */
png_reset_crc(png_ptr); png_reset_crc(png_ptr);
png_calculate_crc(png_ptr, type, (png_uint_32)4); 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) if (length)
{ {
png_calculate_crc(png_ptr, data, length); png_calculate_crc(png_ptr, data, length);
(*(png_ptr->write_data_fn))(png_ptr, data, length); png_write_data(png_ptr, data, length);
} }
/* write the crc */ /* write the crc */
png_write_uint_32(png_ptr, ~png_ptr->crc); png_write_uint_32(png_ptr, ~png_ptr->crc);
@ -86,13 +86,13 @@ png_write_chunk(png_struct *png_ptr, png_byte *type,
The total_length is the sum of the lengths of all the data you will be The total_length is the sum of the lengths of all the data you will be
passing in png_write_chunk_data() */ passing in png_write_chunk_data() */
void void
png_write_chunk_start(png_struct *png_ptr, png_byte *type, png_write_chunk_start(png_structp png_ptr, png_bytep type,
png_uint_32 total_length) png_uint_32 total_length)
{ {
/* write the length */ /* write the length */
png_write_uint_32(png_ptr, total_length); png_write_uint_32(png_ptr, total_length);
/* write the chunk name */ /* write the chunk name */
(*(png_ptr->write_data_fn))(png_ptr, type, (png_uint_32)4); png_write_data(png_ptr, type, (png_uint_32)4);
/* reset the crc and run it over the chunk name */ /* reset the crc and run it over the chunk name */
png_reset_crc(png_ptr); png_reset_crc(png_ptr);
png_calculate_crc(png_ptr, type, (png_uint_32)4); png_calculate_crc(png_ptr, type, (png_uint_32)4);
@ -103,19 +103,19 @@ png_write_chunk_start(png_struct *png_ptr, png_byte *type,
sum of the lengths from these calls *must* add up to the total_length sum of the lengths from these calls *must* add up to the total_length
given to png_write_chunk_start() */ given to png_write_chunk_start() */
void void
png_write_chunk_data(png_struct *png_ptr, png_bytef *data, png_uint_32 length) png_write_chunk_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
{ {
/* write the data, and run the crc over it */ /* write the data, and run the crc over it */
if (length) if (length)
{ {
png_calculate_crc(png_ptr, data, length); png_calculate_crc(png_ptr, data, length);
(*(png_ptr->write_data_fn))(png_ptr, data, length); png_write_data(png_ptr, data, length);
} }
} }
/* finish a chunk started with png_write_chunk_start() */ /* finish a chunk started with png_write_chunk_start() */
void void
png_write_chunk_end(png_struct *png_ptr) png_write_chunk_end(png_structp png_ptr)
{ {
/* write the crc */ /* write the crc */
png_write_uint_32(png_ptr, ~png_ptr->crc); png_write_uint_32(png_ptr, ~png_ptr->crc);
@ -123,17 +123,17 @@ png_write_chunk_end(png_struct *png_ptr)
/* simple function to write the signature */ /* simple function to write the signature */
void void
png_write_sig(png_struct *png_ptr) png_write_sig(png_structp png_ptr)
{ {
/* write the 8 byte signature */ /* write the 8 byte signature */
(*(png_ptr->write_data_fn))(png_ptr, png_sig, (png_uint_32)8); png_write_data(png_ptr, png_sig, (png_uint_32)8);
} }
/* Write the IHDR chunk, and update the png_struct with the necessary /* Write the IHDR chunk, and update the png_struct with the necessary
information. Note that the rest of this code depends upon this information. Note that the rest of this code depends upon this
information being correct. */ information being correct. */
void void
png_write_IHDR(png_struct *png_ptr, png_uint_32 width, png_uint_32 height, png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
int bit_depth, int color_type, int compression_type, int filter_type, int bit_depth, int color_type, int compression_type, int filter_type,
int interlace_type) int interlace_type)
{ {
@ -175,13 +175,13 @@ png_write_IHDR(png_struct *png_ptr, png_uint_32 width, png_uint_32 height,
/* set the usr info, so any transformations can modify it */ /* set the usr info, so any transformations can modify it */
png_ptr->usr_width = png_ptr->width; png_ptr->usr_width = png_ptr->width;
png_ptr->usr_bit_depth = png_ptr->bit_depth; png_ptr->usr_bit_depth = png_ptr->bit_depth;
png_ptr->usr_channels = png_ptr->channels; png_ptr->usr_channels = png_ptr->channels;
/* write the chunk */ /* write the chunk */
png_write_chunk(png_ptr, png_IHDR, buf, (png_uint_32)13); png_write_chunk(png_ptr, png_IHDR, buf, (png_uint_32)13);
/* initialize zlib with png info */ /* initialize zlib with png info */
png_ptr->zstream = &(png_ptr->zstream_struct); png_ptr->zstream = (z_stream *)png_malloc(png_ptr, sizeof (z_stream));
png_ptr->zstream->zalloc = png_zalloc; png_ptr->zstream->zalloc = png_zalloc;
png_ptr->zstream->zfree = png_zfree; png_ptr->zstream->zfree = png_zfree;
png_ptr->zstream->opaque = (voidp)png_ptr; png_ptr->zstream->opaque = (voidp)png_ptr;
@ -221,10 +221,10 @@ png_write_IHDR(png_struct *png_ptr, png_uint_32 width, png_uint_32 height,
correct order for PNG, so people can redefine it to any convient correct order for PNG, so people can redefine it to any convient
structure. */ structure. */
void void
png_write_PLTE(png_struct *png_ptr, png_color *palette, int number) png_write_PLTE(png_structp png_ptr, png_colorp palette, int number)
{ {
int i; int i;
png_color *pal_ptr; png_colorp pal_ptr;
png_byte buf[3]; png_byte buf[3];
png_write_chunk_start(png_ptr, png_PLTE, number * 3); png_write_chunk_start(png_ptr, png_PLTE, number * 3);
@ -242,14 +242,14 @@ png_write_PLTE(png_struct *png_ptr, png_color *palette, int number)
/* write an IDAT chunk */ /* write an IDAT chunk */
void void
png_write_IDAT(png_struct *png_ptr, png_bytef *data, png_uint_32 length) png_write_IDAT(png_structp png_ptr, png_bytep data, png_uint_32 length)
{ {
png_write_chunk(png_ptr, png_IDAT, data, length); png_write_chunk(png_ptr, png_IDAT, data, length);
} }
/* write an IEND chunk */ /* write an IEND chunk */
void void
png_write_IEND(png_struct *png_ptr) png_write_IEND(png_structp png_ptr)
{ {
png_write_chunk(png_ptr, png_IEND, NULL, (png_uint_32)0); png_write_chunk(png_ptr, png_IEND, NULL, (png_uint_32)0);
} }
@ -257,7 +257,7 @@ png_write_IEND(png_struct *png_ptr)
#if defined(PNG_WRITE_gAMA_SUPPORTED) #if defined(PNG_WRITE_gAMA_SUPPORTED)
/* write a gAMA chunk */ /* write a gAMA chunk */
void void
png_write_gAMA(png_struct *png_ptr, float gamma) png_write_gAMA(png_structp png_ptr, double gamma)
{ {
png_uint_32 igamma; png_uint_32 igamma;
png_byte buf[4]; png_byte buf[4];
@ -272,12 +272,12 @@ png_write_gAMA(png_struct *png_ptr, float gamma)
#if defined(PNG_WRITE_sBIT_SUPPORTED) #if defined(PNG_WRITE_sBIT_SUPPORTED)
/* write the sBIT chunk */ /* write the sBIT chunk */
void void
png_write_sBIT(png_struct *png_ptr, png_color_8 *sbit, int color_type) png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
{ {
png_byte buf[4]; png_byte buf[4];
int size; int size;
/* make sure we don't depend upon the order of png_color_8 */ /* make sure we don't depend upon the order of PNG_COLOR_8 */
if (color_type & PNG_COLOR_MASK_COLOR) if (color_type & PNG_COLOR_MASK_COLOR)
{ {
buf[0] = sbit->red; buf[0] = sbit->red;
@ -303,9 +303,9 @@ png_write_sBIT(png_struct *png_ptr, png_color_8 *sbit, int color_type)
#if defined(PNG_WRITE_cHRM_SUPPORTED) #if defined(PNG_WRITE_cHRM_SUPPORTED)
/* write the cHRM chunk */ /* write the cHRM chunk */
void void
png_write_cHRM(png_struct *png_ptr, float white_x, float white_y, png_write_cHRM ( png_structp png_ptr, double white_x, double white_y,
float red_x, float red_y, float green_x, float green_y, double red_x, double red_y, double green_x, double green_y,
float blue_x, float blue_y) double blue_x, double blue_y)
{ {
png_uint_32 itemp; png_uint_32 itemp;
png_byte buf[32]; png_byte buf[32];
@ -334,7 +334,7 @@ png_write_cHRM(png_struct *png_ptr, float white_x, float white_y,
#if defined(PNG_WRITE_tRNS_SUPPORTED) #if defined(PNG_WRITE_tRNS_SUPPORTED)
/* write the tRNS chunk */ /* write the tRNS chunk */
void void
png_write_tRNS(png_struct *png_ptr, png_byte *trans, png_color_16 *tran, png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran,
int num_trans, int color_type) int num_trans, int color_type)
{ {
png_byte buf[6]; png_byte buf[6];
@ -364,7 +364,7 @@ png_write_tRNS(png_struct *png_ptr, png_byte *trans, png_color_16 *tran,
#if defined(PNG_WRITE_bKGD_SUPPORTED) #if defined(PNG_WRITE_bKGD_SUPPORTED)
/* write the background chunk */ /* write the background chunk */
void void
png_write_bKGD(png_struct *png_ptr, png_color_16 *back, int color_type) png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type)
{ {
png_byte buf[6]; png_byte buf[6];
@ -381,7 +381,7 @@ png_write_bKGD(png_struct *png_ptr, png_color_16 *back, int color_type)
png_write_chunk(png_ptr, png_bKGD, buf, (png_uint_32)6); png_write_chunk(png_ptr, png_bKGD, buf, (png_uint_32)6);
} }
else else
{ {
png_save_uint_16(buf, back->gray); png_save_uint_16(buf, back->gray);
png_write_chunk(png_ptr, png_bKGD, buf, (png_uint_32)2); png_write_chunk(png_ptr, png_bKGD, buf, (png_uint_32)2);
} }
@ -391,7 +391,7 @@ png_write_bKGD(png_struct *png_ptr, png_color_16 *back, int color_type)
#if defined(PNG_WRITE_hIST_SUPPORTED) #if defined(PNG_WRITE_hIST_SUPPORTED)
/* write the histogram */ /* write the histogram */
void void
png_write_hIST(png_struct *png_ptr, png_uint_16 *hist, int number) png_write_hIST(png_structp png_ptr, png_uint_16p hist, int number)
{ {
int i; int i;
png_byte buf[3]; png_byte buf[3];
@ -399,7 +399,7 @@ png_write_hIST(png_struct *png_ptr, png_uint_16 *hist, int number)
png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(number * 2)); png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(number * 2));
for (i = 0; i < number; i++) for (i = 0; i < number; i++)
{ {
png_save_uint_16(buf, hist[i]); png_save_uint_16(buf, hist[i]);
png_write_chunk_data(png_ptr, buf, (png_uint_32)2); png_write_chunk_data(png_ptr, buf, (png_uint_32)2);
} }
png_write_chunk_end(png_ptr); png_write_chunk_end(png_ptr);
@ -409,7 +409,7 @@ png_write_hIST(png_struct *png_ptr, png_uint_16 *hist, int number)
#if defined(PNG_WRITE_tEXt_SUPPORTED) #if defined(PNG_WRITE_tEXt_SUPPORTED)
/* write a tEXt chunk */ /* write a tEXt chunk */
void void
png_write_tEXt(png_struct *png_ptr, charf *key, charf *text, png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text,
png_uint_32 text_len) png_uint_32 text_len)
{ {
int key_len; int key_len;
@ -417,11 +417,11 @@ png_write_tEXt(png_struct *png_ptr, charf *key, charf *text,
key_len = png_strlen(key); key_len = png_strlen(key);
/* make sure we count the 0 after the key */ /* make sure we count the 0 after the key */
png_write_chunk_start(png_ptr, png_tEXt, png_write_chunk_start(png_ptr, png_tEXt,
(png_uint_32)(key_len + text_len + 1)); (png_uint_32)(key_len + text_len + 1));
/* key has an 0 at the end. How nice */ /* key has an 0 at the end. How nice */
png_write_chunk_data(png_ptr, (png_bytef *)key, (png_uint_32)(key_len + 1)); png_write_chunk_data(png_ptr, (png_bytep )key, (png_uint_32)(key_len + 1));
if (text && text_len) if (text && text_len)
png_write_chunk_data(png_ptr, (png_bytef *)text, (png_uint_32)text_len); png_write_chunk_data(png_ptr, (png_bytep )text, (png_uint_32)text_len);
png_write_chunk_end(png_ptr); png_write_chunk_end(png_ptr);
} }
#endif #endif
@ -429,13 +429,13 @@ png_write_tEXt(png_struct *png_ptr, charf *key, charf *text,
#if defined(PNG_WRITE_zTXt_SUPPORTED) #if defined(PNG_WRITE_zTXt_SUPPORTED)
/* write a compressed chunk */ /* write a compressed chunk */
void void
png_write_zTXt(png_struct *png_ptr, charf *key, charf *text, png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
png_uint_32 text_len, int compression) png_uint_32 text_len, int compression)
{ {
int key_len; int key_len;
char buf[1]; char buf[1];
int i, ret; int i, ret;
charf **output_ptr = NULL; /* array of pointers to output */ png_charpp output_ptr = NULL; /* array of pointers to output */
int num_output_ptr = 0; /* number of output pointers used */ int num_output_ptr = 0; /* number of output pointers used */
int max_output_ptr = 0; /* size of output_ptr */ int max_output_ptr = 0; /* size of output_ptr */
@ -453,36 +453,36 @@ png_write_zTXt(png_struct *png_ptr, charf *key, charf *text,
png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size; png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
png_ptr->zstream->next_out = (Bytef *)png_ptr->zbuf; png_ptr->zstream->next_out = (Bytef *)png_ptr->zbuf;
/* this is the same compression loop as in png_write_row() */ /* this is the same compression loop as in png_write_row() */
do do
{ {
/* compress the data */ /* compress the data */
ret = deflate(png_ptr->zstream, Z_NO_FLUSH); ret = deflate(png_ptr->zstream, Z_NO_FLUSH);
if (ret != Z_OK) if (ret != Z_OK)
{ {
/* error */ /* error */
if (png_ptr->zstream->msg) if (png_ptr->zstream->msg)
(*(png_ptr->error_fn))(png_ptr, png_ptr->zstream->msg); png_error(png_ptr, png_ptr->zstream->msg);
else else
(*(png_ptr->error_fn))(png_ptr, "zlib error"); png_error(png_ptr, "zlib error");
} }
/* check to see if we need more room */ /* check to see if we need more room */
if (!png_ptr->zstream->avail_out && png_ptr->zstream->avail_in) if (!png_ptr->zstream->avail_out && png_ptr->zstream->avail_in)
{ {
/* make sure the output array has room */ /* make sure the output array has room */
if (num_output_ptr >= max_output_ptr) if (num_output_ptr >= max_output_ptr)
{ {
png_uint_32 old_max; png_uint_32 old_max;
old_max = max_output_ptr; old_max = max_output_ptr;
max_output_ptr = num_output_ptr + 4; max_output_ptr = num_output_ptr + 4;
if (output_ptr) if (output_ptr)
output_ptr = png_realloc(png_ptr, output_ptr, output_ptr = (png_charpp)png_realloc(png_ptr, output_ptr,
max_output_ptr * sizeof (char *), max_output_ptr * sizeof (png_charpp),
old_max * sizeof (char *)); old_max * sizeof (png_charp));
else else
output_ptr = png_malloc(png_ptr, output_ptr = (png_charpp)png_malloc(png_ptr,
max_output_ptr * sizeof (char *)); max_output_ptr * sizeof (png_charp));
} }
/* save the data */ /* save the data */
@ -499,43 +499,43 @@ png_write_zTXt(png_struct *png_ptr, charf *key, charf *text,
/* continue until we don't have anymore to compress */ /* continue until we don't have anymore to compress */
} while (png_ptr->zstream->avail_in); } while (png_ptr->zstream->avail_in);
/* finish the compression */ /* finish the compression */
do do
{ {
/* tell zlib we are finished */ /* tell zlib we are finished */
ret = deflate(png_ptr->zstream, Z_FINISH); ret = deflate(png_ptr->zstream, Z_FINISH);
if (ret != Z_OK && ret != Z_STREAM_END) if (ret != Z_OK && ret != Z_STREAM_END)
{ {
/* we got an error */ /* we got an error */
if (png_ptr->zstream->msg) if (png_ptr->zstream->msg)
(*(png_ptr->error_fn))(png_ptr, png_ptr->zstream->msg); png_error(png_ptr, png_ptr->zstream->msg);
else else
(*(png_ptr->error_fn))(png_ptr, "zlib error"); png_error(png_ptr, "zlib error");
} }
/* check to see if we need more room */ /* check to see if we need more room */
if (!png_ptr->zstream->avail_out && ret == Z_OK) if (!png_ptr->zstream->avail_out && ret == Z_OK)
{ {
/* check to make sure our output array has room */ /* check to make sure our output array has room */
if (num_output_ptr >= max_output_ptr) if (num_output_ptr >= max_output_ptr)
{ {
png_uint_32 old_max; png_uint_32 old_max;
old_max = max_output_ptr; old_max = max_output_ptr;
max_output_ptr = num_output_ptr + 4; max_output_ptr = num_output_ptr + 4;
if (output_ptr) if (output_ptr)
output_ptr = png_realloc(png_ptr, output_ptr, output_ptr = (png_charpp)png_realloc(png_ptr, output_ptr,
max_output_ptr * sizeof (char *), max_output_ptr * sizeof (png_charp),
old_max * sizeof (char *)); old_max * sizeof (png_charp));
else else
output_ptr = png_malloc(png_ptr, output_ptr = (png_charpp)png_malloc(png_ptr,
max_output_ptr * sizeof (char *)); max_output_ptr * sizeof (png_charp));
} }
/* save off the data */ /* save off the data */
output_ptr[num_output_ptr] = png_large_malloc(png_ptr, output_ptr[num_output_ptr] = png_large_malloc(png_ptr,
png_ptr->zbuf_size); png_ptr->zbuf_size);
png_memcpy(output_ptr[num_output_ptr], png_ptr->zbuf, png_memcpy(output_ptr[num_output_ptr], png_ptr->zbuf,
(png_size_t)png_ptr->zbuf_size); (png_size_t)png_ptr->zbuf_size);
num_output_ptr++; num_output_ptr++;
@ -546,7 +546,7 @@ png_write_zTXt(png_struct *png_ptr, charf *key, charf *text,
} while (ret != Z_STREAM_END); } while (ret != Z_STREAM_END);
/* text length is number of buffers plus last buffer */ /* text length is number of buffers plus last buffer */
text_len = png_ptr->zbuf_size * num_output_ptr; text_len = png_ptr->zbuf_size * num_output_ptr;
if (png_ptr->zstream->avail_out < png_ptr->zbuf_size) if (png_ptr->zstream->avail_out < png_ptr->zbuf_size)
text_len += (png_uint_32)(png_ptr->zbuf_size - text_len += (png_uint_32)(png_ptr->zbuf_size -
png_ptr->zstream->avail_out); png_ptr->zstream->avail_out);
@ -555,16 +555,16 @@ png_write_zTXt(png_struct *png_ptr, charf *key, charf *text,
png_write_chunk_start(png_ptr, png_zTXt, png_write_chunk_start(png_ptr, png_zTXt,
(png_uint_32)(key_len + text_len + 2)); (png_uint_32)(key_len + text_len + 2));
/* write key */ /* write key */
png_write_chunk_data(png_ptr, (png_bytef *)key, (png_uint_32)(key_len + 1)); png_write_chunk_data(png_ptr, (png_bytep )key, (png_uint_32)(key_len + 1));
buf[0] = compression; buf[0] = compression;
/* write compression */ /* write compression */
png_write_chunk_data(png_ptr, (png_byte *)buf, (png_uint_32)1); png_write_chunk_data(png_ptr, (png_bytep )buf, (png_uint_32)1);
/* write saved output buffers, if any */ /* write saved output buffers, if any */
for (i = 0; i < num_output_ptr; i++) for (i = 0; i < num_output_ptr; i++)
{ {
png_write_chunk_data(png_ptr, (png_bytef *)output_ptr[i], png_ptr->zbuf_size); png_write_chunk_data(png_ptr, (png_bytep )output_ptr[i], png_ptr->zbuf_size);
png_large_free(png_ptr, output_ptr[i]); png_large_free(png_ptr, output_ptr[i]);
} }
if (max_output_ptr) if (max_output_ptr)
png_free(png_ptr, output_ptr); png_free(png_ptr, output_ptr);
@ -576,14 +576,14 @@ png_write_zTXt(png_struct *png_ptr, charf *key, charf *text,
png_write_chunk_end(png_ptr); png_write_chunk_end(png_ptr);
/* reset zlib for another zTXt or the image data */ /* reset zlib for another zTXt or the image data */
deflateReset(png_ptr->zstream); deflateReset(png_ptr->zstream);
} }
#endif #endif
#if defined(PNG_WRITE_pHYs_SUPPORTED) #if defined(PNG_WRITE_pHYs_SUPPORTED)
/* write the pHYs chunk */ /* write the pHYs chunk */
void void
png_write_pHYs(png_struct *png_ptr, png_uint_32 x_pixels_per_unit, png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
png_uint_32 y_pixels_per_unit, png_uint_32 y_pixels_per_unit,
int unit_type) int unit_type)
{ {
@ -600,7 +600,7 @@ png_write_pHYs(png_struct *png_ptr, png_uint_32 x_pixels_per_unit,
#if defined(PNG_WRITE_oFFs_SUPPORTED) #if defined(PNG_WRITE_oFFs_SUPPORTED)
/* write the oFFs chunk */ /* write the oFFs chunk */
void void
png_write_oFFs(png_struct *png_ptr, png_uint_32 x_offset, png_write_oFFs(png_structp png_ptr, png_uint_32 x_offset,
png_uint_32 y_offset, png_uint_32 y_offset,
int unit_type) int unit_type)
{ {
@ -618,7 +618,7 @@ png_write_oFFs(png_struct *png_ptr, png_uint_32 x_offset,
/* write the tIME chunk. Use either png_convert_from_struct_tm() /* write the tIME chunk. Use either png_convert_from_struct_tm()
or png_convert_from_time_t(), or fill in the structure yourself */ or png_convert_from_time_t(), or fill in the structure yourself */
void void
png_write_tIME(png_struct *png_ptr, png_time *mod_time) png_write_tIME(png_structp png_ptr, png_timep mod_time)
{ {
png_byte buf[7]; png_byte buf[7];
@ -635,26 +635,26 @@ png_write_tIME(png_struct *png_ptr, png_time *mod_time)
/* initializes the row writing capability of libpng */ /* initializes the row writing capability of libpng */
void void
png_write_start_row(png_struct *png_ptr) png_write_start_row(png_structp png_ptr)
{ {
/* set up row buffer */ /* set up row buffer */
png_ptr->row_buf = (png_bytef *)png_large_malloc(png_ptr, png_ptr->row_buf = (png_bytep )png_large_malloc(png_ptr,
(((png_uint_32)png_ptr->usr_channels * (((png_uint_32)png_ptr->usr_channels *
(png_uint_32)png_ptr->usr_bit_depth * (png_uint_32)png_ptr->usr_bit_depth *
png_ptr->width) >> 3) + 1); png_ptr->width + 7) >> 3) + 1);
/* set up filtering buffers, if filtering */ /* set up filtering buffers, if filtering */
if (png_ptr->do_filter) if (png_ptr->do_filter)
{ {
png_ptr->prev_row = (png_bytef *)png_large_malloc(png_ptr, png_ptr->prev_row = (png_bytep )png_large_malloc(png_ptr,
png_ptr->rowbytes + 1); png_ptr->rowbytes + 1);
png_memset(png_ptr->prev_row, 0, (png_size_t)png_ptr->rowbytes + 1); png_memset(png_ptr->prev_row, 0, (png_size_t)png_ptr->rowbytes + 1);
png_ptr->save_row = (png_bytef *)png_large_malloc(png_ptr, png_ptr->save_row = (png_bytep )png_large_malloc(png_ptr,
png_ptr->rowbytes + 1); png_ptr->rowbytes + 1);
png_memset(png_ptr->save_row, 0, (png_size_t)png_ptr->rowbytes + 1); png_memset(png_ptr->save_row, 0, (png_size_t)png_ptr->rowbytes + 1);
} }
/* if interlaced, we need to set up width and height of pass */ /* if interlaced, we need to set up width and height of pass */
if (png_ptr->interlaced) if (png_ptr->interlaced)
{ {
if (!(png_ptr->transformations & PNG_INTERLACE)) if (!(png_ptr->transformations & PNG_INTERLACE))
{ {
@ -672,7 +672,7 @@ png_write_start_row(png_struct *png_ptr)
} }
} }
else else
{ {
png_ptr->num_rows = png_ptr->height; png_ptr->num_rows = png_ptr->height;
png_ptr->usr_width = png_ptr->width; png_ptr->usr_width = png_ptr->width;
} }
@ -682,15 +682,15 @@ png_write_start_row(png_struct *png_ptr)
/* Internal use only. Called when finished processing a row of data */ /* Internal use only. Called when finished processing a row of data */
void void
png_write_finish_row(png_struct *png_ptr) png_write_finish_row(png_structp png_ptr)
{ {
int ret; int ret;
/* next row */ /* next row */
png_ptr->row_number++; png_ptr->row_number++;
/* see if we are done */ /* see if we are done */
if (png_ptr->row_number < png_ptr->num_rows || png_ptr->mode > PNG_HAVE_IDAT) if (png_ptr->row_number < png_ptr->num_rows)
return; return;
/* if interlaced, go to next pass */ /* if interlaced, go to next pass */
if (png_ptr->interlaced) if (png_ptr->interlaced)
@ -708,7 +708,7 @@ png_write_finish_row(png_struct *png_ptr)
png_ptr->pass++; png_ptr->pass++;
if (png_ptr->pass >= 7) if (png_ptr->pass >= 7)
break; break;
png_ptr->usr_width = (png_ptr->width + png_ptr->usr_width = (png_ptr->width +
png_pass_inc[png_ptr->pass] - 1 - png_pass_inc[png_ptr->pass] - 1 -
png_pass_start[png_ptr->pass]) / png_pass_start[png_ptr->pass]) /
png_pass_inc[png_ptr->pass]; png_pass_inc[png_ptr->pass];
@ -726,7 +726,7 @@ png_write_finish_row(png_struct *png_ptr)
if (png_ptr->prev_row) if (png_ptr->prev_row)
png_memset(png_ptr->prev_row, 0, (png_size_t)png_ptr->rowbytes + 1); png_memset(png_ptr->prev_row, 0, (png_size_t)png_ptr->rowbytes + 1);
/* if we have more data to get, go get it */ /* if we have more data to get, go get it */
if (png_ptr->pass < 7) if (png_ptr->pass < 7)
return; return;
} }
@ -735,16 +735,16 @@ png_write_finish_row(png_struct *png_ptr)
do do
{ {
/* tell the compressor we are done */ /* tell the compressor we are done */
ret = deflate(png_ptr->zstream, Z_FINISH); ret = deflate(png_ptr->zstream, Z_FINISH);
/* check for an error */ /* check for an error */
if (ret != Z_OK && ret != Z_STREAM_END) if (ret != Z_OK && ret != Z_STREAM_END)
{ {
if (png_ptr->zstream->msg) if (png_ptr->zstream->msg)
(*(png_ptr->error_fn))(png_ptr, png_ptr->zstream->msg); png_error(png_ptr, png_ptr->zstream->msg);
else else
(*(png_ptr->error_fn))(png_ptr, "zlib error"); png_error(png_ptr, "zlib error");
} }
/* check to see if we need more room */ /* check to see if we need more room */
if (!png_ptr->zstream->avail_out && ret == Z_OK) if (!png_ptr->zstream->avail_out && ret == Z_OK)
{ {
png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
@ -761,7 +761,6 @@ png_write_finish_row(png_struct *png_ptr)
} }
deflateReset(png_ptr->zstream); deflateReset(png_ptr->zstream);
png_ptr->mode = PNG_AFTER_IDAT;
} }
#if defined(PNG_WRITE_INTERLACING_SUPPORTED) #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
@ -774,18 +773,18 @@ png_write_finish_row(png_struct *png_ptr)
See the default: case for the easiest code to understand. See the default: case for the easiest code to understand.
*/ */
void void
png_do_write_interlace(png_row_info *row_info, png_bytef *row, int pass) png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
{ {
/* we don't have to do anything on the last pass (6) */ /* we don't have to do anything on the last pass (6) */
if (row && row_info && pass < 6) if (row && row_info && pass < 6)
{ {
/* each pixel depth is handled seperately */ /* each pixel depth is handled seperately */
switch (row_info->pixel_depth) switch (row_info->pixel_depth)
{ {
case 1: case 1:
{ {
png_bytef *sp; png_bytep sp;
png_bytef *dp; png_bytep dp;
int shift; int shift;
int d; int d;
int value; int value;
@ -799,7 +798,7 @@ png_do_write_interlace(png_row_info *row_info, png_bytef *row, int pass)
i += png_pass_inc[pass]) i += png_pass_inc[pass])
{ {
sp = row + (png_size_t)(i >> 3); sp = row + (png_size_t)(i >> 3);
value = (int)(*sp >> (7 - (int)(i & 7))) & 0x1; value = (int)(*sp >> (7 - (int)(i & 7))) & 0x1;
d |= (value << shift); d |= (value << shift);
if (shift == 0) if (shift == 0)
@ -817,9 +816,9 @@ png_do_write_interlace(png_row_info *row_info, png_bytef *row, int pass)
break; break;
} }
case 2: case 2:
{ {
png_bytef *sp; png_bytep sp;
png_bytef *dp; png_bytep dp;
int shift; int shift;
int d; int d;
int value; int value;
@ -851,9 +850,9 @@ png_do_write_interlace(png_row_info *row_info, png_bytef *row, int pass)
} }
case 4: case 4:
{ {
png_bytef *sp; png_bytep sp;
png_bytef *dp; png_bytep dp;
int shift; int shift;
int d; int d;
int value; int value;
png_uint_32 i; png_uint_32 i;
@ -871,7 +870,7 @@ png_do_write_interlace(png_row_info *row_info, png_bytef *row, int pass)
if (shift == 0) if (shift == 0)
{ {
shift = 4; shift = 4;
*dp++ = d; *dp++ = d;
d = 0; d = 0;
} }
@ -884,12 +883,12 @@ png_do_write_interlace(png_row_info *row_info, png_bytef *row, int pass)
} }
default: default:
{ {
png_bytef *sp; png_bytep sp;
png_bytef *dp; png_bytep dp;
png_uint_32 i; png_uint_32 i;
int pixel_bytes; int pixel_bytes;
/* start at the beginning */ /* start at the beginning */
dp = row; dp = row;
/* find out how many bytes each pixel takes up */ /* find out how many bytes each pixel takes up */
pixel_bytes = (row_info->pixel_depth >> 3); pixel_bytes = (row_info->pixel_depth >> 3);
@ -907,7 +906,7 @@ png_do_write_interlace(png_row_info *row_info, png_bytef *row, int pass)
/* next pixel */ /* next pixel */
dp += pixel_bytes; dp += pixel_bytes;
} }
break; break;
} }
} }
/* set new row width */ /* set new row width */
@ -925,13 +924,13 @@ png_do_write_interlace(png_row_info *row_info, png_bytef *row, int pass)
/* this filters the row. Both row and prev_row have space at the /* this filters the row. Both row and prev_row have space at the
first byte for the filter byte. */ first byte for the filter byte. */
void void
png_write_filter_row(png_row_info *row_info, png_bytef *row, png_write_filter_row(png_row_infop row_info, png_bytep row,
png_bytef *prev_row) png_bytep prev_row)
{ {
int minf, bpp; int minf, bpp;
png_uint_32 i, v; png_uint_32 i, v;
png_uint_32 s0, s1, s2, s3, s4, mins; png_uint_32 s0, s1, s2, s3, s4, mins;
png_bytef *rp, *pp, *cp, *lp; png_bytep rp, pp, cp, lp;
/* find out how many bytes offset each pixel is */ /* find out how many bytes offset each pixel is */
bpp = (row_info->pixel_depth + 7) / 8; bpp = (row_info->pixel_depth + 7) / 8;
@ -943,7 +942,7 @@ png_write_filter_row(png_row_info *row_info, png_bytef *row,
zero using anything >= 128 as negitive numbers. */ zero using anything >= 128 as negitive numbers. */
s0 = s1 = s2 = s3 = s4 = 0; s0 = s1 = s2 = s3 = s4 = 0;
for (i = 0, rp = row + 1, pp = prev_row + 1, lp = row + 1 - bpp, for (i = 0, rp = row + 1, pp = prev_row + 1, lp = row + 1 - bpp,
cp = prev_row + 1 - bpp; cp = prev_row + 1 - bpp;
i < bpp; i++, rp++, pp++, lp++, cp++) i < bpp; i++, rp++, pp++, lp++, cp++)
{ {
@ -979,7 +978,7 @@ png_write_filter_row(png_row_info *row_info, png_bytef *row,
{ {
int a, b, c, pa, pb, pc, p; int a, b, c, pa, pb, pc, p;
/* check none filter */ /* check none filter */
v = *rp; v = *rp;
if (v < 128) if (v < 128)
s0 += v; s0 += v;
@ -997,7 +996,7 @@ png_write_filter_row(png_row_info *row_info, png_bytef *row,
/* check up filter */ /* check up filter */
v = (png_byte)(((int)*rp - (int)*pp) & 0xff); v = (png_byte)(((int)*rp - (int)*pp) & 0xff);
if (v < 128) if (v < 128)
s2 += v; s2 += v;
else else
s2 += 256 - v; s2 += 256 - v;
@ -1015,7 +1014,7 @@ png_write_filter_row(png_row_info *row_info, png_bytef *row,
c = *cp; c = *cp;
a = *lp; a = *lp;
p = a + b - c; p = a + b - c;
pa = abs(p - a); pa = abs(p - a);
pb = abs(p - b); pb = abs(p - b);
pc = abs(p - c); pc = abs(p - c);
@ -1051,7 +1050,7 @@ png_write_filter_row(png_row_info *row_info, png_bytef *row,
if (s3 < mins) if (s3 < mins)
{ {
mins = s3; mins = s3;
minf = 3; minf = 3;
} }
@ -1069,7 +1068,7 @@ png_write_filter_row(png_row_info *row_info, png_bytef *row,
{ {
/* sub filter */ /* sub filter */
case 1: case 1:
for (i = bpp, rp = row + (png_size_t)row_info->rowbytes, for (i = bpp, rp = row + (png_size_t)row_info->rowbytes,
lp = row + (png_size_t)row_info->rowbytes - bpp; lp = row + (png_size_t)row_info->rowbytes - bpp;
i < row_info->rowbytes; i++, rp--, lp--) i < row_info->rowbytes; i++, rp--, lp--)
{ {
@ -1087,7 +1086,7 @@ png_write_filter_row(png_row_info *row_info, png_bytef *row,
break; break;
/* avg filter */ /* avg filter */
case 3: case 3:
for (i = row_info->rowbytes, for (i = row_info->rowbytes,
rp = row + (png_size_t)row_info->rowbytes, rp = row + (png_size_t)row_info->rowbytes,
pp = prev_row + (png_size_t)row_info->rowbytes, pp = prev_row + (png_size_t)row_info->rowbytes,
lp = row + (png_size_t)row_info->rowbytes - bpp; lp = row + (png_size_t)row_info->rowbytes - bpp;
@ -1105,7 +1104,7 @@ png_write_filter_row(png_row_info *row_info, png_bytef *row,
case 4: case 4:
for (i = row_info->rowbytes, for (i = row_info->rowbytes,
rp = row + (png_size_t)row_info->rowbytes, rp = row + (png_size_t)row_info->rowbytes,
pp = prev_row + (png_size_t)row_info->rowbytes, pp = prev_row + (png_size_t)row_info->rowbytes,
lp = row + (png_size_t)row_info->rowbytes - bpp, lp = row + (png_size_t)row_info->rowbytes - bpp,
cp = prev_row + (png_size_t)row_info->rowbytes - bpp; cp = prev_row + (png_size_t)row_info->rowbytes - bpp;
i > 0; i--, rp--, lp--, pp--, cp--) i > 0; i--, rp--, lp--, pp--, cp--)
@ -1123,7 +1122,7 @@ png_write_filter_row(png_row_info *row_info, png_bytef *row,
a = c = 0; a = c = 0;
} }
p = a + b - c; p = a + b - c;
pa = abs(p - a); pa = abs(p - a);
pb = abs(p - b); pb = abs(p - b);
pc = abs(p - c); pc = abs(p - c);

View File

@ -1,31 +1,28 @@
readme.txt - for libpng 0.8 readme.txt - for libpng 0.85
This is the second beta version of libpng 1.0. I've updated most This is a bug fix for the second beta version of libpng 1.0, and
of the stuff I want to before the final 1.0 version. Remaining a first try at a progressive (push) reader. It hasn't been
to do are the medium memory model support (which I'll put in tested very much, but I'm not going to have time to test it for
as soon as we test this version), better dithering, and any bug a few days, and I wanted to give an advanced look at the
fixes and makefile/include additions. I expect a third (and progressive reader to everyone. Please report bugs back
perhaps final) beta after zlib is officially 1.0. (and fixes, if you find them), and I'll release a new version
in a week or two. Thanks.
I've implemented the callback functions for the error/warning
messages and the input/output. See the libpng.txt
for details. I've also added defines to support medium memory
models, so every type now has pointer defines. For example,
a pointer to the png_struct is now png_structp, while a double
pointer is now png_structpp. The old way should work, but I'll
be using the new way from now on in all my examples. Those of
you doing medium memory model or changing the error/warning
or input/output functions should try these and report back to
me any problems.
I've tried to incorporate all the changes and makefiles everyone I've tried to incorporate all the changes and makefiles everyone
sent me. However, I may of lost some in the flood. If you sent sent me. However, I may of lost some in the flood. If you sent
me a change and I didn't put it in, send it again. Sorry. me a change and I didn't put it in, send it again. Sorry.
Updates from libpng 0.71 include a new transformation,
png_set_filler(), which replaces png_set_rgbx() and
png_set_xrgb(). The old functions will be supported for
awhile, but I'd suggest changing to the new function. Also,
I've added defines in png.h to remove unwanted code from the
compiled library. I've added a new field to png_realloc(), and
fixed various bugs. I've also split up pngstub.c into pngmem.c,
pngio.c, and pngerror.c, in case you need to just change some of
these. I've pulled pngconf.h out of png.h, so you don't have to
remake your changes every new release. I've added a function to
update the png_info structure after you're done setting up your
transformations (png_read_update_info()). The complete list of
changes is in pngchang.txt. Most of you won't be much affected
by any of this. Some of you will want to use the new features.
For a detailed description on using libpng, read libpng.txt. For For a detailed description on using libpng, read libpng.txt. For
usage information and restrictions (what little they are) on libpng, usage information and restrictions (what little they are) on libpng,
see png.h. For a description on using zlib (the compression library see png.h. For a description on using zlib (the compression library