Imported from libpng-0.89.tar

This commit is contained in:
Guy Schalnat 1996-06-05 15:50:50 -05:00 committed by Glenn Randers-Pehrson
parent b2e01bd505
commit e5a37797b4
38 changed files with 3198 additions and 2062 deletions

View File

@ -10,7 +10,7 @@ pref = /prefix=all
OBJS = png.obj, pngrcb.obj, pngrutil.obj, pngtrans.obj, pngwutil.obj,\
pngread.obj, pngmem.obj, pngwrite.obj, pngrtran.obj, pngwtran.obj,\
pngio.obj, pngerror.obj, pngpread.obj
pngrio.obj, pngwio.obj, pngerror.obj, pngpread.obj
CFLAGS= $(C_DEB) $(CC_DEFS) $(PREF)
@ -41,7 +41,8 @@ pngrtran.obj : png.h, pngconf.h
pngrutil.obj : png.h, pngconf.h
pngerror.obj : png.h, pngconf.h
pngmem.obj : png.h, pngconf.h
pngio.obj : png.h, pngconf.h
pngrio.obj : png.h, pngconf.h
pngwio.obj : png.h, pngconf.h
pngtest.obj : png.h, pngconf.h
pngtrans.obj : png.h, pngconf.h
pngwrite.obj : png.h, pngconf.h

245
example.c
View File

@ -48,47 +48,45 @@ void read_png(char *file_name)
if (!fp)
return;
/* allocate the necessary structures */
png_ptr = malloc(sizeof (png_struct));
/* Create and initialize the png_struct with the desired error handler
functions. If you want to use the default stderr and longjump method,
you can supply NULL for the last three parameters. We also check that
the header file is compatible with the library version.
*/
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
(void *)user_error_ptr, user_error_fn, user_warning_fn);
if (!png_ptr)
{
fclose(fp);
return;
}
info_ptr = malloc(sizeof (png_info));
info_ptr = png_create_info_struct();
if (!info_ptr)
{
fclose(fp);
free(png_ptr);
png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
return;
}
/* set error handling */
/* set error handling if you are using the setjmp/longjmp method */
if (setjmp(png_ptr->jmpbuf))
{
png_read_destroy(png_ptr, info_ptr, (png_info *)0);
/* Free all of the memory associated with the png_ptr and info_ptr */
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
fclose(fp);
free(png_ptr);
free(info_ptr);
/* If we get here, we had a problem reading the file */
return;
}
/* initialize the structures, info first for error handling */
png_info_init(info_ptr);
png_read_init(png_ptr);
/* set up the input control if you are using standard C streams */
png_init_io(png_ptr, fp);
/* if you are using replacement read functions, here you would call */
png_set_read_fn(png_ptr, (void *)io_ptr, user_read_fn);
/* where io_ptr is a structure you want available to the callbacks */
/* if you are using replacement message functions, here you would call */
png_set_message_fn(png_ptr, (void *)msg_ptr, user_error_fn, user_warning_fn);
/* where msg_ptr is a structure you want available to the callbacks */
/* if you are using replacement read functions, instead of calling
png_init_io() here you would call */
png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn);
/* where user_io_ptr is a structure you want available to the callbacks */
/* read the file information */
png_read_info(png_ptr, info_ptr);
@ -96,29 +94,31 @@ void read_png(char *file_name)
/* set up the transformations you want. Note that these are
all optional. Only call them if you want them */
/* expand paletted colors into true rgb */
/* expand paletted colors into true RGB triplets */
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
png_set_expand(png_ptr);
/* expand grayscale images to the full 8 bits */
if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
info_ptr->bit_depth < 8)
if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY && info_ptr->bit_depth < 8)
png_set_expand(png_ptr);
/* expand images with transparency to full alpha channels */
/* expand paletted or RGB images with transparency to full alpha channels
* so the data will be available as RGBA quartets */
if (info_ptr->valid & PNG_INFO_tRNS)
png_set_expand(png_ptr);
/* Set the background color to draw transparent and alpha
images over */
images over. It is possible to set the red, green, and blue
components directly for paletted images. */
png_color_16 my_background;
if (info_ptr->valid & PNG_INFO_bKGD)
png_set_background(png_ptr, &(info_ptr->background),
PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
else
png_set_background(png_ptr, &my_background,
PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
/* tell libpng to handle the gamma conversion for you */
if (info_ptr->valid & PNG_INFO_gAMA)
@ -126,18 +126,17 @@ void read_png(char *file_name)
else
png_set_gamma(png_ptr, screen_gamma, 0.45);
/* tell libpng to strip 16 bit depth files down to 8 bits */
/* tell libpng to strip 16 bit/color files down to 8 bits/color */
if (info_ptr->bit_depth == 16)
png_set_strip_16(png_ptr);
/* dither rgb files down to 8 bit palettes & reduce palettes
/* dither rgb files down to 8 bit palette & reduce palettes
to the number of colors available on your screen */
if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
{
if (info_ptr->valid & PNG_INFO_PLTE)
png_set_dither(png_ptr, info_ptr->palette,
info_ptr->num_palette, max_screen_colors,
info_ptr->histogram);
png_set_dither(png_ptr, info_ptr->palette, info_ptr->num_palette,
max_screen_colors, info_ptr->histogram);
else
{
png_color std_color_cube[MAX_SCREEN_COLORS] =
@ -148,9 +147,8 @@ void read_png(char *file_name)
}
}
/* invert monocrome files */
if (info_ptr->bit_depth == 1 &&
info_ptr->color_type == PNG_COLOR_GRAY)
/* invert monocrome files to have 0 as white and 1 as black */
if (info_ptr->bit_depth == 1 && info_ptr->color_type == PNG_COLOR_GRAY)
png_set_invert(png_ptr);
/* shift the pixels down to their true bit depth */
@ -158,7 +156,8 @@ void read_png(char *file_name)
info_ptr->bit_depth > info_ptr->sig_bit)
png_set_shift(png_ptr, &(info_ptr->sig_bit));
/* pack pixels into bytes */
/* pack multiple pixels with bit depths of 1, 2, and 4 into bytes
(useful only for paletted and grayscale images) */
if (info_ptr->bit_depth < 8)
png_set_packing(png_ptr);
@ -171,21 +170,15 @@ void read_png(char *file_name)
if (info_ptr->bit_depth == 16)
png_set_swap(png_ptr);
/* add a filler byte to rgb files */
if (info_ptr->bit_depth == 8 &&
info_ptr->color_type == PNG_COLOR_TYPE_RGB)
/* add a filler byte to RGB files (before or after each RGB triplet) */
if (info_ptr->bit_depth == 8 && info_ptr->color_type == PNG_COLOR_TYPE_RGB)
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
/* turn on interlace handling if you are not using png_read_image() */
if (info_ptr->interlace_type)
number_passes = png_set_interlace_handling(png_ptr);
else
number_passes = 1;
number_passes = png_set_interlace_handling(png_ptr);
/* optional call to update palette with transformations */
png_start_read_image(png_ptr);
/* optional call to update the info structure */
/* optional call to gamma correct and add the background to the palette
and update info structure. */
png_read_update_info(png_ptr, info_ptr);
/* allocate the memory to hold the image using the fields
@ -193,6 +186,12 @@ void read_png(char *file_name)
/* the easiest way to read the image */
png_bytep row_pointers[height];
for (row = 0; row < height; row++)
{
row_pointers[row] = malloc(info_ptr->rowbytes);
}
png_read_image(png_ptr, row_pointers);
/* the other way to read images - deal with interlacing */
@ -216,16 +215,11 @@ void read_png(char *file_name)
so here */
}
/* read the rest of the file, getting any additional chunks
in info_ptr */
/* read the rest of the file, getting any additional chunks in info_ptr */
png_read_end(png_ptr, info_ptr);
/* clean up after the read, and free any memory allocated */
png_read_destroy(png_ptr, info_ptr, (png_infop)0);
/* free the structures */
free(png_ptr);
free(info_ptr);
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
/* close the file */
fclose(fp);
@ -236,68 +230,74 @@ void read_png(char *file_name)
/* 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()
initialize_png_reader(png_structp *png_ptr, png_infop *info_ptr)
{
png_ptr = malloc(sizeof (png_struct));
if (!png_ptr)
return -1;
info_ptr = malloc(sizeof (png_info));
if (!info_ptr)
/* Create and initialize the png_struct with the desired error handler
functions. If you want to use the default stderr and longjump method,
you can supply NULL for the last three parameters. We also check that
the library version is compatible in case we are using dynamically
linked libraries.
*/
*png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
(void *)user_error_ptr, user_error_fn, user_warning_fn);
if (! *png_ptr)
{
free(png_ptr);
return -1;
*info_ptr = NULL;
return ERROR;
}
if (setjmp(png_ptr->jmpbuf))
*info_ptr = png_create_info_struct(png_ptr);
if (! *info_ptr)
{
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_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL);
return ERROR;
}
png_info_init(info_ptr);
png_read_init(png_ptr);
if (setjmp((*png_ptr)->jmpbuf))
{
png_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL);
return ERROR;
}
/* 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,
These functions shouldn't be dependent on global or
static variables if you are decoding several images
simultaneously. You should store stream specific data
in a separate struct, given as the second parameter,
and retrieve the pointer from inside the callbacks using
the function png_get_progressive_ptr(png_ptr). */
png_set_progressive_read_fn(*png_ptr, (void *)stream_data,
info_callback, row_callback, end_callback);
return 0;
return OK;
}
int
process_data(png_bytep buffer, png_uint_32 length)
process_data(png_structp *png_ptr, png_infop *info_ptr,
png_bytep buffer, png_uint_32 length)
{
if (setjmp(png_ptr->jmpbuf))
if (setjmp((*png_ptr)->jmpbuf))
{
png_read_destroy(png_ptr, info_ptr, (png_info *)0);
free(png_ptr);
free(info_ptr);
return -1;
/* Free the png_ptr and info_ptr memory on error */
png_destroy_read_struct(png_ptr, info_ptr, (png_infopp)NULL);
return ERROR;
}
/* 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;
/* this one's new also. Simply give it chunks of data as
they arrive from the data stream (in order, of course).
On Segmented machines, don't give it any more than 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 with less
than 256 bytes yet). When this function returns, you may
want to display any rows that were generated in the row
callback, if you aren't already displaying them there. */
png_process_data(*png_ptr, *info_ptr, buffer, length);
return OK;
}
info_callback(png_structp png_ptr, png_infop info)
@ -363,44 +363,41 @@ void write_png(char *file_name, ... other image information ...)
if (!fp)
return;
/* allocate the necessary structures */
png_ptr = malloc(sizeof (png_struct));
/* Create and initialize the png_struct with the desired error handler
functions. If you want to use the default stderr and longjump method,
you can supply NULL for the last three parameters. We also check that
the library version is compatible in case we are using dynamically
linked libraries.
*/
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
(void *)user_error_ptr, user_error_fn, user_warning_fn);
if (!png_ptr)
{
fclose(fp);
return;
}
info_ptr = malloc(sizeof (png_info));
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
fclose(fp);
free(png_ptr);
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
return;
}
/* set error handling */
if (setjmp(png_ptr->jmpbuf))
{
png_write_destroy(png_ptr);
fclose(fp);
free(png_ptr);
free(info_ptr);
/* If we get here, we had a problem reading the file */
fclose(fp);
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
return;
}
/* initialize the structures */
png_info_init(info_ptr);
png_write_init(png_ptr);
/* set up the output control if you are using standard C streams */
png_init_io(png_ptr, fp);
/* if you are using replacement write functions, here you would call */
png_set_write_fn(png_ptr, (void *)io_ptr, user_write_fn, user_flush_fn);
/* where io_ptr is a structure you want available to the callbacks */
/* if you are using replacement message functions, here you would call */
png_set_message_fn(png_ptr, (void *)msg_ptr, user_error_fn, user_warning_fn);
/* where msg_ptr is a structure you want available to the callbacks */
@ -432,9 +429,9 @@ void write_png(char *file_name, ... other image information ...)
info_ptr->valid |= PNG_INFO_gAMA;
info_ptr->gamma = gamma;
/* other optional chunks */
/* other optional chunks like cHRM, bKGD, tRNS, tEXt, tIME, oFFs, pHYs, */
/* write the file information */
/* write the file header information */
png_write_info(png_ptr, info_ptr);
/* set up the transformations you want. Note that these are
@ -466,8 +463,10 @@ void write_png(char *file_name, ... other image information ...)
else
number_passes = 1;
/* the easiest way to write the image */
png_bytep row_pointers[height];
/* the easiest way to write the image (you may choose to allocate the
memory differently, however) */
png_byte row_pointers[height][width];
png_write_image(png_ptr, row_pointers);
/* the other way to write the image - deal with interlacing */
@ -485,19 +484,23 @@ void write_png(char *file_name, ... other image information ...)
}
}
/* You can write optional chunks like tEXt, tIME at the end as well.
* Note that if you wrote tEXt or zTXt chunks before the image, and
* you aren't writing out more at the end, you have to set
* info_ptr->num_text = 0 or they will be written out again.
*/
/* write the rest of the file */
png_write_end(png_ptr, info_ptr);
/* clean up after the write, and free any memory allocated */
png_write_destroy(png_ptr);
/* if you malloced the palette, free it here */
if (info_ptr->palette)
free(info_ptr->palette);
/* free the structures */
free(png_ptr);
free(info_ptr);
/* if you allocated any text comments, free them here */
/* clean up after the write, and free any memory allocated */
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
/* close the file */
fclose(fp);

File diff suppressed because it is too large Load Diff

View File

@ -13,8 +13,8 @@ RANLIB=echo
prefix=/usr/local
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \
pngread.o pngio.o pngwrite.o pngrtran.o pngwtran.o \
pngmem.o pngerror.o pngpread.o
pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o
pngwtran.o pngmem.o pngerror.o pngpread.o
all: libpng.a pngtest
@ -45,7 +45,8 @@ clean:
png.o: png.h pngconf.h
pngerror.o: png.h pngconf.h
pngio.o: png.h pngconf.h
pngrio.o: png.h pngconf.h
pngwio.o: png.h pngconf.h
pngmem.o: png.h pngconf.h
pngrcb.o: png.h pngconf.h
pngread.o: png.h pngconf.h

114
makefile.aco Normal file
View File

@ -0,0 +1,114 @@
# Project: libpng
# Toolflags:
CCflags = -c -depend !Depend -IC:,Zlib: -g -throwback -DRISCOS -fnah
C++flags = -c -depend !Depend -IC: -throwback
Linkflags = -aif -c++ -o $@
ObjAsmflags = -throwback -NoCache -depend !Depend
CMHGflags =
LibFileflags = -c -o $@
Squeezeflags = -o $@
# Final targets:
@.libpng-lib: @.o.png @.o.pngerror @.o.pngrio @.o.pngwio @.o.pngmem \
@.o.pngpread @.o.pngrcb @.o.pngread @.o.pngrtran @.o.pngrutil \
@.o.pngtrans @.o.pngwrite @.o.pngwtran @.o.pngwutil
LibFile $(LibFileflags) @.o.png @.o.pngerror @.o.pngrio @.o.pngwio \
@.o.pngmem @.o.pngpread @.o.pngrcb @.o.pngread @.o.pngrtran \
@.o.pngrutil @.o.pngtrans @.o.pngwrite @.o.pngwtran @.o.pngwutil
@.test: @.tests.pngtest
echo Please run "Test" in directory tests
@.tests.pngtest: @.o.pngtest @.libpng-lib C:o.Stubs Zlib:zlib_lib
Link $(Linkflags) @.o.pngtest @.libpng-lib C:o.Stubs Zlib:zlib_lib
# User-editable dependencies:
.c.o:
cc $(ccflags) -o $@ $<
# Static dependencies:
@.o.example: @.tests.c.example
cc $(ccflags) -o @.o.example @.tests.c.example
@.o.pngtest: @.tests.c.pngtest
cc $(ccflags) -o @.o.pngtest @.tests.c.pngtest
# Dynamic dependencies:
o.png: c.png
o.png: h.png
o.png: Zlib:h.zlib
o.png: Zlib:h.zconf
o.png: h.pngconf
o.pngerror: c.pngerror
o.pngerror: h.png
o.pngerror: Zlib:h.zlib
o.pngerror: Zlib:h.zconf
o.pngerror: h.pngconf
o.pngrio: c.pngrio
o.pngrio: h.png
o.pngrio: Zlib:h.zlib
o.pngrio: Zlib:h.zconf
o.pngrio: h.pngconf
o.pngwio: c.pngwio
o.pngwio: h.png
o.pngwio: Zlib:h.zlib
o.pngwio: Zlib:h.zconf
o.pngwio: h.pngconf
o.pngmem: c.pngmem
o.pngmem: h.png
o.pngmem: Zlib:h.zlib
o.pngmem: Zlib:h.zconf
o.pngmem: h.pngconf
o.pngpread: c.pngpread
o.pngpread: h.png
o.pngpread: Zlib:h.zlib
o.pngpread: Zlib:h.zconf
o.pngpread: h.pngconf
o.pngrcb: c.pngrcb
o.pngrcb: h.png
o.pngrcb: Zlib:h.zlib
o.pngrcb: Zlib:h.zconf
o.pngrcb: h.pngconf
o.pngread: c.pngread
o.pngread: h.png
o.pngread: Zlib:h.zlib
o.pngread: Zlib:h.zconf
o.pngread: h.pngconf
o.pngrtran: c.pngrtran
o.pngrtran: h.png
o.pngrtran: Zlib:h.zlib
o.pngrtran: Zlib:h.zconf
o.pngrtran: h.pngconf
o.pngrutil: c.pngrutil
o.pngrutil: h.png
o.pngrutil: Zlib:h.zlib
o.pngrutil: Zlib:h.zconf
o.pngrutil: h.pngconf
o.pngtrans: c.pngtrans
o.pngtrans: h.png
o.pngtrans: Zlib:h.zlib
o.pngtrans: Zlib:h.zconf
o.pngtrans: h.pngconf
o.pngwrite: c.pngwrite
o.pngwrite: h.png
o.pngwrite: Zlib:h.zlib
o.pngwrite: Zlib:h.zconf
o.pngwrite: h.pngconf
o.pngwtran: c.pngwtran
o.pngwtran: h.png
o.pngwtran: Zlib:h.zlib
o.pngwtran: Zlib:h.zconf
o.pngwtran: h.pngconf
o.pngwutil: c.pngwutil
o.pngwutil: h.png
o.pngwutil: Zlib:h.zlib
o.pngwutil: Zlib:h.zconf
o.pngwutil: h.pngconf
o.pngtest: tests.c.pngtest
o.pngtest: h.png
o.pngtest: Zlib:h.zlib
o.pngtest: Zlib:h.zconf
o.pngtest: h.pngconf

View File

@ -23,7 +23,7 @@ AR= oml
MKDIR= makedir
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o pngpread.o \
pngread.o pngerror.o pngwrite.o pngrtran.o pngwtran.o pngio.o pngmem.o
pngread.o pngerror.o pngwrite.o pngrtran.o pngwtran.o pngrio.o pngwio.o pngmem.o
all: libpng.lib pngtest

View File

@ -14,7 +14,7 @@ OBJS = $(LBR)(png.o) $(LBR)(pngrcb.o) $(LBR)(pngrutil.o)\
$(LBR)(pngtrans.o) $(LBR)(pngwutil.o)\
$(LBR)(pngread.o) $(LBR)(pngerror.o) $(LBR)(pngwrite.o)\
$(LBR)(pngrtran.o) $(LBR)(pngwtran.o)\
$(LBR)(pngmem.o) $(LBR)(pngio.o) $(LBR)(pngpread.o)
$(LBR)(pngmem.o) $(LBR)(pngrio.o) $(LBR)(pngwio.o) $(LBR)(pngpread.o)
all: $(LBR) pngtest.ttp

View File

@ -71,35 +71,35 @@ O=obj
## variables
OBJS = \
png.$(O) \
pngerror.$(O) \
pngmem.$(O) \
pngpread.$(O) \
pngrcb.$(O) \
pngread.$(O) \
pngrio.$(O) \
pngrtran.$(O) \
pngrutil.$(O) \
pngtrans.$(O) \
pngwutil.$(O) \
pngmem.$(O) \
pngread.$(O) \
pngpread.$(O) \
pngerror.$(O) \
pngwrite.$(O) \
pngrtran.$(O) \
pngwtran.$(O) \
pngzlib.$(O) \
pngio.$(O)
pngwio.$(O) \
pngwutil.$(O)
LIBOBJS = \
+png.$(O) \
+pngrcb.$(O) \
+pngrutil.$(O) \
+pngtrans.$(O) \
+pngwutil.$(O) \
+pngerror.$(O) \
+pngmem.$(O) \
+pngpread.$(O) \
+pngread.$(O) \
+pngerror.$(O) \
+pngwrite.$(O) \
+pngrcb.$(O) \
+pngrio.$(O) \
+pngrtran.$(O) \
+pngrutil.$(O) \
+pngtrans.$(O) \
+pngwrite.$(O) \
+pngwtran.$(O) \
+pngzlib.$(O) \
+pngio.$(O)
+pngwio.$(O)
+pngwutil.$(O)
LIBNAME=libpng$(MODEL).lib
@ -133,12 +133,12 @@ pngrtran.obj: pngrtran.c
pngrutil.obj: pngrutil.c
pngerror.obj: pngerror.c
pngmem.obj: pngmem.c
pngio.obj: pngio.c
pngrio.obj: pngrio.c
pngwio.obj: pngwio.c
pngtrans.obj: pngtrans.c
pngwrite.obj: pngwrite.c
pngwtran.obj: pngwtran.c
pngwutil.obj: pngwutil.c
pngzlib.obj: pngzlib.c
$(LIBNAME): $(OBJS)

View File

@ -4,19 +4,19 @@
CC=gcc
CFLAGS=-I../zlib -O2 -Wall -fPIC
LDFLAGS=-L. -L../zlib/ -lpng -lz -lm
LDFLAGS=-L. -Wl,-rpath,. -L../zlib/ -Wl,-rpath,../zlib/ -lpng -lz -lm
RANLIB=ranlib
#RANLIB=echo
PNGVER = 0.86
PNGVER = 0.89
# where make install puts libpng.a, libpng.so*, and png.h
prefix=/usr/local
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \
pngread.o pngio.o pngwrite.o pngrtran.o pngwtran.o \
pngmem.o pngerror.o pngpread.o
pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \
pngwtran.o pngmem.o pngerror.o pngpread.o
all: libpng.so pngtest
@ -59,7 +59,8 @@ clean:
png.o: png.h pngconf.h
pngerror.o: png.h pngconf.h
pngio.o: png.h pngconf.h
pngrio.o: png.h pngconf.h
pngwio.o: png.h pngconf.h
pngmem.o: png.h pngconf.h
pngrcb.o: png.h pngconf.h
pngread.o: png.h pngconf.h

View File

@ -13,7 +13,7 @@ RANLIB=ranlib
prefix=.
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \
pngread.o pngio.o pngwrite.o pngrtran.o pngwtran.o \
pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o pngwtran.o \
pngmem.o pngerror.o pngpread.o
all: libpng.a pngtest
@ -35,7 +35,8 @@ clean:
png.o: png.h pngconf.h
pngerror.o: png.h pngconf.h
pngio.o: png.h pngconf.h
pngrio.o: png.h pngconf.h
pngwio.o: png.h pngconf.h
pngmem.o: png.h pngconf.h
pngrcb.o: png.h pngconf.h
pngread.o: png.h pngconf.h

View File

@ -15,8 +15,8 @@ RANLIB=ranlib
prefix=/usr/local
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \
pngread.o pngio.o pngwrite.o pngrtran.o pngwtran.o \
pngmem.o pngerror.o pngpread.o
pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \
pngwtran.o pngmem.o pngerror.o pngpread.o
all: ansi2knr libpng.a pngtest
@ -57,7 +57,8 @@ clean:
png.o: png.h pngconf.h
pngerror.o: png.h pngconf.h
pngio.o: png.h pngconf.h
pngrio.o: png.h pngconf.h
pngwio.o: png.h pngconf.h
pngmem.o: png.h pngconf.h
pngrcb.o: png.h pngconf.h
pngread.o: png.h pngconf.h

View File

@ -14,8 +14,8 @@ RANLIB=echo
prefix=/usr/local
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \
pngread.o pngio.o pngwrite.o pngrtran.o pngwtran.o \
pngmem.o pngerror.o pngpread.o
pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \
pngwtran.o pngmem.o pngerror.o pngpread.o
all: libpng.a pngtest
@ -46,7 +46,8 @@ clean:
png.o: png.h pngconf.h
pngerror.o: png.h pngconf.h
pngio.o: png.h pngconf.h
pngrio.o: png.h pngconf.h
pngwio.o: png.h pngconf.h
pngmem.o: png.h pngconf.h
pngrcb.o: png.h pngconf.h
pngread.o: png.h pngconf.h

View File

@ -17,7 +17,7 @@ ERRFILE= >> pngerrs
# variables
OBJS1 = png$(O) pngrcb$(O) pngrutil$(O) pngtrans$(O) pngwutil$(O) pngmem$(O) pngpread$(O)
OBJS2 = pngread$(O) pngerror$(O) pngwrite$(O) pngrtran$(O) pngwtran$(O) pngio$(O)
OBJS2 = pngread$(O) pngerror$(O) pngwrite$(O) pngrtran$(O) pngwtran$(O) pngrio$(O) pngwio$(O)
all: libpng.lib
@ -45,7 +45,10 @@ pngerror$(O): png.h pngconf.h
pngmem$(O): png.h pngconf.h
$(CC) -c $(CFLAGS) $*.c $(ERRFILE)
pngio$(O): png.h pngconf.h
pngrio$(O): png.h pngconf.h
$(CC) -c $(CFLAGS) $*.c $(ERRFILE)
pngwio$(O): png.h pngconf.h
$(CC) -c $(CFLAGS) $*.c $(ERRFILE)
pngtest$(O): png.h pngconf.h

View File

@ -13,8 +13,8 @@ RANLIB=echo
prefix=/usr/local
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \
pngread.o pngio.o pngwrite.o pngrtran.o pngwtran.o \
pngmem.o pngerror.o pngpread.o
pngread.o pngrio.o pngwio.o pngwrite.o pngrtran.o \
pngwtran.o pngmem.o pngerror.o pngpread.o
all: libpng.a pngtest
@ -45,7 +45,8 @@ clean:
png.o: png.h pngconf.h
pngerror.o: png.h pngconf.h
pngio.o: png.h pngconf.h
pngrio.o: png.h pngconf.h
pngwio.o: png.h pngconf.h
pngmem.o: png.h pngconf.h
pngrcb.o: png.h pngconf.h
pngread.o: png.h pngconf.h

View File

@ -14,9 +14,9 @@ O=.obj
# variables
OBJS1 = png$(O) pngrcb$(O) pngrutil$(O) pngtrans$(O) pngwutil$(O) pngmem$(O) pngpread$(O)
OBJS2 = pngread$(O) pngerror$(O) pngwrite$(O) pngrtran$(O) pngwtran$(O) pngio$(O)
OBJS2 = pngread$(O) pngerror$(O) pngwrite$(O) pngrtran$(O) pngwtran$(O) pngrio$(O) pngwio$(O)
OBJSL1 = +png$(O) +pngrcb$(O) +pngrutil$(O) +pngtrans$(O) +pngwutil$(O) +pngmem$(O) +pngpread$(O)
OBJSL2 = +pngread$(O) +pngerror$(O) +pngwrite$(O) +pngrtran$(O) +pngwtran$(O) pngio$(O)
OBJSL2 = +pngread$(O) +pngerror$(O) +pngwrite$(O) +pngrtran$(O) +pngwtran$(O) +pngrio$(O) +pngwio$(O)
all: libpng.lib
@ -44,7 +44,10 @@ pngerror$(O): png.h pngconf.h
pngmem$(O): png.h pngconf.h
$(CC) -c $(CFLAGS) $*.c
pngio$(O): png.h pngconf.h
pngrio$(O): png.h pngconf.h
$(CC) -c $(CFLAGS) $*.c
pngwio$(O): png.h pngconf.h
$(CC) -c $(CFLAGS) $*.c
pngtest$(O): png.h pngconf.h

View File

@ -52,8 +52,10 @@ $ CALL MAKE pngerror.OBJ "cc ''CCOPT' pngerror" -
pngerror.c png.h pngconf.h
$ CALL MAKE pngmem.OBJ "cc ''CCOPT' pngmem" -
pngmem.c png.h pngconf.h
$ CALL MAKE pngio.OBJ "cc ''CCOPT' pngio" -
pngio.c png.h pngconf.h
$ CALL MAKE pngrio.OBJ "cc ''CCOPT' pngrio" -
pngrio.c png.h pngconf.h
$ CALL MAKE pngwio.OBJ "cc ''CCOPT' pngwio" -
pngwio.c png.h pngconf.h
$ CALL MAKE pngtrans.OBJ "cc ''CCOPT' pngtrans" -
pngtrans.c png.h pngconf.h
$ CALL MAKE pngwrite.OBJ "cc ''CCOPT' pngwrite" -

60
png.c
View File

@ -1,10 +1,10 @@
/* png.c - location for general purpose png functions
libpng 1.0 beta 2 - version 0.88
libpng 1.0 beta 3 - version 0.89
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 25, 1996
May 25, 1996
*/
#define PNG_INTERNAL
@ -13,7 +13,7 @@
/* version information for c files. This better match the version
string defined in png.h */
char png_libpng_ver[] = "0.88";
char png_libpng_ver[] = "0.89";
/* place to hold the signiture string for a png file. */
png_byte FARDATA png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
@ -25,39 +25,17 @@ png_byte FARDATA png_IHDR[4] = { 73, 72, 68, 82};
png_byte FARDATA png_IDAT[4] = { 73, 68, 65, 84};
png_byte FARDATA png_IEND[4] = { 73, 69, 78, 68};
png_byte FARDATA png_PLTE[4] = { 80, 76, 84, 69};
#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_WRITE_gAMA_SUPPORTED)
png_byte FARDATA png_gAMA[4] = {103, 65, 77, 65};
#endif
#if defined(PNG_READ_sBIT_SUPPORTED) || defined(PNG_WRITE_sBIT_SUPPORTED)
png_byte FARDATA png_sBIT[4] = {115, 66, 73, 84};
#endif
#if defined(PNG_READ_cHRM_SUPPORTED) || defined(PNG_WRITE_cHRM_SUPPORTED)
png_byte FARDATA png_cHRM[4] = { 99, 72, 82, 77};
#endif
#if defined(PNG_READ_tRNS_SUPPORTED) || defined(PNG_WRITE_tRNS_SUPPORTED)
png_byte FARDATA png_tRNS[4] = {116, 82, 78, 83};
#endif
#if defined(PNG_READ_bKGD_SUPPORTED) || defined(PNG_WRITE_bKGD_SUPPORTED)
png_byte FARDATA png_bKGD[4] = { 98, 75, 71, 68};
#endif
#if defined(PNG_READ_hIST_SUPPORTED) || defined(PNG_WRITE_hIST_SUPPORTED)
png_byte FARDATA png_hIST[4] = {104, 73, 83, 84};
#endif
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED)
png_byte FARDATA png_tEXt[4] = {116, 69, 88, 116};
#endif
#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
png_byte FARDATA png_zTXt[4] = {122, 84, 88, 116};
#endif
#if defined(PNG_READ_pHYs_SUPPORTED) || defined(PNG_WRITE_pHYs_SUPPORTED)
png_byte FARDATA png_pHYs[4] = {112, 72, 89, 115};
#endif
#if defined(PNG_READ_oFFs_SUPPORTED) || defined(PNG_WRITE_oFFs_SUPPORTED)
png_byte FARDATA png_oFFs[4] = {111, 70, 70, 115};
#endif
#if defined(PNG_READ_tIME_SUPPORTED) || defined(PNG_WRITE_tIME_SUPPORTED)
png_byte FARDATA png_tIME[4] = {116, 73, 77, 69};
#endif
/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
@ -209,6 +187,21 @@ png_calculate_crc(png_structp png_ptr, png_bytep ptr,
{
png_ptr->crc = update_crc(png_ptr->crc, ptr, length);
}
png_infop
png_create_info_struct(png_structp png_ptr)
{
png_infop info_ptr;
if ((info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO)) != NULL)
{
png_memset(info_ptr, 0, sizeof(png_info));
png_ptr->do_free |= PNG_FREE_INFO;
}
return info_ptr;
}
void
png_info_init(png_infop info)
{
@ -216,3 +209,20 @@ png_info_init(png_infop info)
png_memset(info, 0, sizeof (png_info));
}
/* This function returns a pointer to the io_ptr associated with the user
functions. The application should free any memory associated with this
pointer before png_write_destroy and png_read_destroy are called. */
png_voidp
png_get_io_ptr(png_structp png_ptr)
{
return png_ptr->io_ptr;
}
/* Initialize the default input/output functions for the png file. If you
change the read, or write routines, you can call either png_set_read_fn()
or png_set_write_fn() instead of png_init_io(). */
void
png_init_io(png_structp png_ptr, FILE *fp)
{
png_ptr->io_ptr = (png_voidp)fp;
}

547
png.h
View File

@ -1,8 +1,8 @@
/* png.h - header file for png reference library
libpng 1.0 beta 2 - version 0.88
Jan 25, 1996
libpng 1.0 beta 3 - version 0.89
May 25, 1996
Note: This is a beta version. It reads and writes valid files
on the platforms I have, but it has had limited portability
@ -74,10 +74,10 @@
/* version information for png.h - this should match the version
number in png.c */
#define PNG_LIBPNG_VER_STRING "0.88"
/* careful here. I wanted to use 088, but that would be octal. Version
#define PNG_LIBPNG_VER_STRING "0.89"
/* careful here. I wanted to use 089, but that would be octal. Version
1.0 will be 100 here, etc. */
#define PNG_LIBPNG_VER 88
#define PNG_LIBPNG_VER 89
/* variables defined in png.c - only it needs to define PNG_NO_EXTERN */
#ifndef PNG_NO_EXTERN
@ -88,11 +88,7 @@ extern char png_libpng_ver[];
/* three color definitions. The order of the red, green, and blue, (and the
exact size) is not important, although the size of the fields need to
be png_byte or png_uint_16 (as defined below). While png_color_8 and
png_color_16 have more fields then they need, they are never used in
arrays, so the size isn't that important. I thought about using
unions, but it looked too clumsy, so I left it. If you're using C++,
you can union red, index, and gray, if you really want too. */
be png_byte or png_uint_16 (as defined below). */
typedef struct png_color_struct
{
png_byte red;
@ -144,7 +140,6 @@ typedef struct png_time_struct
{
png_uint_16 year; /* full year, as in, 1995 */
png_byte month; /* month of year, 1 - 12 */
png_byte day; /* day of month, 1 - 31 */
png_byte hour; /* hour of day, 0 - 23 */
png_byte minute; /* minute of hour, 0 - 59 */
@ -165,18 +160,22 @@ typedef struct png_info_struct
/* the following are necessary for every png file */
png_uint_32 width; /* with of file */
png_uint_32 height; /* height of file */
png_uint_32 valid; /* the PNG_INFO_ defines, OR'd together */
png_uint_32 rowbytes; /* bytes needed for untransformed row */
png_colorp palette; /* palette of file */
png_uint_16 num_palette; /* number of values in palette */
png_uint_16 num_trans; /* number of trans values */
png_byte bit_depth; /* 1, 2, 4, 8, or 16 */
png_byte color_type; /* use the PNG_COLOR_TYPE_ defines */
png_byte compression_type; /* must be 0 */
png_byte filter_type; /* must be 0 */
png_byte interlace_type; /* 0 for non-interlaced, 1 for interlaced */
png_uint_32 valid; /* the PNG_INFO_ defines, OR'd together */
/* the following is informational only on read, and not used on
writes */
png_byte channels; /* number of channels of data per pixel */
png_byte pixel_depth; /* number of bits per pixel */
png_byte spare_byte; /* To align the data, and for future use */
png_uint_32 rowbytes; /* bytes needed for untransformed row */
/* the rest are optional. If you are reading, check the valid
field to see if the information in these are valid. If you
are writing, set the valid field to those chunks you want
@ -184,9 +183,38 @@ typedef struct png_info_struct
#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_WRITE_gAMA_SUPPORTED)
float gamma; /* gamma value of file, if gAMA chunk is valid */
#endif
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \
defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
int num_text; /* number of comments */
int max_text; /* size of text array */
png_textp text; /* array of comments */
#endif
#if defined(PNG_READ_tIME_SUPPORTED) || defined(PNG_WRITE_tIME_SUPPORTED)
png_time mod_time; /* modification time */
#endif
#if defined(PNG_READ_sBIT_SUPPORTED) || defined(PNG_WRITE_sBIT_SUPPORTED)
png_color_8 sig_bit; /* significant bits */
#endif
#if defined(PNG_READ_tRNS_SUPPORTED) || defined(PNG_WRITE_tRNS_SUPPORTED)
png_bytep trans; /* tRNS values for palette image */
png_color_16 trans_values; /* tRNS values for non-palette image */
#endif
#if defined(PNG_READ_bKGD_SUPPORTED) || defined(PNG_WRITE_bKGD_SUPPORTED)
png_color_16 background; /* background color of image */
#endif
#if defined(PNG_READ_oFFs_SUPPORTED) || defined(PNG_WRITE_oFFs_SUPPORTED)
png_uint_32 x_offset; /* x offset on page */
png_uint_32 y_offset; /* y offset on page */
png_byte offset_unit_type; /* offset units type */
#endif
#if defined(PNG_READ_pHYs_SUPPORTED) || defined(PNG_WRITE_pHYs_SUPPORTED)
png_uint_32 x_pixels_per_unit; /* x resolution */
png_uint_32 y_pixels_per_unit; /* y resolution */
png_byte phys_unit_type; /* resolution type */
#endif
#if defined(PNG_READ_hIST_SUPPORTED) || defined(PNG_WRITE_hIST_SUPPORTED)
png_uint_16p hist; /* histogram of palette usage */
#endif
#if defined(PNG_READ_cHRM_SUPPORTED) || defined(PNG_WRITE_cHRM_SUPPORTED)
float x_white; /* cHRM chunk values */
float y_white;
@ -196,62 +224,31 @@ typedef struct png_info_struct
float y_green;
float x_blue;
float y_blue;
#endif
png_colorp palette; /* palette of file */
png_uint_16 num_palette; /* number of values in palette */
png_uint_16 num_trans; /* number of trans values */
#if defined(PNG_READ_tRNS_SUPPORTED) || defined(PNG_WRITE_tRNS_SUPPORTED)
png_bytep trans; /* tRNS values for palette image */
png_color_16 trans_values; /* tRNS values for non-palette image */
#endif
#if defined(PNG_READ_bKGD_SUPPORTED) || defined(PNG_WRITE_bKGD_SUPPORTED)
png_color_16 background; /* background color of image */
#endif
#if defined(PNG_READ_hIST_SUPPORTED) || defined(PNG_WRITE_hIST_SUPPORTED)
png_uint_16p hist; /* histogram of palette usage */
#endif
#if defined(PNG_READ_pHYs_SUPPORTED) || defined(PNG_WRITE_pHYs_SUPPORTED)
png_uint_32 x_pixels_per_unit; /* x resolution */
png_uint_32 y_pixels_per_unit; /* y resolution */
png_byte phys_unit_type; /* resolution type */
#endif
#if defined(PNG_READ_oFFs_SUPPORTED) || defined(PNG_WRITE_oFFs_SUPPORTED)
png_uint_32 x_offset; /* x offset on page */
png_uint_32 y_offset; /* y offset on page */
png_byte offset_unit_type; /* offset units type */
#endif
#if defined(PNG_READ_tIME_SUPPORTED) || defined(PNG_WRITE_tIME_SUPPORTED)
png_time mod_time; /* modification time */
#endif
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \
defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
int num_text; /* number of comments */
int max_text; /* size of text array */
png_textp text; /* array of comments */
#endif
} png_info;
typedef png_info FAR * png_infop;
typedef png_info FAR * FAR * png_infopp;
#define PNG_RESOLUTION_UNKNOWN 0
#define PNG_RESOLUTION_METER 1
#define PNG_RESOLUTION_METER 1
#define PNG_RESOLUTION_LAST 2
#define PNG_OFFSET_PIXEL 0
#define PNG_OFFSET_MICROMETER 1
#define PNG_OFFSET_PIXEL 0
#define PNG_OFFSET_MICROMETER 1
#define PNG_OFFSET_LAST 2
/* these describe the color_type field in png_info */
/* color type masks */
#define PNG_COLOR_MASK_PALETTE 1
#define PNG_COLOR_MASK_COLOR 2
#define PNG_COLOR_MASK_ALPHA 4
#define PNG_COLOR_MASK_COLOR 2
#define PNG_COLOR_MASK_ALPHA 4
/* color types. Note that not all combinations are legal */
#define PNG_COLOR_TYPE_GRAY 0
#define PNG_COLOR_TYPE_PALETTE \
(PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR)
#define PNG_COLOR_TYPE_GRAY 0
#define PNG_COLOR_TYPE_RGB_ALPHA \
(PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA)
@ -269,11 +266,6 @@ typedef png_info FAR * FAR * png_infopp;
#define PNG_INFO_oFFs 0x0100
#define PNG_INFO_tIME 0x0200
/* these determine if a function in the info needs to be freed */
#define PNG_FREE_PALETTE 0x0001
#define PNG_FREE_HIST 0x0002
#define PNG_FREE_TRANS 0x0004
/* this is used for the transformation routines, as some of them
change these values for the row. It also should enable using
the routines for other uses. */
@ -291,14 +283,14 @@ typedef png_row_info FAR * png_row_infop;
typedef png_row_info FAR * FAR * png_row_infopp;
/* These are the function types for the I/O functions, and the functions which
* modify the default I/O functions to user I/O functions. The png_msg_ptr
* modify the default I/O functions to user I/O functions. The png_error_ptr
* type should match that of user supplied warning and error functions, while
* the png_rw_ptr type should match that of the user read/write data functions.
*/
typedef struct png_struct_def png_struct;
typedef png_struct FAR * png_structp;
typedef void (*png_msg_ptr) PNGARG((png_structp, png_const_charp));
typedef void (*png_error_ptr) PNGARG((png_structp, png_const_charp));
typedef void (*png_rw_ptr) PNGARG((png_structp, png_bytep, png_uint_32));
typedef void (*png_flush_ptr) PNGARG((png_structp));
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
@ -316,55 +308,28 @@ typedef void (*png_progressive_row_ptr) PNGARG((png_structp, png_bytep,
struct png_struct_def
{
jmp_buf jmpbuf; /* used in png_error */
png_error_ptr error_fn; /* Function for printing errors and aborting */
png_error_ptr warning_fn; /* Function for printing warnings */
png_voidp error_ptr; /* user supplied struct for error functions */
png_rw_ptr write_data_fn; /* Function for writing output data */
png_rw_ptr read_data_fn; /* Function for reading input data */
png_voidp io_ptr; /* Pointer to user supplied struct for I/O functions */
png_byte mode; /* used to determine where we are in the png file */
png_byte read_mode;
png_byte color_type; /* color type of file */
png_byte bit_depth; /* bit depth of file */
png_byte interlaced; /* interlace type of file */
png_byte compession; /* compression type of file */
png_byte filter; /* filter type */
png_byte channels; /* number of channels in file */
png_byte pixel_depth; /* number of bits per pixel */
png_byte usr_bit_depth; /* bit depth of users row */
png_byte usr_channels; /* channels at start of write */
#if defined(PNG_READ_GAMMA_SUPPORTED)
png_byte gamma_shift; /* amount of shift for 16 bit gammas */
#endif
png_byte pass; /* current pass (0 - 6) */
png_byte row_init; /* 1 if png_read_start_row() has been called */
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
png_byte background_gamma_type;
png_byte background_expand;
#endif
png_byte zlib_finished;
png_byte user_palette;
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
png_byte filler;
png_byte filler_loc;
#endif
png_byte zlib_custom_level; /* one if custom compression level */
png_byte zlib_custom_method; /* one if custom compression method */
png_byte zlib_custom_window_bits; /* one if custom compression window bits */
png_byte zlib_custom_mem_level; /* one if custom compression memory level */
png_byte zlib_custom_strategy; /* one if custom compression strategy */
png_byte do_filter; /* one if filtering, zero if not */
png_byte do_custom_filter; /* one if filtering, zero if not */
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
png_byte have_chunk_header;
#endif
png_uint_16 num_palette; /* number of entries in palette */
png_uint_16 num_trans; /* number of transparency values */
png_uint_32 do_free; /* flags indicating if libpng should free memory */
png_uint_32 flags; /* flags indicating various things to libpng */
png_uint_32 transformations; /* which transformations to perform */
z_stream * zstream; /* pointer to decompression structure (below) */
png_bytep zbuf; /* buffer for zlib */
png_uint_32 zbuf_size; /* size of zbuf */
int zlib_level; /* holds zlib compression level */
int zlib_method; /* holds zlib compression method */
int zlib_window_bits; /* holds zlib compression window bits */
int zlib_mem_level; /* holds zlib compression memory level */
int zlib_strategy; /* holds zlib compression strategy */
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
int process_mode;
int cur_palette;
#endif
png_uint_32 transformations; /* which transformations to perform */
png_uint_32 crc; /* current crc value */
png_uint_32 width; /* width of file */
png_uint_32 height; /* height of file */
png_uint_32 num_rows; /* number of rows in current pass */
@ -373,20 +338,87 @@ struct png_struct_def
png_uint_32 iwidth; /* interlaced width */
png_uint_32 irowbytes; /* interlaced rowbytes */
png_uint_32 row_number; /* current row in pass */
png_bytep row_buf; /* row buffer */
png_bytep prev_row; /* previous row */
png_bytep sub_row; /* place to save row when filtering */
png_bytep up_row; /* place to save row when filtering */
png_bytep avg_row; /* place to save row when filtering */
png_bytep paeth_row; /* place to save row when filtering */
png_row_info row_info; /* used for transformation routines */
png_uint_32 idat_size; /* current idat size for read */
png_uint_32 zbuf_size; /* size of zbuf */
png_uint_32 do_free; /* flags indicating if libpng should free memory */
png_uint_32 crc; /* current crc value */
png_colorp palette; /* files palette */
png_uint_16 num_palette; /* number of entries in palette */
png_uint_16 num_trans; /* number of transparency values */
png_byte interlaced; /* interlace type of file */
png_byte pass; /* current pass (0 - 6) */
png_byte compression; /* compression type of file */
png_byte filter; /* filter type */
png_byte do_filter; /* non-zero if row filtering, zero if not */
png_byte color_type; /* color type of file */
png_byte bit_depth; /* bit depth of file */
png_byte usr_bit_depth; /* bit depth of users row */
png_byte pixel_depth; /* number of bits per pixel */
png_byte channels; /* number of channels in file */
png_byte usr_channels; /* channels at start of write */
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
png_byte filler; /* filler byte to be used for 32-bit frame buffers */
#endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
png_byte background_gamma_type;
float background_gamma;
png_color_16 background; /* background color, gamma corrected for screen */
#if defined(PNG_READ_GAMMA_SUPPORTED)
png_color_16 background_1; /* background normalized to gamma 1.0 */
#endif
#endif
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
png_flush_ptr output_flush_fn;/* Function for flushing output */
png_uint_32 flush_dist; /* how many rows apart to flush, 0 for no flush */
png_uint_32 flush_rows; /* number of rows written since last flush */
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
#if defined(PNG_READ_GAMMA_SUPPORTED)
int gamma_shift; /* amount of shift for 16 bit gammas */
float gamma; /* file gamma value */
float display_gamma; /* display gamma value */
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
png_bytep gamma_table; /* gamma table for 8 bit depth files */
png_bytep gamma_from_1; /* converts from 1.0 to screen */
png_bytep gamma_to_1; /* converts from file to 1.0 */
png_uint_16pp gamma_16_table; /* gamma table for 16 bit depth files */
png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */
png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined (PNG_READ_sBIT_SUPPORTED)
png_color_8 sig_bit; /* significant bits in file */
#endif
#if defined(PNG_READ_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
png_bytep trans; /* transparency values for paletted files */
png_color_16 trans_values; /* transparency values for non-paletted files */
#endif
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
png_color_8 shift; /* shift for significant bit tranformation */
#endif
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
png_progressive_info_ptr info_fn;
png_progressive_row_ptr row_fn;
png_progressive_end_ptr end_fn;
png_bytep save_buffer_ptr;
png_bytep save_buffer;
png_bytep current_buffer_ptr;
png_bytep current_buffer;
png_uint_32 push_length;
png_uint_32 skip_length;
png_uint_32 save_buffer_size;
png_uint_32 save_buffer_max;
png_uint_32 buffer_size;
png_uint_32 current_buffer_size;
int process_mode;
int cur_palette;
png_byte push_chunk_name[4];
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
png_uint_32 current_text_size;
png_uint_32 current_text_left;
@ -401,85 +433,29 @@ struct png_struct_def
png_uint_16 offset_table_count;
png_uint_16 offset_table_count_free;
#endif
png_byte push_chunk_name[4];
png_bytep save_buffer_ptr;
png_bytep save_buffer;
png_bytep current_buffer_ptr;
png_bytep current_buffer;
#endif
png_colorp palette; /* files palette */
#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
#if defined(PNG_READ_DITHER_SUPPORTED)
png_bytep palette_lookup; /* lookup table for dithering */
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
png_bytep gamma_table; /* gamma table for 8 bit depth files */
#endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
png_bytep gamma_from_1; /* converts from 1.0 to screen */
png_bytep gamma_to_1; /* converts from file to 1.0 */
#endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
png_bytep trans; /* transparency values for paletted files */
#endif
#if defined(PNG_READ_DITHER_SUPPORTED)
png_bytep dither_index; /* index translation for palette files */
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
png_uint_16pp gamma_16_table; /* gamma table for 16 bit depth files */
#endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */
png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */
#endif
#if defined(PNG_READ_DITHER_SUPPORTED)
png_uint_16p hist; /* histogram */
#endif
png_bytep zbuf; /* buffer for zlib */
png_bytep row_buf; /* row buffer */
png_bytep prev_row; /* previous row */
png_bytep save_row; /* place to save row before filtering */
z_stream * zstream; /* pointer to decompression structure (below) */
#if defined(PNG_READ_GAMMA_SUPPORTED)
float gamma; /* file gamma value */
float display_gamma; /* display gamma value */
#endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
float background_gamma;
#endif
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
png_color_8 shift; /* shift for significant bit tranformation */
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined (PNG_READ_sBIT_SUPPORTED)
png_color_8 sig_bit; /* significant bits in file */
#endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
png_color_16 trans_values; /* transparency values for non-paletted files */
png_color_16 background; /* background color, gamma corrected for screen */
#if defined(PNG_READ_GAMMA_SUPPORTED)
png_color_16 background_1; /* background normalized to gamma 1.0 */
#endif
#endif
png_row_info row_info; /* used for transformation routines */
FILE *fp; /* used for default png_read and png_write */
png_msg_ptr error_fn; /* Function for printing errors and aborting */
png_msg_ptr warning_fn; /* Function for printing warnings */
png_rw_ptr write_data_fn; /* Function for writing output data */
png_rw_ptr read_data_fn; /* Function for reading input data */
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
png_flush_ptr output_flush_fn;/* Function for flushing output */
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
png_progressive_info_ptr info_fn;
png_progressive_row_ptr row_fn;
png_progressive_end_ptr end_fn;
png_voidp push_ptr;
#endif
png_voidp io_ptr; /* Pointer to user supplied struct for I/O functions */
png_voidp msg_ptr; /* Pointer to user supplied struct for message functions */
};
typedef png_struct FAR * FAR * png_structpp;
/* flags for png_set_filter() to say which filters to use. The flags
are chosen so that they don't conflict with real filter types, in case they
are supplied instead of the #defined constants.
*/
#define PNG_NO_FILTERS 0x00
#define PNG_FILTER_NONE 0x08
#define PNG_FILTER_SUB 0x10
#define PNG_FILTER_UP 0x20
#define PNG_FILTER_AVG 0x40
#define PNG_FILTER_PAETH 0x80
#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \
PNG_FILTER_AVG | PNG_FILTER_PAETH)
/* Here are the function definitions most commonly used. This is not
the place to find out how to use libpng. See libpng.txt for the
full explanation, see example.c for the summary. This just provides
@ -488,13 +464,31 @@ typedef png_struct FAR * FAR * png_structpp;
/* check the first 1 - 8 bytes to see if it is a png file */
extern int png_check_sig PNGARG((png_bytep sig, int num));
/* initialize png structure for reading, and allocate any memory needed */
/* allocate and initialize png structure for reading, and any other memory */
extern png_structp png_create_read_struct PNGARG((png_const_charp user_png_ver,
voidp error_ptr, png_error_ptr warn_fn, png_error_ptr error_fn));
/* reset the png_struct to read a new image */
extern void png_reset_read_struct PNGARG((png_structpp png_ptr));
/* initialize png structure for reading, and allocate any other memory (old) */
extern void png_read_init PNGARG((png_structp png_ptr));
/* initialize png structure for writing, and allocate any memory needed */
/* allocate and initialize png structure for reading, and any other memory */
extern png_structp png_create_write_struct
PNGARG((png_const_charp user_png_ver, voidp error_ptr,
png_error_ptr warn_fn, png_error_ptr error_fn));
/* reset the png_struct to read a new image */
extern void png_reset_write_struct PNGARG((png_structpp png_ptr));
/* initialize png structure for writing, and allocate any other memory (old) */
extern void png_write_init PNGARG((png_structp png_ptr));
/* initialize the info structure */
/* allocate and initialize the info structure */
extern png_infop png_create_info_struct PNGARG((png_structp png_ptr));
/* initialize the info structure (old interface) */
extern void png_info_init PNGARG((png_infop info));
/* Writes all the png information before the image. */
@ -506,7 +500,7 @@ extern void png_read_info PNGARG((png_structp png_ptr, png_infop info));
#if defined(PNG_WRITE_tIME_SUPPORTED)
/* convert from a struct tm to png_time */
extern void png_convert_from_struct_tm PNGARG((png_timep ptime,
struct tm FAR * ttime)); /*SJT: struct tm FAR *tttime ??? */
struct tm FAR * ttime));
/* convert from time_t to png_time. Uses gmtime() */
extern void png_convert_from_time_t PNGARG((png_timep ptime, time_t ttime));
@ -533,7 +527,7 @@ extern void png_set_gray_to_rgb PNGARG((png_structp png_ptr));
#define PNG_FILLER_AFTER 1
/* Add a filler byte to rgb images. */
extern void png_set_filler PNGARG((png_structp png_ptr, int filler,
int filler_loc));
int flags));
/* old ways of doing this, still supported through 1.x for backwards
compatability, but not suggested */
@ -574,10 +568,10 @@ extern void png_set_invert_mono PNGARG((png_structp png_ptr));
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
/* Handle alpha and tRNS by replacing with a background color. */
#define PNG_BACKGROUND_GAMMA_SCREEN 0
#define PNG_BACKGROUND_GAMMA_FILE 1
#define PNG_BACKGROUND_GAMMA_UNIQUE 2
#define PNG_BACKGROUND_GAMMA_UNKNOWN 3
#define PNG_BACKGROUND_GAMMA_UNKNOWN 0
#define PNG_BACKGROUND_GAMMA_SCREEN 1
#define PNG_BACKGROUND_GAMMA_FILE 2
#define PNG_BACKGROUND_GAMMA_UNIQUE 3
extern void png_set_background PNGARG((png_structp png_ptr,
png_color_16p background_color, int background_gamma_code,
int need_expand, double background_gamma));
@ -653,10 +647,22 @@ extern void png_write_end PNGARG((png_structp png_ptr, png_infop info));
/* read the end of the png file. */
extern void png_read_end PNGARG((png_structp png_ptr, png_infop info));
/* free all memory used by the read */
/* free the info structure */
extern void png_destroy_info_struct PNGARG((png_structp png_ptr,
png_infopp info_ptr));
/* free any memory associated with the png_struct and the info_structs */
extern void png_destroy_read_struct PNGARG((png_structpp png_ptr,
png_infopp info, png_infopp end_info));
/* free all memory used by the read (old method) */
extern void png_read_destroy PNGARG((png_structp png_ptr, png_infop info,
png_infop end_info));
/* free any memory associated with the png_struct and the info_structs */
extern void png_destroy_write_struct PNGARG((png_structpp png_ptr,
png_infopp info));
/* free any memory used in png struct */
extern void png_write_destroy PNGARG((png_structp png_ptr));
@ -667,7 +673,8 @@ extern void png_write_destroy PNGARG((png_structp png_ptr));
performance at the expense of compression can modify them.
See the compression library header file for an explination
of these functions */
extern void png_set_filtering PNGARG((png_structp png_ptr, int filter));
extern void png_set_filter PNGARG((png_structp png_ptr, int method,
int filters));
extern void png_set_compression_level PNGARG((png_structp png_ptr,
int level));
@ -684,10 +691,12 @@ extern void png_set_compression_window_bits PNGARG((png_structp png_ptr,
extern void png_set_compression_method PNGARG((png_structp png_ptr,
int method));
/* These next functions are stubs of typical c functions for input/output,
memory, and error handling. They are in the file pngio.c, and pngerror.c.
These functions can be replaced at run time for those applications that
need to handle I/O in a different manner. See the file libpng.txt for
/* These next functions are called for input/output, memory, and error
handling. They are in the file pngrio.c, pngwio.c, and pngerror.c,
and call standard C I/O routines such as fread(), fwrite(), and
fprintf(). These functions can be made to use other I/O routines
at run time for those applications that need to handle I/O in a
different manner by calling png_set_???_fn(). See libpng.txt for
more information */
/* Write the data to whatever output you are using. */
@ -707,11 +716,11 @@ extern void png_init_io PNGARG((png_structp png_ptr, FILE *fp));
still do a longjmp to the last setjmp location if you are using this
method of error handling. If error_fn or warning_fn is NULL, the
default functions will be used. */
extern void png_set_message_fn PNGARG((png_structp png_ptr, png_voidp msg_ptr,
png_msg_ptr error_fn, png_msg_ptr warning_fn));
extern void png_set_error_fn PNGARG((png_structp png_ptr, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warning_fn));
/* Return the user pointer associated with the message functions */
extern png_voidp png_get_msg_ptr PNGARG((png_structp png_ptr));
/* Return the user pointer associated with the error functions */
extern png_voidp png_get_error_ptr PNGARG((png_structp png_ptr));
/* Replace the default data output functions with a user supplied one(s).
If buffered output is not used, then output_flush_fn can be set to NULL.
@ -753,6 +762,12 @@ extern void * png_realloc PNGARG((png_structp png_ptr, void * ptr,
/* free's a pointer allocated by png_malloc() */
extern void png_free PNGARG((png_structp png_ptr, void * ptr));
/* allocate memory for an internal libpng struct */
extern voidp png_create_struct PNGARG((uInt type));
/* free memory from internal libpng struct */
extern void png_destroy_struct PNGARG((voidp struct_ptr));
/* Fatal error in libpng - can't continue */
extern void png_error PNGARG((png_structp png_ptr, png_const_charp error));
@ -767,50 +782,74 @@ extern void png_warning PNGARG((png_structp png_ptr, png_const_charp message));
define PNG_INTERNAL inside your code, so everyone who includes png.h
won't get yet another definition the compiler has to deal with. */
#ifdef PNG_INTERNAL
#if defined(PNG_INTERNAL)
/* various modes of operation. Note that after an init, mode is set to
zero automatically */
#define PNG_BEFORE_IHDR 0
#define PNG_HAVE_IHDR 1
#define PNG_HAVE_PLTE 2
#define PNG_HAVE_IDAT 3
#define PNG_AT_LAST_IDAT 4
#define PNG_AFTER_IDAT 5
#define PNG_AFTER_IEND 6
#define PNG_BEFORE_IHDR 0x00
#define PNG_HAVE_IHDR 0x01
#define PNG_HAVE_PLTE 0x02
#define PNG_HAVE_IDAT 0x04
#define PNG_AT_LAST_IDAT 0x08
#define PNG_AFTER_IDAT 0x10
#define PNG_AFTER_IEND 0x20
/* push model modes */
#define PNG_READ_SIG_MODE 0
#define PNG_READ_SIG_MODE 0
#define PNG_READ_CHUNK_MODE 1
#define PNG_READ_IDAT_MODE 2
#define PNG_READ_PLTE_MODE 3
#define PNG_READ_END_MODE 4
#define PNG_SKIP_MODE 5
#define PNG_READ_tEXt_MODE 6
#define PNG_READ_zTXt_MODE 7
#define PNG_READ_DONE_MODE 8
#define PNG_ERROR_MODE 9
#define PNG_READ_IDAT_MODE 2
#define PNG_READ_PLTE_MODE 3
#define PNG_READ_END_MODE 4
#define PNG_SKIP_MODE 5
#define PNG_READ_tEXt_MODE 6
#define PNG_READ_zTXt_MODE 7
#define PNG_READ_DONE_MODE 8
#define PNG_ERROR_MODE 9
/* read modes */
#define PNG_READ_PULL_MODE 0
#define PNG_READ_PUSH_MODE 1
/* defines for the transformations the png library does on the image data */
#define PNG_BGR 0x0001
#define PNG_INTERLACE 0x0002
#define PNG_PACK 0x0004
#define PNG_SHIFT 0x0008
#define PNG_SWAP_BYTES 0x0010
#define PNG_INVERT_MONO 0x0020
#define PNG_DITHER 0x0040
#define PNG_BACKGROUND 0x0080
#define PNG_XRGB 0x0100
#define PNG_16_TO_8 0x0200
#define PNG_RGBA 0x0400
#define PNG_EXPAND 0x0800
#define PNG_GAMMA 0x1000
#define PNG_GRAY_TO_RGB 0x2000
#define PNG_FILLER 0x4000
#define PNG_BGR 0x0001
#define PNG_INTERLACE 0x0002
#define PNG_PACK 0x0004
#define PNG_SHIFT 0x0008
#define PNG_SWAP_BYTES 0x0010
#define PNG_INVERT_MONO 0x0020
#define PNG_DITHER 0x0040
#define PNG_BACKGROUND 0x0080
#define PNG_BACKGROUND_EXPAND 0x0100
#define PNG_XRGB 0x0200
#define PNG_16_TO_8 0x0400
#define PNG_RGBA 0x0800
#define PNG_EXPAND 0x1000
#define PNG_GAMMA 0x2000
#define PNG_GRAY_TO_RGB 0x4000
#define PNG_FILLER 0x8000
/* flags for png_ptr->do_free to say if memory in png_info needs to be freed */
#define PNG_FREE_PALETTE 0x0001
#define PNG_FREE_HIST 0x0002
#define PNG_FREE_TRANS 0x0004
#define PNG_FREE_STRUCT 0x0008
#define PNG_FREE_INFO 0x0010
/* flags for png_create_struct */
#define PNG_STRUCT_PNG 0x0001
#define PNG_STRUCT_INFO 0x0002
/* flags for the png_ptr->flags rather than declaring a bye for each one */
#define PNG_FLAG_WROTE_tIME 0x0001
#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0002
#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0004
#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0008
#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0010
#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0020
#define PNG_FLAG_ZLIB_FINISHED 0x0040
#define PNG_FLAG_ROW_INIT 0x0080
#define PNG_FLAG_FILLER_AFTER 0x0100
#define PNG_FLAG_HAVE_CHUNK_HEADER 0x0200
/* save typing and make code easier to understand */
#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \
@ -826,44 +865,24 @@ extern png_byte png_sig[];
extern char png_libpng_ver[];
/* constant strings for known chunk types. If you need to add a chunk,
add a string holding the name here. See png.c for more details */
add a string holding the name here. See png.c for more details. We
can't selectively include these, since we still check for chunk in the
wrong locations with these labels. */
extern png_byte FARDATA png_IHDR[];
extern png_byte FARDATA png_IDAT[];
extern png_byte FARDATA png_IEND[];
extern png_byte FARDATA png_PLTE[];
#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_WRITE_gAMA_SUPPORTED)
extern png_byte FARDATA png_gAMA[];
#endif
#if defined(PNG_READ_sBIT_SUPPORTED) || defined(PNG_WRITE_sBIT_SUPPORTED)
extern png_byte FARDATA png_sBIT[];
#endif
#if defined(PNG_READ_cHRM_SUPPORTED) || defined(PNG_WRITE_cHRM_SUPPORTED)
extern png_byte FARDATA png_cHRM[];
#endif
#if defined(PNG_READ_tRNS_SUPPORTED) || defined(PNG_WRITE_tRNS_SUPPORTED)
extern png_byte FARDATA png_tRNS[];
#endif
#if defined(PNG_READ_bKGD_SUPPORTED) || defined(PNG_WRITE_bKGD_SUPPORTED)
extern png_byte FARDATA png_bKGD[];
#endif
#if defined(PNG_READ_hIST_SUPPORTED) || defined(PNG_WRITE_hIST_SUPPORTED)
extern png_byte FARDATA png_hIST[];
#endif
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED)
extern png_byte FARDATA png_tEXt[];
#endif
#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
extern png_byte FARDATA png_zTXt[];
#endif
#if defined(PNG_READ_pHYs_SUPPORTED) || defined(PNG_WRITE_pHYs_SUPPORTED)
extern png_byte FARDATA png_pHYs[];
#endif
#if defined(PNG_READ_oFFs_SUPPORTED) || defined(PNG_WRITE_oFFs_SUPPORTED)
extern png_byte FARDATA png_oFFs[];
#endif
#if defined(PNG_READ_tIME_SUPPORTED) || defined(PNG_WRITE_tIME_SUPPORTED)
extern png_byte FARDATA png_tIME[];
#endif
/* Structures to facilitate easy interlacing. See png.c for more details */
extern int FARDATA png_pass_start[];
extern int FARDATA png_pass_inc[];
@ -894,14 +913,8 @@ extern void png_reset_crc PNGARG((png_structp png_ptr));
extern void png_calculate_crc PNGARG((png_structp png_ptr, png_bytep ptr,
png_uint_32 length));
/* default error and warning functions if user doesn't supply them */
extern void png_default_warning PNGARG((png_structp png_ptr,
png_const_charp message));
extern void png_default_error PNGARG((png_structp png_ptr,
png_const_charp error));
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
extern void png_flush PNGARG((png_structp png_ptr));
extern void png_default_flush PNGARG((png_structp png_ptr));
#endif
/* place a 32 bit number into a buffer in png byte order. We work
@ -1105,11 +1118,14 @@ extern void png_do_write_interlace PNGARG((png_row_infop row_info,
#endif
/* unfilter a row */
extern void png_read_filter_row PNGARG((png_row_infop row_info,
png_bytep row, png_bytep prev_row, int filter));
/* filter a row, and place the correct filter byte in the row */
extern void png_write_filter_row PNGARG((png_row_infop row_info,
png_bytep row, png_bytep prev_row));
extern void png_read_filter_row PNGARG((png_structp png_ptr,
png_row_infop row_info, png_bytep row, png_bytep prev_row, int filter));
/* choose the best filter to use and filter the row data */
extern void png_write_find_filter PNGARG((png_structp png_ptr,
png_row_infop row_info));
/* write out the filtered row */
extern void png_write_filtered_row PNGARG((png_structp png_ptr,
png_bytep filtered_row));
/* finish a row while reading, dealing with interlacing passes, etc. */
extern void png_read_finish_row PNGARG((png_structp png_ptr));
/* initialize the row buffers, etc. */
@ -1163,6 +1179,11 @@ extern void png_do_dither PNGARG((png_row_infop row_info,
png_bytep row, png_bytep palette_lookup, png_bytep dither_lookup));
#endif
#if defined(PNG_CORRECT_PALETTE_SUPPORTED)
extern void png_correct_palette PNGARG((png_structp png_ptr,
png_colorp palette, int num_palette));
#endif
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
extern void png_do_bgr PNGARG((png_row_infop row_info, png_bytep row));
#endif
@ -1289,13 +1310,13 @@ extern void png_push_fill_buffer PNGARG((png_structp png_ptr, png_bytep buffer,
extern void png_push_save_buffer PNGARG((png_structp png_ptr));
extern void png_push_restore_buffer PNGARG((png_structp png_ptr, png_bytep buffer,
png_uint_32 buffer_length));
extern void png_push_read_idat PNGARG((png_structp png_ptr));
extern void png_push_read_IDAT PNGARG((png_structp png_ptr));
extern void png_process_IDAT_data PNGARG((png_structp png_ptr,
png_bytep buffer, png_uint_32 buffer_length));
extern void png_push_process_row PNGARG((png_structp png_ptr));
extern void png_push_handle_PLTE PNGARG((png_structp png_ptr,
png_uint_32 length));
extern void png_push_read_plte PNGARG((png_structp png_ptr, png_infop info));
extern void png_push_read_PLTE PNGARG((png_structp png_ptr, png_infop info));
extern void png_push_handle_tRNS PNGARG((png_structp png_ptr, png_infop info,
png_uint_32 length));
extern void png_push_handle_hIST PNGARG((png_structp png_ptr, png_infop info,
@ -1310,12 +1331,12 @@ extern void png_read_push_finish_row PNGARG((png_structp png_ptr));
#if defined(PNG_READ_tEXt_SUPPORTED)
extern void png_push_handle_tEXt PNGARG((png_structp png_ptr,
png_uint_32 length));
extern void png_push_read_text PNGARG((png_structp png_ptr, png_infop info));
extern void png_push_read_tEXt PNGARG((png_structp png_ptr, png_infop info));
#endif
#if defined(PNG_READ_zTXt_SUPPORTED)
extern void png_push_handle_zTXt PNGARG((png_structp png_ptr,
png_uint_32 length));
extern void png_push_read_ztxt PNGARG((png_structp png_ptr, png_infop info));
extern void png_push_read_zTXt PNGARG((png_structp png_ptr, png_infop info));
#endif
#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */

View File

@ -74,3 +74,30 @@ version 0.88
fixed progressive bugs
replaced tabs with spaces
cleaned up documentation
added callbacks for read/write and warning/error functions
version 0.89
added new initialization API to make libpng work better with shared libs
we now have png_create_read_struct(), png_create_write_struct(),
png_create_info_struct(), png_destroy_read_struct(), and
png_destroy_write_struct() instead of the separate calls to
malloc and png_read_init(), png_info_init(), and png_write_init()
changed warning/error callback functions to fix bug - this means you
should use the new initialization API if you were using the old
png_set_message_fn() calls, and that the old API no longer exists
so that people are aware that they need to change their code
changed filter selection API to allow selection of multiple filters
since it didn't work in previous versions of libpng anyways
optimized filter selection code
fixed png_set_background() to allow using an arbitrary RGB color for
paletted images
fixed gamma and background correction for paletted images, so
png_correct_palette is not needed unless you are correcting an
external palette (you will need to #define PNG_CORRECT_PALETTE_SUPPORTED
in pngconf.h)
fixed bug with Borland 64K memory allocation (Alexander Lehmann)
fixed bug in interlace handling (Smaraderagd, I think)
added more error checking for writing and image to reduce invalid files
separated read and write functions so that they won't both be linked
into a binary when only reading or writing functionality is used
new pngtest image also has interlacing and zTXt
updated dcumentation to reflect new API

View File

@ -1,10 +1,10 @@
/* pngconf.c - machine configurable file for libpng
libpng 1.0 beta 2 - version 0.88
libpng 1.0 beta 3 - version 0.89
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 25, 1996
May 25, 1996
*/
/* Any machine specific code is near the front of this file, so if you
@ -78,7 +78,7 @@
#endif /* PNGARG */
/* enough people need this for various reasons to include it here */
#ifndef MACOS
#if !defined(MACOS) && !defined(RISCOS)
#include <sys/types.h>
#endif
/* need the time information for reading tIME chunks */
@ -179,6 +179,7 @@
#define PNG_READ_FILLER_SUPPORTED
#define PNG_READ_GAMMA_SUPPORTED
#define PNG_READ_GRAY_TO_RGB_SUPPORTED
#undef PNG_CORRECT_PALETTE_SUPPORTED
#define PNG_WRITE_INTERLACING_SUPPORTED
#define PNG_WRITE_SHIFT_SUPPORTED

View File

@ -1,22 +1,27 @@
/* pngerror.c - stub functions for i/o and memory allocation
libpng 1.0 beta 2 - version 0.88
libpng 1.0 beta 3 - version 0.89
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 25, 1996
May 25, 1996
This file provides a location for all error handling. Users which
need special error handling are expected to write replacement functions
and use png_set_message_fn() to use those functions. See the instructions
and use png_set_error_fn() to use those functions. See the instructions
at each function. */
#define PNG_INTERNAL
#include "png.h"
static void png_default_error PNGARG((png_structp png_ptr,
png_const_charp message));
static void png_default_warning PNGARG((png_structp png_ptr,
png_const_charp message));
/* This function is called whenever there is a fatal error. This function
should not be changed. If there is a need to handle errors differently,
you should supply a replacement error function and use png_set_message_fn()
you should supply a replacement error function and use png_set_error_fn()
to replace the error function at run-time. */
void
png_error(png_structp png_ptr, png_const_charp message)
@ -32,7 +37,7 @@ png_error(png_structp png_ptr, png_const_charp message)
/* This function is called whenever there is a non-fatal error. This function
should not be changed. If there is a need to handle warnings differently,
you should supply a replacement warning function and use
png_set_message_fn() to replace the warning function at run-time. */
png_set_error_fn() to replace the warning function at run-time. */
void
png_warning(png_structp png_ptr, png_const_charp message)
{
@ -45,8 +50,8 @@ png_warning(png_structp png_ptr, png_const_charp message)
/* This is the default error handling function. Note that replacements for
this function MUST NOT RETURN, or the program will likely crash. This
function is used by default, or if the program supplies NULL for the
error function pointer in png_set_message_fn(). */
void
error function pointer in png_set_error_fn(). */
static void
png_default_error(png_structp png_ptr, png_const_charp message)
{
#ifndef PNG_NO_STDIO
@ -68,7 +73,7 @@ png_default_error(png_structp png_ptr, png_const_charp message)
it can continue anyway. Replacement functions 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
static void
png_default_warning(png_structp png_ptr, png_const_charp message)
{
if (!png_ptr)
@ -81,27 +86,25 @@ png_default_warning(png_structp png_ptr, png_const_charp message)
/* 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) */
return to the calling routine or serious problems will occur. The 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_set_error_fn(png_structp png_ptr, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warning_fn)
{
png_ptr->msg_ptr = msg_ptr;
png_ptr->error_ptr = error_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
/* This function returns a pointer to the error_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)
png_get_error_ptr(png_structp png_ptr)
{
return png_ptr->msg_ptr;
return png_ptr->error_ptr;
}

318
pngio.c
View File

@ -1,318 +0,0 @@
/* pngio.c - stub functions for i/o and memory allocation
libpng 1.0 beta 2 - version 0.88
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 25, 1996
This file provides a location for all input/output. Users which need
special handling are expected to write functions which have the same
arguments as these, and perform similar functions, but possibly have
different I/O methods. Note that you shouldn't change these functions,
but rather write replacement functions and then change them at run
time with png_set_write_fn(...) or png_set_read_fn(...), etc */
#define PNG_INTERNAL
#include "png.h"
/* Write the data to whatever output you are using. The default routine
writes to a file pointer. Note that this routine sometimes gets called
with very small lengths, so you should implement some kind of simple
buffering if you are using unbuffered writes. This should never be asked
to write more then 64K on a 16 bit machine. The cast to png_size_t is
there to quiet warnings of certain compilers. */
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");
}
/* This is the function which does the actual writing of data. If you are
not writing to a standard C stream, you should create a replacement
write_data function and use it at run time with png_set_write_fn(), rather
than changing the library. */
#ifndef USE_FAR_KEYWORD
void
png_default_write_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
{
png_uint_32 check;
check = fwrite(data, 1, (png_size_t)length, png_ptr->fp);
if (check != length)
{
png_error(png_ptr, "Write Error");
}
}
#else
/* 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
the data.
*/
#define NEAR_BUF_SIZE 1024
#define MIN(a,b) (a <= b ? a : b)
#ifdef _MSC_VER
/* for FP_OFF */
#include <dos.h>
#endif
void
png_default_write_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
{
png_uint_32 check;
png_byte *n_data;
/* Check if data really is near. If so, use usual code. */
#ifdef _MSC_VER
/* do it this way just to quiet warning */
FP_OFF(n_data) = FP_OFF(data);
if (FP_SEG(n_data) == FP_SEG(data))
#else
/* this works in MSC also but with lost segment warning */
n_data = (png_byte *)data;
if ((png_bytep)n_data == data)
#endif
{
check = fwrite(n_data, 1, (png_size_t)length, png_ptr->fp);
}
else
{
png_byte buf[NEAR_BUF_SIZE];
png_size_t written, remaining, err;
check = 0;
remaining = (png_size_t)length;
do
{
written = MIN(NEAR_BUF_SIZE, remaining);
png_memcpy(buf, data, written); /* copy far buffer to near buffer */
err = fwrite(buf, 1, written, png_ptr->fp);
if (err != written)
break;
else
check += err;
data += written;
remaining -= written;
}
while (remaining != 0);
}
if (check != length)
{
png_error(png_ptr, "Write Error");
}
}
#endif
/* Read the data from whatever input you are using. The default routine
reads from a file pointer. Note that this routine sometimes gets called
with very small lengths, so you should implement some kind of simple
buffering if you are using unbuffered reads. This should never be asked
to read more then 64K on a 16 bit machine. The cast to png_size_t is
there to quiet some compilers */
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");
}
}
/* This is the function which does the actual reading of data. If you are
not reading from a standard C stream, you should create a replacement
read_data function and use it at run time with png_set_read_fn(), rather
than changing the library. */
#ifndef USE_FAR_KEYWORD
void
png_default_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
{
png_uint_32 check;
check = fread(data, 1, (size_t)length, png_ptr->fp);
if (check != length)
{
png_error(png_ptr, "Read Error");
}
}
#else
void
png_default_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
{
png_uint_32 check;
png_byte *n_data;
/* Check if data really is near. If so, use usual code. */
#ifdef _MSC_VER
/* do it this way just to quiet warning */
FP_OFF(n_data) = FP_OFF(data);
if (FP_SEG(n_data) == FP_SEG(data))
#else
/* this works in MSC also but with lost segment warning */
n_data = (png_byte *)data;
if ((png_bytep)n_data == data)
#endif
{
check = fread(n_data, 1, (size_t)length, png_ptr->fp);
}
else
{
png_byte buf[NEAR_BUF_SIZE];
png_size_t read, remaining, err;
check = 0;
remaining = (png_size_t)length;
do
{
read = MIN(NEAR_BUF_SIZE, remaining);
err = fread(buf, 1, read, png_ptr->fp);
png_memcpy(data, buf, read); /* copy far buffer to near buffer */
if(err != read)
break;
else
check += err;
data += read;
remaining -= read;
}
while (remaining != 0);
}
if (check != length)
{
png_error(png_ptr, "read Error");
}
}
#endif
/* This function is called to output any data pending writing (normally
to disk. After png_flush is called, there should be no data pending
writing in any buffers. */
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
void
png_flush(png_structp png_ptr)
{
if (png_ptr->output_flush_fn)
(*(png_ptr->output_flush_fn))(png_ptr);
}
void
png_default_flush(png_structp png_ptr)
{
if (png_ptr->fp)
fflush(png_ptr->fp);
}
#endif
/* This function allows the application to supply new output functions for
libpng if standard C streams aren't being used.
This function takes as its arguments:
png_ptr - pointer to a png output data structure
io_ptr - pointer to user supplied structure containing info about
the output functions. May be NULL.
write_data_fn - pointer to a new output function which takes as its
arguments a pointer to a png_struct, a pointer to
data to be written, and a 32-bit unsigned int which is
the number of bytes to be written. The new write
function should call png_error(png_ptr, "Error msg")
to exit and output any fatal error messages.
flush_data_fn - pointer to a new flush function which takes as its
arguments a pointer to a png_struct. After a call to
the flush function, there should be no data in any buffers
or pending transmission. If the output method doesn't do
any buffering of ouput, a function prototype must still be
supplied although it doesn't have to do anything. If
PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
time, output_flush_fn will be ignored, although it must be
supplied for compatibility. */
void
png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
{
png_ptr->io_ptr = io_ptr;
if (write_data_fn)
png_ptr->write_data_fn = write_data_fn;
else
png_ptr->write_data_fn = png_default_write_data;
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
if (output_flush_fn)
png_ptr->output_flush_fn = output_flush_fn;
else
png_ptr->output_flush_fn = png_default_flush;
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
/* It is an error to read while writing a png file */
png_ptr->read_data_fn = NULL;
}
/* This function allows the application to supply a new input function
for libpng if standard C streams aren't being used.
This function takes as its arguments:
png_ptr - pointer to a png input data structure
io_ptr - pointer to user supplied structure containing info about
the input functions. May be NULL.
read_data_fn - pointer to a new input function which takes as it's
arguments a pointer to a png_struct, a pointer to
a location where input data can be stored, and a 32-bit
unsigned int which is the number of bytes to be read.
To exit and output any fatal error messages the new write
function should call png_error(png_ptr, "Error msg"). */
void
png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
png_rw_ptr read_data_fn)
{
png_ptr->io_ptr = io_ptr;
if (read_data_fn)
png_ptr->read_data_fn = read_data_fn;
else
png_ptr->read_data_fn = png_default_read_data;
/* It is an error to write to a read device */
png_ptr->write_data_fn = NULL;
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
png_ptr->output_flush_fn = NULL;
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
}
/* This function returns a pointer to the io_ptr associated with the user
functions. The application should free any memory associated with this
pointer before png_write_destroy and png_read_destroy are called. */
png_voidp
png_get_io_ptr(png_structp png_ptr)
{
return png_ptr->io_ptr;
}
/* Initialize the default input/output functions for the png file. If you
change the read, or write routines, you can call either png_set_read_fn()
or png_set_write_fn() instead of png_init_io(). */
void
png_init_io(png_structp png_ptr, FILE *fp)
{
png_ptr->fp = fp;
png_ptr->read_data_fn = png_default_read_data;
png_ptr->write_data_fn = png_default_write_data;
#ifdef PNG_WRITE_FLUSH_SUPPORTED
png_ptr->output_flush_fn = png_default_flush;
#endif
}

136
pngmem.c
View File

@ -1,10 +1,10 @@
/* pngmem.c - stub functions for memory allocation
libpng 1.0 beta 2 - version 0.88
libpng 1.0 beta 3 - version 0.89
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 25, 1996
May 25, 1996
This file provides a location for all memory allocation. Users which
need special memory handling are expected to modify the code in this file
@ -17,6 +17,39 @@
#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
/* if you change this, be sure to change the one in png.h also */
/* Allocate memory for a png_struct. The malloc and memset can be replaced
* by a single call to calloc() if this is thought to improve performance.
*/
png_voidp
png_create_struct(uInt type)
{
png_size_t type;
png_voidp struct_ptr;
if (type == PNG_STRUCT_INFO)
size = sizeof(png_info);
else if (type == PNG_STRUCT_PNG)
size = sizeof(png_struct);
else
return (png_voidp)NULL;
if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL)
{
png_memset(struct_ptr, 0, size);
}
return (struct_ptr);
}
/* Free memory allocated by a png_create_struct() call */
void
png_destroy_struct(png_voidp struct_ptr)
{
if (struct_ptr)
farfree (struct_ptr);
}
/* Allocate memory. For reasonable files, size should never exceed
64K. However, zlib may allocate more then 64K if you don't tell
it not to. See zconf.h and png.h for more information. zlib does
@ -27,7 +60,9 @@
It gives you a segment with an offset of 8 (perhaps to store it's
memory stuff). zlib doesn't like this at all, so we have to
detect and deal with it. This code should not be needed in
Windows or OS/2 modes, and only in 16 bit mode.
Windows or OS/2 modes, and only in 16 bit mode. This code has
been updated by Alexander Lehmann for version 0.89 to waste less
memory.
*/
png_voidp
@ -35,7 +70,7 @@ png_large_malloc(png_structp png_ptr, png_uint_32 size)
{
png_voidp ret;
if (!png_ptr || !size)
return ((voidp)0);
return ((voidp)NULL);
#ifdef PNG_MAX_MALLOC_64K
if (size > (png_uint_32)65536L)
@ -58,7 +93,7 @@ png_large_malloc(png_structp png_ptr, png_uint_32 size)
if (ret)
farfree(ret);
ret = 0;
ret = NULL;
num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14));
if (num_blocks < 1)
@ -68,7 +103,7 @@ png_large_malloc(png_structp png_ptr, png_uint_32 size)
else
num_blocks++;
total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks;
total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16;
table = farmalloc(total_size);
@ -77,27 +112,25 @@ png_large_malloc(png_structp png_ptr, png_uint_32 size)
png_error(png_ptr, "Out of Memory");
}
if ((long)table & 0xffff)
if ((long)table & 0xfff0)
{
farfree(table);
total_size += (png_uint_32)65536L;
}
table = farmalloc(total_size);
if (!table)
{
png_error(png_ptr, "Out of Memory");
png_error(png_ptr, "Farmalloc didn't return normalized pointer");
}
png_ptr->offset_table = table;
png_ptr->offset_table_ptr = farmalloc(
num_blocks * sizeof (png_bytep));
hptr = (png_byte huge *)table;
if ((long)hptr & 0xffff)
if (!png_ptr->offset_table_ptr)
{
hptr = (png_byte huge *)((long)(hptr) & 0xffff0000L);
hptr += 65536L;
png_error(png_ptr, "Out of memory");
}
hptr = (png_byte huge *)table;
if ((long)hptr & 0xf)
{
hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
hptr += 16L;
}
for (i = 0; i < num_blocks; i++)
{
@ -109,12 +142,12 @@ png_large_malloc(png_structp png_ptr, png_uint_32 size)
png_ptr->offset_table_count = 0;
png_ptr->offset_table_count_free = 0;
}
if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
png_error(png_ptr, "Out of Memory");
ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
}
if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
png_error(png_ptr, "Out of Memory");
ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
}
else
ret = farmalloc(size);
@ -167,13 +200,63 @@ png_large_free(png_structp png_ptr, png_voidp ptr)
#else /* Not the Borland DOS special memory handler */
/* Allocate memory for a png_struct or a png_info. The malloc and
* memset can be replaced by a single call to calloc() if this is thought
* to improve performance noticably.
*/
png_voidp
png_create_struct(uInt type)
{
size_t size;
png_voidp struct_ptr;
if (type == PNG_STRUCT_INFO)
size = sizeof(png_info);
else if (type == PNG_STRUCT_PNG)
size = sizeof(png_struct);
else
return (png_voidp)NULL;
#if defined(__TURBOC__) && !defined(__FLAT__)
if ((struct_ptr = (png_voidp)farmalloc(size)) != NULL)
#else
# if defined(_MSC_VER) && defined(MAXSEG_64K)
if ((struct_ptr = (png_voidp)halloc(size)) != NULL)
# else
if ((struct_ptr = (png_voidp)malloc(size)) != NULL)
# endif
#endif
{
png_memset(struct_ptr, 0, size);
}
return (struct_ptr);
}
/* Free memory allocated by a png_create_struct() call */
void
png_destroy_struct(png_voidp struct_ptr)
{
if (struct_ptr)
#if defined(__TURBOC__) && !defined(__FLAT__)
farfree(struct_ptr);
#else
# if defined(_MSC_VER) && defined(MAXSEG_64K)
hfree(struct_ptr);
# else
free(struct_ptr);
# endif
#endif
}
/* Allocate memory. For reasonable files, size should never exceed
64K. However, zlib may allocate more then 64K if you don't tell
it not to. See zconf.h and png.h for more information. zlib does
need to allocate exactly 64K, so whatever you call here must
have the ability to do that. */
png_voidp
png_large_malloc(png_structp png_ptr, png_uint_32 size)
{
@ -300,4 +383,3 @@ png_free(png_structp png_ptr, void * ptr)
free(ptr);
}

View File

@ -1,10 +1,10 @@
/* pngpread.c - read a png file in push mode
libpng 1.0 beta 2 - version 0.88
libpng 1.0 beta 3 - version 0.89
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 25, 1996
May 25, 1996
*/
#define PNG_INTERNAL
@ -41,25 +41,25 @@ png_process_some_data(png_structp png_ptr, png_infop info)
}
case PNG_READ_IDAT_MODE:
{
png_push_read_idat(png_ptr);
png_push_read_IDAT(png_ptr);
break;
}
case PNG_READ_PLTE_MODE:
{
png_push_read_plte(png_ptr, info);
png_push_read_PLTE(png_ptr, info);
break;
}
#if defined(PNG_READ_tEXt_SUPPORTED)
case PNG_READ_tEXt_MODE:
{
png_push_read_text(png_ptr, info);
png_push_read_tEXt(png_ptr, info);
break;
}
#endif
#if defined(PNG_READ_zTXt_SUPPORTED)
case PNG_READ_zTXt_MODE:
{
png_push_read_ztxt(png_ptr, info);
png_push_read_zTXt(png_ptr, info);
break;
}
#endif
@ -107,7 +107,7 @@ png_push_read_sig(png_structp png_ptr)
void
png_push_read_chunk(png_structp png_ptr, png_infop info)
{
if (!png_ptr->have_chunk_header)
if (!(png_ptr->flags & PNG_FLAG_HAVE_CHUNK_HEADER))
{
png_byte chunk_start[8];
@ -120,7 +120,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info)
png_push_fill_buffer(png_ptr, chunk_start, 8);
png_ptr->push_length = png_get_uint_32(chunk_start);
png_memcpy(png_ptr->push_chunk_name, (png_voidp)(chunk_start + 4), 4);
png_ptr->have_chunk_header = 1;
png_ptr->flags |= PNG_FLAG_HAVE_CHUNK_HEADER;
png_reset_crc(png_ptr);
png_calculate_crc(png_ptr, chunk_start + 4, 4);
}
@ -128,7 +128,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info)
if (!png_memcmp(png_ptr->push_chunk_name, png_IHDR, 4))
{
if (png_ptr->mode != PNG_BEFORE_IHDR)
png_error(png_ptr, "Out of Place IHDR");
png_error(png_ptr, "Out of place IHDR");
if (png_ptr->push_length + 4 > png_ptr->buffer_size)
{
@ -168,7 +168,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info)
}
else if (!png_memcmp(png_ptr->push_chunk_name, png_IEND, 4))
{
png_error(png_ptr, "No Image in File");
png_error(png_ptr, "No image in file");
}
#if defined(PNG_READ_gAMA_SUPPORTED)
else if (!png_memcmp(png_ptr->push_chunk_name, png_gAMA, 4))
@ -180,7 +180,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info)
}
if (png_ptr->mode != PNG_HAVE_IHDR)
png_error(png_ptr, "Out of Place gAMA");
png_error(png_ptr, "Out of place gAMA");
png_handle_gAMA(png_ptr, info, png_ptr->push_length);
png_push_check_crc(png_ptr);
@ -196,7 +196,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info)
}
if (png_ptr->mode != PNG_HAVE_IHDR)
png_error(png_ptr, "Out of Place sBIT");
png_error(png_ptr, "Out of place sBIT");
png_handle_sBIT(png_ptr, info, png_ptr->push_length);
png_push_check_crc(png_ptr);
@ -212,7 +212,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info)
}
if (png_ptr->mode != PNG_HAVE_IHDR)
png_error(png_ptr, "Out of Place cHRM");
png_error(png_ptr, "Out of place cHRM");
png_handle_cHRM(png_ptr, info, png_ptr->push_length);
png_push_check_crc(png_ptr);
@ -228,7 +228,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info)
}
if (png_ptr->mode != PNG_HAVE_IHDR &&
png_ptr->mode != PNG_HAVE_PLTE)
png_error(png_ptr, "Out of Place tRNS");
png_error(png_ptr, "Out of place tRNS");
png_handle_tRNS(png_ptr, info, png_ptr->push_length);
png_push_check_crc(png_ptr);
@ -245,7 +245,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info)
if (png_ptr->mode != PNG_HAVE_IHDR &&
png_ptr->mode != PNG_HAVE_PLTE)
png_error(png_ptr, "Out of Place bKGD");
png_error(png_ptr, "Out of place bKGD");
png_handle_bKGD(png_ptr, info, png_ptr->push_length);
png_push_check_crc(png_ptr);
@ -261,7 +261,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info)
}
if (png_ptr->mode != PNG_HAVE_PLTE)
png_error(png_ptr, "Out of Place hIST");
png_error(png_ptr, "Out of place hIST");
png_handle_hIST(png_ptr, info, png_ptr->push_length);
png_push_check_crc(png_ptr);
@ -278,7 +278,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info)
if (png_ptr->mode != PNG_HAVE_IHDR &&
png_ptr->mode != PNG_HAVE_PLTE)
png_error(png_ptr, "Out of Place pHYs");
png_error(png_ptr, "Out of place pHYs");
png_handle_pHYs(png_ptr, info, png_ptr->push_length);
png_push_check_crc(png_ptr);
@ -295,7 +295,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info)
if (png_ptr->mode != PNG_HAVE_IHDR &&
png_ptr->mode != PNG_HAVE_PLTE)
png_error(png_ptr, "Out of Place oFFs");
png_error(png_ptr, "Out of place oFFs");
png_handle_oFFs(png_ptr, info, png_ptr->push_length);
png_push_check_crc(png_ptr);
@ -312,7 +312,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info)
if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND)
png_error(png_ptr, "Out of Place tIME");
png_error(png_ptr, "Out of place tIME");
png_handle_tIME(png_ptr, info, png_ptr->push_length);
png_push_check_crc(png_ptr);
@ -323,7 +323,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info)
{
if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND)
png_error(png_ptr, "Out of Place tEXt");
png_error(png_ptr, "Out of place tEXt");
png_push_handle_tEXt(png_ptr, png_ptr->push_length);
}
@ -333,19 +333,43 @@ png_push_read_chunk(png_structp png_ptr, png_infop info)
{
if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND)
png_error(png_ptr, "Out of Place zTXt");
png_error(png_ptr, "Out of place zTXt");
png_push_handle_zTXt(png_ptr, png_ptr->push_length);
}
#endif
else
{
if (png_ptr->push_chunk_name[0] <41 || png_ptr->push_chunk_name[0]> 122 ||
(png_ptr->push_chunk_name[0]>90 && png_ptr->push_chunk_name[0]< 97) ||
png_ptr->push_chunk_name[1] <41 || png_ptr->push_chunk_name[1]> 122 ||
(png_ptr->push_chunk_name[1]>90 && png_ptr->push_chunk_name[1]< 97) ||
png_ptr->push_chunk_name[2] <41 || png_ptr->push_chunk_name[2]> 122 ||
(png_ptr->push_chunk_name[2]>90 && png_ptr->push_chunk_name[2]< 97) ||
png_ptr->push_chunk_name[3] <41 || png_ptr->push_chunk_name[3]> 122 ||
(png_ptr->push_chunk_name[3]>90 && png_ptr->push_chunk_name[3]< 97))
{
char msg[200];
sprintf(msg, "Invalid chunk type 0x%02X 0x%02X 0x%02X 0x%02X",
png_ptr->push_chunk_name[0], png_ptr->push_chunk_name[1],
png_ptr->push_chunk_name[2], png_ptr->push_chunk_name[3]);
png_error(png_ptr, msg);
}
if ((png_ptr->push_chunk_name[0] & 0x20) == 0)
png_error(png_ptr, "Unknown Critical Chunk");
{
char msg[200];
sprintf(msg, "Unknown critical chunk %c%c%c%c",
png_ptr->push_chunk_name[0], png_ptr->push_chunk_name[1],
png_ptr->push_chunk_name[2], png_ptr->push_chunk_name[3]);
png_error(png_ptr, msg);
}
png_push_crc_skip(png_ptr, png_ptr->push_length);
}
png_ptr->have_chunk_header = 0;
png_ptr->flags &= ~PNG_FLAG_HAVE_CHUNK_HEADER;
}
void
@ -513,9 +537,9 @@ png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,
}
void
png_push_read_idat(png_structp png_ptr)
png_push_read_IDAT(png_structp png_ptr)
{
if (!png_ptr->have_chunk_header)
if (!(png_ptr->flags & PNG_FLAG_HAVE_CHUNK_HEADER))
{
png_byte chunk_start[8];
@ -529,13 +553,13 @@ png_push_read_idat(png_structp png_ptr)
png_ptr->push_length = png_get_uint_32(chunk_start);
png_memcpy(png_ptr->push_chunk_name,
(png_voidp)(chunk_start + 4), 4);
png_ptr->have_chunk_header = 1;
png_ptr->flags |= PNG_FLAG_HAVE_CHUNK_HEADER;
png_reset_crc(png_ptr);
png_calculate_crc(png_ptr, chunk_start + 4, 4);
if (png_memcmp(png_ptr->push_chunk_name, png_IDAT, 4))
{
png_ptr->process_mode = PNG_READ_END_MODE;
if (!png_ptr->zlib_finished)
if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
png_error(png_ptr, "Not enough compressed data");
return;
}
@ -585,7 +609,7 @@ png_push_read_idat(png_structp png_ptr)
}
png_push_check_crc(png_ptr);
png_ptr->have_chunk_header = 0;
png_ptr->flags &= ~PNG_FLAG_HAVE_CHUNK_HEADER;
}
}
@ -595,7 +619,7 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
{
int ret;
if (png_ptr->zlib_finished && buffer_length)
if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length)
png_error(png_ptr, "Extra compression data");
png_ptr->zstream->next_in = buffer;
@ -612,11 +636,11 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
png_push_process_row(png_ptr);
}
png_ptr->mode = PNG_AT_LAST_IDAT;
png_ptr->zlib_finished = 1;
png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
break;
}
if (ret != Z_OK)
png_error(png_ptr, "Compression Error");
png_error(png_ptr, "Decompression Error");
if (!(png_ptr->zstream->avail_out))
{
png_push_process_row(png_ptr);
@ -638,10 +662,9 @@ png_push_process_row(png_structp png_ptr)
png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
(png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
if (png_ptr->row_buf[0])
png_read_filter_row(&(png_ptr->row_info),
png_ptr->row_buf + 1, png_ptr->prev_row + 1,
(int)(png_ptr->row_buf[0]));
png_read_filter_row(png_ptr, &(png_ptr->row_info),
png_ptr->row_buf + 1, png_ptr->prev_row + 1,
(int)(png_ptr->row_buf[0]));
png_memcpy(png_ptr->prev_row, png_ptr->row_buf, (png_size_t)png_ptr->rowbytes + 1);
@ -811,7 +834,7 @@ void
png_push_handle_PLTE(png_structp png_ptr, png_uint_32 length)
{
if (length % 3)
png_error(png_ptr, "Invalid Palette Chunk");
png_error(png_ptr, "Invalid palette chunk");
png_ptr->num_palette = (png_uint_16)(length / 3);
png_ptr->cur_palette = 0;
@ -821,7 +844,7 @@ png_push_handle_PLTE(png_structp png_ptr, png_uint_32 length)
}
void
png_push_read_plte(png_structp png_ptr, png_infop info)
png_push_read_PLTE(png_structp png_ptr, png_infop info)
{
while (png_ptr->cur_palette < png_ptr->num_palette &&
png_ptr->buffer_size >= 3)
@ -862,7 +885,7 @@ png_push_handle_tEXt(png_structp png_ptr, png_uint_32 length)
}
void
png_push_read_text(png_structp png_ptr, png_infop info)
png_push_read_tEXt(png_structp png_ptr, png_infop info)
{
if (png_ptr->buffer_size && png_ptr->current_text_left)
{
@ -931,7 +954,7 @@ png_push_handle_zTXt(png_structp png_ptr,
}
void
png_push_read_ztxt(png_structp png_ptr, png_infop info)
png_push_read_zTXt(png_structp png_ptr, png_infop info)
{
if (png_ptr->buffer_size && png_ptr->current_text_left)
{
@ -1105,13 +1128,13 @@ png_push_have_row(png_structp png_ptr, png_bytep row)
png_voidp
png_get_progressive_ptr(png_structp png_ptr)
{
return png_ptr->push_ptr;
return png_ptr->io_ptr;
}
void
png_push_read_end(png_structp png_ptr, png_infop info)
{
if (!png_ptr->have_chunk_header)
if (!(png_ptr->flags & PNG_FLAG_HAVE_CHUNK_HEADER))
{
png_byte chunk_start[8];
@ -1124,23 +1147,23 @@ png_push_read_end(png_structp png_ptr, png_infop info)
png_push_fill_buffer(png_ptr, chunk_start, 8);
png_ptr->push_length = png_get_uint_32(chunk_start);
png_memcpy(png_ptr->push_chunk_name, (png_voidp)(chunk_start + 4), 4);
png_ptr->have_chunk_header = 1;
png_ptr->flags |= PNG_FLAG_HAVE_CHUNK_HEADER;
png_reset_crc(png_ptr);
png_calculate_crc(png_ptr, chunk_start + 4, 4);
}
if (!png_memcmp(png_ptr->push_chunk_name, png_IHDR, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid IHDR after IDAT");
}
else if (!png_memcmp(png_ptr->push_chunk_name, png_PLTE, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid PLTE after IDAT");
}
else if (!png_memcmp(png_ptr->push_chunk_name, png_IDAT, 4))
{
if (png_ptr->push_length > 0 || png_ptr->mode != PNG_AT_LAST_IDAT)
png_error(png_ptr, "too many IDAT's found");
png_error(png_ptr, "Too many IDAT's found");
}
else if (!png_memcmp(png_ptr->push_chunk_name, png_IEND, 4))
{
@ -1159,49 +1182,49 @@ png_push_read_end(png_structp png_ptr, png_infop info)
#if defined(PNG_READ_gAMA_SUPPORTED)
else if (!png_memcmp(png_ptr->push_chunk_name, png_gAMA, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid gAMA after IDAT");
}
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
else if (!png_memcmp(png_ptr->push_chunk_name, png_sBIT, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid sBIT after IDAT");
}
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
else if (!png_memcmp(png_ptr->push_chunk_name, png_cHRM, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid cHRM after IDAT");
}
#endif
#if defined(PNG_READ_tRNS_SUPPORTED)
else if (!png_memcmp(png_ptr->push_chunk_name, png_tRNS, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid tRNS after IDAT");
}
#endif
#if defined(PNG_READ_bKGD_SUPPORTED)
else if (!png_memcmp(png_ptr->push_chunk_name, png_bKGD, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid bKGD after IDAT");
}
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
else if (!png_memcmp(png_ptr->push_chunk_name, png_hIST, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid hIST after IDAT");
}
#endif
#if defined(PNG_READ_pHYs_SUPPORTED)
else if (!png_memcmp(png_ptr->push_chunk_name, png_pHYs, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid pHYs after IDAT");
}
#endif
#if defined(PNG_READ_oFFs_SUPPORTED)
else if (!png_memcmp(png_ptr->push_chunk_name, png_oFFs, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid oFFs after IDAT");
}
#endif
#if defined(PNG_READ_tIME_SUPPORTED)
@ -1215,7 +1238,7 @@ png_push_read_end(png_structp png_ptr, png_infop info)
if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND)
png_error(png_ptr, "Out of Place tIME");
png_error(png_ptr, "Out of place tIME");
png_handle_tIME(png_ptr, info, png_ptr->push_length);
png_push_check_crc(png_ptr);
@ -1226,7 +1249,7 @@ png_push_read_end(png_structp png_ptr, png_infop info)
{
if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND)
png_error(png_ptr, "Out of Place tEXt");
png_error(png_ptr, "Out of place tEXt");
png_push_handle_tEXt(png_ptr, png_ptr->push_length);
}
@ -1236,21 +1259,45 @@ png_push_read_end(png_structp png_ptr, png_infop info)
{
if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND)
png_error(png_ptr, "Out of Place zTXt");
png_error(png_ptr, "Out of place zTXt");
png_push_handle_zTXt(png_ptr, png_ptr->push_length);
}
#endif
else
{
if (png_ptr->push_chunk_name[0] <41 || png_ptr->push_chunk_name[0]> 122 ||
(png_ptr->push_chunk_name[0]>90 && png_ptr->push_chunk_name[0]< 97) ||
png_ptr->push_chunk_name[1] <41 || png_ptr->push_chunk_name[1]> 122 ||
(png_ptr->push_chunk_name[1]>90 && png_ptr->push_chunk_name[1]< 97) ||
png_ptr->push_chunk_name[2] <41 || png_ptr->push_chunk_name[2]> 122 ||
(png_ptr->push_chunk_name[2]>90 && png_ptr->push_chunk_name[2]< 97) ||
png_ptr->push_chunk_name[3] <41 || png_ptr->push_chunk_name[3]> 122 ||
(png_ptr->push_chunk_name[3]>90 && png_ptr->push_chunk_name[3]< 97))
{
char msg[45];
sprintf(msg, "Invalid chunk type 0x%02X 0x%02X 0x%02X 0x%02X",
png_ptr->push_chunk_name[0], png_ptr->push_chunk_name[1],
png_ptr->push_chunk_name[2], png_ptr->push_chunk_name[3]);
png_error(png_ptr, msg);
}
if ((png_ptr->push_chunk_name[0] & 0x20) == 0)
png_error(png_ptr, "Unknown Critical Chunk");
{
char msg[40];
sprintf(msg, "Unknown critical chunk %c%c%c%c",
png_ptr->push_chunk_name[0], png_ptr->push_chunk_name[1],
png_ptr->push_chunk_name[2], png_ptr->push_chunk_name[3]);
png_error(png_ptr, msg);
}
png_push_crc_skip(png_ptr, png_ptr->push_length);
}
if (png_ptr->mode == PNG_AT_LAST_IDAT)
png_ptr->mode = PNG_AFTER_IDAT;
png_ptr->have_chunk_header = 0;
png_ptr->flags &= ~PNG_FLAG_HAVE_CHUNK_HEADER;
}
void
@ -1260,9 +1307,9 @@ png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,
{
png_ptr->info_fn = info_fn;
png_ptr->row_fn = row_fn;
png_ptr->push_ptr = progressive_ptr;
png_ptr->end_fn = end_fn;
png_ptr->read_mode = PNG_READ_PUSH_MODE;
png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
}
void

View File

@ -1,9 +1,9 @@
/* pngrcb.c - callbacks while reading a png file
libpng 1.0 beta 2 - version 0.88
libpng 1.0 beta 3 - version 0.89
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 25, 1996
May 25, 1996
*/
#define PNG_INTERNAL
@ -185,7 +185,7 @@ png_read_tIME(png_structp png_ptr, png_infop info,
}
#endif
#if defined(PNG_READ_zTXt_SUPPORTED)
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
void
png_read_zTXt(png_structp png_ptr, png_infop info,
png_charp key, png_charp text, png_uint_32 text_len, int compression)
@ -214,10 +214,10 @@ png_read_zTXt(png_structp png_ptr, png_infop info,
}
else
{
info->max_text = info->num_text + 16;
info->max_text = 16;
info->num_text = 0;
info->text = (png_textp)png_large_malloc(png_ptr,
info->max_text * sizeof (png_text));
info->num_text = 0;
}
}

406
pngread.c
View File

@ -1,45 +1,116 @@
/* pngread.c - read a png file
libpng 1.0 beta 2 - version 0.88
libpng 1.0 beta 3 - version 0.89
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 25, 1996
May 25, 1996
*/
#define PNG_INTERNAL
#include "png.h"
/* initialize png structure for reading, and allocate any memory needed */
void
png_read_init(png_structp png_ptr)
/* Create a png structure for reading, and allocate any memory needed. */
png_structp
png_create_read_struct(png_const_charp user_png_ver, voidp error_ptr,
png_error_ptr warn_fn, png_error_ptr error_fn)
{
jmp_buf tmp_jmp;
png_msg_ptr error_fn;
png_msg_ptr warning_fn;
png_voidp msg_ptr;
png_structp png_ptr;
png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
error_fn = png_ptr->error_fn;
warning_fn = png_ptr->warning_fn;
msg_ptr = png_ptr->msg_ptr;
if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
{
return (png_structp)NULL;
}
png_memset(png_ptr, 0, sizeof (png_struct));
if (setjmp(png_ptr->jmpbuf))
{
png_large_free(png_ptr, png_ptr->zbuf);
png_free(png_ptr, png_ptr->zstream);
png_destroy_struct(png_ptr);
return (png_structp)NULL;
}
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_set_error_fn(png_ptr, error_ptr, warn_fn, error_fn);
if (user_png_ver == NULL || strcmp(user_png_ver, png_libpng_ver))
{
if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0])
{
png_error(png_ptr, "Incompatible libpng versions");
}
else
{
png_warning(png_ptr, "Different libpng versions");
}
}
/* initialize zbuf - compression buffer */
png_ptr->zbuf_size = PNG_ZBUF_SIZE;
png_ptr->zbuf = png_large_malloc(png_ptr, png_ptr->zbuf_size);
png_ptr->zstream = (z_stream *)png_malloc(png_ptr, sizeof (z_stream));
png_ptr->zstream->zalloc = png_zalloc;
png_ptr->zstream->zfree = png_zfree;
png_ptr->zstream->opaque = (voidpf)png_ptr;
inflateInit(png_ptr->zstream);
switch (inflateInit(png_ptr->zstream))
{
case Z_OK: /* Do nothing */ break;
case Z_MEM_ERROR:
case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break;
case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break;
default: png_error(png_ptr, "Unknown zlib error");
}
png_ptr->zstream->next_out = png_ptr->zbuf;
png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
png_set_read_fn(png_ptr, NULL, NULL);
png_ptr->do_free |= PNG_FREE_STRUCT;
return (png_ptr);
}
/* initialize png structure for reading, and allocate any memory needed */
/* This interface is depreciated in favour of the png_create_read_struct() */
void
png_read_init(png_structp png_ptr)
{
jmp_buf tmp_jmp; /* to save current jump buffer */
/* save jump buffer and error functions */
png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
/* reset all variables to 0 */
png_memset(png_ptr, 0, sizeof (png_struct));
/* restore jump buffer */
png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
/* initialize zbuf - compression buffer */
png_ptr->zbuf_size = PNG_ZBUF_SIZE;
png_ptr->zbuf = png_large_malloc(png_ptr, png_ptr->zbuf_size);
png_ptr->zstream = (z_stream *)png_malloc(png_ptr, sizeof (z_stream));
png_ptr->zstream->zalloc = png_zalloc;
png_ptr->zstream->zfree = png_zfree;
png_ptr->zstream->opaque = (voidpf)png_ptr;
switch (inflateInit(png_ptr->zstream))
{
case Z_OK: /* Do nothing */ break;
case Z_MEM_ERROR:
case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break;
case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break;
default: png_error(png_ptr, "Unknown zlib error");
}
png_ptr->zstream->next_out = png_ptr->zbuf;
png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
png_set_read_fn(png_ptr, NULL, NULL);
}
/* read the information before the actual image data. */
@ -50,8 +121,13 @@ png_read_info(png_structp png_ptr, png_infop info)
png_uint_32 length;
png_read_data(png_ptr, chunk_start, 8);
if (png_memcmp(chunk_start, png_sig, 8))
png_error(png_ptr, "Not a Png File");
if (!png_check_sig(chunk_start, 8))
{
if (!png_check_sig(chunk_start, 4))
png_error(png_ptr, "Not a PNG file");
else
png_error(png_ptr, "PNG file corrupted by ASCII conversion");
}
while (1)
{
@ -62,167 +138,110 @@ png_read_info(png_structp png_ptr, png_infop info)
png_reset_crc(png_ptr);
png_calculate_crc(png_ptr, chunk_start + 4, 4);
if (!png_memcmp(chunk_start + 4, png_IHDR, 4))
{
if (png_ptr->mode != PNG_BEFORE_IHDR)
png_error(png_ptr, "Out of Place IHDR");
png_handle_IHDR(png_ptr, info, length);
png_ptr->mode = PNG_HAVE_IHDR;
}
else if (!png_memcmp(chunk_start + 4, png_PLTE, 4))
{
if (png_ptr->mode != PNG_HAVE_IHDR)
png_error(png_ptr, "Missing IHDR");
#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
png_crc_skip(png_ptr, length);
else
#else
{
png_handle_PLTE(png_ptr, info, length);
}
#endif
png_ptr->mode = PNG_HAVE_PLTE;
}
png_handle_PLTE(png_ptr, info, length);
else if (!png_memcmp(chunk_start + 4, png_IDAT, 4))
{
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before IDAT");
else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
!(png_ptr->mode & PNG_HAVE_PLTE))
png_error(png_ptr, "Missing PLTE before IDAT");
png_ptr->idat_size = length;
png_ptr->mode = PNG_HAVE_IDAT;
png_ptr->mode |= PNG_HAVE_IDAT;
break;
}
else if (!png_memcmp(chunk_start + 4, png_IEND, 4))
{
png_error(png_ptr, "No Image in File");
}
png_error(png_ptr, "No image in file");
#if defined(PNG_READ_gAMA_SUPPORTED)
else if (!png_memcmp(chunk_start + 4, png_gAMA, 4))
{
if (png_ptr->mode != PNG_HAVE_IHDR)
png_error(png_ptr, "Out of Place PLTE");
png_handle_gAMA(png_ptr, info, length);
}
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
else if (!png_memcmp(chunk_start + 4, png_sBIT, 4))
{
if (png_ptr->mode != PNG_HAVE_IHDR)
png_error(png_ptr, "Out of Place sBIT");
png_handle_sBIT(png_ptr, info, length);
}
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
else if (!png_memcmp(chunk_start + 4, png_cHRM, 4))
{
if (png_ptr->mode != PNG_HAVE_IHDR)
png_error(png_ptr, "Out of Place cHRM");
png_handle_cHRM(png_ptr, info, length);
}
#endif
#if defined(PNG_READ_tRNS_SUPPORTED)
else if (!png_memcmp(chunk_start + 4, png_tRNS, 4))
{
if (png_ptr->mode != PNG_HAVE_IHDR &&
png_ptr->mode != PNG_HAVE_PLTE)
png_error(png_ptr, "Out of Place tRNS");
png_handle_tRNS(png_ptr, info, length);
}
#endif
#if defined(PNG_READ_bKGD_SUPPORTED)
else if (!png_memcmp(chunk_start + 4, png_bKGD, 4))
{
if (png_ptr->mode != PNG_HAVE_IHDR &&
png_ptr->mode != PNG_HAVE_PLTE)
png_error(png_ptr, "Out of Place bKGD");
png_handle_bKGD(png_ptr, info, length);
}
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
else if (!png_memcmp(chunk_start + 4, png_hIST, 4))
{
if (png_ptr->mode != PNG_HAVE_PLTE)
png_error(png_ptr, "Out of Place hIST");
png_handle_hIST(png_ptr, info, length);
}
#endif
#if defined(PNG_READ_pHYs_SUPPORTED)
else if (!png_memcmp(chunk_start + 4, png_pHYs, 4))
{
if (png_ptr->mode != PNG_HAVE_IHDR &&
png_ptr->mode != PNG_HAVE_PLTE)
png_error(png_ptr, "Out of Place pHYs");
png_handle_pHYs(png_ptr, info, length);
}
#endif
#if defined(PNG_READ_oFFs_SUPPORTED)
else if (!png_memcmp(chunk_start + 4, png_oFFs, 4))
{
if (png_ptr->mode != PNG_HAVE_IHDR &&
png_ptr->mode != PNG_HAVE_PLTE)
png_error(png_ptr, "Out of Place oFFs");
png_handle_oFFs(png_ptr, info, length);
}
#endif
#if defined(PNG_READ_tIME_SUPPORTED)
else if (!png_memcmp(chunk_start + 4, png_tIME, 4))
{
if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND)
png_error(png_ptr, "Out of Place tIME");
png_handle_tIME(png_ptr, info, length);
}
#endif
#if defined(PNG_READ_tEXt_SUPPORTED)
else if (!png_memcmp(chunk_start + 4, png_tEXt, 4))
{
if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND)
png_error(png_ptr, "Out of Place tEXt");
png_handle_tEXt(png_ptr, info, length);
}
#endif
#if defined(PNG_READ_zTXt_SUPPORTED)
else if (!png_memcmp(chunk_start + 4, png_zTXt, 4))
{
if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND)
png_error(png_ptr, "Out of Place zTXt");
png_handle_zTXt(png_ptr, info, length);
}
#endif
else
{
if (chunk_start[4] < 41 || chunk_start[4] > 122 ||
(chunk_start[4] > 90 && chunk_start[4] < 97) ||
chunk_start[5] < 41 || chunk_start[5] > 122 ||
(chunk_start[5] > 90 && chunk_start[5] < 97) ||
chunk_start[6] < 41 || chunk_start[6] > 122 ||
(chunk_start[6] > 90 && chunk_start[6] < 97) ||
chunk_start[7] < 41 || chunk_start[7] > 122 ||
(chunk_start[7] > 90 && chunk_start[7] < 97))
{
char msg[45];
sprintf(msg, "Invalid chunk type 0x%02X 0x%02X 0x%02X 0x%02X",
chunk_start[4], chunk_start[5], chunk_start[6], chunk_start[7]);
png_error(png_ptr, msg);
}
if ((chunk_start[4] & 0x20) == 0)
png_error(png_ptr, "Unknown Critical Chunk");
{
char msg[40];
sprintf(msg, "Unknown critical chunk %c%c%c%c",
chunk_start[4], chunk_start[5], chunk_start[6], chunk_start[7]);
png_error(png_ptr, msg);
}
png_crc_skip(png_ptr, length);
}
png_read_data(png_ptr, chunk_start, 4);
crc = png_get_uint_32(chunk_start);
if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
(png_ptr->crc & 0xffffffffL))
if (((crc ^ 0xffffffffL) & 0xffffffffL) != (png_ptr->crc & 0xffffffffL))
png_error(png_ptr, "Bad CRC value");
}
}
/* optional call to update the users info structure */
void
png_read_update_info(png_structp png_ptr, png_infop info_ptr)
png_read_update_info(png_structp png_ptr, png_infop info)
{
if (!(png_ptr->row_init))
if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
png_read_start_row(png_ptr);
png_read_transform_info(png_ptr, info_ptr);
png_read_transform_info(png_ptr, info);
}
/* initialize palette, background, etc, after transformations
@ -232,7 +251,7 @@ png_read_update_info(png_structp png_ptr, png_infop info_ptr)
void
png_start_read_image(png_structp png_ptr)
{
if (!(png_ptr->row_init))
if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
png_read_start_row(png_ptr);
}
@ -240,7 +259,7 @@ void
png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
{
int ret;
if (!(png_ptr->row_init))
if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
png_read_start_row(png_ptr);
#if defined(PNG_READ_INTERLACING_SUPPORTED)
@ -320,8 +339,8 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
}
#endif
if (png_ptr->mode != PNG_HAVE_IDAT)
png_error(png_ptr, "invalid attempt to read row data");
if (!(png_ptr->mode & PNG_HAVE_IDAT))
png_error(png_ptr, "Invalid attempt to read row data");
png_ptr->zstream->next_out = png_ptr->row_buf;
png_ptr->zstream->avail_out = (uInt)png_ptr->irowbytes;
@ -346,8 +365,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
png_crc_read(png_ptr, buf, 4);
if (png_memcmp(buf, png_IDAT, 4))
png_error(png_ptr, "Not enough image data");
png_error(png_ptr, "Not enough IDATs for image");
}
png_ptr->zstream->avail_in = (uInt)png_ptr->zbuf_size;
png_ptr->zstream->next_in = png_ptr->zbuf;
@ -362,17 +380,15 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
if (png_ptr->zstream->avail_out || png_ptr->zstream->avail_in ||
png_ptr->idat_size)
png_error(png_ptr, "Extra compressed data");
png_ptr->mode = PNG_AT_LAST_IDAT;
png_ptr->mode |= PNG_AT_LAST_IDAT;
png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
break;
}
if (ret != Z_OK)
png_error(png_ptr, "Compression Error");
png_error(png_ptr, png_ptr->zstream->msg ? png_ptr->zstream->msg :
"Decompression error");
} while (png_ptr->zstream->avail_out);
if (ret == Z_STREAM_END)
png_ptr->zlib_finished = 1;
png_ptr->row_info.color_type = png_ptr->color_type;
png_ptr->row_info.width = png_ptr->iwidth;
png_ptr->row_info.channels = png_ptr->channels;
@ -381,10 +397,9 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
(png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
if (png_ptr->row_buf[0])
png_read_filter_row(&(png_ptr->row_info),
png_ptr->row_buf + 1, png_ptr->prev_row + 1,
(int)(png_ptr->row_buf[0]));
png_read_filter_row(png_ptr, &(png_ptr->row_info),
png_ptr->row_buf + 1, png_ptr->prev_row + 1,
(int)(png_ptr->row_buf[0]));
png_memcpy(png_ptr->prev_row, png_ptr->row_buf, (png_size_t)png_ptr->rowbytes + 1);
@ -471,9 +486,12 @@ png_read_rows(png_structp png_ptr, png_bytepp row,
/* read the image. If the image has an alpha channel or a transparency
chunk, and you have called png_handle_alpha(), you will need to
initialize the image to the current image that png will be overlaying.
Note that png_set_interlace_handling() has no effect on this call.
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() */
We set the num_rows again here, in case it was incorrectly set in
png_read_start_row() by a call to png_read_update_info() or
png_start_read_image() if png_set_interlace_handling() wasn't called
prior to either of these functions like it should have been. 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() instead */
void
png_read_image(png_structp png_ptr, png_bytepp image)
{
@ -482,6 +500,9 @@ png_read_image(png_structp png_ptr, png_bytepp image)
png_bytepp rp;
pass = png_set_interlace_handling(png_ptr);
png_ptr->num_rows = png_ptr->height; /* Make sure this is set correctly */
for (j = 0; j < pass; j++)
{
rp = image;
@ -518,55 +539,53 @@ png_read_end(png_structp png_ptr, png_infop info)
if (!png_memcmp(chunk_start + 4, png_IHDR, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid IHDR after IDAT");
}
else if (!png_memcmp(chunk_start + 4, png_PLTE, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid PLTE after IDAT");
}
else if (!png_memcmp(chunk_start + 4, png_gAMA, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid gAMA after IDAT");
}
else if (!png_memcmp(chunk_start + 4, png_sBIT, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid sBIT after IDAT");
}
else if (!png_memcmp(chunk_start + 4, png_cHRM, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid cHRM after IDAT");
}
else if (!png_memcmp(chunk_start + 4, png_tRNS, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid tRNS after IDAT");
}
else if (!png_memcmp(chunk_start + 4, png_bKGD, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid bKGD after IDAT");
}
else if (!png_memcmp(chunk_start + 4, png_hIST, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid hIST after IDAT");
}
else if (!png_memcmp(chunk_start + 4, png_IDAT, 4))
{
if (length > 0 || png_ptr->mode != PNG_AT_LAST_IDAT)
png_error(png_ptr, "too many IDAT's found");
if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT)
png_error(png_ptr, "Too many IDAT's found");
}
else if (!png_memcmp(chunk_start + 4, png_pHYs, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid pHYs after IDAT");
}
else if (!png_memcmp(chunk_start + 4, png_oFFs, 4))
{
png_error(png_ptr, "invalid chunk after IDAT");
png_error(png_ptr, "Invalid oFFs after IDAT");
}
#if defined(PNG_READ_tIME_SUPPORTED)
else if (!png_memcmp(chunk_start + 4, png_tIME, 4))
{
if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND)
png_error(png_ptr, "Out of Place tIME");
png_ptr->mode |= PNG_AFTER_IDAT;
if (info)
png_handle_tIME(png_ptr, info, length);
@ -577,9 +596,7 @@ png_read_end(png_structp png_ptr, png_infop info)
#if defined(PNG_READ_tEXt_SUPPORTED)
else if (!png_memcmp(chunk_start + 4, png_tEXt, 4))
{
if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND)
png_error(png_ptr, "Out of Place tEXt");
png_ptr->mode |= PNG_AFTER_IDAT;
if (info)
png_handle_tEXt(png_ptr, info, length);
@ -590,9 +607,7 @@ png_read_end(png_structp png_ptr, png_infop info)
#if defined(PNG_READ_zTXt_SUPPORTED)
else if (!png_memcmp(chunk_start + 4, png_zTXt, 4))
{
if (png_ptr->mode == PNG_BEFORE_IHDR ||
png_ptr->mode == PNG_AFTER_IEND)
png_error(png_ptr, "Out of Place zTXt");
png_ptr->mode |= PNG_AFTER_IDAT;
if (info)
png_handle_zTXt(png_ptr, info, length);
@ -602,31 +617,83 @@ png_read_end(png_structp png_ptr, png_infop info)
#endif
else if (!png_memcmp(chunk_start + 4, png_IEND, 4))
{
png_ptr->mode = PNG_AFTER_IEND;
png_ptr->mode |= PNG_AFTER_IDAT;
png_ptr->mode |= PNG_AFTER_IEND;
}
else
{
if ((chunk_start[4] & 0x20) == 0)
png_error(png_ptr, "Unknown Critical Chunk");
if (chunk_start[4] < 41 || chunk_start[4] > 122 ||
(chunk_start[4] > 90 && chunk_start[4] < 97) ||
chunk_start[5] < 41 || chunk_start[5] > 122 ||
(chunk_start[5] > 90 && chunk_start[5] < 97) ||
chunk_start[6] < 41 || chunk_start[6] > 122 ||
(chunk_start[6] > 90 && chunk_start[6] < 97) ||
chunk_start[7] < 41 || chunk_start[7] > 122 ||
(chunk_start[7] > 90 && chunk_start[7] < 97))
{
png_error(png_ptr, "Invalid chunk type");
}
if ((chunk_start[4] & 0x20) == 0)
png_error(png_ptr, "Unknown critical chunk");
png_ptr->mode |= PNG_AFTER_IDAT;
png_crc_skip(png_ptr, length);
}
png_read_data(png_ptr, chunk_start, 4);
crc = png_get_uint_32(chunk_start);
if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
(png_ptr->crc & 0xffffffffL))
if (((crc ^ 0xffffffffL) & 0xffffffffL) != (png_ptr->crc & 0xffffffffL))
png_error(png_ptr, "Bad CRC value");
if (png_ptr->mode == PNG_AT_LAST_IDAT)
png_ptr->mode = PNG_AFTER_IDAT;
} while (png_ptr->mode != PNG_AFTER_IEND);
} while (!(png_ptr->mode & PNG_AFTER_IEND));
}
/* free all memory used by the read */
void
png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
png_infopp end_info_ptr)
{
png_structp png_ptr = NULL;
png_infop info_ptr = NULL, end_info = NULL;
if (png_ptr_ptr)
png_ptr = *png_ptr_ptr;
if (info_ptr_ptr)
info_ptr = *info_ptr_ptr;
if (end_info_ptr)
end_info = *end_info_ptr;
png_read_destroy(png_ptr, info_ptr, end_info);
if (info_ptr)
{
png_destroy_struct((voidp)info_ptr);
*info_ptr_ptr = (png_infop)NULL;
}
if (end_info)
{
png_destroy_struct((voidp)end_info);
*end_info_ptr = (png_infop)NULL;
}
if (png_ptr)
{
png_destroy_struct((voidp)png_ptr);
*png_ptr_ptr = (png_structp)NULL;
}
}
/* free all memory used by the read (old) */
void
png_read_destroy(png_structp png_ptr, png_infop info, png_infop end_info)
{
int i;
jmp_buf tmp_jmp;
png_error_ptr error_fn;
png_error_ptr warning_fn;
png_voidp error_ptr;
if (info)
{
@ -712,8 +779,21 @@ png_read_destroy(png_structp png_ptr, png_infop info, png_infop end_info)
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
png_large_free(png_ptr, png_ptr->save_buffer);
#endif
/* Save the important info out of the png_struct, in case it is
* being used again.
*/
png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
error_fn = png_ptr->error_fn;
warning_fn = png_ptr->warning_fn;
error_ptr = png_ptr->error_ptr;
png_memset(png_ptr, 0, sizeof (png_struct));
png_ptr->error_fn = error_fn;
png_ptr->warning_fn = warning_fn;
png_ptr->error_ptr = error_ptr;
png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
}

141
pngrio.c Normal file
View File

@ -0,0 +1,141 @@
/* pngrio.c - functions for data input
libpng 1.0 beta 3 - version 0.89
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
May 25, 1996
This file provides a location for all input. Users which need
special handling are expected to write a function which has the same
arguments as this, and perform a similar function, but possibly has
a different input method. Note that you shouldn't change this
function, but rather write a replacement function and then make
libpng use it at run time with png_set_read_fn(...) */
#define PNG_INTERNAL
#include "png.h"
/* Read the data from whatever input you are using. The default routine
reads from a file pointer. Note that this routine sometimes gets called
with very small lengths, so you should implement some kind of simple
buffering if you are using unbuffered reads. This should never be asked
to read more then 64K on a 16 bit machine. The cast to png_size_t is
there to quiet some compilers */
void
png_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
{
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");
}
/* This is the function which does the actual reading of data. If you are
not reading from a standard C stream, you should create a replacement
read_data function and use it at run time with png_set_read_fn(), rather
than changing the library. */
#ifndef USE_FAR_KEYWORD
static void
png_default_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
{
png_uint_32 check;
check = fread(data, 1, (size_t)length, (FILE *)png_ptr->io_ptr);
if (check != length)
{
png_error(png_ptr, "Read Error");
}
}
#else
/* 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
the data.
*/
#define NEAR_BUF_SIZE 1024
#define MIN(a,b) (a <= b ? a : b)
#ifdef _MSC_VER
/* for FP_OFF */
#include <dos.h>
#endif
static void
png_default_read_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
{
png_uint_32 check;
png_byte *n_data;
/* Check if data really is near. If so, use usual code. */
#ifdef _MSC_VER
/* do it this way just to quiet warning */
FP_OFF(n_data) = FP_OFF(data);
if (FP_SEG(n_data) == FP_SEG(data))
#else
/* this works in MSC also but with lost segment warning */
n_data = (png_byte *)data;
if ((png_bytep)n_data == data)
#endif
{
check = fread(n_data, 1, (size_t)length, (FILE *)png_ptr->io_ptr);
}
else
{
png_byte buf[NEAR_BUF_SIZE];
png_size_t read, remaining, err;
check = 0;
remaining = (png_size_t)length;
do
{
read = MIN(NEAR_BUF_SIZE, remaining);
err = fread(buf, 1, read, (FILE *)png_ptr->io_ptr);
png_memcpy(data, buf, read); /* copy far buffer to near buffer */
if(err != read)
break;
else
check += err;
data += read;
remaining -= read;
}
while (remaining != 0);
}
if (check != length)
{
png_error(png_ptr, "read Error");
}
}
#endif
/* This function allows the application to supply a new input function
for libpng if standard C streams aren't being used.
This function takes as its arguments:
png_ptr - pointer to a png input data structure
io_ptr - pointer to user supplied structure containing info about
the input functions. May be NULL.
read_data_fn - pointer to a new input function which takes as it's
arguments a pointer to a png_struct, a pointer to
a location where input data can be stored, and a 32-bit
unsigned int which is the number of bytes to be read.
To exit and output any fatal error messages the new write
function should call png_error(png_ptr, "Error msg"). */
void
png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
png_rw_ptr read_data_fn)
{
png_ptr->io_ptr = io_ptr;
if (read_data_fn)
png_ptr->read_data_fn = read_data_fn;
else
png_ptr->read_data_fn = png_default_read_data;
/* It is an error to write to a read device */
png_ptr->write_data_fn = NULL;
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
png_ptr->output_flush_fn = NULL;
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
}

View File

@ -1,10 +1,10 @@
/* pngrtran.c - transforms the data in a row for png readers
libpng 1.0 beta 2 - version 0.88
libpng 1.0 beta 3 - version 0.89
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 25, 1996
May 25, 1996
*/
#define PNG_INTERNAL
@ -22,7 +22,7 @@ png_set_background(png_structp png_ptr,
sizeof(png_color_16));
png_ptr->background_gamma = (float)background_gamma;
png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
png_ptr->background_expand = (png_byte)need_expand;
png_ptr->transformations |= (need_expand ? PNG_BACKGROUND_EXPAND : 0);
}
#endif
@ -353,7 +353,6 @@ png_set_dither(png_structp png_ptr, png_colorp palette,
if (!(png_ptr->palette))
{
png_ptr->palette = palette;
png_ptr->user_palette = 1;
}
png_ptr->num_palette = (png_uint_16)num_palette;
@ -468,45 +467,44 @@ png_init_read_transformations(png_structp png_ptr)
color_type = png_ptr->color_type;
#if defined(PNG_READ_EXPAND_SUPPORTED) && \
defined(PNG_READ_BACKGROUND_SUPPORTED)
if (png_ptr->transformations & PNG_EXPAND)
#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
if (png_ptr->transformations & PNG_BACKGROUND_EXPAND)
{
if (color_type == PNG_COLOR_TYPE_GRAY &&
png_ptr->bit_depth < 8 &&
(png_ptr->transformations & PNG_BACKGROUND) &&
png_ptr->background_expand)
/* (!(png_ptr->transformations & PNG_BACKGROUND) ||
png_ptr->background_expand)) */
if (color_type == PNG_COLOR_TYPE_GRAY)
{
/* expand background chunk. While this may not be
the fastest way to do this, it only happens once
per file. */
/* expand background chunk. */
switch (png_ptr->bit_depth)
{
case 1:
png_ptr->background.gray *= (png_byte)0xff;
png_ptr->background.gray *= (png_uint_16)0xff;
png_ptr->background.red = png_ptr->background.green =
png_ptr->background.blue = png_ptr->background.gray;
break;
case 2:
png_ptr->background.gray *= (png_byte)0x55;
png_ptr->background.gray *= (png_uint_16)0x55;
png_ptr->background.red = png_ptr->background.green =
png_ptr->background.blue = png_ptr->background.gray;
break;
case 4:
png_ptr->background.gray *= (png_byte)0x11;
png_ptr->background.gray *= (png_uint_16)0x11;
png_ptr->background.red = png_ptr->background.green =
png_ptr->background.blue = png_ptr->background.gray;
break;
case 8:
case 16:
png_ptr->background.red = png_ptr->background.green =
png_ptr->background.blue = png_ptr->background.gray;
break;
}
}
if (color_type == PNG_COLOR_TYPE_PALETTE &&
(png_ptr->transformations & PNG_BACKGROUND) &&
png_ptr->background_expand)
else if (color_type == PNG_COLOR_TYPE_PALETTE)
{
/* expand background chunk */
png_ptr->background.red =
png_ptr->background.red =
png_ptr->palette[png_ptr->background.index].red;
png_ptr->background.green =
png_ptr->palette[png_ptr->background.index].green;
png_ptr->background.blue =
png_ptr->background.blue =
png_ptr->palette[png_ptr->background.index].blue;
color_type = PNG_COLOR_TYPE_RGB;
}
}
#endif
@ -519,10 +517,71 @@ png_init_read_transformations(png_structp png_ptr)
{
png_build_gamma_table(png_ptr);
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
if ((png_ptr->transformations & PNG_BACKGROUND) &&
(color_type != PNG_COLOR_TYPE_PALETTE))
if (png_ptr->transformations & PNG_BACKGROUND)
{
if (png_ptr->background_gamma_type != PNG_BACKGROUND_GAMMA_UNKNOWN)
if (color_type == PNG_COLOR_TYPE_PALETTE)
{
int num_palette, i;
png_color back, back_1;
png_colorp palette;
palette = png_ptr->palette;
num_palette = png_ptr->num_palette;
back.red = png_ptr->gamma_table[png_ptr->background.red];
back.green = png_ptr->gamma_table[png_ptr->background.green];
back.blue = png_ptr->gamma_table[png_ptr->background.blue];
back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
for (i = 0; i < num_palette; i++)
{
if (i < (int)png_ptr->num_trans)
{
if (png_ptr->trans[i] == 0)
{
palette[i] = back;
}
else if (png_ptr->trans[i] != 0xff)
{
int v, w;
v = png_ptr->gamma_to_1[palette[i].red];
w = (int)(((png_uint_32)(v) *
(png_uint_32)(png_ptr->trans[i]) +
(png_uint_32)(back_1.red) *
(png_uint_32)(255 - png_ptr->trans[i]) +
127) / 255);
palette[i].red = png_ptr->gamma_from_1[w];
v = png_ptr->gamma_to_1[palette[i].green];
w = (int)(((png_uint_32)(v) *
(png_uint_32)(png_ptr->trans[i]) +
(png_uint_32)(back_1.green) *
(png_uint_32)(255 - png_ptr->trans[i]) +
127) / 255);
palette[i].green = png_ptr->gamma_from_1[w];
v = png_ptr->gamma_to_1[palette[i].blue];
w = (int)(((png_uint_32)(v) *
(png_uint_32)(png_ptr->trans[i]) +
(png_uint_32)(back_1.blue) *
(png_uint_32)(255 - png_ptr->trans[i]) +
127) / 255);
palette[i].blue = png_ptr->gamma_from_1[w];
}
}
else
{
palette[i].red = png_ptr->gamma_table[palette[i].red];
palette[i].green = png_ptr->gamma_table[palette[i].green];
palette[i].blue = png_ptr->gamma_table[palette[i].blue];
}
}
}
else if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN)
{
double g, gs, m;
@ -571,7 +630,69 @@ png_init_read_transformations(png_structp png_ptr)
}
}
}
else
#endif
if (color_type == PNG_COLOR_TYPE_PALETTE)
{
int num_palette, i;
png_colorp palette;
palette = png_ptr->palette;
num_palette = png_ptr->num_palette;
for (i = 0; i < num_palette; i++)
{
palette[i].red = png_ptr->gamma_table[palette[i].red];
palette[i].green = png_ptr->gamma_table[palette[i].green];
palette[i].blue = png_ptr->gamma_table[palette[i].blue];
}
}
}
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
else
#endif
#endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
if (png_ptr->transformations & PNG_BACKGROUND &&
color_type == PNG_COLOR_TYPE_PALETTE)
{
int i;
png_color back;
png_colorp palette;
palette = png_ptr->palette;
back.red = (png_byte)png_ptr->background.red;
back.green = (png_byte)png_ptr->background.green;
back.blue = (png_byte)png_ptr->background.blue;
for (i = 0; i < png_ptr->num_trans; i++)
{
if (png_ptr->trans[i] == 0)
{
palette[i] = back;
}
else if (png_ptr->trans[i] != 0xff)
{
palette[i].red = (png_byte)((
(png_uint_32)(palette[i].red) *
(png_uint_32)(png_ptr->trans[i]) +
(png_uint_32)(back.red) *
(png_uint_32)(255 - png_ptr->trans[i]) +
127) / 255);
palette[i].green = (png_byte)((
(png_uint_32)(palette[i].green) *
(png_uint_32)(png_ptr->trans[i]) +
(png_uint_32)(back.green) *
(png_uint_32)(255 - png_ptr->trans[i]) +
127) / 255);
palette[i].blue = (png_byte)((
(png_uint_32)(palette[i].blue) *
(png_uint_32)(png_ptr->trans[i]) +
(png_uint_32)(back.blue) *
(png_uint_32)(255 - png_ptr->trans[i]) +
127) / 255);
}
}
}
#endif
@ -769,7 +890,7 @@ png_do_read_transformations(png_structp png_ptr)
#if defined(PNG_READ_FILLER_SUPPORTED)
if (png_ptr->transformations & PNG_FILLER)
png_do_read_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
png_ptr->filler, png_ptr->filler_loc);
png_ptr->filler, png_ptr->flags);
#endif
}
@ -1002,14 +1123,14 @@ png_do_chop(png_row_infop row_info, png_bytep row)
/* add filler byte */
void
png_do_read_filler(png_row_infop row_info, png_bytep row,
png_byte filler, png_byte filler_loc)
png_byte filler, png_byte flags)
{
png_bytep sp, dp;
png_uint_32 i;
if (row && row_info && row_info->color_type == 2 &&
row_info->bit_depth == 8)
{
if (filler_loc == PNG_FILLER_AFTER)
if (flags & PNG_FLAG_FILLER_AFTER)
{
for (i = 1, sp = row + (png_size_t)row_info->width * 3,
dp = row + (png_size_t)row_info->width * 4;
@ -1183,32 +1304,28 @@ png_build_grayscale_palette(int bit_depth, png_colorp palette)
}
}
#if defined(PNG_READ_DITHER_SUPPORTED)
/* This function is currently unused? */
#if defined(PNG_READ_DITHER_SUPPORTED) || defined(PNG_CORRECT_PALETTE_SUPPORTED)
void
png_correct_palette(png_structp png_ptr, png_colorp palette,
int num_palette)
{
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
if ((png_ptr->transformations & (PNG_GAMMA)) &&
(png_ptr->transformations & (PNG_BACKGROUND)))
{
if (png_ptr->color_type == 3)
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
int i;
png_color back, back_1;
back.red = png_ptr->gamma_table[png_ptr->palette[
png_ptr->background.index].red];
back.green = png_ptr->gamma_table[png_ptr->palette[
png_ptr->background.index].green];
back.blue = png_ptr->gamma_table[png_ptr->palette[
png_ptr->background.index].blue];
back.red = png_ptr->gamma_table[png_ptr->background.red];
back.green = png_ptr->gamma_table[png_ptr->background.green];
back.blue = png_ptr->gamma_table[png_ptr->background.blue];
back_1.red = png_ptr->gamma_to_1[png_ptr->palette[
png_ptr->background.index].red];
back_1.green = png_ptr->gamma_to_1[png_ptr->palette[
png_ptr->background.index].green];
back_1.blue = png_ptr->gamma_to_1[png_ptr->palette[
png_ptr->background.index].blue];
back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
for (i = 0; i < num_palette; i++)
{
@ -1256,17 +1373,18 @@ png_correct_palette(png_structp png_ptr, png_colorp palette,
}
else
{
int i, back;
int i;
png_color back;
back = png_ptr->gamma_table[png_ptr->background.gray];
back.red = png_ptr->gamma_table[png_ptr->background.red];
back.green = png_ptr->gamma_table[png_ptr->background.green];
back.blue = png_ptr->gamma_table[png_ptr->background.blue];
for (i = 0; i < num_palette; i++)
{
if (palette[i].red == png_ptr->trans_values.gray)
{
palette[i].red = (png_byte)back;
palette[i].green = (png_byte)back;
palette[i].blue = (png_byte)back;
palette[i] = back;
}
else
{
@ -1277,7 +1395,10 @@ png_correct_palette(png_structp png_ptr, png_colorp palette,
}
}
}
else if (png_ptr->transformations & (PNG_GAMMA))
else
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED)
if (png_ptr->transformations & (PNG_GAMMA))
{
int i;
@ -1288,25 +1409,30 @@ png_correct_palette(png_structp png_ptr, png_colorp palette,
palette[i].blue = png_ptr->gamma_table[palette[i].blue];
}
}
else if (png_ptr->transformations & (PNG_BACKGROUND))
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
else
#endif
#endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
if (png_ptr->transformations & (PNG_BACKGROUND))
{
if (png_ptr->color_type == 3)
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
int i;
png_byte br, bg, bb;
png_color back;
br = palette[png_ptr->background.index].red;
bg = palette[png_ptr->background.index].green;
bb = palette[png_ptr->background.index].blue;
back.red = (png_byte)png_ptr->background.red;
back.green = (png_byte)png_ptr->background.green;
back.blue = (png_byte)png_ptr->background.blue;
for (i = 0; i < num_palette; i++)
{
if (i >= (int)png_ptr->num_trans ||
png_ptr->trans[i] == 0)
{
palette[i].red = br;
palette[i].green = bg;
palette[i].blue = bb;
palette[i].red = back.red;
palette[i].green = back.green;
palette[i].blue = back.blue;
}
else if (i < (int)png_ptr->num_trans ||
png_ptr->trans[i] != 0xff)
@ -1314,19 +1440,19 @@ png_correct_palette(png_structp png_ptr, png_colorp palette,
palette[i].red = (png_byte)((
(png_uint_32)(png_ptr->palette[i].red) *
(png_uint_32)(png_ptr->trans[i]) +
(png_uint_32)(br) *
(png_uint_32)(back.red) *
(png_uint_32)(255 - png_ptr->trans[i]) +
127) / 255);
palette[i].green = (png_byte)((
(png_uint_32)(png_ptr->palette[i].green) *
(png_uint_32)(png_ptr->trans[i]) +
(png_uint_32)(bg) *
(png_uint_32)(back.green) *
(png_uint_32)(255 - png_ptr->trans[i]) +
127) / 255);
palette[i].blue = (png_byte)((
(png_uint_32)(png_ptr->palette[i].blue) *
(png_uint_32)(png_ptr->trans[i]) +
(png_uint_32)(bb) *
(png_uint_32)(back.blue) *
(png_uint_32)(255 - png_ptr->trans[i]) +
127) / 255);
}
@ -1340,20 +1466,21 @@ png_correct_palette(png_structp png_ptr, png_colorp palette,
{
if (i == (int)png_ptr->trans_values.gray)
{
palette[i].red = (png_byte)png_ptr->background.gray;
palette[i].green = (png_byte)png_ptr->background.gray;
palette[i].blue = (png_byte)png_ptr->background.gray;
palette[i].red = (png_byte)png_ptr->background.red;
palette[i].green = (png_byte)png_ptr->background.green;
palette[i].blue = (png_byte)png_ptr->background.blue;
}
}
}
}
#endif
}
#endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
/* replace any alpha or transparency with the supplied background color.
background is the color (in rgb or grey or palette index, as
appropriate). note that paletted files are taken care of elsewhere */
background is the color. note that paletted files are taken care of
elsewhere */
void
png_do_background(png_row_infop row_info, png_bytep row,
png_color_16p trans_values, png_color_16p background,
@ -1364,8 +1491,8 @@ png_do_background(png_row_infop row_info, png_bytep row,
{
png_bytep sp, dp;
png_uint_32 i;
int shift;
if (row && row_info && background &&
(!(row_info->color_type & PNG_COLOR_MASK_ALPHA) ||
(row_info->color_type != PNG_COLOR_TYPE_PALETTE &&
@ -1423,7 +1550,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
}
case 4:
{
sp = row + 1;
sp = row;
shift = 4;
for (i = 0; i < row_info->width; i++)
{
@ -2013,7 +2140,7 @@ png_do_background(png_row_infop row_info, png_bytep row,
if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
{
row_info->color_type &= ~PNG_COLOR_MASK_ALPHA;
row_info->channels -= (png_byte)1;
row_info->channels--;
row_info->pixel_depth = (png_byte)(row_info->channels *
row_info->bit_depth);
row_info->rowbytes = ((row_info->width *

View File

@ -1,10 +1,10 @@
/* pngrutil.c - utilities to read a png file
libpng 1.0 beta 2 - version 0.88
libpng 1.0 beta 3 - version 0.89
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 25, 1996
May 25, 1996
*/
#define PNG_INTERNAL
@ -71,6 +71,9 @@ png_handle_IHDR(png_structp png_ptr, png_infop info, png_uint_32 length)
int bit_depth, color_type, compression_type, filter_type;
int interlace_type;
if (png_ptr->mode != PNG_BEFORE_IHDR)
png_error(png_ptr, "Out of place IHDR");
/* check the length */
if (length != 13)
png_error(png_ptr, "Invalid IHDR chunk");
@ -87,36 +90,36 @@ png_handle_IHDR(png_structp png_ptr, png_infop info, png_uint_32 length)
/* check for width and height valid values */
if (width == 0 || height == 0)
png_error(png_ptr, "Invalid Width or Height Found");
png_error(png_ptr, "Invalid image size in IHDR");
/* check other values */
if (bit_depth != 1 && bit_depth != 2 &&
bit_depth != 4 && bit_depth != 8 &&
bit_depth != 16)
png_error(png_ptr, "Invalid Bit Depth Found");
png_error(png_ptr, "Invalid bit depth in IHDR");
if (color_type < 0 || color_type == 1 ||
color_type == 5 || color_type > 6)
png_error(png_ptr, "Invalid Color Type Found");
png_error(png_ptr, "Invalid color type in IHDR");
if (color_type == PNG_COLOR_TYPE_PALETTE &&
bit_depth == 16)
png_error(png_ptr, "Found Invalid Color Type and Bit Depth Combination");
png_error(png_ptr, "Invalid color type and bit depth combination in IHDR");
if ((color_type == PNG_COLOR_TYPE_RGB ||
color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
bit_depth < 8)
png_error(png_ptr, "Found Invalid Color Type and Bit Depth Combination");
png_error(png_ptr, "Invalid color type and bit depth in IHDR");
if (interlace_type > 1)
png_error(png_ptr, "Found Invalid Interlace Value");
png_error(png_ptr, "Invalid interlace method in IHDR");
if (compression_type > 0)
png_error(png_ptr, "Found Invalid Compression Value");
png_error(png_ptr, "Invalid compression method in IHDR");
if (filter_type > 0)
png_error(png_ptr, "Found Invalid Filter Value");
png_error(png_ptr, "Invalid filter method in IHDR");
/* set internal variables */
png_ptr->width = width;
@ -150,6 +153,8 @@ png_handle_IHDR(png_structp png_ptr, png_infop info, png_uint_32 length)
/* call the IHDR callback (which should just set up info) */
png_read_IHDR(png_ptr, info, width, height, bit_depth,
color_type, compression_type, filter_type, interlace_type);
png_ptr->mode |= PNG_HAVE_IHDR;
}
/* read and check the palette */
@ -159,8 +164,32 @@ png_handle_PLTE(png_structp png_ptr, png_infop info, png_uint_32 length)
int num, i;
png_colorp palette;
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before PLTE");
else if (png_ptr->mode & PNG_HAVE_PLTE)
png_error(png_ptr, "Multiple PLTE");
#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
{
png_crc_skip(png_ptr, length);
return;
}
#endif
if (length % 3)
png_error(png_ptr, "Invalid Palette Chunk");
{
if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
{
png_warning(png_ptr, "Invalid palette chunk");
png_crc_skip(png_ptr, length);
return;
}
else
{
png_error(png_ptr, "Invalid palette chunk");
}
}
num = (int)length / 3;
palette = (png_colorp)png_large_malloc(png_ptr, num * sizeof (png_color));
@ -178,6 +207,8 @@ png_handle_PLTE(png_structp png_ptr, png_infop info, png_uint_32 length)
png_ptr->palette = palette;
png_ptr->num_palette = (png_uint_16)num;
png_read_PLTE(png_ptr, info, palette, num);
png_ptr->mode |= PNG_HAVE_PLTE;
}
#if defined(PNG_READ_gAMA_SUPPORTED)
@ -188,6 +219,12 @@ png_handle_gAMA(png_structp png_ptr, png_infop info, png_uint_32 length)
float gamma;
png_byte buf[4];
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before gAMA");
else if (png_ptr->mode & PNG_HAVE_PLTE)
/* Should be an error, but we can cope with it */
png_warning(png_ptr, "Out of place gAMA chunk");
if (length != 4)
{
png_warning(png_ptr, "Incorrect gAMA chunk length");
@ -216,6 +253,12 @@ png_handle_sBIT(png_structp png_ptr, png_infop info, png_uint_32 length)
buf[0] = buf[1] = buf[2] = buf[3] = 0;
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before sBIT");
else if (png_ptr->mode & PNG_HAVE_PLTE)
/* Should be an error, but we can cope with it */
png_warning(png_ptr, "Out of place sBIT chunk");
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
slen = 3;
else
@ -253,6 +296,12 @@ png_handle_cHRM(png_structp png_ptr, png_infop info, png_uint_32 length)
png_uint_32 v;
float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before sBIT");
else if (png_ptr->mode & PNG_HAVE_PLTE)
/* Should be an error, but we can cope with it */
png_warning(png_ptr, "Missing PLTE before cHRM");
if (length != 32)
{
png_warning(png_ptr, "Incorrect cHRM chunk length");
@ -301,9 +350,17 @@ png_handle_cHRM(png_structp png_ptr, png_infop info, png_uint_32 length)
void
png_handle_tRNS(png_structp png_ptr, png_infop info, png_uint_32 length)
{
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before tRNS");
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
if (length > png_ptr->num_palette)
if (!(png_ptr->mode & PNG_HAVE_PLTE))
{
/* Should be an error, but we can cope with it */
png_warning(png_ptr, "Missing PLTE before tRNS");
}
else if (length > png_ptr->num_palette)
{
png_warning(png_ptr, "Incorrect tRNS chunk length");
png_crc_skip(png_ptr, length);
@ -348,7 +405,11 @@ png_handle_tRNS(png_structp png_ptr, png_infop info, png_uint_32 length)
png_ptr->trans_values.gray = png_get_uint_16(buf);
}
else
png_warning(png_ptr, "Invalid tRNS chunk");
{
png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
png_crc_skip(png_ptr, length);
return;
}
png_read_tRNS(png_ptr, info, png_ptr->trans, png_ptr->num_trans,
&(png_ptr->trans_values));
@ -362,6 +423,16 @@ png_handle_bKGD(png_structp png_ptr, png_infop info, png_uint_32 length)
int truelen;
png_byte buf[6];
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before bKGD");
else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
!(png_ptr->mode & PNG_HAVE_PLTE))
{
png_warning(png_ptr, "Missing PLTE before bKGD");
png_crc_skip(png_ptr, length);
return;
}
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
truelen = 1;
else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
@ -377,10 +448,24 @@ png_handle_bKGD(png_structp png_ptr, png_infop info, png_uint_32 length)
}
png_crc_read(png_ptr, buf, length);
/* We convert the index value into RGB components so that we can allow
* arbitrary RGB values for background when we have transparency, and
* so it is easy to determine the RGB values of the background color
* from the info_ptr. */
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
png_ptr->background.index = buf[0];
png_ptr->background.red = (png_uint_16)png_ptr->palette[buf[0]].red;
png_ptr->background.green = (png_uint_16)png_ptr->palette[buf[0]].green;
png_ptr->background.blue = (png_uint_16)png_ptr->palette[buf[0]].blue;
}
else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
{
png_ptr->background.red =
png_ptr->background.green =
png_ptr->background.blue =
png_ptr->background.gray = png_get_uint_16(buf);
}
else
{
png_ptr->background.red = png_get_uint_16(buf);
@ -398,6 +483,15 @@ png_handle_hIST(png_structp png_ptr, png_infop info, png_uint_32 length)
{
int num, i;
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before hIST");
else if (!(png_ptr->mode & PNG_HAVE_PLTE))
{
png_warning(png_ptr, "Missing PLTE before hIST");
png_crc_skip(png_ptr, length);
return;
}
if (length != 2 * png_ptr->num_palette)
{
png_warning(png_ptr, "Incorrect hIST chunk length");
@ -428,6 +522,9 @@ png_handle_pHYs(png_structp png_ptr, png_infop info, png_uint_32 length)
png_uint_32 res_x, res_y;
int unit_type;
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before pHYS");
if (length != 9)
{
png_warning(png_ptr, "Incorrect pHYs chunk length");
@ -452,6 +549,9 @@ png_handle_oFFs(png_structp png_ptr, png_infop info, png_uint_32 length)
png_uint_32 offset_x, offset_y;
int unit_type;
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before oFFs");
if (length != 9)
{
png_warning(png_ptr, "Incorrect oFFs chunk length");
@ -475,6 +575,9 @@ png_handle_tIME(png_structp png_ptr, png_infop info, png_uint_32 length)
png_byte buf[7];
png_time mod_time;
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before tIME");
if (length != 7)
{
png_warning(png_ptr, "Incorrect tIME chunk length");
@ -503,12 +606,15 @@ png_handle_tEXt(png_structp png_ptr, png_infop info, png_uint_32 length)
png_charp key;
png_charp text;
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before tEXt");
key = (png_charp )png_large_malloc(png_ptr, length + 1);
png_crc_read(png_ptr, (png_bytep )key, length);
key[(png_size_t)length] = '\0';
for (text = key; *text; text++)
/* empty loop */ ;
/* empty loop to check key length */ ;
if (text != key + (png_size_t)length)
text++;
@ -518,15 +624,19 @@ png_handle_tEXt(png_structp png_ptr, png_infop info, png_uint_32 length)
#endif
#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
on those systems that can't malloc more than 64KB at a time. */
void
png_handle_zTXt(png_structp png_ptr, png_infop info, png_uint_32 length)
{
static char msg[] = "Error decoding zTXt chunk";
png_charp key;
png_charp text;
int ret;
png_uint_32 text_size, key_size;
if (!(png_ptr->mode & PNG_HAVE_IHDR))
png_error(png_ptr, "Missing IHDR before zTXt");
key = png_large_malloc(png_ptr, length + 1);
png_crc_read(png_ptr, (png_bytep )key, length);
key[(png_size_t)length] = '\0';
@ -538,103 +648,108 @@ png_handle_zTXt(png_structp png_ptr, png_infop info, png_uint_32 length)
if (text == key + (png_size_t)length)
{
png_warning(png_ptr, "Zero length zTXt chunk");
png_large_free(png_ptr, key);
return;
text_size = 0;
}
text++;
if (*text) /* check compression byte */
else if (*(++text)) /* check compression type byte */
{
png_large_free(png_ptr, key);
return;
png_warning(png_ptr, "Unknown zTXt compression type");
/* Copy what we can of the error message into the text chunk */
text_size = length - (text - key) - 1;
text_size = sizeof(msg) > text_size ? text_size : sizeof(msg);
png_memcpy(text, msg, (png_size_t)(text_size + 1));
}
text++;
png_ptr->zstream->next_in = (png_bytep )text;
png_ptr->zstream->avail_in = (uInt)(length - (text - key));
png_ptr->zstream->next_out = png_ptr->zbuf;
png_ptr->zstream->avail_out = (png_size_t)png_ptr->zbuf_size;
key_size = text - key;
text_size = 0;
text = NULL;
ret = Z_STREAM_END;
while (png_ptr->zstream->avail_in)
else
{
ret = inflate(png_ptr->zstream, Z_PARTIAL_FLUSH);
if (ret != Z_OK && ret != Z_STREAM_END)
{
if (png_ptr->zstream->msg)
png_warning(png_ptr, png_ptr->zstream->msg);
else
png_warning(png_ptr, "zTXt decompression error");
inflateReset(png_ptr->zstream);
png_ptr->zstream->avail_in = 0;
png_large_free(png_ptr, key);
png_large_free(png_ptr, text);
return;
}
if (!png_ptr->zstream->avail_out || ret == Z_STREAM_END)
{
if (!text)
{
text = (png_charp)png_large_malloc(png_ptr,
png_ptr->zbuf_size - png_ptr->zstream->avail_out +
key_size + 1);
png_memcpy(text + (png_size_t)key_size, png_ptr->zbuf,
(png_size_t)(png_ptr->zbuf_size - png_ptr->zstream->avail_out));
png_memcpy(text, key, (png_size_t)key_size);
text_size = key_size + (png_size_t)png_ptr->zbuf_size -
png_ptr->zstream->avail_out;
*(text + (png_size_t)text_size) = '\0';
}
else
{
png_charp tmp;
text++;
tmp = text;
text = png_large_malloc(png_ptr, text_size +
png_ptr->zbuf_size - png_ptr->zstream->avail_out + 1);
png_memcpy(text, tmp, (png_size_t)text_size);
png_large_free(png_ptr, tmp);
png_memcpy(text + (png_size_t)text_size, png_ptr->zbuf,
(png_size_t)(png_ptr->zbuf_size - png_ptr->zstream->avail_out));
text_size += png_ptr->zbuf_size - png_ptr->zstream->avail_out;
*(text + (png_size_t)text_size) = '\0';
}
if (ret != Z_STREAM_END)
png_ptr->zstream->next_in = (png_bytep )text;
png_ptr->zstream->avail_in = (uInt)(length - (text - key));
png_ptr->zstream->next_out = png_ptr->zbuf;
png_ptr->zstream->avail_out = (png_size_t)png_ptr->zbuf_size;
key_size = text - key;
text_size = 0;
text = NULL;
while (png_ptr->zstream->avail_in)
{
int ret;
ret = inflate(png_ptr->zstream, Z_PARTIAL_FLUSH);
if (ret != Z_OK && ret != Z_STREAM_END)
{
png_ptr->zstream->next_out = png_ptr->zbuf;
png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
if (png_ptr->zstream->msg)
png_warning(png_ptr, png_ptr->zstream->msg);
else
png_warning(png_ptr, "zTXt decompression error");
inflateReset(png_ptr->zstream);
png_ptr->zstream->avail_in = 0;
if (!text)
{
text_size = key_size + sizeof(msg) + 1;
text = (png_charp)png_large_malloc(png_ptr, text_size);
png_memcpy(text, key, (png_size_t)key_size);
}
text[text_size - 1] = '\0';
/* Copy what we can of the error message into the text chunk */
text_size = length - (text - key) - 1;
text_size = sizeof(msg) > text_size ? text_size : sizeof(msg);
png_memcpy(text + key_size, msg, (png_size_t)(text_size + 1));
break;
}
if (!png_ptr->zstream->avail_out || ret == Z_STREAM_END)
{
if (!text)
{
text = (png_charp)png_large_malloc(png_ptr,
png_ptr->zbuf_size - png_ptr->zstream->avail_out +
key_size + 1);
png_memcpy(text + (png_size_t)key_size, png_ptr->zbuf,
(png_size_t)(png_ptr->zbuf_size - png_ptr->zstream->avail_out));
png_memcpy(text, key, (png_size_t)key_size);
text_size = key_size + (png_size_t)png_ptr->zbuf_size -
png_ptr->zstream->avail_out;
*(text + (png_size_t)text_size) = '\0';
}
else
{
png_charp tmp;
tmp = text;
text = png_large_malloc(png_ptr, text_size +
png_ptr->zbuf_size - png_ptr->zstream->avail_out + 1);
png_memcpy(text, tmp, (png_size_t)text_size);
png_large_free(png_ptr, tmp);
png_memcpy(text + (png_size_t)text_size, png_ptr->zbuf,
(png_size_t)(png_ptr->zbuf_size - png_ptr->zstream->avail_out));
text_size += png_ptr->zbuf_size - png_ptr->zstream->avail_out;
*(text + (png_size_t)text_size) = '\0';
}
if (ret != Z_STREAM_END)
{
png_ptr->zstream->next_out = png_ptr->zbuf;
png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
}
else
{
break;
}
}
}
else
{
break;
}
if (ret == Z_STREAM_END)
break;
}
inflateReset(png_ptr->zstream);
png_ptr->zstream->avail_in = 0;
inflateReset(png_ptr->zstream);
png_ptr->zstream->avail_in = 0;
if (ret != Z_STREAM_END)
{
png_large_free(png_ptr, key);
png_large_free(png_ptr, text);
return;
key = text;
text += (png_size_t)key_size;
text_size -= key_size;
}
png_large_free(png_ptr, key);
key = text;
text += (png_size_t)key_size;
text_size -= key_size;
png_read_zTXt(png_ptr, info, key, text, text_size, 0);
}
#endif
@ -964,7 +1079,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass)
#endif
void
png_read_filter_row(png_row_infop row_info, png_bytep row,
png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
png_bytep prev_row, int filter)
{
switch (filter)
@ -1064,6 +1179,7 @@ png_read_filter_row(png_row_infop row_info, png_bytep row,
break;
}
default:
png_error(png_ptr, "Bad adaptive filter type");
break;
}
}
@ -1107,7 +1223,7 @@ png_read_finish_row(png_structp png_ptr)
return;
}
if (!png_ptr->zlib_finished)
if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
{
char extra;
int ret;
@ -1127,7 +1243,7 @@ png_read_finish_row(png_structp png_ptr)
crc = png_get_uint_32(buf);
if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
(png_ptr->crc & 0xffffffffL))
png_error(png_ptr, "Bad CRC value");
png_warning(png_ptr, "Bad CRC value");
png_read_data(png_ptr, buf, 4);
png_ptr->idat_size = png_get_uint_32(buf);
@ -1151,11 +1267,12 @@ png_read_finish_row(png_structp png_ptr)
if (!(png_ptr->zstream->avail_out) || png_ptr->zstream->avail_in ||
png_ptr->idat_size)
png_error(png_ptr, "Extra compressed data");
png_ptr->mode = PNG_AT_LAST_IDAT;
png_ptr->mode |= PNG_AT_LAST_IDAT;
break;
}
if (ret != Z_OK)
png_error(png_ptr, "Compression Error");
png_error(png_ptr, png_ptr->zstream->msg ? png_ptr->zstream->msg :
"Decompression Error");
if (!(png_ptr->zstream->avail_out))
png_error(png_ptr, "Extra compressed data");
@ -1169,7 +1286,7 @@ png_read_finish_row(png_structp png_ptr)
inflateReset(png_ptr->zstream);
png_ptr->mode = PNG_AT_LAST_IDAT;
png_ptr->mode |= PNG_AT_LAST_IDAT;
}
void
@ -1206,13 +1323,11 @@ png_read_start_row(png_structp png_ptr)
#if defined(PNG_READ_PACK_SUPPORTED)
if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
{
max_pixel_depth = 8;
}
#endif
#if defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_PACK_SUPPORTED)
if (png_ptr->transformations & (PNG_EXPAND | PNG_PACK))
#if defined(PNG_READ_EXPAND_SUPPORTED)
if (png_ptr->transformations & PNG_EXPAND)
{
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
@ -1277,19 +1392,18 @@ png_read_start_row(png_structp png_ptr)
1 + ((max_pixel_depth + 7) >> 3);
#ifdef PNG_MAX_MALLOC_64K
if (rowbytes > 65536L)
png_error(png_ptr, "This image requires a row greater then 64KB");
png_error(png_ptr, "This image requires a row greater than 64KB");
#endif
png_ptr->row_buf = (png_bytep )png_large_malloc(png_ptr, rowbytes);
#ifdef PNG_MAX_MALLOC_64K
if (png_ptr->rowbytes + 1 > 65536L)
png_error(png_ptr, "This image requires a row greater then 64KB");
png_error(png_ptr, "This image requires a row greater than 64KB");
#endif
png_ptr->prev_row = png_large_malloc(png_ptr,
png_ptr->rowbytes + 1);
png_ptr->prev_row = png_large_malloc(png_ptr, png_ptr->rowbytes + 1);
png_memset(png_ptr->prev_row, 0, (png_size_t)png_ptr->rowbytes + 1);
png_ptr->row_init = 1;
png_ptr->flags |= PNG_FLAG_ROW_INIT;
}

117
pngtest.c
View File

@ -1,9 +1,9 @@
/* pngtest.c - a simple test program to test libpng
libpng 1.0 beta 2 - version 0.87
libpng 1.0 beta 3 - version 0.89
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 15, 1996
May 25, 1996
*/
#include <stdio.h>
@ -19,27 +19,31 @@
#define STDERR stdout /* for DOS */
/* input and output filenames */
char inname[] = "pngtest.png";
char outname[] = "pngout.png";
png_struct read_ptr;
png_struct write_ptr;
png_info info_ptr;
png_info end_info;
#ifdef RISCOS
char *inname = "pngtest_pn";
char *outname = "pngout_png";
#else
char *inname = "pngtest.png";
char *outname = "pngout.png";
#endif
char inbuf[256], outbuf[256];
int main()
int main(int argc, char *argv[])
{
FILE *fpin, *fpout;
png_structp read_ptr;
png_structp write_ptr;
png_infop info_ptr;
png_infop end_info;
png_bytep row_buf;
png_byte * near_row_buf;
png_byte *near_row_buf;
png_uint_32 rowbytes;
png_uint_32 y;
int channels, num_pass, pass;
row_buf = (png_bytep)0;
near_row_buf = (png_byte *)0;
row_buf = (png_bytep)NULL;
near_row_buf = (png_byte *)NULL;
fprintf(STDERR, "Testing libpng version %s\n", PNG_LIBPNG_VER_STRING);
@ -51,6 +55,18 @@ int main()
fprintf(STDERR, " png.c version: %s\n\n", png_libpng_ver);
}
if (argc > 1)
inname = argv[1];
if (argc > 2)
outname = argv[2];
if (argc > 3)
{
fprintf(stderr, "usage: %s [infile.png] [outfile.png]\n", argv[0]);
exit(1);
}
fpin = fopen(inname, "rb");
if (!fpin)
{
@ -61,62 +77,68 @@ int main()
fpout = fopen(outname, "wb");
if (!fpout)
{
fprintf(STDERR, "could not open output file %s\n", outname);
fprintf(STDERR, "Could not open output file %s\n", outname);
fclose(fpin);
return 1;
}
if (setjmp(read_ptr.jmpbuf))
read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (void *)NULL,
(png_error_ptr)NULL, (png_error_ptr)NULL);
write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (void *)NULL,
(png_error_ptr)NULL, (png_error_ptr)NULL);
info_ptr = png_create_info_struct(read_ptr);
end_info = png_create_info_struct(read_ptr);
if (setjmp(read_ptr->jmpbuf))
{
fprintf(STDERR, "libpng read error\n");
png_destroy_read_struct(&read_ptr, &info_ptr, &end_info);
png_destroy_write_struct(&write_ptr, (png_infopp)NULL);
fclose(fpin);
fclose(fpout);
return 1;
}
if (setjmp(write_ptr.jmpbuf))
if (setjmp(write_ptr->jmpbuf))
{
fprintf(STDERR, "libpng write error\n");
png_destroy_read_struct(&read_ptr, &info_ptr, &end_info);
png_destroy_write_struct(&write_ptr, (png_infopp)NULL);
fclose(fpin);
fclose(fpout);
return 1;
}
png_read_init(&read_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(write_ptr, fpout);
png_init_io(&read_ptr, fpin);
png_init_io(&write_ptr, fpout);
png_read_info(read_ptr, info_ptr);
png_write_info(write_ptr, info_ptr);
png_read_info(&read_ptr, &info_ptr);
png_write_info(&write_ptr, &info_ptr);
if ((info_ptr.color_type & 3) == 2)
channels = 3;
else
if ((info_ptr->color_type & PNG_COLOR_TYPE_PALETTE)==PNG_COLOR_TYPE_PALETTE)
channels = 1;
if (info_ptr.color_type & 4)
else
channels = 3;
if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
channels++;
rowbytes = ((info_ptr.width * info_ptr.bit_depth * channels + 7) >> 3);
rowbytes = ((info_ptr->width * info_ptr->bit_depth * channels + 7) >> 3);
near_row_buf = (png_byte *)malloc((size_t)rowbytes);
row_buf = (png_bytep)near_row_buf;
if (!row_buf)
{
fprintf(STDERR, "no memory to allocate row buffer\n");
png_read_destroy(&read_ptr, &info_ptr, (png_infop )0);
png_write_destroy(&write_ptr);
fprintf(STDERR, "No memory to allocate row buffer\n");
png_destroy_read_struct(&read_ptr, &info_ptr, &end_info);
png_destroy_write_struct(&write_ptr, (png_infopp)NULL);
fclose(fpin);
fclose(fpout);
return 1;
}
if (info_ptr.interlace_type)
if (info_ptr->interlace_type)
{
num_pass = png_set_interlace_handling(&read_ptr);
num_pass = png_set_interlace_handling(&write_ptr);
num_pass = png_set_interlace_handling(read_ptr);
num_pass = png_set_interlace_handling(write_ptr);
}
else
{
@ -125,21 +147,21 @@ int main()
for (pass = 0; pass < num_pass; pass++)
{
for (y = 0; y < info_ptr.height; y++)
for (y = 0; y < info_ptr->height; y++)
{
#ifdef TESTING
fprintf(STDERR, "Processing line #%ld\n", y);
#endif
png_read_rows(&read_ptr, (png_bytepp)&row_buf, (png_bytepp)0, 1);
png_write_rows(&write_ptr, (png_bytepp)&row_buf, 1);
png_read_rows(read_ptr, (png_bytepp)&row_buf, (png_bytepp)0, 1);
png_write_rows(write_ptr, (png_bytepp)&row_buf, 1);
}
}
png_read_end(&read_ptr, &end_info);
png_write_end(&write_ptr, &end_info);
png_read_end(read_ptr, end_info);
png_write_end(write_ptr, end_info);
png_read_destroy(&read_ptr, &info_ptr, &end_info);
png_write_destroy(&write_ptr);
png_destroy_read_struct(&read_ptr, &info_ptr, &end_info);
png_destroy_write_struct(&write_ptr, (png_infopp)NULL);
fclose(fpin);
fclose(fpout);
@ -150,14 +172,14 @@ int main()
if (!fpin)
{
fprintf(STDERR, "could not find file %s\n", inname);
fprintf(STDERR, "Could not find file %s\n", inname);
return 1;
}
fpout = fopen(outname, "rb");
if (!fpout)
{
fprintf(STDERR, "could not find file %s\n", outname);
fprintf(STDERR, "Could not find file %s\n", outname);
fclose(fpin);
return 1;
}
@ -171,7 +193,8 @@ int main()
if (num_in != num_out)
{
fprintf(STDERR, "files are of a different size\n");
fprintf(STDERR, "Files %s and %s are of a different size\n",
inname, outname);
fclose(fpin);
fclose(fpout);
return 1;
@ -182,7 +205,7 @@ int main()
if (memcmp(inbuf, outbuf, num_in))
{
fprintf(STDERR, "files are different\n");
fprintf(STDERR, "Files %s and %s are different\n", inname, outname);
fclose(fpin);
fclose(fpout);
return 1;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

@ -8,6 +8,8 @@ for 0.9
after 1.0
overlaying one image on top of another
make pull reader use push reader internally to reduce code, and
increase amount of image read in an error situation
optional palette creation
histogram creation
text conversion between different code types

View File

@ -2,10 +2,10 @@
/* pngtrans.c - transforms the data in a row
routines used by both readers and writers
libpng 1.0 beta 2 - version 0.88
libpng 1.0 beta 3 - version 0.89
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 25, 1996
May 25, 1996
*/
#define PNG_INTERNAL
@ -72,7 +72,11 @@ png_set_filler(png_structp png_ptr, int filler, int filler_loc)
{
png_ptr->transformations |= PNG_FILLER;
png_ptr->filler = (png_byte)filler;
png_ptr->filler_loc = (png_byte)filler_loc;
if (filler_loc == PNG_FILLER_AFTER)
png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
else
png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
if (png_ptr->color_type == PNG_COLOR_TYPE_RGB &&
png_ptr->bit_depth == 8)
png_ptr->usr_channels = 4;

174
pngwio.c Normal file
View File

@ -0,0 +1,174 @@
/* pngwio.c - functions for data output
libpng 1.0 beta 3 - version 0.89
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
May 25, 1996
This file provides a location for all output. Users which need
special handling are expected to write functions which have the same
arguments as these, and perform similar functions, but possibly use
different output methods. Note that you shouldn't change these
functions, but rather write replacement functions and then change
them at run time with png_set_write_fn(...) */
#define PNG_INTERNAL
#include "png.h"
/* Write the data to whatever output you are using. The default routine
writes to a file pointer. Note that this routine sometimes gets called
with very small lengths, so you should implement some kind of simple
buffering if you are using unbuffered writes. This should never be asked
to write more then 64K on a 16 bit machine. The cast to png_size_t is
there to quiet warnings of certain compilers. */
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");
}
/* This is the function which does the actual writing of data. If you are
not writing to a standard C stream, you should create a replacement
write_data function and use it at run time with png_set_write_fn(), rather
than changing the library. */
#ifndef USE_FAR_KEYWORD
static void
png_default_write_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
{
png_uint_32 check;
check = fwrite(data, 1, (png_size_t)length, (FILE *)(png_ptr->io_ptr));
if (check != length)
{
png_error(png_ptr, "Write Error");
}
}
#else
/* 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
the data.
*/
#define NEAR_BUF_SIZE 1024
#define MIN(a,b) (a <= b ? a : b)
#ifdef _MSC_VER
/* for FP_OFF */
#include <dos.h>
#endif
static void
png_default_write_data(png_structp png_ptr, png_bytep data, png_uint_32 length)
{
png_uint_32 check;
png_byte *n_data;
/* Check if data really is near. If so, use usual code. */
#ifdef _MSC_VER
/* do it this way just to quiet warning */
FP_OFF(n_data) = FP_OFF(data);
if (FP_SEG(n_data) == FP_SEG(data))
#else
/* this works in MSC also but with lost segment warning */
n_data = (png_byte *)data;
if ((png_bytep)n_data == data)
#endif
{
check = fwrite(n_data, 1, (png_size_t)length, (FILE *)(png_ptr->io_ptr));
}
else
{
png_byte buf[NEAR_BUF_SIZE];
png_size_t written, remaining, err;
check = 0;
remaining = (png_size_t)length;
do
{
written = MIN(NEAR_BUF_SIZE, remaining);
png_memcpy(buf, data, written); /* copy far buffer to near buffer */
err = fwrite(buf, 1, written, (FILE *)(png_ptr->io_ptr));
if (err != written)
break;
else
check += err;
data += written;
remaining -= written;
}
while (remaining != 0);
}
if (check != length)
{
png_error(png_ptr, "Write Error");
}
}
#endif
/* This function is called to output any data pending writing (normally
to disk). After png_flush is called, there should be no data pending
writing in any buffers. */
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
void
png_flush(png_structp png_ptr)
{
if (png_ptr->output_flush_fn)
(*(png_ptr->output_flush_fn))(png_ptr);
}
static void
png_default_flush(png_structp png_ptr)
{
if ((FILE *)(png_ptr->io_ptr))
fflush((FILE *)(png_ptr->io_ptr));
}
#endif
/* This function allows the application to supply new output functions for
libpng if standard C streams aren't being used.
This function takes as its arguments:
png_ptr - pointer to a png output data structure
io_ptr - pointer to user supplied structure containing info about
the output functions. May be NULL.
write_data_fn - pointer to a new output function which takes as its
arguments a pointer to a png_struct, a pointer to
data to be written, and a 32-bit unsigned int which is
the number of bytes to be written. The new write
function should call png_error(png_ptr, "Error msg")
to exit and output any fatal error messages.
flush_data_fn - pointer to a new flush function which takes as its
arguments a pointer to a png_struct. After a call to
the flush function, there should be no data in any buffers
or pending transmission. If the output method doesn't do
any buffering of ouput, a function prototype must still be
supplied although it doesn't have to do anything. If
PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
time, output_flush_fn will be ignored, although it must be
supplied for compatibility. */
void
png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
{
png_ptr->io_ptr = io_ptr;
if (write_data_fn)
png_ptr->write_data_fn = write_data_fn;
else
png_ptr->write_data_fn = png_default_write_data;
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
if (output_flush_fn)
png_ptr->output_flush_fn = output_flush_fn;
else
png_ptr->output_flush_fn = png_default_flush;
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
/* It is an error to read while writing a png file */
png_ptr->read_data_fn = NULL;
}

View File

@ -1,10 +1,10 @@
/* pngwrite.c - general routines to write a png file
libpng 1.0 beta 2 - version 0.88
libpng 1.0 beta 3 - version 0.89
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 25, 1996
May 25, 1996
*/
/* get internal access to png.h */
@ -48,6 +48,8 @@ png_write_info(png_structp png_ptr, png_infop info)
#endif
if (info->valid & PNG_INFO_PLTE)
png_write_PLTE(png_ptr, info->palette, info->num_palette);
else if (info->color_type == PNG_COLOR_TYPE_PALETTE)
png_error(png_ptr, "Valid palette required for paletted images\n");
#if defined(PNG_WRITE_tRNS_SUPPORTED)
if (info->valid & PNG_INFO_tRNS)
png_write_tRNS(png_ptr, info->trans, &(info->trans_values),
@ -73,10 +75,13 @@ png_write_info(png_structp png_ptr, png_infop info)
#endif
#if defined(PNG_WRITE_tIME_SUPPORTED)
if (info->valid & PNG_INFO_tIME)
{
png_write_tIME(png_ptr, &(info->mod_time));
/* Check to see if we need to write text chunks */
png_ptr->flags |= PNG_FLAG_WROTE_tIME;
}
#endif
#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
/* Check to see if we need to write text chunks */
if (info->num_text)
{
int i; /* local counter */
@ -92,6 +97,8 @@ png_write_info(png_structp png_ptr, png_infop info)
png_write_zTXt(png_ptr, info->text[i].key,
info->text[i].text, info->text[i].text_length,
info->text[i].compression);
#else
png_warning(png_ptr, "Unable to write compressed text\n");
#endif
}
else
@ -100,6 +107,8 @@ png_write_info(png_structp png_ptr, png_infop info)
/* write uncompressed chunk */
png_write_tEXt(png_ptr, info->text[i].key,
info->text[i].text, info->text[i].text_length);
#else
png_warning(png_ptr, "Unable to write uncompressed text\n");
#endif
}
}
@ -114,12 +123,16 @@ png_write_info(png_structp png_ptr, png_infop info)
void
png_write_end(png_structp png_ptr, png_infop info)
{
if (!(png_ptr->mode & PNG_HAVE_IDAT))
png_error(png_ptr, "No IDATs written into file");
/* see if user wants us to write information chunks */
if (info)
{
#if defined(PNG_WRITE_tIME_SUPPORTED)
/* check to see if user has supplied a time chunk */
if (info->valid & PNG_INFO_tIME)
if (info->valid & PNG_INFO_tIME &&
!(png_ptr->flags & PNG_FLAG_WROTE_tIME))
png_write_tIME(png_ptr, &(info->mod_time));
#endif
#if defined(PNG_WRITE_tEXt_SUPPORTED) || defined(PNG_WRITE_zTXt_SUPPORTED)
@ -131,28 +144,33 @@ png_write_end(png_structp png_ptr, png_infop info)
/* loop through comment chunks */
for (i = 0; i < info->num_text; i++)
{
#if defined(PNG_WRITE_zTXt_SUPPORTED)
/* check to see if comment is to be compressed */
if (info->text[i].compression >= 0)
{
#if defined(PNG_WRITE_zTXt_SUPPORTED)
/* write compressed chunk */
png_write_zTXt(png_ptr, info->text[i].key,
info->text[i].text, info->text[i].text_length,
info->text[i].compression);
#endif
}
else
{
#if defined(PNG_WRITE_tEXt_SUPPORTED)
else
#endif
#endif
#if defined(PNG_WRITE_tEXt_SUPPORTED)
{
/* write uncompressed chunk */
png_write_tEXt(png_ptr, info->text[i].key,
info->text[i].text, info->text[i].text_length);
#endif
}
#endif
}
}
#endif
}
png_ptr->mode |= PNG_AFTER_IDAT;
/* write end of png file */
png_write_IEND(png_ptr);
}
@ -180,31 +198,70 @@ png_convert_from_time_t(png_timep ptime, time_t ttime)
#endif
/* initialize png structure, and allocate any memory needed */
void
png_write_init(png_structp png_ptr)
png_structp
png_create_write_struct(png_const_charp user_png_ver, voidp error_ptr,
png_error_ptr warn_fn, png_error_ptr error_fn)
{
jmp_buf tmp_jmp; /* to save current jump buffer */
png_msg_ptr error_fn;
png_msg_ptr warning_fn;
png_voidp msg_ptr;
png_structp png_ptr;
/* save jump buffer and error functions */
png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
error_fn = png_ptr->error_fn;
warning_fn = png_ptr->warning_fn;
msg_ptr = png_ptr->msg_ptr;
if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
{
return (png_structp)NULL;
}
/* 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_ptr->error_fn = error_fn;
png_ptr->warning_fn = warning_fn;
png_ptr->msg_ptr = msg_ptr;
if (setjmp(png_ptr->jmpbuf))
{
png_large_free(png_ptr, png_ptr->zbuf);
png_free(png_ptr, png_ptr->zstream);
png_destroy_struct(png_ptr);
return (png_structp)NULL;
}
png_set_error_fn(png_ptr, error_ptr, warn_fn, error_fn);
if (user_png_ver == NULL || strcmp(user_png_ver, png_libpng_ver))
{
if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0])
{
png_error(png_ptr, "Incompatible libpng versions");
}
else
{
png_warning(png_ptr, "Different libpng versions");
}
}
/* initialize zbuf - compression buffer */
png_ptr->zbuf_size = PNG_ZBUF_SIZE;
png_ptr->zbuf = png_large_malloc(png_ptr, png_ptr->zbuf_size);
png_set_write_fn(png_ptr, NULL, NULL, NULL);
png_ptr->do_free |= PNG_FREE_STRUCT;
return (png_ptr);
}
/* initialize png structure, and allocate any memory needed */
void
png_write_init(png_structp png_ptr)
{
jmp_buf tmp_jmp; /* to save current jump buffer */
/* save jump buffer and error functions */
png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
/* reset all variables to 0 */
png_memset(png_ptr, 0, sizeof (png_struct));
/* restore jump buffer */
png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
/* initialize zbuf - compression buffer */
png_ptr->zbuf_size = PNG_ZBUF_SIZE;
png_ptr->zbuf = png_large_malloc(png_ptr, png_ptr->zbuf_size);
png_set_write_fn(png_ptr, NULL, NULL, NULL);
}
/* write a few rows of image data. If the image is interlaced,
@ -248,7 +305,7 @@ png_write_image(png_structp png_ptr, png_bytepp image)
}
}
/* write a row of image data */
/* called by user to write a row of image data */
void
png_write_row(png_structp png_ptr, png_bytep row)
{
@ -350,72 +407,18 @@ png_write_row(png_structp png_ptr, png_bytep row)
if (png_ptr->transformations)
png_do_write_transformations(png_ptr);
/* filter rows that have been proved to help */
if (png_ptr->do_filter)
/* find a filter if necessary, filter the row and write it out */
png_write_find_filter(png_ptr, &(png_ptr->row_info));
/* trade current and prev rows so next filter references are correct */
if (png_ptr->prev_row)
{
/* save row to previous row */
png_memcpy(png_ptr->save_row, png_ptr->row_buf,
(png_size_t)png_ptr->row_info.rowbytes + 1);
png_bytep tptr;
/* filter row */
png_write_filter_row(&(png_ptr->row_info), png_ptr->row_buf,
png_ptr->prev_row);
/* trade saved pointer and prev pointer so next row references are correctly */
{ /* scope limiter */
png_bytep tptr;
tptr = png_ptr->prev_row;
png_ptr->prev_row = png_ptr->save_row;
png_ptr->save_row = tptr;
}
tptr = png_ptr->prev_row;
png_ptr->prev_row = png_ptr->row_buf;
png_ptr->row_buf = tptr;
}
else
/* set filter row to "none" */
png_ptr->row_buf[0] = 0;
/* set up the zlib input buffer */
png_ptr->zstream->next_in = png_ptr->row_buf;
png_ptr->zstream->avail_in = (uInt)png_ptr->row_info.rowbytes + 1;
/* repeat until we have compressed all the data */
do
{
int ret; /* return of zlib */
/* compress the data */
ret = deflate(png_ptr->zstream, Z_NO_FLUSH);
/* check for compression errors */
if (ret != Z_OK)
{
if (png_ptr->zstream->msg)
png_error(png_ptr, png_ptr->zstream->msg);
else
png_error(png_ptr, "zlib error");
}
/* see if it is time to write another IDAT */
if (!png_ptr->zstream->avail_out)
{
/* write the IDAT and reset the zlib output buffer */
png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
png_ptr->zstream->next_out = png_ptr->zbuf;
png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
}
/* repeat until all data has been compressed */
} while (png_ptr->zstream->avail_in);
/* finish row - updates counters and flushes zlib if last row */
png_write_finish_row(png_ptr);
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
png_ptr->flush_rows++;
if (png_ptr->flush_dist > 0 &&
png_ptr->flush_rows >= png_ptr->flush_dist)
{
png_write_flush(png_ptr);
}
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
}
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
@ -432,7 +435,8 @@ png_write_flush(png_structp png_ptr)
{
int wrote_IDAT;
if (png_ptr->mode != PNG_HAVE_IDAT)
/* We have already written out all of the data */
if (png_ptr->row_number >= png_ptr->num_rows)
return;
do
@ -477,65 +481,184 @@ png_write_flush(png_structp png_ptr)
}
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
/* free all memory used by the write */
void
png_destroy_write_struct(png_structpp png_ptr, png_infopp info_ptr)
{
if (info_ptr && *info_ptr)
{
png_destroy_struct((voidp)*info_ptr);
*info_ptr = (png_infop)NULL;
}
/* free any memory used in png struct */
if (png_ptr && *png_ptr)
{
png_write_destroy(*png_ptr);
png_destroy_struct((voidp)*png_ptr);
*png_ptr = (png_structp)NULL;
}
}
/* free any memory used in png struct (old) */
void
png_write_destroy(png_structp png_ptr)
{
jmp_buf tmp_jmp; /* save jump buffer */
png_error_ptr error_fn;
png_error_ptr warning_fn;
png_voidp error_ptr;
/* free any memory zlib uses */
deflateEnd(png_ptr->zstream);
png_free(png_ptr, png_ptr->zstream);
/* free our memory. png_free checks NULL for us. */
png_large_free(png_ptr, png_ptr->zbuf);
png_large_free(png_ptr, png_ptr->row_buf);
png_large_free(png_ptr, png_ptr->prev_row);
png_large_free(png_ptr, png_ptr->save_row);
png_large_free(png_ptr, png_ptr->sub_row);
png_large_free(png_ptr, png_ptr->up_row);
png_large_free(png_ptr, png_ptr->avg_row);
png_large_free(png_ptr, png_ptr->paeth_row);
/* reset structure */
png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
error_fn = png_ptr->error_fn;
warning_fn = png_ptr->warning_fn;
error_ptr = png_ptr->error_ptr;
png_memset(png_ptr, 0, sizeof (png_struct));
png_ptr->error_fn = error_fn;
png_ptr->warning_fn = warning_fn;
png_ptr->error_ptr = error_ptr;
png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
}
/* Allow the application to select one or more filters to use */
void
png_set_filtering(png_structp png_ptr, int filter)
png_set_filter(png_structp png_ptr, int method, int filters)
{
png_ptr->do_custom_filter = 1;
png_ptr->do_filter = (png_byte)filter;
/* We allow 'method' only for future expansion of the base filter method */
if (method == 0)
{
switch (filters & (PNG_ALL_FILTERS | 0x07))
{
case 5:
case 6:
case 7: png_warning(png_ptr, "Unknown custom row filter for method 0");
case 0: png_ptr->do_filter = PNG_FILTER_NONE; break;
case 1: png_ptr->do_filter = PNG_FILTER_SUB; break;
case 2: png_ptr->do_filter = PNG_FILTER_UP; break;
case 3: png_ptr->do_filter = PNG_FILTER_AVG; break;
case 4: png_ptr->do_filter = PNG_FILTER_PAETH; break;
default: png_ptr->do_filter = (png_byte)filters; break;
}
/* If we have allocated the row_buf, then we should have also allocated
* all of the filter buffers that have been selected.
*/
if (png_ptr->row_buf)
{
if (png_ptr->do_filter & PNG_FILTER_SUB && !(png_ptr->sub_row))
{
png_ptr->sub_row = (png_bytep )png_large_malloc(png_ptr,
png_ptr->rowbytes + 1);
png_ptr->sub_row[0] = 1; /* Set the row filter type */
}
if (png_ptr->do_filter & PNG_FILTER_UP && !(png_ptr->up_row))
{
if (!(png_ptr->prev_row))
{
png_warning(png_ptr, "Can't to add up filter after starting");
png_ptr->do_filter &= ~PNG_FILTER_UP;
}
else
{
png_ptr->up_row = (png_bytep )png_large_malloc(png_ptr,
png_ptr->rowbytes + 1);
png_ptr->up_row[0] = 2; /* Set the row filter type */
}
}
if (png_ptr->do_filter & PNG_FILTER_AVG && !(png_ptr->avg_row))
{
if (!(png_ptr->prev_row))
{
png_warning(png_ptr, "Can't add average filter after starting");
png_ptr->do_filter &= ~PNG_FILTER_AVG;
}
else
{
png_ptr->up_row = (png_bytep )png_large_malloc(png_ptr,
png_ptr->rowbytes + 1);
png_ptr->up_row[0] = 3; /* Set the row filter type */
}
}
if (png_ptr->do_filter & PNG_FILTER_PAETH && !(png_ptr->paeth_row))
{
if (!(png_ptr->prev_row))
{
png_warning(png_ptr, "Can't add Paeth filter after starting");
png_ptr->do_filter &= ~PNG_FILTER_PAETH;
}
else
{
png_ptr->paeth_row = (png_bytep )png_large_malloc(png_ptr,
png_ptr->rowbytes + 1);
png_ptr->paeth_row[0] = 4; /* Set the row filter type */
}
}
if (png_ptr->do_filter == PNG_NO_FILTERS)
png_ptr->do_filter = PNG_FILTER_NONE;
}
}
else
png_error(png_ptr, "Unknown custom filter method");
}
void
png_set_compression_level(png_structp png_ptr, int level)
{
png_ptr->zlib_custom_level = 1;
png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL;
png_ptr->zlib_level = level;
}
void
png_set_compression_mem_level(png_structp png_ptr, int mem_level)
{
png_ptr->zlib_custom_mem_level = 1;
png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL;
png_ptr->zlib_mem_level = mem_level;
}
void
png_set_compression_strategy(png_structp png_ptr, int strategy)
{
png_ptr->zlib_custom_strategy = 1;
png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
png_ptr->zlib_strategy = strategy;
}
void
png_set_compression_window_bits(png_structp png_ptr, int window_bits)
{
png_ptr->zlib_custom_window_bits = 1;
if (window_bits > 15)
png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS;
png_ptr->zlib_window_bits = window_bits;
}
void
png_set_compression_method(png_structp png_ptr, int method)
{
png_ptr->zlib_custom_method = 1;
if (method != 8)
png_warning(png_ptr, "Only compression method 8 is supported by PNG");
png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD;
png_ptr->zlib_method = method;
}

View File

@ -1,10 +1,10 @@
/* pngwtran.c - transforms the data in a row for png writers
libpng 1.0 beta 2 - version 0.88
libpng 1.0 beta 3 - version 0.89
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 25, 1996
May 25, 1996
*/
#define PNG_INTERNAL
@ -18,7 +18,7 @@ png_do_write_transformations(png_structp png_ptr)
#if defined(PNG_WRITE_FILLER_SUPPORTED)
if (png_ptr->transformations & PNG_FILLER)
png_do_write_filler(&(png_ptr->row_info), png_ptr->row_buf + 1,
png_ptr->filler_loc);
png_ptr->flags);
#endif
#if defined(PNG_WRITE_PACK_SUPPORTED)
if (png_ptr->transformations & PNG_PACK)
@ -299,12 +299,12 @@ png_do_shift(png_row_infop row_info, png_bytep row, png_color_8p bit_depth)
/* remove filler byte */
void
png_do_write_filler(png_row_infop row_info, png_bytep row,
png_byte filler_loc)
png_byte flags)
{
if (row && row_info && row_info->color_type == PNG_COLOR_TYPE_RGB &&
row_info->bit_depth == 8)
{
if (filler_loc == PNG_FILLER_AFTER)
if (flags & PNG_FLAG_FILLER_AFTER)
{
png_bytep sp, dp;

View File

@ -1,10 +1,10 @@
/* pngwutil.c - utilities to write a png file
libpng 1.0 beta 2 - version 0.88
libpng 1.0 beta 3 - version 0.89
For conditions of distribution and use, see copyright notice in png.h
Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
January 25, 1996
May 25, 1996
*/
#define PNG_INTERNAL
#include "png.h"
@ -139,6 +139,81 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
{
png_byte buf[13]; /* buffer to store the IHDR info */
/* Check that we have valid input data from the application info */
switch (color_type)
{
case 0:
switch (bit_depth)
{
case 1:
case 2:
case 4:
case 8:
case 16: png_ptr->channels = 1; break;
default: png_error(png_ptr, "Invalid bit depth for grayscale image");
}
break;
case 2:
if (bit_depth != 8 && bit_depth != 16)
png_error(png_ptr, "Invalid bit depth for RGB image");
png_ptr->channels = 3;
break;
case 3:
switch (bit_depth)
{
case 1:
case 2:
case 4:
case 8: png_ptr->channels = 1; break;
default: png_error(png_ptr, "Invalid bit depth for paletted image");
}
break;
case 4:
if (bit_depth != 8 && bit_depth != 16)
png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
png_ptr->channels = 2;
break;
case 6:
if (bit_depth != 8 && bit_depth != 16)
png_error(png_ptr, "Invalid bit depth for RGBA image");
png_ptr->channels = 4;
break;
default:
png_error(png_ptr, "Invalid image color type specified");
}
if (compression_type != 0)
{
png_warning(png_ptr, "Invalid compression type specified");
compression_type = 0;
}
if (filter_type != 0)
{
png_warning(png_ptr, "Invalid filter type specified");
filter_type = 0;
}
if (interlace_type != 0 && interlace_type != 1)
{
png_warning(png_ptr, "Invalid interlace type specified");
interlace_type = 1;
}
/* save off the relevent information */
png_ptr->bit_depth = (png_byte)bit_depth;
png_ptr->color_type = (png_byte)color_type;
png_ptr->interlaced = (png_byte)interlace_type;
png_ptr->width = width;
png_ptr->height = height;
png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
png_ptr->rowbytes = ((width * (png_uint_32)png_ptr->pixel_depth + 7) >> 3);
/* set the usr info, so any transformations can modify it */
png_ptr->usr_width = png_ptr->width;
png_ptr->usr_bit_depth = png_ptr->bit_depth;
png_ptr->usr_channels = png_ptr->channels;
/* pack the header information into the buffer */
png_save_uint_32(buf, width);
png_save_uint_32(buf + 4, height);
@ -147,65 +222,36 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
buf[10] = (png_byte)compression_type;
buf[11] = (png_byte)filter_type;
buf[12] = (png_byte)interlace_type;
/* save off the relevent information */
png_ptr->bit_depth = (png_byte)bit_depth;
png_ptr->color_type = (png_byte)color_type;
png_ptr->interlaced = (png_byte)interlace_type;
png_ptr->width = width;
png_ptr->height = height;
switch (color_type)
{
case 0:
case 3:
png_ptr->channels = 1;
break;
case 2:
png_ptr->channels = 3;
break;
case 4:
png_ptr->channels = 2;
break;
case 6:
png_ptr->channels = 4;
break;
}
png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
png_ptr->rowbytes = ((width * (png_uint_32)png_ptr->pixel_depth + 7) >> 3);
/* set the usr info, so any transformations can modify it */
png_ptr->usr_width = png_ptr->width;
png_ptr->usr_bit_depth = png_ptr->bit_depth;
png_ptr->usr_channels = png_ptr->channels;
/* 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 */
png_ptr->zstream = (z_stream *)png_malloc(png_ptr, sizeof (z_stream));
png_ptr->zstream->zalloc = png_zalloc;
png_ptr->zstream->zfree = png_zfree;
png_ptr->zstream->opaque = (voidpf)png_ptr;
if (!png_ptr->do_custom_filter)
if (!(png_ptr->do_filter))
{
if (png_ptr->color_type == 3 || png_ptr->bit_depth < 8)
png_ptr->do_filter = 0;
png_ptr->do_filter = PNG_FILTER_NONE;
else
png_ptr->do_filter = 1;
png_ptr->do_filter = PNG_ALL_FILTERS;
}
if (!png_ptr->zlib_custom_strategy)
if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY))
{
if (png_ptr->do_filter)
if (png_ptr->do_filter != PNG_FILTER_NONE)
png_ptr->zlib_strategy = Z_FILTERED;
else
png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY;
}
if (!png_ptr->zlib_custom_level)
if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL))
png_ptr->zlib_level = Z_DEFAULT_COMPRESSION;
if (!png_ptr->zlib_custom_mem_level)
if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL))
png_ptr->zlib_mem_level = 8;
if (!png_ptr->zlib_custom_window_bits)
if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS))
png_ptr->zlib_window_bits = 15;
if (!png_ptr->zlib_custom_method)
if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD))
png_ptr->zlib_method = 8;
deflateInit2(png_ptr->zstream, png_ptr->zlib_level,
png_ptr->zlib_method,
@ -215,6 +261,7 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
png_ptr->zstream->next_out = png_ptr->zbuf;
png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
png_ptr->mode = PNG_HAVE_IHDR;
}
/* write the palette. We are careful not to trust png_color to be in the
@ -227,6 +274,21 @@ png_write_PLTE(png_structp png_ptr, png_colorp palette, int number)
png_colorp pal_ptr;
png_byte buf[3];
if (number == 0 || number > 256)
{
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
png_error(png_ptr, "Invalid number of colors in palette");
}
else
{
png_warning(png_ptr, "Invalid number of colors in palette");
return;
}
}
png_ptr->num_palette = number;
png_write_chunk_start(png_ptr, png_PLTE, number * 3);
for (i = 0, pal_ptr = palette;
i < number;
@ -238,6 +300,7 @@ png_write_PLTE(png_structp png_ptr, png_colorp palette, int number)
png_write_chunk_data(png_ptr, buf, (png_uint_32)3);
}
png_write_chunk_end(png_ptr);
png_ptr->mode |= PNG_HAVE_PLTE;
}
/* write an IDAT chunk */
@ -245,6 +308,7 @@ void
png_write_IDAT(png_structp png_ptr, png_bytep data, png_uint_32 length)
{
png_write_chunk(png_ptr, png_IDAT, data, length);
png_ptr->mode |= PNG_HAVE_IDAT;
}
/* write an IEND chunk */
@ -252,6 +316,7 @@ void
png_write_IEND(png_structp png_ptr)
{
png_write_chunk(png_ptr, png_IEND, NULL, (png_uint_32)0);
png_ptr->mode |= PNG_AFTER_IEND;
}
#if defined(PNG_WRITE_gAMA_SUPPORTED)
@ -280,6 +345,16 @@ png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
/* make sure we don't depend upon the order of PNG_COLOR_8 */
if (color_type & PNG_COLOR_MASK_COLOR)
{
int maxbits;
maxbits = color_type==PNG_COLOR_TYPE_PALETTE ? 8:png_ptr->usr_bit_depth;
if (sbit->red == 0 || sbit->red > maxbits ||
sbit->green == 0 || sbit->green > maxbits ||
sbit->blue == 0 || sbit->blue > maxbits)
{
png_warning(png_ptr, "Invalid sBIT depth specified");
return;
}
buf[0] = sbit->red;
buf[1] = sbit->green;
buf[2] = sbit->blue;
@ -287,12 +362,22 @@ png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
}
else
{
if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
{
png_warning(png_ptr, "Invalid sBIT depth specified");
return;
}
buf[0] = sbit->gray;
size = 1;
}
if (color_type & PNG_COLOR_MASK_ALPHA)
{
if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
{
png_warning(png_ptr, "Invalid sBIT depth specified");
return;
}
buf[size++] = sbit->alpha;
}
@ -311,22 +396,50 @@ png_write_cHRM ( png_structp png_ptr, double white_x, double white_y,
png_byte buf[32];
/* each value is saved int 1/100,000ths */
if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 ||
white_x + white_y > 1.0)
{
png_warning(png_ptr, "Invalid cHRM white point specified");
return;
}
itemp = (png_uint_32)(white_x * 100000.0 + 0.5);
png_save_uint_32(buf, itemp);
itemp = (png_uint_32)(white_y * 100000.0 + 0.5);
png_save_uint_32(buf + 4, itemp);
if (red_x < 0 || red_x > 0.8 || red_y < 0 || red_y > 0.8 ||
red_x + red_y > 1.0)
{
png_warning(png_ptr, "Invalid cHRM red point specified");
return;
}
itemp = (png_uint_32)(red_x * 100000.0 + 0.5);
png_save_uint_32(buf + 8, itemp);
itemp = (png_uint_32)(red_y * 100000.0 + 0.5);
png_save_uint_32(buf + 12, itemp);
if (green_x < 0 || green_x > 0.8 || green_y < 0 || green_y > 0.8 ||
green_x + green_y > 1.0)
{
png_warning(png_ptr, "Invalid cHRM green point specified");
return;
}
itemp = (png_uint_32)(green_x * 100000.0 + 0.5);
png_save_uint_32(buf + 16, itemp);
itemp = (png_uint_32)(green_y * 100000.0 + 0.5);
png_save_uint_32(buf + 20, itemp);
if (blue_x < 0 || blue_x > 0.8 || blue_y < 0 || blue_y > 0.8 ||
blue_x + blue_y > 1.0)
{
png_warning(png_ptr, "Invalid cHRM blue point specified");
return;
}
itemp = (png_uint_32)(blue_x * 100000.0 + 0.5);
png_save_uint_32(buf + 24, itemp);
itemp = (png_uint_32)(blue_y * 100000.0 + 0.5);
png_save_uint_32(buf + 28, itemp);
png_write_chunk(png_ptr, png_cHRM, buf, (png_uint_32)32);
}
#endif
@ -341,6 +454,11 @@ png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran,
if (color_type == PNG_COLOR_TYPE_PALETTE)
{
if (num_trans <= 0 || num_trans > png_ptr->num_palette)
{
png_warning(png_ptr,"Invalid number of transparent colors specified");
return;
}
/* write the chunk out as it is */
png_write_chunk(png_ptr, png_tRNS, trans, (png_uint_32)num_trans);
}
@ -358,6 +476,10 @@ png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran,
png_save_uint_16(buf + 4, tran->blue);
png_write_chunk(png_ptr, png_tRNS, buf, (png_uint_32)6);
}
else
{
png_warning(png_ptr, "Can't write tRNS with and alpha channel");
}
}
#endif
@ -370,6 +492,11 @@ png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type)
if (color_type == PNG_COLOR_TYPE_PALETTE)
{
if (back->index > png_ptr->num_palette)
{
png_warning(png_ptr, "Invalid background palette index");
return;
}
buf[0] = back->index;
png_write_chunk(png_ptr, png_bKGD, buf, (png_uint_32)1);
}
@ -396,6 +523,12 @@ png_write_hIST(png_structp png_ptr, png_uint_16p hist, int number)
int i;
png_byte buf[3];
if (number <= 0 || number > png_ptr->num_palette)
{
png_warning(png_ptr, "Invalid number of histogram entries specified");
return;
}
png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(number * 2));
for (i = 0; i < number; i++)
{
@ -415,6 +548,19 @@ png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text,
int key_len;
key_len = png_strlen(key);
if (key_len == 0)
{
png_warning(png_ptr, "Invalid text keyword length");
return;
}
else if (key_len > 80)
{
png_warning(png_ptr, "Text keyword length restricted to 80 characters\n");
key[80] = '\0';
key_len = 80;
}
/* make sure we count the 0 after the key */
png_write_chunk_start(png_ptr, png_tEXt,
(png_uint_32)(key_len + text_len + 1));
@ -441,6 +587,24 @@ png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
key_len = png_strlen(key);
if (key_len == 0)
{
png_warning(png_ptr, "Invalid text keyword length");
return;
}
else if (key_len > 80)
{
png_warning(png_ptr, "Text keyword length restricted to 80 characters\n");
key[80] = '\0';
key_len = 80;
}
if (compression != 0)
{
png_warning(png_ptr, "Only type 0 compression allowed for text\n");
compression = 0;
}
/* we can't write the chunk until we find out how much data we have,
which means we need to run the compresser first, and save the
output. This shouldn't be a problem, as the vast majority of
@ -603,6 +767,9 @@ png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
{
png_byte buf[9];
if (unit_type >= PNG_RESOLUTION_LAST)
png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
png_save_uint_32(buf, x_pixels_per_unit);
png_save_uint_32(buf + 4, y_pixels_per_unit);
buf[8] = (png_byte)unit_type;
@ -620,6 +787,9 @@ png_write_oFFs(png_structp png_ptr, png_uint_32 x_offset,
{
png_byte buf[9];
if (unit_type >= PNG_OFFSET_LAST)
png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
png_save_uint_32(buf, x_offset);
png_save_uint_32(buf + 4, y_offset);
buf[8] = (png_byte)unit_type;
@ -636,6 +806,14 @@ png_write_tIME(png_structp png_ptr, png_timep mod_time)
{
png_byte buf[7];
if (mod_time->month > 12 || mod_time->month < 1 ||
mod_time->day > 31 || mod_time->day < 1 ||
mod_time->hour > 23 || mod_time->second > 60)
{
png_warning(png_ptr, "Invalid time specified for tIME chunk");
return;
}
png_save_uint_16(buf, mod_time->year);
buf[2] = mod_time->month;
buf[3] = mod_time->day;
@ -656,15 +834,47 @@ png_write_start_row(png_structp png_ptr)
(((png_uint_32)png_ptr->usr_channels *
(png_uint_32)png_ptr->usr_bit_depth *
png_ptr->width + 7) >> 3) + 1);
/* set up filtering buffers, if filtering */
if (png_ptr->do_filter)
png_ptr->row_buf[0] = 0;
/* set up filtering buffer, if using this filter */
if (png_ptr->do_filter & PNG_FILTER_SUB)
{
png_ptr->sub_row = (png_bytep )png_large_malloc(png_ptr,
png_ptr->rowbytes + 1);
png_ptr->sub_row[0] = 1; /* Set the row filter type */
}
/* We only need to keep the previous row if we are using one of these */
if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
{
/* set up previous row buffer */
png_ptr->prev_row = (png_bytep )png_large_malloc(png_ptr,
png_ptr->rowbytes + 1);
png_memset(png_ptr->prev_row, 0, (png_size_t)png_ptr->rowbytes + 1);
png_ptr->save_row = (png_bytep )png_large_malloc(png_ptr,
png_ptr->rowbytes + 1);
png_memset(png_ptr->save_row, 0, (png_size_t)png_ptr->rowbytes + 1);
(((png_uint_32)png_ptr->usr_channels *
(png_uint_32)png_ptr->usr_bit_depth *
png_ptr->width + 7) >> 3) + 1);
png_memset(png_ptr->prev_row, 0, (((png_uint_32)png_ptr->usr_channels *
(png_uint_32)png_ptr->usr_bit_depth * png_ptr->width + 7) >> 3) + 1);
if (png_ptr->do_filter & PNG_FILTER_UP)
{
png_ptr->up_row = (png_bytep )png_large_malloc(png_ptr,
png_ptr->rowbytes + 1);
png_ptr->up_row[0] = 2; /* Set the row filter type */
}
if (png_ptr->do_filter & PNG_FILTER_AVG)
{
png_ptr->avg_row = (png_bytep )png_large_malloc(png_ptr,
png_ptr->rowbytes + 1);
png_ptr->avg_row[0] = 3; /* Set the row filter type */
}
if (png_ptr->do_filter & PNG_FILTER_PAETH)
{
png_ptr->paeth_row = (png_bytep )png_large_malloc(png_ptr,
png_ptr->rowbytes + 1);
png_ptr->paeth_row[0] = 4; /* Set the row filter type */
}
}
/* if interlaced, we need to set up width and height of pass */
@ -736,9 +946,11 @@ png_write_finish_row(png_structp png_ptr)
}
/* reset filter row */
/* reset the row above the image for the next pass */
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_uint_32)png_ptr->usr_channels *
(png_uint_32)png_ptr->usr_bit_depth * png_ptr->width + 7) >> 3) + 1);
/* if we have more data to get, go get it */
if (png_ptr->pass < 7)
return;
@ -935,220 +1147,215 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
}
#endif
/* this filters the row. Both row and prev_row have space at the
first byte for the filter byte. */
/* this filters the row, chooses which filter to use, if it has not already
* been given by the application, and then writes the row out with the
* chosen filter */
void
png_write_filter_row(png_row_infop row_info, png_bytep row,
png_bytep prev_row)
png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
{
int minf, bpp;
png_uint_32 i, v;
png_uint_32 s0, s1, s2, s3, s4, mins;
png_bytep rp, pp, cp, lp;
png_bytep prev_row, best_row, row_buf;
png_uint_32 mins;
int bpp;
/* find out how many bytes offset each pixel is */
bpp = (row_info->pixel_depth + 7) / 8;
if (bpp < 1)
bpp = 1;
prev_row = png_ptr->prev_row;
best_row = row_buf = png_ptr->row_buf;
mins = 0xffffffff;
/* the prediction method we use is to find which method provides
the smallest value when summing the abs of the distances from
zero using anything >= 128 as negitive numbers. */
s0 = s1 = s2 = s3 = s4 = 0;
for (i = 0, rp = row + 1, pp = prev_row + 1, lp = row + 1 - bpp,
cp = prev_row + 1 - bpp;
i < bpp; i++, rp++, pp++, lp++, cp++)
/* We don't need to test the 'no filter' case if this is the only filter
* that has been chosen, as it doesn't actually do anything to the data. */
if (png_ptr->do_filter & PNG_FILTER_NONE &&
png_ptr->do_filter != PNG_FILTER_NONE)
{
/* check none filter */
v = *rp;
if (v < 128)
s0 += v;
else
s0 += 256 - v;
png_bytep rp;
png_uint_32 sum = 0;
int i, v;
/* check up filter */
v = (png_byte)(((int)*rp - (int)*pp) & 0xff);
if (v < 128)
s2 += v;
else
s2 += 256 - v;
/* check avg filter */
v = (png_byte)(((int)*rp - ((int)*pp / 2)) & 0xff);
if (v < 128)
s3 += v;
else
s3 += 256 - v;
for (i = 0, rp = row_buf + 1; i < row_info->rowbytes; i++, rp++)
{
v = *rp;
sum += (v < 128) ? v : 256 - v;
}
mins = sum;
}
/* some filters are same until we get past bpp */
s1 = s0;
s4 = s2;
for (; i < row_info->rowbytes; i++, rp++, pp++, lp++, cp++)
/* sub filter */
if (png_ptr->do_filter & PNG_FILTER_SUB)
{
int a, b, c, pa, pb, pc, p;
png_bytep rp, dp, lp;
png_uint_32 sum = 0;
int i, v;
/* check none filter */
v = *rp;
if (v < 128)
s0 += v;
else
s0 += 256 - v;
for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
i++, rp++, dp++)
{
v = *dp = *rp;
/* check sub filter */
v = (png_byte)(((int)*rp - (int)*lp) & 0xff);
sum += (v < 128) ? v : 256 - v;
}
for (lp = row_buf + 1; i < row_info->rowbytes; i++, rp++, lp++, dp++)
{
v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
if (v < 128)
s1 += v;
else
s1 += 256 - v;
/* check up filter */
v = (png_byte)(((int)*rp - (int)*pp) & 0xff);
if (v < 128)
s2 += v;
else
s2 += 256 - v;
/* check avg filter */
v = (png_byte)(((int)*rp - (((int)*pp + (int)*lp) / 2)) & 0xff);
if (v < 128)
s3 += v;
else
s3 += 256 - v;
/* check paeth filter */
b = *pp;
c = *cp;
a = *lp;
p = a + b - c;
pa = abs(p - a);
pb = abs(p - b);
pc = abs(p - c);
if (pa <= pb && pa <= pc)
p = a;
else if (pb <= pc)
p = b;
else
p = c;
v = (png_byte)(((int)*rp - p) & 0xff);
if (v < 128)
s4 += v;
else
s4 += 256 - v;
sum += (v < 128) ? v : 256 - v;
}
if (sum < mins)
{
mins = sum;
best_row = png_ptr->sub_row;
}
}
mins = s0;
minf = 0;
if (s1 < mins)
/* up filter */
if (png_ptr->do_filter & PNG_FILTER_UP)
{
mins = s1;
minf = 1;
png_bytep rp, dp, pp;
png_uint_32 sum = 0;
int i, v;
for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
pp = prev_row + 1; i < row_info->rowbytes; i++, rp++, pp++, dp++)
{
v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
sum += (v < 128) ? v : 256 - v;
}
if (sum < mins)
{
mins = sum;
best_row = png_ptr->up_row;
}
}
if (s2 < mins)
/* avg filter */
if (png_ptr->do_filter & PNG_FILTER_AVG)
{
mins = s2;
minf = 2;
png_bytep rp, dp, pp, lp;
png_uint_32 sum = 0;
int i, v;
for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
pp = prev_row + 1; i < bpp; i++, rp++, pp++, dp++)
{
v = *dp = (png_byte)(((int)*rp - ((int)*pp / 2)) & 0xff);
sum += (v < 128) ? v : 256 - v;
}
for (lp = row_buf + 1; i < row_info->rowbytes;
i++, rp++, pp++, lp++, dp++)
{
v = *dp = (png_byte)(((int)*rp - (((int)*pp + (int)*lp) / 2)) & 0xff);
sum += (v < 128) ? v : 256 - v;
}
if (sum < mins)
{
mins = sum;
best_row = png_ptr->avg_row;
}
}
if (s3 < mins)
/* paeth filter */
if (png_ptr->do_filter & PNG_FILTER_PAETH)
{
mins = s3;
minf = 3;
png_bytep rp, dp, pp, cp, lp;
png_uint_32 sum = 0;
int i, v;
for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
pp = prev_row + 1; i < bpp; i++, rp++, pp++, dp++)
{
v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
sum += (v < 128) ? v : 256 - v;
}
for (lp = row_buf + 1, cp = prev_row + 1; i < row_info->rowbytes;
i++, rp++, pp++, lp++, dp++, cp++)
{
int a, b, c, pa, pb, pc, p;
b = *pp;
c = *cp;
a = *lp;
p = a + b - c;
pa = abs(p - a);
pb = abs(p - b);
pc = abs(p - c);
if (pa <= pb && pa <= pc)
p = a;
else if (pb <= pc)
p = b;
else
p = c;
v = *dp = (png_byte)(((int)*rp - p) & 0xff);
sum += (v < 128) ? v : 256 - v;
}
if (sum < mins)
{
best_row = png_ptr->paeth_row;
}
}
if (s4 < mins)
{
minf = 4;
}
/* set filter byte */
row[0] = (png_byte)minf;
/* do filter */
switch (minf)
{
/* sub filter */
case 1:
for (i = bpp, rp = row + (png_size_t)row_info->rowbytes,
lp = row + (png_size_t)row_info->rowbytes - bpp;
i < row_info->rowbytes; i++, rp--, lp--)
{
*rp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
}
break;
/* up filter */
case 2:
for (i = 0, rp = row + (png_size_t)row_info->rowbytes,
pp = prev_row + (png_size_t)row_info->rowbytes;
i < row_info->rowbytes; i++, rp--, pp--)
{
*rp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
}
break;
/* avg filter */
case 3:
for (i = row_info->rowbytes,
rp = 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;
i > bpp; i--, rp--, lp--, pp--)
{
*rp = (png_byte)(((int)*rp - (((int)*lp + (int)*pp) /
2)) & 0xff);
}
for (; i > 0; i--, rp--, pp--)
{
*rp = (png_byte)(((int)*rp - ((int)*pp / 2)) & 0xff);
}
break;
/* paeth filter */
case 4:
for (i = row_info->rowbytes,
rp = 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,
cp = prev_row + (png_size_t)row_info->rowbytes - bpp;
i > 0; i--, rp--, lp--, pp--, cp--)
{
int a, b, c, pa, pb, pc, p;
b = *pp;
if (i > bpp)
{
c = *cp;
a = *lp;
}
else
{
a = c = 0;
}
p = a + b - c;
pa = abs(p - a);
pb = abs(p - b);
pc = abs(p - c);
if (pa <= pb && pa <= pc)
p = a;
else if (pb <= pc)
p = b;
else
p = c;
*rp = (png_byte)(((int)*rp - p) & 0xff);
}
break;
}
/* Do the actual writing of the filtered row data from the chosen filter */
png_write_filtered_row(png_ptr, best_row);
}
/* do the actual writing of a filtered row */
void
png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row)
{
/* set up the zlib input buffer */
png_ptr->zstream->next_in = filtered_row;
png_ptr->zstream->avail_in = (uInt)png_ptr->row_info.rowbytes + 1;
/* repeat until we have compressed all the data */
do
{
int ret; /* return of zlib */
/* compress the data */
ret = deflate(png_ptr->zstream, Z_NO_FLUSH);
/* check for compression errors */
if (ret != Z_OK)
{
if (png_ptr->zstream->msg)
png_error(png_ptr, png_ptr->zstream->msg);
else
png_error(png_ptr, "zlib error");
}
/* see if it is time to write another IDAT */
if (!png_ptr->zstream->avail_out)
{
/* write the IDAT and reset the zlib output buffer */
png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
png_ptr->zstream->next_out = png_ptr->zbuf;
png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
}
/* repeat until all data has been compressed */
} while (png_ptr->zstream->avail_in);
/* finish row - updates counters and flushes zlib if last row */
png_write_finish_row(png_ptr);
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
png_ptr->flush_rows++;
if (png_ptr->flush_dist > 0 &&
png_ptr->flush_rows >= png_ptr->flush_dist)
{
png_write_flush(png_ptr);
}
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
}

View File

@ -1,41 +1,56 @@
readme.txt - for libpng 0.88
readme.txt - for libpng 0.89
This is a bug fix for the second beta version of libpng 1.0, and
a more secure progressive (push) reader. The progressive reader
hasn't been tested as much as the pull reader, but seems to work ok.
This is a bug fix for the third beta version of libpng 1.0. The
changes from libpng-0.88 are bug fixes and some changes to the
API itself to increase robustness with shared libraries. This
release is based on libpng-0.88, but has been modified from that
version by Andreas Dilger <adilger@enel.ucalgary.ca> because the
original author, Guy Schalnat, has not been able to keep up with
the time demands of maintaining this library.
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.
The callback functions for the error/warning messages have changed
since the last release because their implementation was broken,
and it was thought best to change the API itself (which was only
introduced in libpng-0.88 itself) to alert the user to the change,
rather than mislead the user into thinking their application was
OK after re-compiling. This means that calls to png_set_message_fn()
no longer exist, because the previously suggested method of calling
them before png_read_init() or png_write_init() is now ineffective.
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
me a change and I didn't put it in, send it again. Sorry.
The preferred method of setting the error and warning callbacks
has been incorporated into the allocation of the png_struct and
info_struct itself, which allow them to be safely used during the
initialization of the structure, as well as to keep the size of
the png_struct internal to the library, rather than at compile time
of the application. This will hopefully remove any problems with
dynamically linked libraries, and should be considered the preferred
method of creating these structures, although the previous
initialization API is still available for compatibility. See libpng.txt
for more information on the new API.
The changes made to the library, and bugs fixed are based on discussions
on the PNG implementation mailing list <png-implement@dworking.wustl.edu>
and not on material submitted to Guy.
For a detailed description on using libpng, read libpng.txt. For
usage information and restrictions (what little they are) on libpng,
see png.h. For a description on using zlib (the compression library
used by libpng) and zlib's restrictions, see zlib.h
I have included a general makefile, but you may have to modify it
for your own needs.
I have included a general makefile, as well as several machine and compiler
specific ones, but you may have to modify one for your own needs.
You will need zlib 0.95 or later to run this. zlib is a compression
library that is useful for more things then just png files. If
you need a compression library, check out zlib.h
you need a compression library, check out zlib.h. There was a bug in
zlib <= 0.99 which caused it to generate invalid compression streams
on some occasions. Later versions of zlib do not have this problem.
zlib should be available at the same place that libpng is.
If not, it should be at ftp.uu.net in /graphics/png
Eventually, it will be at ftp.uu.net in /pub/archiving/zip/zlib
You will also want a copy of the PNG specification. It should
You may also want a copy of the PNG specification. It should
be available at the same place you picked up libpng. If it is
not there, try ftp.uu.net in the /graphics/png directory.
@ -55,17 +70,18 @@ Finally, if you get any warning messages when compiling libpng
(note: not zlib), and they are easy to fix, I'd appreciate the
fix. Please mention "libpng" somewhere in the subject line. Thanks.
You can reach me at:
This release was created and will be supported by myself, and the
PNG group.
adilger@enel.ucalgary.ca
png-implement@dworkin.wustl.edu
You can reach Guy, the original libpng author, at (internet preferred):
internet: schalnat@group42.com
CompuServe: 75501,1625
I tend to check my CompuServe account very infrequently, so you may
want to use the internet account. If I don't answer your email
immediately, please be patient. If you don't receive a reply within
a week, you may want to write and ask if I got the first email.
Please do not send me general questions about PNG. Send them to
Please do not send general questions about PNG. Send them to
the address in the specification. At the same time, please do
not send libpng questions to that address, send them to me. I'll
get them in the end anyway. If you have a question about something