Imported from libpng-0.71.tar
This commit is contained in:
commit
0d5805822f
|
@ -0,0 +1,488 @@
|
|||
/* Copyright (C) 1989, 1991, 1993 Aladdin Enterprises. All rights reserved. */
|
||||
|
||||
/* ansi2knr.c */
|
||||
/* Convert ANSI function declarations to K&R syntax */
|
||||
|
||||
/*
|
||||
ansi2knr is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY. No author or distributor accepts responsibility
|
||||
to anyone for the consequences of using it or for whether it serves any
|
||||
particular purpose or works at all, unless he says so in writing. Refer
|
||||
to the GNU General Public License for full details.
|
||||
|
||||
Everyone is granted permission to copy, modify and redistribute
|
||||
ansi2knr, but only under the conditions described in the GNU
|
||||
General Public License. A copy of this license is supposed to have been
|
||||
given to you along with ansi2knr so you can know your rights and
|
||||
responsibilities. It should be in a file named COPYING. Among other
|
||||
things, the copyright notice and this notice must be preserved on all
|
||||
copies.
|
||||
*/
|
||||
|
||||
/*
|
||||
---------- Here is the GNU GPL file COPYING, referred to above ----------
|
||||
----- These terms do NOT apply to the JPEG software itself; see README ------
|
||||
|
||||
GHOSTSCRIPT GENERAL PUBLIC LICENSE
|
||||
(Clarified 11 Feb 1988)
|
||||
|
||||
Copyright (C) 1988 Richard M. Stallman
|
||||
Everyone is permitted to copy and distribute verbatim copies of this
|
||||
license, but changing it is not allowed. You can also use this wording
|
||||
to make the terms for other programs.
|
||||
|
||||
The license agreements of most software companies keep you at the
|
||||
mercy of those companies. By contrast, our general public license is
|
||||
intended to give everyone the right to share Ghostscript. To make sure
|
||||
that you get the rights we want you to have, we need to make
|
||||
restrictions that forbid anyone to deny you these rights or to ask you
|
||||
to surrender the rights. Hence this license agreement.
|
||||
|
||||
Specifically, we want to make sure that you have the right to give
|
||||
away copies of Ghostscript, that you receive source code or else can get
|
||||
it if you want it, that you can change Ghostscript or use pieces of it
|
||||
in new free programs, and that you know you can do these things.
|
||||
|
||||
To make sure that everyone has such rights, we have to forbid you to
|
||||
deprive anyone else of these rights. For example, if you distribute
|
||||
copies of Ghostscript, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must tell them their rights.
|
||||
|
||||
Also, for our own protection, we must make certain that everyone finds
|
||||
out that there is no warranty for Ghostscript. If Ghostscript is
|
||||
modified by someone else and passed on, we want its recipients to know
|
||||
that what they have is not what we distributed, so that any problems
|
||||
introduced by others will not reflect on our reputation.
|
||||
|
||||
Therefore we (Richard M. Stallman and the Free Software Foundation,
|
||||
Inc.) make the following terms which say what you must do to be allowed
|
||||
to distribute or change Ghostscript.
|
||||
|
||||
|
||||
COPYING POLICIES
|
||||
|
||||
1. You may copy and distribute verbatim copies of Ghostscript source
|
||||
code as you receive it, in any medium, provided that you conspicuously
|
||||
and appropriately publish on each copy a valid copyright and license
|
||||
notice "Copyright (C) 1989 Aladdin Enterprises. All rights reserved.
|
||||
Distributed by Free Software Foundation, Inc." (or with whatever year is
|
||||
appropriate); keep intact the notices on all files that refer to this
|
||||
License Agreement and to the absence of any warranty; and give any other
|
||||
recipients of the Ghostscript program a copy of this License Agreement
|
||||
along with the program. You may charge a distribution fee for the
|
||||
physical act of transferring a copy.
|
||||
|
||||
2. You may modify your copy or copies of Ghostscript or any portion of
|
||||
it, and copy and distribute such modifications under the terms of
|
||||
Paragraph 1 above, provided that you also do the following:
|
||||
|
||||
a) cause the modified files to carry prominent notices stating
|
||||
that you changed the files and the date of any change; and
|
||||
|
||||
b) cause the whole of any work that you distribute or publish,
|
||||
that in whole or in part contains or is a derivative of Ghostscript
|
||||
or any part thereof, to be licensed at no charge to all third
|
||||
parties on terms identical to those contained in this License
|
||||
Agreement (except that you may choose to grant more extensive
|
||||
warranty protection to some or all third parties, at your option).
|
||||
|
||||
c) You may charge a distribution fee for the physical act of
|
||||
transferring a copy, and you may at your option offer warranty
|
||||
protection in exchange for a fee.
|
||||
|
||||
Mere aggregation of another unrelated program with this program (or its
|
||||
derivative) on a volume of a storage or distribution medium does not bring
|
||||
the other program under the scope of these terms.
|
||||
|
||||
3. You may copy and distribute Ghostscript (or a portion or derivative
|
||||
of it, under Paragraph 2) in object code or executable form under the
|
||||
terms of Paragraphs 1 and 2 above provided that you also do one of the
|
||||
following:
|
||||
|
||||
a) accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of
|
||||
Paragraphs 1 and 2 above; or,
|
||||
|
||||
b) accompany it with a written offer, valid for at least three
|
||||
years, to give any third party free (except for a nominal
|
||||
shipping charge) a complete machine-readable copy of the
|
||||
corresponding source code, to be distributed under the terms of
|
||||
Paragraphs 1 and 2 above; or,
|
||||
|
||||
c) accompany it with the information you received as to where the
|
||||
corresponding source code may be obtained. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form alone.)
|
||||
|
||||
For an executable file, complete source code means all the source code for
|
||||
all modules it contains; but, as a special exception, it need not include
|
||||
source code for modules which are standard libraries that accompany the
|
||||
operating system on which the executable file runs.
|
||||
|
||||
4. You may not copy, sublicense, distribute or transfer Ghostscript
|
||||
except as expressly provided under this License Agreement. Any attempt
|
||||
otherwise to copy, sublicense, distribute or transfer Ghostscript is
|
||||
void and your rights to use the program under this License agreement
|
||||
shall be automatically terminated. However, parties who have received
|
||||
computer software programs from you with this License Agreement will not
|
||||
have their licenses terminated so long as such parties remain in full
|
||||
compliance.
|
||||
|
||||
5. If you wish to incorporate parts of Ghostscript into other free
|
||||
programs whose distribution conditions are different, write to the Free
|
||||
Software Foundation at 675 Mass Ave, Cambridge, MA 02139. We have not
|
||||
yet worked out a simple rule that can be stated here, but we will often
|
||||
permit this. We will be guided by the two goals of preserving the free
|
||||
status of all derivatives of our free software and of promoting the
|
||||
sharing and reuse of software.
|
||||
|
||||
Your comments and suggestions about our licensing policies and our
|
||||
software are welcome! Please contact the Free Software Foundation,
|
||||
Inc., 675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
BECAUSE GHOSTSCRIPT IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY
|
||||
NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT
|
||||
WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, RICHARD
|
||||
M. STALLMAN, ALADDIN ENTERPRISES, L. PETER DEUTSCH, AND/OR OTHER PARTIES
|
||||
PROVIDE GHOSTSCRIPT "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
|
||||
ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF GHOSTSCRIPT IS WITH
|
||||
YOU. SHOULD GHOSTSCRIPT PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
|
||||
NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M.
|
||||
STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., L. PETER DEUTSCH, ALADDIN
|
||||
ENTERPRISES, AND/OR ANY OTHER PARTY WHO MAY MODIFY AND REDISTRIBUTE
|
||||
GHOSTSCRIPT AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING
|
||||
ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
|
||||
(INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
|
||||
INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE
|
||||
PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GHOSTSCRIPT, EVEN IF YOU
|
||||
HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM
|
||||
BY ANY OTHER PARTY.
|
||||
|
||||
-------------------- End of file COPYING ------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef BSD
|
||||
#include <strings.h>
|
||||
#else
|
||||
#ifdef VMS
|
||||
extern int strlen(), strncmp();
|
||||
#else
|
||||
#include <string.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* malloc and free should be declared in stdlib.h, */
|
||||
/* but if you've got a K&R compiler, they probably aren't. */
|
||||
#ifdef MSDOS
|
||||
#include <malloc.h>
|
||||
#else
|
||||
#ifdef VMS
|
||||
extern char *malloc();
|
||||
extern void free();
|
||||
#else
|
||||
extern char *malloc();
|
||||
extern int free();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Usage:
|
||||
ansi2knr input_file [output_file]
|
||||
* If no output_file is supplied, output goes to stdout.
|
||||
* There are no error messages.
|
||||
*
|
||||
* ansi2knr recognizes functions by seeing a non-keyword identifier
|
||||
* at the left margin, followed by a left parenthesis,
|
||||
* with a right parenthesis as the last character on the line.
|
||||
* It will recognize a multi-line header provided that the last character
|
||||
* of the last line of the header is a right parenthesis,
|
||||
* and no intervening line ends with a left brace or a semicolon.
|
||||
* These algorithms ignore whitespace and comments, except that
|
||||
* the function name must be the first thing on the line.
|
||||
* The following constructs will confuse it:
|
||||
* - Any other construct that starts at the left margin and
|
||||
* follows the above syntax (such as a macro or function call).
|
||||
* - Macros that tinker with the syntax of the function header.
|
||||
*/
|
||||
|
||||
/* Scanning macros */
|
||||
#define isidchar(ch) (isalnum(ch) || (ch) == '_')
|
||||
#define isidfirstchar(ch) (isalpha(ch) || (ch) == '_')
|
||||
|
||||
/* Forward references */
|
||||
char *skipspace();
|
||||
int writeblanks();
|
||||
int test1();
|
||||
int convert1();
|
||||
|
||||
/* The main program */
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{ FILE *in, *out;
|
||||
#define bufsize 5000 /* arbitrary size */
|
||||
char *buf;
|
||||
char *line;
|
||||
switch ( argc )
|
||||
{
|
||||
default:
|
||||
printf("Usage: ansi2knr input_file [output_file]\n");
|
||||
exit(0);
|
||||
case 2:
|
||||
out = stdout; break;
|
||||
case 3:
|
||||
out = fopen(argv[2], "w");
|
||||
if ( out == NULL )
|
||||
{ fprintf(stderr, "Cannot open %s\n", argv[2]);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
in = fopen(argv[1], "r");
|
||||
if ( in == NULL )
|
||||
{ fprintf(stderr, "Cannot open %s\n", argv[1]);
|
||||
exit(1);
|
||||
}
|
||||
fprintf(out, "#line 1 \"%s\"\n", argv[1]);
|
||||
buf = malloc(bufsize);
|
||||
line = buf;
|
||||
while ( fgets(line, (unsigned)(buf + bufsize - line), in) != NULL )
|
||||
{ switch ( test1(buf) )
|
||||
{
|
||||
case 1: /* a function */
|
||||
convert1(buf, out);
|
||||
break;
|
||||
case -1: /* maybe the start of a function */
|
||||
line = buf + strlen(buf);
|
||||
if ( line != buf + (bufsize - 1) ) /* overflow check */
|
||||
continue;
|
||||
/* falls through */
|
||||
default: /* not a function */
|
||||
fputs(buf, out);
|
||||
break;
|
||||
}
|
||||
line = buf;
|
||||
}
|
||||
if ( line != buf ) fputs(buf, out);
|
||||
free(buf);
|
||||
fclose(out);
|
||||
fclose(in);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Skip over space and comments, in either direction. */
|
||||
char *
|
||||
skipspace(p, dir)
|
||||
register char *p;
|
||||
register int dir; /* 1 for forward, -1 for backward */
|
||||
{ for ( ; ; )
|
||||
{ while ( isspace(*p) ) p += dir;
|
||||
if ( !(*p == '/' && p[dir] == '*') ) break;
|
||||
p += dir; p += dir;
|
||||
while ( !(*p == '*' && p[dir] == '/') )
|
||||
{ if ( *p == 0 ) return p; /* multi-line comment?? */
|
||||
p += dir;
|
||||
}
|
||||
p += dir; p += dir;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write blanks over part of a string.
|
||||
*/
|
||||
int
|
||||
writeblanks(start, end)
|
||||
char *start;
|
||||
char *end;
|
||||
{ char *p;
|
||||
for ( p = start; p < end; p++ ) *p = ' ';
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test whether the string in buf is a function definition.
|
||||
* The string may contain and/or end with a newline.
|
||||
* Return as follows:
|
||||
* 0 - definitely not a function definition;
|
||||
* 1 - definitely a function definition;
|
||||
* -1 - may be the beginning of a function definition,
|
||||
* append another line and look again.
|
||||
*/
|
||||
int
|
||||
test1(buf)
|
||||
char *buf;
|
||||
{ register char *p = buf;
|
||||
char *bend;
|
||||
char *endfn;
|
||||
int contin;
|
||||
if ( !isidfirstchar(*p) )
|
||||
return 0; /* no name at left margin */
|
||||
bend = skipspace(buf + strlen(buf) - 1, -1);
|
||||
switch ( *bend )
|
||||
{
|
||||
case ')': contin = 1; break;
|
||||
case '{':
|
||||
case ';': return 0; /* not a function */
|
||||
default: contin = -1;
|
||||
}
|
||||
while ( isidchar(*p) ) p++;
|
||||
endfn = p;
|
||||
p = skipspace(p, 1);
|
||||
if ( *p++ != '(' )
|
||||
return 0; /* not a function */
|
||||
p = skipspace(p, 1);
|
||||
if ( *p == ')' )
|
||||
return 0; /* no parameters */
|
||||
/* Check that the apparent function name isn't a keyword. */
|
||||
/* We only need to check for keywords that could be followed */
|
||||
/* by a left parenthesis (which, unfortunately, is most of them). */
|
||||
{ static char *words[] =
|
||||
{ "asm", "auto", "case", "char", "const", "double",
|
||||
"extern", "float", "for", "if", "int", "long",
|
||||
"register", "return", "short", "signed", "sizeof",
|
||||
"static", "switch", "typedef", "unsigned",
|
||||
"void", "volatile", "while", 0
|
||||
};
|
||||
char **key = words;
|
||||
char *kp;
|
||||
int len = endfn - buf;
|
||||
while ( (kp = *key) != 0 )
|
||||
{ if ( strlen(kp) == len && !strncmp(kp, buf, len) )
|
||||
return 0; /* name is a keyword */
|
||||
key++;
|
||||
}
|
||||
}
|
||||
return contin;
|
||||
}
|
||||
|
||||
int
|
||||
convert1(buf, out)
|
||||
char *buf;
|
||||
FILE *out;
|
||||
{ char *endfn;
|
||||
register char *p;
|
||||
char **breaks;
|
||||
unsigned num_breaks = 2; /* for testing */
|
||||
char **btop;
|
||||
char **bp;
|
||||
char **ap;
|
||||
/* Pre-ANSI implementations don't agree on whether strchr */
|
||||
/* is called strchr or index, so we open-code it here. */
|
||||
for ( endfn = buf; *(endfn++) != '('; ) ;
|
||||
top: p = endfn;
|
||||
breaks = (char **)malloc(sizeof(char *) * num_breaks * 2);
|
||||
if ( breaks == 0 )
|
||||
{ /* Couldn't allocate break table, give up */
|
||||
fprintf(stderr, "Unable to allocate break table!\n");
|
||||
fputs(buf, out);
|
||||
return -1;
|
||||
}
|
||||
btop = breaks + num_breaks * 2 - 2;
|
||||
bp = breaks;
|
||||
/* Parse the argument list */
|
||||
do
|
||||
{ int level = 0;
|
||||
char *end = NULL;
|
||||
if ( bp >= btop )
|
||||
{ /* Filled up break table. */
|
||||
/* Allocate a bigger one and start over. */
|
||||
free((char *)breaks);
|
||||
num_breaks <<= 1;
|
||||
goto top;
|
||||
}
|
||||
*bp++ = p;
|
||||
/* Find the end of the argument */
|
||||
for ( ; end == NULL; p++ )
|
||||
{ switch(*p)
|
||||
{
|
||||
case ',': if ( !level ) end = p; break;
|
||||
case '(': level++; break;
|
||||
case ')': if ( --level < 0 ) end = p; break;
|
||||
case '/': p = skipspace(p, 1) - 1; break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
p--; /* back up over terminator */
|
||||
/* Find the name being declared. */
|
||||
/* This is complicated because of procedure and */
|
||||
/* array modifiers. */
|
||||
for ( ; ; )
|
||||
{ p = skipspace(p - 1, -1);
|
||||
switch ( *p )
|
||||
{
|
||||
case ']': /* skip array dimension(s) */
|
||||
case ')': /* skip procedure args OR name */
|
||||
{ int level = 1;
|
||||
while ( level )
|
||||
switch ( *--p )
|
||||
{
|
||||
case ']': case ')': level++; break;
|
||||
case '[': case '(': level--; break;
|
||||
case '/': p = skipspace(p, -1) + 1; break;
|
||||
default: ;
|
||||
}
|
||||
}
|
||||
if ( *p == '(' && *skipspace(p + 1, 1) == '*' )
|
||||
{ /* We found the name being declared */
|
||||
while ( !isidfirstchar(*p) )
|
||||
p = skipspace(p, 1) + 1;
|
||||
goto found;
|
||||
}
|
||||
break;
|
||||
default: goto found;
|
||||
}
|
||||
}
|
||||
found: if ( *p == '.' && p[-1] == '.' && p[-2] == '.' )
|
||||
{ p++;
|
||||
if ( bp == breaks + 1 ) /* sole argument */
|
||||
writeblanks(breaks[0], p);
|
||||
else
|
||||
writeblanks(bp[-1] - 1, p);
|
||||
bp--;
|
||||
}
|
||||
else
|
||||
{ while ( isidchar(*p) ) p--;
|
||||
*bp++ = p+1;
|
||||
}
|
||||
p = end;
|
||||
}
|
||||
while ( *p++ == ',' );
|
||||
*bp = p;
|
||||
/* Make a special check for 'void' arglist */
|
||||
if ( bp == breaks+2 )
|
||||
{ p = skipspace(breaks[0], 1);
|
||||
if ( !strncmp(p, "void", 4) )
|
||||
{ p = skipspace(p+4, 1);
|
||||
if ( p == breaks[2] - 1 )
|
||||
{ bp = breaks; /* yup, pretend arglist is empty */
|
||||
writeblanks(breaks[0], p + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Put out the function name */
|
||||
p = buf;
|
||||
while ( p != endfn ) putc(*p, out), p++;
|
||||
/* Put out the declaration */
|
||||
for ( ap = breaks+1; ap < bp; ap += 2 )
|
||||
{ p = *ap;
|
||||
while ( isidchar(*p) ) putc(*p, out), p++;
|
||||
if ( ap < bp - 1 ) fputs(", ", out);
|
||||
}
|
||||
fputs(") ", out);
|
||||
/* Put out the argument declarations */
|
||||
for ( ap = breaks+2; ap <= bp; ap += 2 ) (*ap)[-1] = ';';
|
||||
fputs(breaks[0], out);
|
||||
free((char *)breaks);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,360 @@
|
|||
/* example.c - an example of using libpng */
|
||||
|
||||
/* this is an example of how to use libpng to read and write
|
||||
png files. The file libpng.txt is much more verbose then
|
||||
this. If you have not read it, do so first. This was
|
||||
designed to be a starting point of an implementation.
|
||||
This is not officially part of libpng, and therefore
|
||||
does not require a copyright notice.
|
||||
*/
|
||||
|
||||
#include <png.h>
|
||||
|
||||
/* check to see if a file is a png file using png_check_sig() */
|
||||
int check_png(char *file_name)
|
||||
{
|
||||
FILE *fp;
|
||||
char buf[8];
|
||||
int ret;
|
||||
|
||||
fp = fopen(file_name, "rb");
|
||||
if (!fp)
|
||||
return 0;
|
||||
ret = fread(buf, 1, 8, fp);
|
||||
fclose(fp);
|
||||
|
||||
if (ret != 8)
|
||||
return 0;
|
||||
|
||||
ret = png_check_sig(buf, 8);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* read a png file. You may want to return an error code if the read
|
||||
fails (depending upon the failure). */
|
||||
void read_png(char *file_name)
|
||||
{
|
||||
FILE *fp;
|
||||
png_struct *png_ptr;
|
||||
png_info *info_ptr;
|
||||
|
||||
/* open the file */
|
||||
fp = fopen(file_name, "rb");
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
/* allocate the necessary structures */
|
||||
png_ptr = malloc(sizeof (png_struct));
|
||||
if (!png_ptr)
|
||||
{
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
info_ptr = malloc(sizeof (png_info));
|
||||
if (!info_ptr)
|
||||
{
|
||||
fclose(fp);
|
||||
free(png_ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* set error handling */
|
||||
if (setjmp(png_ptr->jmpbuf))
|
||||
{
|
||||
png_read_destroy(png_ptr, info_ptr, (png_info *)0);
|
||||
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 */
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
/* read the file information */
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
/* allocate the memory to hold the image using the fields
|
||||
of png_info. */
|
||||
|
||||
/* 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 */
|
||||
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
|
||||
info_ptr->bit_depth < 8)
|
||||
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)
|
||||
png_set_expand(png_ptr);
|
||||
|
||||
/* expand images with transparency to full alpha channels */
|
||||
if (info_ptr->valid & PNG_INFO_tRNS)
|
||||
png_set_expand(png_ptr);
|
||||
|
||||
/* Set the background color to draw transparent and alpha
|
||||
images over */
|
||||
png_color_16 my_background;
|
||||
|
||||
if (info_ptr->valid & PNG_INFO_bKGD)
|
||||
png_set_background(png_ptr, &(info_ptr->background),
|
||||
PNG_GAMMA_FILE, 1, 1.0);
|
||||
else
|
||||
png_set_background(png_ptr, &my_background,
|
||||
PNG_GAMMA_SCREEN, 0, 1.0);
|
||||
|
||||
/* tell libpng to handle the gamma conversion for you */
|
||||
if (info_ptr->valid & PNG_INFO_gAMA)
|
||||
png_set_gamma(png_ptr, screen_gamma, info_ptr->gamma);
|
||||
else
|
||||
png_set_gamma(png_ptr, screen_gamma, 0.45);
|
||||
|
||||
/* tell libpng to strip 16 bit depth files down to 8 bits */
|
||||
if (info_ptr->bit_depth == 16)
|
||||
png_set_strip_16(png_ptr);
|
||||
|
||||
/* dither rgb files down to 8 bit palettes & 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);
|
||||
else
|
||||
{
|
||||
png_color std_color_cube[MAX_SCREEN_COLORS] =
|
||||
{/* ... colors ... */};
|
||||
|
||||
png_set_dither(png_ptr, std_color_cube, MAX_SCREEN_COLORS,
|
||||
MAX_SCREEN_COLORS, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* invert monocrome files */
|
||||
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 */
|
||||
if (info_ptr->valid & PNG_INFO_sBIT &&
|
||||
info_ptr->bit_depth > info_ptr->sig_bit)
|
||||
png_set_shift(png_ptr, &(info_ptr->sig_bit));
|
||||
|
||||
/* pack pixels into bytes */
|
||||
if (info_ptr->bit_depth < 8)
|
||||
png_set_packing(png_ptr);
|
||||
|
||||
/* flip the rgb pixels to bgr */
|
||||
if (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
|
||||
info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
png_set_bgr(png_ptr);
|
||||
|
||||
/* swap bytes of 16 bit files to least significant bit first */
|
||||
if (info_ptr->bit_depth == 16)
|
||||
png_set_swap(png_ptr);
|
||||
|
||||
/* add a filler byte to store rgb files as rgbx */
|
||||
if (info_ptr->bit_depth == 8 &&
|
||||
info_ptr->color_type == PNG_COLOR_TYPE_RGB)
|
||||
png_set_rgbx(png_ptr);
|
||||
|
||||
/* optional call to update palette with transformations */
|
||||
png_start_read_image(png_ptr);
|
||||
|
||||
/* the easiest way to read the image */
|
||||
void *row_pointers[height];
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
|
||||
/* the other way to read images - deal with interlacing */
|
||||
|
||||
/* turn on interlace handling */
|
||||
if (info_ptr->interlace_type)
|
||||
number_passes = png_set_interlace_handling(png_ptr);
|
||||
else
|
||||
number_passes = 1;
|
||||
|
||||
for (pass = 0; pass < number_passes; pass++)
|
||||
{
|
||||
/* Read the image using the "sparkle" effect. */
|
||||
png_read_rows(png_ptr, row_pointers, NULL, number_of_rows);
|
||||
|
||||
/* If you are only reading on row at a time, this works */
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
char *row_pointers = row[y];
|
||||
png_read_rows(png_ptr, &row_pointers, NULL, 1);
|
||||
}
|
||||
|
||||
/* to get the rectangle effect, use the third parameter */
|
||||
png_read_rows(png_ptr, NULL, row_pointers, number_of_rows);
|
||||
|
||||
/* if you want to display the image after every pass, do
|
||||
so here */
|
||||
}
|
||||
|
||||
/* 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_info *)0);
|
||||
|
||||
/* free the structures */
|
||||
free(png_ptr);
|
||||
free(info_ptr);
|
||||
|
||||
/* close the file */
|
||||
fclose(fp);
|
||||
|
||||
/* that's it */
|
||||
return;
|
||||
}
|
||||
|
||||
/* write a png file */
|
||||
void write_png(char *file_name, ... other image information ...)
|
||||
{
|
||||
FILE *fp;
|
||||
png_struct *png_ptr;
|
||||
png_info *info_ptr;
|
||||
|
||||
/* open the file */
|
||||
fp = fopen(file_name, "wb");
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
/* allocate the necessary structures */
|
||||
png_ptr = malloc(sizeof (png_struct));
|
||||
if (!png_ptr)
|
||||
{
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
info_ptr = malloc(sizeof (png_info));
|
||||
if (!info_ptr)
|
||||
{
|
||||
fclose(fp);
|
||||
free(png_ptr);
|
||||
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 */
|
||||
return;
|
||||
}
|
||||
|
||||
/* initialize the structures */
|
||||
png_info_init(info_ptr);
|
||||
png_write_init(png_ptr);
|
||||
|
||||
/* set up the output control */
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
/* set the file information here */
|
||||
info_ptr->width = ;
|
||||
info_ptr->height = ;
|
||||
etc.
|
||||
|
||||
/* set the palette if there is one */
|
||||
info_ptr->valid |= PNG_INFO_PLTE;
|
||||
info_ptr->palette = malloc(256 * sizeof (png_color));
|
||||
info_ptr->num_palette = 256;
|
||||
... set palette colors ...
|
||||
|
||||
/* optional significant bit chunk */
|
||||
info_ptr->valid |= PNG_INFO_sBIT;
|
||||
info_ptr->sig_bit = true_bit_depth;
|
||||
|
||||
/* optional gamma chunk */
|
||||
info_ptr->valid |= PNG_INFO_gAMA;
|
||||
info_ptr->gamma = gamma;
|
||||
|
||||
/* other optional chunks */
|
||||
|
||||
/* write the file information */
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
|
||||
/* set up the transformations you want. Note that these are
|
||||
all optional. Only call them if you want them */
|
||||
|
||||
/* invert monocrome pixels */
|
||||
png_set_invert(png_ptr);
|
||||
|
||||
/* shift the pixels up to a legal bit depth and fill in
|
||||
as appropriate to correctly scale the image */
|
||||
png_set_shift(png_ptr, &(info_ptr->sig_bit));
|
||||
|
||||
/* pack pixels into bytes */
|
||||
png_set_packing(png_ptr);
|
||||
|
||||
/* flip bgr pixels to rgb */
|
||||
png_set_bgr(png_ptr);
|
||||
|
||||
/* swap bytes of 16 bit files to most significant bit first */
|
||||
png_set_swap(png_ptr);
|
||||
|
||||
/* get rid of filler bytes, pack rgb into 3 bytes */
|
||||
png_set_rgbx(png_ptr);
|
||||
|
||||
/* the easiest way to write the image */
|
||||
void *row_pointers[height];
|
||||
png_write_image(png_ptr, row_pointers);
|
||||
|
||||
/* the other way to write the image - deal with interlacing */
|
||||
|
||||
/* turn on interlace handling */
|
||||
if (interlacing)
|
||||
number_passes = png_set_interlace_handling(png_ptr);
|
||||
else
|
||||
number_passes = 1;
|
||||
|
||||
for (pass = 0; pass < number_passes; pass++)
|
||||
{
|
||||
/* Write a few rows at a time. */
|
||||
png_write_rows(png_ptr, row_pointers, number_of_rows);
|
||||
|
||||
/* If you are only writing one row at a time, this works */
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
char *row_pointers = row[y];
|
||||
png_write_rows(png_ptr, &row_pointers, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
/* close the file */
|
||||
fclose(fp);
|
||||
|
||||
/* that's it */
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,821 @@
|
|||
libpng.txt - a description on how to use and modify libpng
|
||||
|
||||
libpng 1.0 beta 1 - version 0.71
|
||||
For conditions of distribution and use, see copyright notice in png.h
|
||||
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
|
||||
June 26, 1995
|
||||
|
||||
This file describes how to use and modify the PNG reference library
|
||||
(known as libpng) for your own use. There are four sections to this
|
||||
file: reading, writing, modifying, and configuration notes for various
|
||||
special platforms. Other then this file, the file example.c is a good
|
||||
starting point for using the library, as it is heavily commented and
|
||||
should include everything most people will need.
|
||||
|
||||
Libpng was written as a companion to the PNG specification, as a
|
||||
way to reduce the amount of time and effort it takes to support
|
||||
the PNG file format in application programs. Most users will not
|
||||
have to modify the library significantly; advanced users may want
|
||||
to modify it more. The library was coded for both users. All
|
||||
attempts were made to make it as complete as possible, while
|
||||
keeping the code easy to understand. Currently, this library
|
||||
only supports C. Support for other languages is being considered.
|
||||
|
||||
Libpng has been designed to handle multiple sessions at one time,
|
||||
to be easily modifiable, to be portable to the vast majority of
|
||||
machines (ANSI, K&R, 16 bit, 32 bit) available, and to be easy to
|
||||
use. The ultimate goal of libpng is to promote the acceptance of
|
||||
the PNG file format in whatever way possible. While there is still
|
||||
work to be done (see the todo.txt file), libpng should cover the
|
||||
majority of the needs of it's users.
|
||||
|
||||
Libpng uses zlib for its compression and decompression of PNG files.
|
||||
The zlib compression utility is a general purpose utility that is
|
||||
useful for more then PNG files, and can be used without libpng for
|
||||
whatever use you want. See the documentation delivered with zlib for
|
||||
more details.
|
||||
|
||||
Those people who do not need to modify libpng should still read at
|
||||
least part of the PNG specification. The most important parts are
|
||||
the data formats and the chunk descriptions. Those who will be
|
||||
making changes to libpng should read the whole specification.
|
||||
|
||||
The structures:
|
||||
|
||||
There are two main structures that are important to libpng, png_struct
|
||||
and png_info. The first, png_struct, is an internal structure that
|
||||
will not, for the most part, be used by the general user except as
|
||||
the first variable passed to every png function call.
|
||||
|
||||
The png_info structure is designed to provide information about the
|
||||
png file. All of it's fields are intended to be examined or modified
|
||||
by the user. See png.h for a good description of the png_info fields.
|
||||
|
||||
And while I'm on the topic, make sure you include the png header file:
|
||||
|
||||
#include <png.h>
|
||||
|
||||
Checking PNG files:
|
||||
|
||||
Libpng provides a simple check to see if a file is a png file. To
|
||||
use it, pass in the first 1 to 8 bytes of the file, and it will return
|
||||
true or false (1 or 0) depending on whether the bytes could be part
|
||||
of a png file. Of course, the more bytes you pass in, the greater
|
||||
the accuracy of the prediction.
|
||||
|
||||
fread(header, 1, number, fp);
|
||||
is_png = png_check_sig(header, number);
|
||||
|
||||
Reading PNG files:
|
||||
|
||||
The first thing you need to do while reading a PNG file is to allocate
|
||||
and initialize png_struct and png_info. As these are both large, you
|
||||
may not want to store these on the stack, unless you have stack space
|
||||
to spare. Of course, you will want to check if malloc returns NULL.
|
||||
|
||||
png_struct *png_ptr = malloc(sizeof (png_struct));
|
||||
if (!png_ptr)
|
||||
return;
|
||||
png_info *info_ptr = malloc(sizeof (png_info));
|
||||
if (!info_ptr)
|
||||
{
|
||||
free(png_ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
You may also want to do any i/o initialization here, before
|
||||
you get into libpng, so if it doesn't work, you don't have
|
||||
much to undo.
|
||||
|
||||
FILE *fp = fopen(file_name, "rb");
|
||||
if (!fp)
|
||||
{
|
||||
free(png_ptr);
|
||||
free(info_ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
After you have these structures, you will need to set up the
|
||||
error handling. When libpng encounters an error, it expects to
|
||||
longjmp back to your routine. Therefore, you will need to call
|
||||
setjmp and pass the jmpbuf field of your png_struct. If you
|
||||
read the file from different routines, you will need to update
|
||||
the jmpbuf field every time you enter a new routine that will
|
||||
call a png_ function. See your documentation of setjmp/longjmp
|
||||
for your compiler for more information on setjmp/longjmp. See
|
||||
the discussion on png error handling in the Customizing Libpng
|
||||
section below for more information on the png error handling.
|
||||
If an error occurs, and libpng longjmp's back to your setjmp,
|
||||
you will want to call png_read_destroy() to free any memory.
|
||||
|
||||
if (setjmp(png_ptr->jmpbuf))
|
||||
{
|
||||
png_read_destroy(png_ptr, info_ptr, (png_info *)0);
|
||||
/* free pointers before returning, if necessary */
|
||||
free(png_ptr);
|
||||
free(info_ptr);
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
Next, you will need to call png_read_init() and png_info_init().
|
||||
These functions make sure all the fields are initialized to useful
|
||||
values, and, in the case of png_read_init(), and allocate any memory
|
||||
needed for internal uses. You must call png_info_init() first, as
|
||||
png_read_init() could do a longjmp, and if the info is not initialized,
|
||||
the png_read_destroy() could try to png_free() random addresses, which
|
||||
would be bad.
|
||||
|
||||
png_info_init(info_ptr);
|
||||
png_read_init(png_ptr);
|
||||
|
||||
Now you need to set up the input code. The default for libpng is
|
||||
to use the C function fread(). If you use this, you will need to
|
||||
pass a valid FILE * in the function png_init_io(). Be sure that
|
||||
the file is opened in binary mode. If you wish to handle reading
|
||||
data in another way, see the discussion on png i/o handling in the
|
||||
Customizing Libpng section below.
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
You are now ready to read all the file information up to the actual
|
||||
image data. You do this with a call to png_read_info().
|
||||
|
||||
png_read_info(png_ptr, info_ptr);
|
||||
|
||||
The png_info structure is now filled in with all the data necessary
|
||||
to read the file. Some of the more important parts of the png_info are:
|
||||
width - holds the width of the file
|
||||
height - holds the height of the file
|
||||
bit_depth - holds the bit depth of one of the image channels
|
||||
color_type - describes the channels and what they mean
|
||||
see the PNG_COLOR_TYPE_ macros for more information
|
||||
channels - number of channels of info for the color type
|
||||
pixel_depth - bits per pixel
|
||||
rowbytes - number of bytes needed to hold a row
|
||||
interlace_type - currently 0 for none, 1 for interlaced
|
||||
valid - this details which optional chunks were found in the file
|
||||
to see if a chunk was present, OR valid with the appropriate
|
||||
PNG_INFO_<chunk name> define.
|
||||
palette and num_palette - the palette for the file
|
||||
gamma - the gamma the file is written at
|
||||
sig_bit and sig_bit_number - the number of significant bits
|
||||
trans, trans_values, and number_trans - transparency info
|
||||
hist - histogram of palette
|
||||
text and num_text - text comments in the file.
|
||||
for more information, see the png_info definition in png.h and the
|
||||
PNG specification for chunk contents. Be careful with trusting
|
||||
rowbytes, as some of the transformations could increase the space
|
||||
needed to hold a row (expand, rgbx, xrgb, graph_to_rgb, etc.).
|
||||
|
||||
A quick word about text and num_text. PNG stores comments in
|
||||
keyword/text pairs, one pair per chunk. While there are
|
||||
suggested keywords, there is no requirement to restrict the use
|
||||
to these strings. There is a requirement to have at least one
|
||||
character for a keyword. It is strongly suggested that keywords
|
||||
be sensible to humans (that's the point), so don't use abbreviations.
|
||||
See the png specification for more details. There is no requirement
|
||||
to have text after the keyword on tEXt chunks. However, you must
|
||||
have text after the keyword on zTXt chunks, as only the text gets
|
||||
compressed, and compressing nothing will result in an error.
|
||||
|
||||
There is no maximum length on the keyword, and nothing
|
||||
prevents you from duplicating the keyword. The text field is an
|
||||
array of png_text structures, each holding pointer to a keyword
|
||||
and a pointer to a text string. Only the text string may be null.
|
||||
The keyword/text pairs are put into the array in the order that
|
||||
they are received. However, some or all of the text chunks may be
|
||||
after the image, so to make sure you have read all the text chunks,
|
||||
don't mess with these until after you read the stuff after the image.
|
||||
This will be mentioned again below in the discussion that goes with
|
||||
png_read_end().
|
||||
|
||||
After you've read the file information, you can set up the library to
|
||||
handle any special transformations of the image data. The various
|
||||
ways to transform the data will be described in the order that they
|
||||
occur. This is important, as some of these change the color type
|
||||
and bit depth of the data, and some others only work on certain
|
||||
color types and bit depths. Even though each transformation should
|
||||
check to see if it has data that it can do somthing with, you should
|
||||
make sure to only enable a transformation if it will be valid for
|
||||
the data. For example, don't swap red and blue on grayscale data.
|
||||
|
||||
This transforms bit depths of less then 8 to 8 bits, changes paletted
|
||||
images to rgb, and adds an alpha channel if there is transparency
|
||||
information in a tRNS chunk. This is probably most useful on grayscale
|
||||
images with bit depths of 2 or 4 and tRNS chunks.
|
||||
|
||||
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
|
||||
info_ptr->bit_depth < 8)
|
||||
png_set_expand(png_ptr);
|
||||
|
||||
if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
|
||||
info_ptr->bit_depth < 8)
|
||||
png_set_expand(png_ptr);
|
||||
|
||||
if (info_ptr->valid & PNG_INFO_tRNS)
|
||||
png_set_expand(png_ptr);
|
||||
|
||||
This handles alpha and transparency by replacing it with a background
|
||||
value. If there was a valid one in the file, you can use it if you
|
||||
want. However, you can replace it with your own if you want also. If
|
||||
there wasn't one in the file, you must supply a color. If libpng is
|
||||
doing gamma correction, you will need to tell libpng where the
|
||||
background came from so it can do the appropriate gamma correction.
|
||||
If you are modifying the color data with png_set_expand(), you must
|
||||
indicate whether the background needs to be expanded. See the
|
||||
function definition in png.h for more details.
|
||||
|
||||
png_color_16 my_background;
|
||||
|
||||
if (info_ptr->valid & PNG_INFO_bKGD)
|
||||
png_set_backgrond(png_ptr, &(info_ptr->background),
|
||||
PNG_GAMMA_FILE, 1, 1.0);
|
||||
else
|
||||
png_set_background(png_ptr, &my_background,
|
||||
PNG_GAMMA_SCREEN, 0, 1.0);
|
||||
|
||||
This handles gamma transformations of the data. Pass both the file
|
||||
gamma and the desired screen gamma. If the file does not have a
|
||||
gamma value, you can pass one anyway if you wish. Note that file
|
||||
gammas are inverted from screen gammas. See the discussions on
|
||||
gamma in the PNG specification for more information.
|
||||
|
||||
if (info_ptr->valid & PNG_INFO_gAMA)
|
||||
png_set_gamma(png_ptr, screen_gamma, info_ptr->gamma);
|
||||
else
|
||||
png_set_gamma(png_ptr, screen_gamma, 0.45);
|
||||
|
||||
PNG can have files with 16 bits per channel. If you only can handle
|
||||
8 bits per channel, this will strip the pixels down to 8 bit.
|
||||
|
||||
if (info_ptr->bit_depth == 16)
|
||||
png_set_strip_16(png_ptr);
|
||||
|
||||
If you need to reduce an rgb file to a paletted file, or if a
|
||||
paletted file has more entries then will fit on your screen, this
|
||||
function will do that. Note that this is a simple match dither, that
|
||||
merely finds the closest color available. This should work fairly
|
||||
well with optimized palettes, and fairly badly with linear color
|
||||
cubes. If you pass a palette that is larger then maximum_colors,
|
||||
the file will reduce the number of colors in the palette so it
|
||||
will fit into maximum_colors. If there is an histogram, it will
|
||||
use it to make intelligent choises when reducing the palette. If
|
||||
there is no histogram, it may not do a good job.
|
||||
|
||||
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);
|
||||
else
|
||||
{
|
||||
png_color std_color_cube[MAX_SCREEN_COLORS] =
|
||||
{ ... colors ... };
|
||||
|
||||
png_set_dither(png_ptr, std_color_cube, MAX_SCREEN_COLORS,
|
||||
MAX_SCREEN_COLORS, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
PNG files describe monocrome as black is zero and white is one. If you
|
||||
want this reversed (black is one and white is zero), call this:
|
||||
|
||||
if (info_ptr->bit_depth == 1 &&
|
||||
info_ptr->color_type == PNG_COLOR_GRAY)
|
||||
png_set_invert(png_ptr);
|
||||
|
||||
PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. However,
|
||||
they also provide a way to describe the true bit depth of the image.
|
||||
Then they require bits to be scaled to full range for the bit depth
|
||||
used in the file. If you want to reduce your pixels back down to
|
||||
the true bit depth, call this:
|
||||
|
||||
if (info_ptr->valid & PNG_INFO_sBIT)
|
||||
png_set_shift(png_ptr, &(info_ptr->sig_bit));
|
||||
|
||||
PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as
|
||||
they can, resulting in, for example, 8 pixels per byte for 1 bit files.
|
||||
If you would rather these were expanded to 1 pixel per byte without
|
||||
changing the values of the pixels, call this:
|
||||
|
||||
if (info_ptr->bit_depth < 8)
|
||||
png_set_packing(png_ptr);
|
||||
|
||||
PNG files store 3 color pixels in red, green, blue order. If you would
|
||||
rather have the pixels as blue, green, red, call this.
|
||||
|
||||
if (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
|
||||
info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
|
||||
png_set_bgr(png_ptr);
|
||||
|
||||
For some uses, you may want a grayscale image to be represented as
|
||||
rgb. If you need this, call this:
|
||||
|
||||
if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY ||
|
||||
info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
png_set_gray_to_rgb(png_ptr);
|
||||
|
||||
PNG files store 16 bit pixels in network byte order (most significant
|
||||
bit first). If you would rather store them the other way, (the way
|
||||
PC's store them, for example), call this:
|
||||
|
||||
if (info_ptr->bit_depth == 16)
|
||||
png_set_swap(png_ptr);
|
||||
|
||||
PNG files store rgb pixels packed into 3 bytes. If you would rather
|
||||
pack them into 4 bytes, with the filler byte last, call this:
|
||||
|
||||
if (info_ptr->bit_depth == 8 &&
|
||||
info_ptr->color_type == PNG_COLOR_TYPE_RGB)
|
||||
png_set_rgbx(png_ptr);
|
||||
|
||||
If you need the filler byte first, call this:
|
||||
|
||||
if (info_ptr->bit_depth == 8 &&
|
||||
info_ptr->color_type == PNG_COLOR_TYPE_RGB)
|
||||
png_set_xrgb(png_ptr);
|
||||
|
||||
After setting the transformations, you can update your palette by
|
||||
calling png_start_read_image(). This function is provided for those
|
||||
who need an updated palette before they read the image data. If you
|
||||
don't call this function, the library will automatically call it
|
||||
before it reads the first row.
|
||||
|
||||
png_start_read_image(png_ptr);
|
||||
|
||||
That's it for the transformations. Now you can read the image data.
|
||||
The simplest way to do this is in one function call. If you are
|
||||
allocating enough memory to hold the whole image, you can just
|
||||
call png_read_image() and libpng will read in all the image data
|
||||
and put it in the memory area supplied. You will need to pass in
|
||||
an array of pointers to each row.
|
||||
|
||||
This function automatically handles interlacing, so you don't need
|
||||
to call png_set_interlace_handling() or call this function multiple
|
||||
times, or any of that other stuff necessary with png_read_rows().
|
||||
|
||||
png_read_image(png_ptr, row_pointers);
|
||||
|
||||
where row_pointers is:
|
||||
|
||||
void *row_pointers[height];
|
||||
|
||||
You can point to void or char or whatever you use for pixels.
|
||||
|
||||
If you don't want to read the whole image in at once, you can
|
||||
use png_read_rows() instead. If there is no interlacing (check
|
||||
info_ptr->interlace_type), this is simple:
|
||||
|
||||
png_read_rows(png_ptr, row_pointers, NULL, number_of_rows);
|
||||
|
||||
row_pointers is the same as in the png_read_image() call.
|
||||
|
||||
If you are just calling one row at a time, you can do this for
|
||||
row_pointers:
|
||||
|
||||
char *row_pointers = row;
|
||||
|
||||
png_read_rows(png_ptr, &row_pointers, NULL, 1);
|
||||
|
||||
When the file is interlaced (info_ptr->interlace_type == 1), things
|
||||
get a good deal harder. PNG files have a complicated interlace scheme
|
||||
that breaks down an image into seven smaller images of varying size.
|
||||
Libpng will fill out those images if you want, or it will give them
|
||||
to you "as is". If you want to fill them out, there is two ways
|
||||
to do that. The one mentioned in the PNG specification is to expand
|
||||
each pixel to cover those pixels that have not been read yet. This
|
||||
results in a blocky image for the first pass, which gradually smooths
|
||||
out as more pixels are read. The other method is the "sparkle" method,
|
||||
where pixels are draw only in their final locations, with the rest of
|
||||
the image remaining whatever colors they were initialized to before
|
||||
the start of the read. The first method usually looks better, but
|
||||
tends to be slower, as there are more pixels to put in the rows. Some
|
||||
examples to help clear this up:
|
||||
|
||||
If you don't want libpng to handle the interlacing details, just
|
||||
call png_read_rows() the correct number of times to read in all
|
||||
seven images. See the PNG specification for more details on the
|
||||
interlacing scheme.
|
||||
|
||||
If you want libpng to expand the images, call this:
|
||||
|
||||
if (info_ptr->interlace_type)
|
||||
number_passes = png_set_interlace_handling(png_ptr);
|
||||
|
||||
This will return the number of passes needed. Currently, this
|
||||
is seven, but may change if another interlace type is added.
|
||||
This function can be called even if the file is not interlaced,
|
||||
when it will return one.
|
||||
|
||||
If you are not going to display the image after each pass, but are
|
||||
going to wait until the entire image is read in, use the sparkle
|
||||
effect. This effect is faster and the end result of either method
|
||||
is exactly the same. If you are planning on displaying the image
|
||||
after each pass, the rectangle effect is generally considered the
|
||||
better looking one.
|
||||
|
||||
If you only want the "sparkle" effect, just call png_read_rows() as
|
||||
normal, with the third parameter NULL. Make sure you make pass over
|
||||
the image number_passes times, and you don't change the data in the
|
||||
rows between calls. You can change the locations of the data, just
|
||||
not the data. Each pass only writes the pixels appropriate for that
|
||||
pass, and assumes the data from previous passes is still valid.
|
||||
|
||||
png_read_rows(png_ptr, row_pointers, NULL, number_of_rows);
|
||||
|
||||
If you only want the first effect (the rectangles), do the same as
|
||||
before except pass the row buffer in the third parameter, and leave
|
||||
the second parameter NULL.
|
||||
|
||||
png_read_rows(png_ptr, NULL, row_pointers, number_of_rows);
|
||||
|
||||
After you are finished reading the image, you can finish reading
|
||||
the file. If you are interested in comments or time, you should
|
||||
pass the png_info pointer from the png_read_info() call. If you
|
||||
are not interested, you can pass NULL.
|
||||
|
||||
png_read_end(png_ptr, info_ptr);
|
||||
|
||||
When you are done, you can free all memory used by libpng like this:
|
||||
|
||||
png_read_destroy(png_ptr, info_ptr, (png_info *)0);
|
||||
|
||||
After that, you can discard the structures, or reuse them another
|
||||
read or write. For a more compact example of reading a PNG image,
|
||||
see the file example.c.
|
||||
|
||||
|
||||
Writing PNG files:
|
||||
|
||||
Much of this is very similar to reading. However, everything of
|
||||
importance is repeated here, so you don't have to constantly look
|
||||
back up in the Reading PNG files section to understand writing.
|
||||
|
||||
The first thing you need to do while writing a PNG file is to allocate
|
||||
and initialize png_struct and png_info. As these are both large, you
|
||||
may not want to store these on the stack, unless you have stack space
|
||||
to spare.
|
||||
|
||||
png_struct *png_ptr = malloc(sizeof (png_struct));
|
||||
if (!png_ptr)
|
||||
return;
|
||||
png_info *info_ptr = malloc(sizeof (png_info));
|
||||
if (!info_ptr)
|
||||
{
|
||||
free(png_ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
You may also want to do any i/o initialization here, before
|
||||
you get into libpng, so if it doesn't work, you don't have
|
||||
much to undo.
|
||||
|
||||
FILE *fp = fopen(file_name, "wb");
|
||||
if (!fp)
|
||||
{
|
||||
free(png_ptr);
|
||||
free(info_ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
After you have these structures, you will need to set up the
|
||||
error handling. When libpng encounters an error, it expects to
|
||||
longjmp back to your routine. Therefore, you will need to call
|
||||
setjmp and pass the jmpbuf field of your png_struct. If you
|
||||
write the file from different routines, you will need to update
|
||||
the jmpbuf field every time you enter a new routine that will
|
||||
call a png_ function. See your documentation of setjmp/longjmp
|
||||
for your compiler for more information on setjmp/longjmp. See
|
||||
the discussion on png error handling in the Customizing Libpng
|
||||
section below for more information on the png error handling.
|
||||
|
||||
if (setjmp(png_ptr->jmpbuf))
|
||||
{
|
||||
png_write_destroy(png_ptr);
|
||||
/* free pointers before returning. Make sure you clean up
|
||||
anything else you've done. */
|
||||
free(png_ptr);
|
||||
free(info_ptr);
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
|
||||
Next, you will need to call png_write_init() and png_info_init().
|
||||
These functions make sure all the fields are initialized to useful
|
||||
values, and, in the case of png_write_init(), allocate any memory
|
||||
needed for internal uses. Do png_info_init() first, so if
|
||||
png_write_init() longjmps, you know info_ptr is valid, so you
|
||||
don't free random memory pointers, which would be bad.
|
||||
|
||||
png_info_init(info_ptr);
|
||||
png_write_init(png_ptr);
|
||||
|
||||
Now you need to set up the input code. The default for libpng is
|
||||
to use the C function fwrite(). If you use this, you will need to
|
||||
pass a valid FILE * in the function png_init_io(). Be sure that
|
||||
the file is opened in binary mode. If you wish to handle writing
|
||||
data in another way, see the discussion on png i/o handling in the
|
||||
Customizing Libpng section below.
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
You now need to fill in the png_info structure with all the data
|
||||
you wish to write before the actual image. Note that the only thing
|
||||
you are allowed to write after the image is the text chunks and the
|
||||
time chunk. See png_write_end() for more information on that. If you
|
||||
wish to write them before the image, fill them in now. If you want to
|
||||
wait until after the data, don't fill them until png_write_end(). For
|
||||
all the fields in png_info, see png.h. For explinations of what the
|
||||
fields contain, see the PNG specification. Some of the more important
|
||||
parts of the png_info are:
|
||||
width - holds the width of the file
|
||||
height - holds the height of the file
|
||||
bit_depth - holds the bit depth of one of the image channels
|
||||
color_type - describes the channels and what they mean
|
||||
see the PNG_COLOR_TYPE_ defines for more information
|
||||
interlace_type - currently 0 for none, 1 for interlaced
|
||||
valid - this describes which optional chunks to write to the
|
||||
file. Note that if you are writing a PNG_COLOR_TYPE_PALETTE
|
||||
file, the PLTE chunk is not optional, but must still be marked
|
||||
for writing. To mark chunks for writing, OR valid with the
|
||||
appropriate PNG_INFO_<chunk name> define.
|
||||
palette and num_palette - the palette for the file
|
||||
gamma - the gamma the file is written at
|
||||
sig_bit and sig_bit_number - the number of significant bits
|
||||
trans, trans_values, and number_trans - transparency info
|
||||
hist - histogram of palette
|
||||
text and num_text - text comments in the file.
|
||||
|
||||
A quick word about text and num_text. text is an array of png_text
|
||||
structures. num_text is the number of valid structures in the array.
|
||||
If you want, you can use max_text to hold the size of the array, but
|
||||
libpng ignores it for writing (it does use it for reading). Each
|
||||
png_text structure holds a keyword-text value, and a compression type.
|
||||
The compression types have the same valid numbers as the compression
|
||||
types of the image data. Currently, the only valid number is zero.
|
||||
However, you can store text either compressed or uncompressed, unlike
|
||||
images which always have to be compressed. So if you don't want the
|
||||
text compressed, set the compression type to -1. Until text gets
|
||||
arount 1000 bytes, it is not worth compressing it.
|
||||
|
||||
The keyword-text pairs work like this. Keywords should be short
|
||||
simple descriptions of what the comment is about. Some typical
|
||||
keywords are found in the PNG specification, as is some recomendations
|
||||
on keywords. You can repeat keywords in a file. You can even write
|
||||
some text before the image and some after. For example, you may want
|
||||
to put a description of the image before the image, but leave the
|
||||
disclaimer until after, so viewers working over modem connections
|
||||
don't have to wait for the disclaimer to go over the modem before
|
||||
they start seeing the image. Finally, keywords should be full
|
||||
words, not abbreviations. Keywords can not contain NUL characters,
|
||||
and should not contain control characters. Text in general should
|
||||
not contain control characters. The keyword must be present, but
|
||||
you can leave off the text string on non-compressed pairs.
|
||||
Compressed pairs must have a text string, as only the text string
|
||||
is compressed anyway, so the compression would be meaningless.
|
||||
|
||||
PNG supports modification time via the png_time structure. Two
|
||||
conversion routines are proved, png_convert_from_time_t() for
|
||||
time_t and png_convert_from_struct_tm() for struct tm. The
|
||||
time_t routine uses gmtime(). You don't have to use either of
|
||||
these, but if you wish to fill in the png_time structure directly,
|
||||
you should provide the time in universal time (GMT) if possible
|
||||
instead of your local time.
|
||||
|
||||
You are now ready to write all the file information up to the actual
|
||||
image data. You do this with a call to png_write_info().
|
||||
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
|
||||
After you've read the file information, you can set up the library to
|
||||
handle any special transformations of the image data. The various
|
||||
ways to transform the data will be described in the order that they
|
||||
occur. This is important, as some of these change the color type
|
||||
and bit depth of the data, and some others only work on certain
|
||||
color types and bit depths. Even though each transformation should
|
||||
check to see if it has data that it can do somthing with, you should
|
||||
make sure to only enable a transformation if it will be valid for
|
||||
the data. For example, don't swap red and blue on grayscale data.
|
||||
|
||||
PNG files store rgb pixels packed into 3 bytes. If you would rather
|
||||
supply the pixels as 4 bytes per pixel, with the filler byte last,
|
||||
call this:
|
||||
|
||||
png_set_rgbx(png_ptr);
|
||||
|
||||
If your filler byte goes first, call this:
|
||||
|
||||
png_set_xrgb(png_ptr);
|
||||
|
||||
PNG files pack pixels of bit depths 1, 2, and 4 into bytes as small as
|
||||
they can, resulting in, for example, 8 pixels per byte for 1 bit files.
|
||||
If you would rather supply the data 1 pixel per byte, but with the
|
||||
values limited to the correct number of bits, call this:
|
||||
|
||||
png_set_packing(png_ptr);
|
||||
|
||||
PNG files reduce possible bit depths to 1, 2, 4, 8, and 16. If your
|
||||
data is of another bit depth, but is packed into the bytes correctly,
|
||||
this will scale the values to appear to be the correct bit depth.
|
||||
Make sure you write a sBIT chunk when you do this, so others, if
|
||||
they want, can reduce the values down to their true depth.
|
||||
|
||||
/* do this before png_write_info() */
|
||||
info_ptr->valid |= PNG_INFO_sBIT;
|
||||
|
||||
/* note that you can cheat and set all the values of
|
||||
sig_bit to true_bit_depth if you want */
|
||||
if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
|
||||
{
|
||||
info_ptr->sig_bit.red = true_bit_depth;
|
||||
info_ptr->sig_bit.green = true_bit_depth;
|
||||
info_ptr->sig_bit.blue = true_bit_depth;
|
||||
}
|
||||
else
|
||||
{
|
||||
info_ptr->sig_bit.gray = true_bit_depth;
|
||||
}
|
||||
|
||||
if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
|
||||
{
|
||||
info_ptr->sig_bit.alpha = true_bit_depth;
|
||||
}
|
||||
|
||||
png_set_shift(png_ptr, &(info_ptr->sig_bit));
|
||||
|
||||
PNG files store 16 bit pixels in network byte order (most significant
|
||||
bit first). If you would rather supply them the other way, (the way
|
||||
PC's store them, for example), call this:
|
||||
|
||||
png_set_swap(png_ptr);
|
||||
|
||||
PNG files store 3 color pixels in red, green, blue order. If you would
|
||||
rather supply the pixels as blue, green, red, call this.
|
||||
|
||||
png_set_bgr(png_ptr);
|
||||
|
||||
PNG files describe moncrome as black is zero and white is one. If you
|
||||
would rather supply the pixels with this reversed (black is one and
|
||||
white is zero), call this:
|
||||
|
||||
png_set_invert(png_ptr);
|
||||
|
||||
That's it for the transformations. Now you can write the image data.
|
||||
The simplest way to do this is in one function call. If have the
|
||||
whole image in memory, you can just call png_write_image() and libpng
|
||||
will write the image. You will need to pass in an array of pointers to
|
||||
each row. This function automatically handles interlacing, so you don't
|
||||
need to call png_set_interlace_handling() or call this function multiple
|
||||
times, or any of that other stuff necessary with png_write_rows().
|
||||
|
||||
png_write_image(png_ptr, row_pointers);
|
||||
|
||||
where row_pointers is:
|
||||
|
||||
void *row_pointers[height];
|
||||
|
||||
You can point to void or char or whatever you use for pixels.
|
||||
|
||||
If you can't want to write the whole image at once, you can
|
||||
use png_write_rows() instead. If the file is not interlaced,
|
||||
this is simple:
|
||||
|
||||
png_write_rows(png_ptr, row_pointers, number_of_rows);
|
||||
|
||||
row_pointers is the same as in the png_write_image() call.
|
||||
|
||||
If you are just calling one row at a time, you can do this for
|
||||
row_pointers:
|
||||
|
||||
char *row_pointers = row;
|
||||
|
||||
png_write_rows(png_ptr, &row_pointers, 1);
|
||||
|
||||
When the file is interlaced, things can get a good deal harder.
|
||||
PNG files have a complicated interlace scheme that breaks down an
|
||||
image into seven smaller images of varying size. Libpng will
|
||||
build these images if you want, or you can do them yourself. If
|
||||
you want to build them yourself, see the PNG specification for
|
||||
details of which pixels to write when.
|
||||
|
||||
If you don't want libpng to handle the interlacing details, just
|
||||
call png_write_rows() the correct number of times to write all
|
||||
seven sub-images.
|
||||
|
||||
If you want libpng to build the sub-images, call this:
|
||||
|
||||
number_passes = png_set_interlace_handling(png_ptr);
|
||||
|
||||
This will return the number of passes needed. Currently, this
|
||||
is seven, but may change if another interlace type is added.
|
||||
|
||||
Then write the image number_passes times.
|
||||
|
||||
png_write_rows(png_ptr, row_pointers, number_of_rows);
|
||||
|
||||
As some of these rows are not used, and thus return immediately,
|
||||
you may want to read about interlacing in the PNG specification,
|
||||
and only update the rows that are actually used.
|
||||
|
||||
After you are finished writing the image, you should finish writing
|
||||
the file. If you are interested in writing comments or time, you should
|
||||
pass the an appropriately filled png_info pointer. If you
|
||||
are not interested, you can pass NULL. Be careful that you don't
|
||||
write the same text or time chunks here as you did in png_write_info().
|
||||
|
||||
png_write_end(png_ptr, info_ptr);
|
||||
|
||||
When you are done, you can free all memory used by libpng like this:
|
||||
|
||||
png_write_destroy(png_ptr);
|
||||
|
||||
Any data you allocated for png_info, you must free yourself.
|
||||
|
||||
After that, you can discard the structures, or reuse them another
|
||||
read or write. For a more compact example of writing a PNG image,
|
||||
see the file example.c.
|
||||
|
||||
|
||||
Customizing libpng:
|
||||
|
||||
There are two issues here. The first is changing how libpng does
|
||||
standard things like memory allocation, input/output, and error handling.
|
||||
The second deals with more complicated things like adding new chunks,
|
||||
adding new transformations, and generally changing how libpng works.
|
||||
|
||||
All of the memory allocation, input/output, and error handling in libpng
|
||||
goes through the routines in pngstub.c. The file as plenty of comments
|
||||
describing each function and how it expects to work, so I will just
|
||||
summarize here. See pngstub.c for more details.
|
||||
|
||||
Memory allocation is done through the functions png_large_malloc(),
|
||||
png_malloc(), png_realloc(), png_large_free(), and png_free().
|
||||
These currently just call the standard C functions. The large
|
||||
functions must handle exactly 64K, but they don't have to handle
|
||||
more then that. If your pointers can't access more then 64K at a
|
||||
time, you will want to set MAXSEG_64K in zlib.h.
|
||||
|
||||
Input/Output in libpng is done throught png_read() and png_write(), which
|
||||
currently just call fread() and fwrite(). The FILE * is stored in
|
||||
png_struct, and is initialized via png_init_io(). If you wish to change
|
||||
this, make the appropriate changes in pngstub.c and png.h. Make sure you
|
||||
change the function prototype for png_init_io() if you are no longer
|
||||
using a FILE *.
|
||||
|
||||
Error handling in libpng is done through png_error() and png_warning().
|
||||
Errors handled through png_error() are fatal, meaning that png_error()
|
||||
should never return to it's caller. Currently, this is handled via
|
||||
setjmp() and longjmp(), but you could change this to do things like
|
||||
exit() if you should wish. Similarly, both png_error() and png_warning()
|
||||
print a message on stderr, but that can also be changed. The motivation
|
||||
behind using setjmp() and longjmp() is the C++ throw and catch exception
|
||||
handling methods. This makes the code much easier to write, as there
|
||||
is no need to check every return code of every function call. However,
|
||||
there are some uncertainties about the status of local variables after
|
||||
a longjmp, so the user may want to be careful about doing anything after
|
||||
setjmp returns non zero besides returning itself. Consult your compiler
|
||||
documentation for more details.
|
||||
|
||||
If you need to read or write custom chunks, you will need to get deeper
|
||||
into the libpng code. First, read the PNG specification, and have
|
||||
a first level of understanding of how it works. Pay particular
|
||||
attention to the sections that describe chunk names, and look
|
||||
at how other chunks were designed, so you can do things similar.
|
||||
Second, check out the sections of libpng that read and write chunks.
|
||||
Try to find a chunk that is similar to yours, and copy off of it.
|
||||
More details can be found in the comments inside the code.
|
||||
|
||||
If you wish to write your own transformation for the data, look
|
||||
through the part of the code that does the transformations, and check
|
||||
out some of the more simple ones to get an idea of how they work. Try
|
||||
to find a similar transformation to the one you want to add, and copy
|
||||
off of it. More details can be found in the comments inside the code
|
||||
itself.
|
||||
|
||||
Configuring for 16 bit platforms:
|
||||
|
||||
You will probably need to change the png__large_malloc() and
|
||||
png_large_free() routines in pngstub.c, as these are requred
|
||||
to allocate 64K. Also, you will want to look into zconf.h to tell
|
||||
zlib (and thus libpng) that it cannot allocate more then 64K at a
|
||||
time. Even if you can, the memory won't be accessable. So limit zlib
|
||||
and libpng to 64K by defining MAXSEG_64K.
|
||||
|
||||
Configuring for gui/windowing platforms:
|
||||
|
||||
You will need to change the error message display in png_error() and
|
||||
png_warning() to display a message instead of fprinting it to stderr.
|
||||
You may want to write a single function to do this and call it something
|
||||
like png_message(). On some compliers, you may have to change the
|
||||
memory allocators (png_malloc, etc.).
|
||||
|
||||
Configuring for compiler xxx:
|
||||
|
||||
All includes for libpng are in png.h. If you need to add/change/delete
|
||||
an include, this is the place to do it. The includes that are not
|
||||
needed outside libpng are protected by the PNG_INTERNAL definition,
|
||||
which is only defined for those routines inside libpng itself. The
|
||||
files in libpng proper only include png.h.
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
# makefile for libpng
|
||||
# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc.
|
||||
# For conditions of distribution and use, see copyright notice in png.h
|
||||
|
||||
CC=gcc
|
||||
CFLAGS=-I../zlib -O3
|
||||
LDFLAGS=-L. -L../zlib/ -lpng -lgz -lm
|
||||
|
||||
RANLIB=ranlib
|
||||
#RANLIB=echo
|
||||
|
||||
# where make install puts libpng.a and png.h
|
||||
prefix=/usr/local
|
||||
|
||||
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \
|
||||
pngread.o pngstub.o pngwrite.o pngrtran.o pngwtran.o
|
||||
|
||||
all: libpng.a pngtest
|
||||
|
||||
libpng.a: $(OBJS)
|
||||
ar rc $@ $(OBJS)
|
||||
$(RANLIB) $@
|
||||
|
||||
pngtest: pngtest.o libpng.a
|
||||
cc -o pngtest $(CCFLAGS) pngtest.o $(LDFLAGS)
|
||||
|
||||
install: libpng.a
|
||||
-@mkdir $(prefix)/include
|
||||
-@mkdir $(prefix)/lib
|
||||
cp png.h $(prefix)/include
|
||||
chmod 644 $(prefix)/include/png.h
|
||||
cp libpng.a $(prefix)/lib
|
||||
chmod 644 $(prefix)/lib/libpng.a
|
||||
|
||||
clean:
|
||||
rm -f *.o libpng.a pngtest pngout.png
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
pngrcb.o: png.h
|
||||
pngread.o: png.h
|
||||
pngrtran.o: png.h
|
||||
pngrutil.o: png.h
|
||||
pngstub.o: png.h
|
||||
pngtest.o: png.h
|
||||
pngtrans.o: png.h
|
||||
pngwrite.o: png.h
|
||||
pngwtran.o: png.h
|
||||
pngwutil.o: png.h
|
|
@ -0,0 +1,61 @@
|
|||
# makefile for libpng
|
||||
# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc.
|
||||
# For conditions of distribution and use, see copyright notice in png.h
|
||||
|
||||
CC=cc
|
||||
CFLAGS=-I../zlib -O
|
||||
LDFLAGS=-L. -L../zlib/ -lpng -lgz -lm
|
||||
# flags for ansi2knr
|
||||
ANSI2KNRFLAGS=
|
||||
|
||||
RANLIB=ranlib
|
||||
#RANLIB=echo
|
||||
|
||||
# where make install puts libpng.a and png.h
|
||||
prefix=/usr/local
|
||||
|
||||
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \
|
||||
pngread.o pngstub.o pngwrite.o pngrtran.o pngwtran.o
|
||||
|
||||
all: ansi2knr libpng.a pngtest
|
||||
|
||||
# general rule to allow ansi2knr to work
|
||||
.c.o:
|
||||
./ansi2knr $*.c T$*.c
|
||||
$(CC) $(CFLAGS) -c T$*.c
|
||||
rm -f T$*.c $*.o
|
||||
mv T$*.o $*.o
|
||||
|
||||
ansi2knr: ansi2knr.c
|
||||
$(CC) $(CFLAGS) $(ANSI2KNRFLAGS) -o ansi2knr ansi2knr.c
|
||||
|
||||
libpng.a: ansi2knr $(OBJS)
|
||||
ar rc $@ $(OBJS)
|
||||
$(RANLIB) $@
|
||||
|
||||
pngtest: pngtest.o libpng.a ansi2knr
|
||||
cc -o pngtest $(CCFLAGS) pngtest.o $(LDFLAGS)
|
||||
|
||||
install: libpng.a
|
||||
-@mkdir $(prefix)/include
|
||||
-@mkdir $(prefix)/lib
|
||||
cp png.h $(prefix)/include
|
||||
chmod 644 $(prefix)/include/png.h
|
||||
cp libpng.a $(prefix)/lib
|
||||
chmod 644 $(prefix)/lib/libpng.a
|
||||
|
||||
clean:
|
||||
rm -f *.o libpng.a pngtest pngout.png ansi2knr
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
pngrcb.o: png.h
|
||||
pngread.o: png.h
|
||||
pngrtran.o: png.h
|
||||
pngrutil.o: png.h
|
||||
pngstub.o: png.h
|
||||
pngtest.o: png.h
|
||||
pngtrans.o: png.h
|
||||
pngwrite.o: png.h
|
||||
pngwtran.o: png.h
|
||||
pngwutil.o: png.h
|
|
@ -0,0 +1,50 @@
|
|||
# makefile for libpng
|
||||
# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc.
|
||||
# For conditions of distribution and use, see copyright notice in png.h
|
||||
|
||||
CC=cc
|
||||
CFLAGS=-I../zlib -O -systype sysv -DSYSV -w -Dmips
|
||||
#CFLAGS=-O
|
||||
LDFLAGS=-L. -L../zlib/ -lpng -lgz -lm
|
||||
|
||||
#RANLIB=ranlib
|
||||
RANLIB=echo
|
||||
|
||||
# where make install puts libpng.a and png.h
|
||||
prefix=/usr/local
|
||||
|
||||
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \
|
||||
pngread.o pngstub.o pngwrite.o pngrtran.o pngwtran.o
|
||||
|
||||
all: libpng.a pngtest
|
||||
|
||||
libpng.a: $(OBJS)
|
||||
ar rc $@ $(OBJS)
|
||||
$(RANLIB) $@
|
||||
|
||||
pngtest: pngtest.o libpng.a
|
||||
cc -o pngtest $(CCFLAGS) pngtest.o $(LDFLAGS)
|
||||
|
||||
install: libpng.a
|
||||
-@mkdir $(prefix)/include
|
||||
-@mkdir $(prefix)/lib
|
||||
cp png.h $(prefix)/include
|
||||
chmod 644 $(prefix)/include/png.h
|
||||
cp libpng.a $(prefix)/lib
|
||||
chmod 644 $(prefix)/lib/libpng.a
|
||||
|
||||
clean:
|
||||
rm -f *.o libpng.a pngtest pngout.png
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
pngrcb.o: png.h
|
||||
pngread.o: png.h
|
||||
pngrtran.o: png.h
|
||||
pngrutil.o: png.h
|
||||
pngstub.o: png.h
|
||||
pngtest.o: png.h
|
||||
pngtrans.o: png.h
|
||||
pngwrite.o: png.h
|
||||
pngwtran.o: png.h
|
||||
pngwutil.o: png.h
|
|
@ -0,0 +1,49 @@
|
|||
# makefile for libpng
|
||||
# Copyright (C) 1995 Guy Eric Schalnat, Group 42, Inc.
|
||||
# For conditions of distribution and use, see copyright notice in png.h
|
||||
|
||||
CC=cc
|
||||
CFLAGS=-I../zlib -O
|
||||
LDFLAGS=-L. -L../zlib/ -lpng -lgz -lm
|
||||
|
||||
#RANLIB=ranlib
|
||||
RANLIB=echo
|
||||
|
||||
# where make install puts libpng.a and png.h
|
||||
prefix=/usr/local
|
||||
|
||||
OBJS = png.o pngrcb.o pngrutil.o pngtrans.o pngwutil.o \
|
||||
pngread.o pngstub.o pngwrite.o pngrtran.o pngwtran.o
|
||||
|
||||
all: libpng.a pngtest
|
||||
|
||||
libpng.a: $(OBJS)
|
||||
ar rc $@ $(OBJS)
|
||||
$(RANLIB) $@
|
||||
|
||||
pngtest: pngtest.o libpng.a
|
||||
cc -o pngtest $(CCFLAGS) pngtest.o $(LDFLAGS)
|
||||
|
||||
install: libpng.a
|
||||
-@mkdir $(prefix)/include
|
||||
-@mkdir $(prefix)/lib
|
||||
cp png.h $(prefix)/include
|
||||
chmod 644 $(prefix)/include/png.h
|
||||
cp libpng.a $(prefix)/lib
|
||||
chmod 644 $(prefix)/lib/libpng.a
|
||||
|
||||
clean:
|
||||
rm -f *.o libpng.a pngtest pngout.png
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
pngrcb.o: png.h
|
||||
pngread.o: png.h
|
||||
pngrtran.o: png.h
|
||||
pngrutil.o: png.h
|
||||
pngstub.o: png.h
|
||||
pngtest.o: png.h
|
||||
pngtrans.o: png.h
|
||||
pngwrite.o: png.h
|
||||
pngwtran.o: png.h
|
||||
pngwutil.o: png.h
|
|
@ -0,0 +1,172 @@
|
|||
|
||||
/* png.c - location for general purpose png functions
|
||||
|
||||
libpng 1.0 beta 1 - version 0.71
|
||||
For conditions of distribution and use, see copyright notice in png.h
|
||||
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
|
||||
June 26, 1995
|
||||
*/
|
||||
|
||||
#define PNG_INTERNAL
|
||||
#define PNG_NO_EXTERN
|
||||
#include "png.h"
|
||||
|
||||
/* place to hold the signiture string for a png file. */
|
||||
png_byte png_sig[8] = {137, 80, 78, 71, 13, 10, 26, 10};
|
||||
|
||||
/* constant strings for known chunk types. If you need to add a chunk,
|
||||
add a string holding the name here. If you want to make the code
|
||||
portable to EBCDIC machines, use ASCII numbers, not characters. */
|
||||
png_byte png_IHDR[4] = { 73, 72, 68, 82};
|
||||
png_byte png_IDAT[4] = { 73, 68, 65, 84};
|
||||
png_byte png_IEND[4] = { 73, 69, 78, 68};
|
||||
png_byte png_PLTE[4] = { 80, 76, 84, 69};
|
||||
png_byte png_gAMA[4] = {103, 65, 77, 65};
|
||||
png_byte png_sBIT[4] = {115, 66, 73, 84};
|
||||
png_byte png_cHRM[4] = { 99, 72, 82, 77};
|
||||
png_byte png_tRNS[4] = {116, 82, 78, 83};
|
||||
png_byte png_bKGD[4] = { 98, 75, 71, 68};
|
||||
png_byte png_hIST[4] = {104, 73, 83, 84};
|
||||
png_byte png_tEXt[4] = {116, 69, 88, 116};
|
||||
png_byte png_zTXt[4] = {122, 84, 88, 116};
|
||||
png_byte png_pHYs[4] = {112, 72, 89, 115};
|
||||
png_byte png_oFFs[4] = {111, 70, 70, 115};
|
||||
png_byte png_tIME[4] = {116, 73, 77, 69};
|
||||
|
||||
/* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
|
||||
|
||||
/* start of interlace block */
|
||||
int png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
|
||||
|
||||
/* offset to next interlace block */
|
||||
int png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
|
||||
|
||||
/* start of interlace block in the y direction */
|
||||
int png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
|
||||
|
||||
/* offset to next interlace block in the y direction */
|
||||
int png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
|
||||
|
||||
/* width of interlace block */
|
||||
/* this is not currently used - if you need it, uncomment it here and
|
||||
in png.h
|
||||
int png_pass_width[] = {8, 4, 4, 2, 2, 1, 1};
|
||||
*/
|
||||
|
||||
/* height of interlace block */
|
||||
/* this is not currently used - if you need it, uncomment it here and
|
||||
in png.h
|
||||
int png_pass_height[] = {8, 8, 4, 4, 4, 2, 2, 1};
|
||||
*/
|
||||
|
||||
/* mask to determine which pixels are valid in a pass */
|
||||
int png_pass_mask[] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
|
||||
|
||||
/* mask to determine which pixels to overwrite while displaying */
|
||||
int png_pass_dsp_mask[] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
|
||||
|
||||
|
||||
int
|
||||
png_check_sig(png_byte *sig, int num)
|
||||
{
|
||||
if (num > 8)
|
||||
num = 8;
|
||||
if (num < 1)
|
||||
return 0;
|
||||
|
||||
return (!memcmp(sig, png_sig, num));
|
||||
}
|
||||
|
||||
/* Function to allocate memory for zlib. */
|
||||
voidp
|
||||
png_zalloc(voidp png_ptr, uInt items, uInt size)
|
||||
{
|
||||
return ((voidp)png_large_malloc((png_struct *)png_ptr,
|
||||
(png_uint_32)items * (png_uint_32)size));
|
||||
}
|
||||
|
||||
/* function to free memory for zlib */
|
||||
void
|
||||
png_zfree(voidp png_ptr, voidp ptr)
|
||||
{
|
||||
png_large_free((png_struct *)png_ptr, (void *)ptr);
|
||||
}
|
||||
|
||||
/* reset the crc variable to 32 bits of 1's. Care must be taken
|
||||
in case crc is > 32 bits to leave the top bits 0 */
|
||||
void
|
||||
png_reset_crc(png_struct *png_ptr)
|
||||
{
|
||||
/* set crc to all 1's */
|
||||
png_ptr->crc = 0xffffffffL;
|
||||
}
|
||||
|
||||
/* Note: the crc code below was copied from the sample code in the
|
||||
PNG spec, with appropriate modifications made to ensure the
|
||||
variables are large enough */
|
||||
|
||||
/* table of crc's of all 8-bit messages. If you wish to png_malloc this
|
||||
table, turn this into a pointer, and png_malloc it in make_crc_table().
|
||||
You may then want to hook it into png_struct and free it with the
|
||||
destroy functions. */
|
||||
static png_uint_32 crc_table[256];
|
||||
|
||||
/* Flag: has the table been computed? Initially false. */
|
||||
static int crc_table_computed = 0;
|
||||
|
||||
/* make the table for a fast crc */
|
||||
static void
|
||||
make_crc_table(void)
|
||||
{
|
||||
png_uint_32 c;
|
||||
int n, k;
|
||||
|
||||
for (n = 0; n < 256; n++)
|
||||
{
|
||||
c = (png_uint_32)n;
|
||||
for (k = 0; k < 8; k++)
|
||||
c = c & 1 ? 0xedb88320L ^ (c >> 1) : c >> 1;
|
||||
crc_table[n] = c;
|
||||
}
|
||||
crc_table_computed = 1;
|
||||
}
|
||||
|
||||
/* update a running crc with the bytes buf[0..len-1]--the crc should be
|
||||
initialized to all 1's, and the transmitted value is the 1's complement
|
||||
of the final running crc. */
|
||||
static png_uint_32
|
||||
update_crc(png_uint_32 crc, png_byte *buf, png_uint_32 len)
|
||||
{
|
||||
png_uint_32 c;
|
||||
png_byte *p;
|
||||
png_uint_32 n;
|
||||
|
||||
c = crc;
|
||||
p = buf;
|
||||
n = len;
|
||||
|
||||
if (!crc_table_computed)
|
||||
{
|
||||
make_crc_table();
|
||||
}
|
||||
|
||||
if (n > 0) do
|
||||
{
|
||||
c = crc_table[(png_byte)((c ^ (*p++)) & 0xff)] ^ (c >> 8);
|
||||
} while (--n);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/* calculate the crc over a section of data. Note that while we
|
||||
are passing in a 32 bit value for length, on 16 bit machines, you
|
||||
would need to use huge pointers to access all that data. If you
|
||||
need this, put huge here and above. */
|
||||
void
|
||||
png_calculate_crc(png_struct *png_ptr, png_byte *ptr,
|
||||
png_uint_32 length)
|
||||
{
|
||||
png_ptr->crc = update_crc(png_ptr->crc, ptr, length);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,913 @@
|
|||
|
||||
/* png.h - header file for png reference library
|
||||
libpng 1.0 beta 1 - version 0.71
|
||||
June 26, 1995
|
||||
|
||||
Note: This is a beta version. It reads and writes valid files
|
||||
on the platforms I have, but it has had limited portability
|
||||
testing. Furthermore, you will probably have to modify the
|
||||
includes below to get it to work on your system, and you
|
||||
may have to supply the correct compiler flags in the makefile.
|
||||
Read the readme.txt for more information, and how to contact
|
||||
me if you have any problems, or if you want your compiler/
|
||||
platform to be supported in the next official libpng release.
|
||||
|
||||
See readme.txt for more information
|
||||
|
||||
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
|
||||
Contributing Authors:
|
||||
Guy Eric Schalnat
|
||||
|
||||
The PNG Reference Library is supplied "AS IS". The Contributing Authors
|
||||
and Group 42, Inc. disclaim all warranties, expressed or implied,
|
||||
including, without limitation, the warranties of merchantability and of
|
||||
fitness for any purpose. The Contributing Authors and Group 42, Inc.
|
||||
assume no liability for damages, direct or consequential, which may
|
||||
result from the use of the PNG Reference Library.
|
||||
|
||||
Permission is hereby granted to use, copy, modify, and distribute this
|
||||
source code, or portions hereof, for any purpose, without fee, subject
|
||||
to the following restrictions:
|
||||
1. The origin of this source code must not be misrepresented.
|
||||
2. Altered versions must be plainly marked as such and must not be
|
||||
misrepresented as being the original source.
|
||||
3. This Copyright notice may not be removed or altered from any source or
|
||||
altered source distribution.
|
||||
|
||||
The Contributing Authors and Group 42, Inc. specifically permit, without
|
||||
fee, and encourage the use of this source code as a component to
|
||||
supporting the PNG file format in commercial products. If you use this
|
||||
source code in a product, acknowledgment is not required but would be
|
||||
appreciated.
|
||||
*/
|
||||
|
||||
#ifndef _PNG_H
|
||||
#define _PNG_H
|
||||
|
||||
/* This is not the place to learn how to use libpng. The file libpng.txt
|
||||
describes how to use libpng, and the file example.c summarizes it
|
||||
with some code to build around. This file is useful for looking
|
||||
at the actual function definitions and structure components. */
|
||||
|
||||
/* This file is arranged in several sections. The first section contains
|
||||
all the definitions for libpng. The second section details the functions
|
||||
most users will use. The third section describes the stub files that
|
||||
users will most likely need to change. The last section contains
|
||||
functions used internally by the code.
|
||||
|
||||
Any machine specific code is near the front of this file, so if you
|
||||
are configuring libpng for a machine, you may want to read the section
|
||||
starting here down to where it starts to typedef png_color, png_text,
|
||||
and png_info */
|
||||
|
||||
/* this is the size of the compression buffer, and thus the size of
|
||||
an IDAT chunk. Make this whatever size you feel is best for your
|
||||
machine. One of these will be allocated per png_struct. When this
|
||||
is full, it writes the data to the disk, and does some other
|
||||
calculations. Making this an extreamly small size will slow
|
||||
the library down, but you may want to experiment to determine
|
||||
where it becomes significant, if you are concerned with memory
|
||||
usage. Note that zlib allocates at least 32Kb also. For readers,
|
||||
this describes the size of the buffer available to read the data in.
|
||||
Unless this gets smaller then the size of a row (compressed),
|
||||
it should not make much difference how big this is. */
|
||||
|
||||
#define PNG_ZBUF_SIZE 8192;
|
||||
|
||||
/* include the compression library's header */
|
||||
#include "zlib.h"
|
||||
|
||||
/* While libpng currently uses zlib for it's compression, it has been designed
|
||||
to stand on it's own. Towards this end, there are two defines that are
|
||||
used to help portability between machines. To make it simpler to
|
||||
setup libpng on a machine, this currently uses zlib's definitions, so
|
||||
any changes should be made in zlib. Libpng will check zlib's settings
|
||||
and adjust it's own accordingly. */
|
||||
|
||||
/* if you are running on a machine where you cannot allocate more then
|
||||
64K of memory, uncomment this. While libpng will not normally need
|
||||
that much memory in a chunk (unless you load up a very large file),
|
||||
zlib needs to know how big of a chunk it can use, and libpng thus
|
||||
makes sure to check any memory allocation to verify it will fit
|
||||
into memory.
|
||||
#define PNG_MAX_ALLOC_64K
|
||||
*/
|
||||
#ifdef MAXSEG_64K
|
||||
#define PNG_MAX_ALLOC_64K
|
||||
#endif
|
||||
|
||||
/* this macro protects us against machines that don't have function
|
||||
prototypes. If your compiler does not handle function prototypes,
|
||||
define this macro. I've always been able to use _NO_PROTO as the
|
||||
indicator, but you may need to drag the empty declaration out in
|
||||
front of here, or change the ifdef to suit your own needs. */
|
||||
#ifndef PNGARG
|
||||
|
||||
#ifdef __P
|
||||
#define PNGARG(arglist) __P(arglist)
|
||||
#else
|
||||
|
||||
#ifdef _NO_PROTO
|
||||
#define PNGARG(arglist)
|
||||
#else
|
||||
#define PNGARG(arglist) arglist
|
||||
#endif /* _NO_PROTO */
|
||||
|
||||
#endif /* __P(arglist) */
|
||||
|
||||
#endif /* PNGARG */
|
||||
|
||||
/* enough people need this for various reasons to include it here */
|
||||
#include <sys/types.h>
|
||||
/* need the time information for reading tIME chunks */
|
||||
#include <time.h>
|
||||
|
||||
/* for FILE. If you are not using standard io, you don't need this */
|
||||
#include <stdio.h>
|
||||
|
||||
/* include setjmp.h for error handling */
|
||||
#include <setjmp.h>
|
||||
|
||||
/* other defines for things like memory and the like can go here. These
|
||||
are the only files included in libpng, so if you need to change them,
|
||||
change them here. They are only included if PNG_INTERNAL is defined. */
|
||||
#ifdef PNG_INTERNAL
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#ifdef BSD
|
||||
#include <strings.h>
|
||||
#else
|
||||
#include <string.h>
|
||||
#endif
|
||||
#include <math.h>
|
||||
|
||||
/* other defines specific to compilers can go here. Try to keep
|
||||
them inside an appropriate ifdef/endif pair for portability */
|
||||
|
||||
/* for some reason, Borland C++ defines memcmp, etc. in mem.h, not
|
||||
stdlib.h like it should (I think). Or perhaps this is a C++
|
||||
feature */
|
||||
#ifdef __TURBOC__
|
||||
#include <mem.h>
|
||||
#include "alloc.h"
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <malloc.h>
|
||||
#endif
|
||||
|
||||
/* this controls how fine the dithering gets. As this allocates
|
||||
a largish chunk of memory (32K), those who are not as concerned
|
||||
with dithering quality can decrease some or all of these */
|
||||
#define PNG_DITHER_RED_BITS 5
|
||||
#define PNG_DITHER_GREEN_BITS 5
|
||||
#define PNG_DITHER_BLUE_BITS 5
|
||||
|
||||
/* this controls how fine the gamma correction becomes when you
|
||||
are only interested in 8 bits anyway. Increasing this value
|
||||
results in more memory being used, and more pow() functions
|
||||
being called to fill in the gamma tables. Don't get this
|
||||
value less then 8, and even that may not work (I haven't tested
|
||||
it). */
|
||||
|
||||
#define PNG_MAX_GAMMA_8 11
|
||||
|
||||
#endif /* PNG_INTERNAL */
|
||||
|
||||
/* some typedefs to get us started. These should be safe on most of the
|
||||
common platforms. The typedefs should be at least as large
|
||||
as the numbers suggest (a png_uint_32 must be at least 32 bits long),
|
||||
but they don't have to be exactly that size. */
|
||||
|
||||
typedef unsigned long png_uint_32;
|
||||
typedef long png_int_32;
|
||||
typedef unsigned short png_uint_16;
|
||||
typedef short png_int_16;
|
||||
typedef unsigned char png_byte;
|
||||
|
||||
/* this is usually size_t. it is typedef'ed just in case you need it to
|
||||
change (I'm not sure if you will or not, so I thought I'd be safe) */
|
||||
typedef size_t png_size_t;
|
||||
|
||||
/* 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 want. */
|
||||
typedef struct png_color_struct
|
||||
{
|
||||
png_byte red;
|
||||
png_byte green;
|
||||
png_byte blue;
|
||||
} png_color;
|
||||
|
||||
typedef struct png_color_16_struct
|
||||
{
|
||||
png_byte index; /* used for palette files */
|
||||
png_uint_16 red; /* for use in red green blue files */
|
||||
png_uint_16 green;
|
||||
png_uint_16 blue;
|
||||
png_uint_16 gray; /* for use in grayscale files */
|
||||
} png_color_16;
|
||||
|
||||
typedef struct png_color_8_struct
|
||||
{
|
||||
png_byte red; /* for use in red green blue files */
|
||||
png_byte green;
|
||||
png_byte blue;
|
||||
png_byte gray; /* for use in grayscale files */
|
||||
png_byte alpha; /* for alpha channel files */
|
||||
} png_color_8;
|
||||
|
||||
/* png_text holds the text in a png file, and whether they are compressed
|
||||
or not. If compression is -1, the text is not compressed. */
|
||||
typedef struct png_text_struct
|
||||
{
|
||||
int compression; /* compression value, -1 if uncompressed */
|
||||
char *key; /* keyword */
|
||||
char *text; /* comment */
|
||||
png_uint_32 text_length; /* length of text field */
|
||||
} png_text;
|
||||
|
||||
/* png_time is a way to hold the time in an machine independent way.
|
||||
Two conversions are provided, both from time_t and struct tm. There
|
||||
is no portable way to convert to either of these structures, as far
|
||||
as I know. If you know of a portable way, send it to me. */
|
||||
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 */
|
||||
png_byte second; /* second of minute, 0 - 60 (for leap seconds) */
|
||||
} png_time;
|
||||
|
||||
/* png_info is a structure that holds the information in a png file.
|
||||
If you are reading the file, This structure will tell you what is
|
||||
in the png file. If you are writing the file, fill in the information
|
||||
you want to put into the png file, then call png_write_info().
|
||||
The names chosen should be very close to the PNG
|
||||
specification, so consult that document for information
|
||||
about the meaning of each field. */
|
||||
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_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_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
|
||||
written, and initialize the appropriate fields below */
|
||||
float gamma; /* gamma value of file, if gAMA chunk is valid */
|
||||
png_color_8 sig_bit; /* significant bits */
|
||||
float x_white; /* cHRM chunk values */
|
||||
float y_white;
|
||||
float x_red;
|
||||
float y_red;
|
||||
float x_green;
|
||||
float y_green;
|
||||
float x_blue;
|
||||
float y_blue;
|
||||
png_color *palette; /* palette of file */
|
||||
png_uint_16 num_palette; /* number of values in palette */
|
||||
png_byte *trans; /* tRNS values for palette image */
|
||||
png_uint_16 num_trans; /* number of trans values */
|
||||
png_color_16 trans_values; /* tRNS values for non-palette image */
|
||||
png_color_16 background; /* background color of image */
|
||||
png_uint_16 *hist; /* histogram of palette usage */
|
||||
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 */
|
||||
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 */
|
||||
png_time mod_time; /* modification time */
|
||||
int num_text; /* number of comments */
|
||||
int max_text; /* size of text array */
|
||||
png_text *text; /* array of comments */
|
||||
} png_info;
|
||||
|
||||
#define PNG_RESOLUTION_UNKNOWN 0
|
||||
#define PNG_RESOLUTION_METER 1
|
||||
|
||||
#define PNG_OFFSET_PIXEL 0
|
||||
#define PNG_OFFSET_MICROMETER 1
|
||||
|
||||
/* 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
|
||||
|
||||
/* color types. Note that not all combinations are legal */
|
||||
#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)
|
||||
|
||||
/* These determine if a chunks information is present in a read operation, or
|
||||
if the chunk should be written in a write operation. */
|
||||
#define PNG_INFO_gAMA 0x0001
|
||||
#define PNG_INFO_sBIT 0x0002
|
||||
#define PNG_INFO_cHRM 0x0004
|
||||
#define PNG_INFO_PLTE 0x0008
|
||||
#define PNG_INFO_tRNS 0x0010
|
||||
#define PNG_INFO_bKGD 0x0020
|
||||
#define PNG_INFO_hIST 0x0040
|
||||
#define PNG_INFO_pHYs 0x0080
|
||||
#define PNG_INFO_oFFs 0x0100
|
||||
#define PNG_INFO_tIME 0x0200
|
||||
|
||||
/* 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. */
|
||||
typedef struct png_row_info_struct
|
||||
{
|
||||
png_uint_32 width; /* width of row */
|
||||
png_uint_32 rowbytes; /* number of bytes in row */
|
||||
png_byte color_type; /* color type of row */
|
||||
png_byte bit_depth; /* bit depth of row */
|
||||
png_byte channels; /* number of channels (1, 2, 3, or 4) */
|
||||
png_byte pixel_depth; /* bits per pixel (depth * channels) */
|
||||
} png_row_info;
|
||||
|
||||
/* The structure that holds the information to read and write png files.
|
||||
The only people who need to care about what is inside of this are the
|
||||
people who will be modifying the library for their own special needs.
|
||||
*/
|
||||
typedef struct png_struct_def
|
||||
{
|
||||
jmp_buf jmpbuf; /* used in png_error */
|
||||
png_byte mode; /* used to determine where we are in the png file */
|
||||
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 */
|
||||
png_byte gamma_shift; /* amount of shift for 16 bit gammas */
|
||||
png_byte pass; /* current pass (0 - 6) */
|
||||
png_byte row_init; /* 1 if png_read_start_row() has been called */
|
||||
png_byte background_gamma_type;
|
||||
png_byte background_expand;
|
||||
png_byte zlib_finished;
|
||||
png_byte user_palette;
|
||||
png_uint_16 num_palette; /* number of entries in palette */
|
||||
png_uint_16 num_trans; /* number of transparency values */
|
||||
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 */
|
||||
png_uint_32 rowbytes; /* size of row in bytes */
|
||||
png_uint_32 usr_width; /* width of row at start of write */
|
||||
png_uint_32 iwidth; /* interlaced width */
|
||||
png_uint_32 irowbytes; /* interlaced rowbytes */
|
||||
png_uint_32 row_number; /* current row in pass */
|
||||
png_uint_32 idat_size; /* current idat size for read */
|
||||
png_uint_32 zbuf_size; /* size of zbuf */
|
||||
png_color *palette; /* files palette */
|
||||
png_byte *palette_lookup; /* lookup table for dithering */
|
||||
png_byte *gamma_table; /* gamma table for 8 bit depth files */
|
||||
png_byte *gamma_from_1; /* converts from 1.0 to screen */
|
||||
png_byte *gamma_to_1; /* converts from file to 1.0 */
|
||||
png_byte *trans; /* transparency values for paletted files */
|
||||
png_byte *dither_index; /* index translation for palette files */
|
||||
png_uint_16 **gamma_16_table; /* gamma table for 16 bit depth files */
|
||||
png_uint_16 **gamma_16_from_1; /* converts from 1.0 to screen */
|
||||
png_uint_16 **gamma_16_to_1; /* converts from file to 1.0 */
|
||||
png_uint_16 *hist; /* histogram */
|
||||
png_byte *zbuf; /* buffer for zlib */
|
||||
png_byte *row_buf; /* row buffer */
|
||||
png_byte *prev_row; /* previous row */
|
||||
png_byte *save_row; /* place to save row before filtering */
|
||||
z_stream *zstream; /* pointer to decompression structure (below) */
|
||||
float gamma; /* file gamma value */
|
||||
float display_gamma; /* display gamma value */
|
||||
float background_gamma;
|
||||
png_color_8 shift; /* shift for significant bit tranformation */
|
||||
png_color_8 sig_bit; /* significant bits in file */
|
||||
png_color_16 trans_values; /* transparency values for non-paletted files */
|
||||
png_color_16 background; /* background color, gamma corrected for screen */
|
||||
png_color_16 background_1; /* background normalized to gamma 1.0 */
|
||||
png_row_info row_info; /* used for transformation routines */
|
||||
z_stream zstream_struct; /* decompression structure */
|
||||
FILE *fp; /* used for png_read and png_write */
|
||||
} png_struct;
|
||||
|
||||
|
||||
/* 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
|
||||
a simple one line of the use of each function. */
|
||||
|
||||
/* check the first 1 - 8 bytes to see if it is a png file */
|
||||
extern int png_check_sig PNGARG((png_byte *sig, int num));
|
||||
|
||||
/* initialize png structure for reading, and allocate any memory needed */
|
||||
extern void png_read_init PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* initialize png structure for writing, and allocate any memory needed */
|
||||
extern void png_write_init PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* initialize the info structure */
|
||||
extern void png_info_init PNGARG((png_info *info));
|
||||
|
||||
/* Writes all the png information before the image. */
|
||||
extern void png_write_info PNGARG((png_struct *png_ptr, png_info *info));
|
||||
|
||||
/* read the information before the actual image data. */
|
||||
extern void png_read_info PNGARG((png_struct *png_ptr, png_info *info));
|
||||
|
||||
/* convert from a struct tm to png_time */
|
||||
extern void png_convert_from_struct_tm PNGARG((png_time *ptime,
|
||||
struct tm *ttime));
|
||||
|
||||
/* convert from time_t to png_time. Uses gmtime() */
|
||||
extern void png_convert_from_time_t PNGARG((png_time *ptime, time_t ttime));
|
||||
|
||||
/* Expand the data to 24 bit RGB, or 8 bit Grayscale,
|
||||
with alpha if necessary. */
|
||||
extern void png_set_expand PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* Use blue, green, red order for pixels. */
|
||||
extern void png_set_bgr PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* Add a filler byte to rgb images after the colors. */
|
||||
extern void png_set_rgbx PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* Add a filler byte to rgb images before the colors. */
|
||||
extern void png_set_xrgb PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* Swap bytes in 16 bit depth files. */
|
||||
extern void png_set_swap PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* Use 1 byte per pixel in 1, 2, or 4 bit depth files. */
|
||||
extern void png_set_packing PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* Converts files to legal bit depths. */
|
||||
extern void png_set_shift PNGARG((png_struct *png_ptr,
|
||||
png_color_8 *true_bits));
|
||||
|
||||
/* Have the code handle the interlacing. Returns the number of passes. */
|
||||
extern int png_set_interlace_handling PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* Invert monocrome files */
|
||||
extern void png_set_invert_mono PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* 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
|
||||
extern void png_set_background PNGARG((png_struct *png_ptr,
|
||||
png_color_16 *background_color, int background_gamma_code,
|
||||
int need_expand, float background_gamma));
|
||||
|
||||
/* strip the second byte of information from a 16 bit depth file. */
|
||||
extern void png_set_strip_16 PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* convert a grayscale file into rgb. */
|
||||
extern void png_set_gray_to_rgb PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* Turn on dithering, and reduce the palette to the number of colors available. */
|
||||
extern void png_set_dither PNGARG((png_struct *png_ptr, png_color *palette,
|
||||
int num_palette, int maximum_colors, png_uint_16 *histogram, int full_dither));
|
||||
|
||||
/* Handle gamma correction. */
|
||||
extern void png_set_gamma PNGARG((png_struct *png_ptr, float screen_gamma,
|
||||
float default_file_gamma));
|
||||
|
||||
/* optional update palette with requested transformations */
|
||||
void png_start_read_image PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* read a one or more rows of image data.*/
|
||||
extern void png_read_rows PNGARG((png_struct *png_ptr,
|
||||
png_byte **row,
|
||||
png_byte **display_row, png_uint_32 num_rows));
|
||||
|
||||
/* read a row of data.*/
|
||||
extern void png_read_row PNGARG((png_struct *png_ptr,
|
||||
png_byte *row,
|
||||
png_byte *display_row));
|
||||
|
||||
/* read the whole image into memory at once. */
|
||||
extern void png_read_image PNGARG((png_struct *png_ptr,
|
||||
png_byte **image));
|
||||
|
||||
/* write a row of image data */
|
||||
extern void png_write_row PNGARG((png_struct *png_ptr,
|
||||
png_byte *row));
|
||||
|
||||
/* write a few rows of image data */
|
||||
extern void png_write_rows PNGARG((png_struct *png_ptr,
|
||||
png_byte **row,
|
||||
png_uint_32 num_rows));
|
||||
|
||||
/* write the image data */
|
||||
extern void png_write_image PNGARG((png_struct *png_ptr, png_byte **image));
|
||||
|
||||
/* writes the end of the png file. */
|
||||
extern void png_write_end PNGARG((png_struct *png_ptr, png_info *info));
|
||||
|
||||
/* read the end of the png file. */
|
||||
extern void png_read_end PNGARG((png_struct *png_ptr, png_info *info));
|
||||
|
||||
/* free all memory used by the read */
|
||||
extern void png_read_destroy PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_info *end_info));
|
||||
|
||||
/* free any memory used in png struct */
|
||||
extern void png_write_destroy PNGARG((png_struct *png_ptr));
|
||||
|
||||
|
||||
/* These next functions are stubs of typical c functions for input/output,
|
||||
memory, and error handling. They are in the file pngstub.c, and are
|
||||
set up to be easily modified for users that need to. See the file
|
||||
pngstub.c for more information */
|
||||
|
||||
/* Write the data to whatever output you are using. */
|
||||
extern void png_write_data PNGARG((png_struct *png_ptr, png_byte *data,
|
||||
png_uint_32 length));
|
||||
|
||||
/* Read data from whatever input you are using */
|
||||
extern void png_read_data PNGARG((png_struct *png_ptr, png_byte *data,
|
||||
png_uint_32 length));
|
||||
|
||||
/* Initialize the input/output for the png file. */
|
||||
extern void png_init_io PNGARG((png_struct *png_ptr, FILE *fp));
|
||||
|
||||
/* Allocate memory in larger chunks. */
|
||||
extern void *png_large_malloc PNGARG((png_struct *png_ptr, png_uint_32 size));
|
||||
|
||||
/* free's a pointer allocated by png_large_malloc() */
|
||||
extern void png_large_free PNGARG((png_struct *png_ptr, void *ptr));
|
||||
|
||||
/* Allocate memory. */
|
||||
extern void *png_malloc PNGARG((png_struct *png_ptr, png_uint_32 size));
|
||||
|
||||
/* Reallocate memory. */
|
||||
extern void *png_realloc PNGARG((png_struct *png_ptr, void *ptr,
|
||||
png_uint_32 size));
|
||||
|
||||
/* free's a pointer allocated by png_malloc() */
|
||||
extern void png_free PNGARG((png_struct *png_ptr, void *ptr));
|
||||
|
||||
/* Fatal error in libpng - can't continue */
|
||||
extern void png_error PNGARG((png_struct *png_ptr, char *error));
|
||||
|
||||
/* Non-fatal error in libpng. Can continue, but may have a problem. */
|
||||
extern void png_warning PNGARG((png_struct *png_ptr, char *message));
|
||||
|
||||
|
||||
/* These next functions are used internally in the code. If you use
|
||||
them, make sure you read and understand the png spec. More information
|
||||
about them can be found in the files where the functions are.
|
||||
Feel free to move any of these outside the PNG_INTERNAL define if
|
||||
you just need a few of them, but if you need access to more, you should
|
||||
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
|
||||
|
||||
/* 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
|
||||
|
||||
/* 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
|
||||
|
||||
/* save typing and make code easier to understand */
|
||||
#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \
|
||||
abs((int)((c1).green) - (int)((c2).green)) + \
|
||||
abs((int)((c1).blue) - (int)((c2).blue)))
|
||||
|
||||
/* variables defined in png.c - only it needs to define PNG_NO_EXTERN */
|
||||
#ifndef PNG_NO_EXTERN
|
||||
/* place to hold the signiture string for a png file. */
|
||||
extern png_byte png_sig[];
|
||||
|
||||
/* 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 */
|
||||
extern png_byte png_IHDR[];
|
||||
extern png_byte png_IDAT[];
|
||||
extern png_byte png_IEND[];
|
||||
extern png_byte png_PLTE[];
|
||||
extern png_byte png_gAMA[];
|
||||
extern png_byte png_sBIT[];
|
||||
extern png_byte png_cHRM[];
|
||||
extern png_byte png_tRNS[];
|
||||
extern png_byte png_bKGD[];
|
||||
extern png_byte png_hIST[];
|
||||
extern png_byte png_tEXt[];
|
||||
extern png_byte png_zTXt[];
|
||||
extern png_byte png_pHYs[];
|
||||
extern png_byte png_oFFs[];
|
||||
extern png_byte png_tIME[];
|
||||
/* Structures to facilitate easy interlacing. See png.c for more details */
|
||||
extern int png_pass_start[];
|
||||
extern int png_pass_inc[];
|
||||
extern int png_pass_ystart[];
|
||||
extern int png_pass_yinc[];
|
||||
/* these are not currently used. If you need them, see png.c
|
||||
extern int png_pass_width[];
|
||||
extern int png_pass_height[];
|
||||
*/
|
||||
extern int png_pass_mask[];
|
||||
extern int png_pass_dsp_mask[];
|
||||
|
||||
#endif /* PNG_NO_EXTERN */
|
||||
|
||||
/* Function to allocate memory for zlib. */
|
||||
extern voidp png_zalloc PNGARG((voidp png_ptr, uInt items, uInt size));
|
||||
|
||||
/* function to free memory for zlib */
|
||||
extern void png_zfree PNGARG((voidp png_ptr, voidp ptr));
|
||||
|
||||
/* reset the crc variable */
|
||||
extern void png_reset_crc PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* calculate the crc over a section of data. Note that while we
|
||||
are passing in a 32 bit value for length, on 16 bit machines, you
|
||||
would need to use huge pointers to access all that data. See the
|
||||
code in png.c for more information. */
|
||||
extern void png_calculate_crc PNGARG((png_struct *png_ptr, png_byte *ptr,
|
||||
png_uint_32 length));
|
||||
|
||||
/* place a 32 bit number into a buffer in png byte order. We work
|
||||
with unsigned numbers for convenience, you may have to cast
|
||||
signed numbers (if you use any, most png data is unsigned). */
|
||||
extern void png_save_uint_32 PNGARG((png_byte *buf, png_uint_32 i));
|
||||
|
||||
/* place a 16 bit number into a buffer in png byte order */
|
||||
extern void png_save_uint_16 PNGARG((png_byte *buf, png_uint_16 i));
|
||||
|
||||
/* write a 32 bit number */
|
||||
extern void png_write_uint_32 PNGARG((png_struct *png_ptr, png_uint_32 i));
|
||||
|
||||
/* write a 16 bit number */
|
||||
extern void png_write_uint_16 PNGARG((png_struct *png_ptr, png_uint_16 i));
|
||||
|
||||
/* Write a png chunk. */
|
||||
extern void png_write_chunk PNGARG((png_struct *png_ptr, png_byte *type,
|
||||
png_byte *data, png_uint_32 length));
|
||||
|
||||
/* Write the start of a png chunk. */
|
||||
extern void png_write_chunk_start PNGARG((png_struct *png_ptr, png_byte *type,
|
||||
png_uint_32 total_length));
|
||||
|
||||
/* write the data of a png chunk started with png_write_chunk_start(). */
|
||||
extern void png_write_chunk_data PNGARG((png_struct *png_ptr, png_byte *data,
|
||||
png_uint_32 length));
|
||||
|
||||
/* finish a chunk started with png_write_chunk_start() */
|
||||
extern void png_write_chunk_end PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* simple function to write the signiture */
|
||||
extern void png_write_sig PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* write various chunks */
|
||||
|
||||
/* Write the IHDR chunk, and update the png_struct with the necessary
|
||||
information. */
|
||||
extern void png_write_IHDR PNGARG((png_struct *png_ptr, png_uint_32 width,
|
||||
png_uint_32 height,
|
||||
int bit_depth, int color_type, int compression_type, int filter_type,
|
||||
int interlace_type));
|
||||
|
||||
extern void png_write_PLTE PNGARG((png_struct *png_ptr, png_color *palette,
|
||||
int number));
|
||||
|
||||
extern void png_write_IDAT PNGARG((png_struct *png_ptr, png_byte *data,
|
||||
png_uint_32 length));
|
||||
|
||||
extern void png_write_IEND PNGARG((png_struct *png_ptr));
|
||||
|
||||
extern void png_write_gAMA PNGARG((png_struct *png_ptr, float gamma));
|
||||
|
||||
extern void png_write_sBIT PNGARG((png_struct *png_ptr, png_color_8 *sbit,
|
||||
int color_type));
|
||||
|
||||
extern void png_write_cHRM PNGARG((png_struct *png_ptr,
|
||||
float white_x, float white_y,
|
||||
float red_x, float red_y, float green_x, float green_y,
|
||||
float blue_x, float blue_y));
|
||||
|
||||
extern void png_write_tRNS PNGARG((png_struct *png_ptr, png_byte *trans,
|
||||
png_color_16 *values, int number, int color_type));
|
||||
|
||||
extern void png_write_bKGD PNGARG((png_struct *png_ptr, png_color_16 *values,
|
||||
int color_type));
|
||||
|
||||
extern void png_write_hIST PNGARG((png_struct *png_ptr, png_uint_16 *hist,
|
||||
int number));
|
||||
|
||||
extern void png_write_tEXt PNGARG((png_struct *png_ptr, char *key,
|
||||
char *text, png_uint_32 text_len));
|
||||
|
||||
extern void png_write_zTXt PNGARG((png_struct *png_ptr, char *key,
|
||||
char *text, png_uint_32 text_len, int compression));
|
||||
|
||||
extern void png_write_pHYs PNGARG((png_struct *png_ptr,
|
||||
png_uint_32 x_pixels_per_unit,
|
||||
png_uint_32 y_pixels_per_unit,
|
||||
int unit_type));
|
||||
|
||||
extern void png_write_oFFs PNGARG((png_struct *png_ptr,
|
||||
png_uint_32 x_offset,
|
||||
png_uint_32 y_offset,
|
||||
int unit_type));
|
||||
|
||||
extern void png_write_tIME PNGARG((png_struct *png_ptr, png_time *mod_time));
|
||||
|
||||
/* Internal use only. Called when finished processing a row of data */
|
||||
extern void png_write_finish_row PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* Internal use only. Called before first row of data */
|
||||
extern void png_write_start_row PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* callbacks for png chunks */
|
||||
extern void png_read_IHDR PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 width, png_uint_32 height, int bit_depth,
|
||||
int color_type, int compression_type, int filter_type,
|
||||
int interlace_type));
|
||||
extern void png_read_PLTE PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_color *palette, int num));
|
||||
extern void png_read_gAMA PNGARG((png_struct *png_ptr, png_info *info,
|
||||
float gamma));
|
||||
extern void png_read_sBIT PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_color_8 *sig_bit));
|
||||
extern void png_read_cHRM PNGARG((png_struct *png_ptr, png_info *info,
|
||||
float white_x, float white_y, float red_x, float red_y,
|
||||
float green_x, float green_y, float blue_x, float blue_y));
|
||||
extern void png_read_tRNS PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_byte *trans, int num_trans, png_color_16 *trans_values));
|
||||
extern void png_read_bKGD PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_color_16 *background));
|
||||
extern void png_read_hIST PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_uint_16 *hist));
|
||||
extern void png_read_pHYs PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 res_x, png_uint_32 res_y, int unit_type));
|
||||
extern void png_read_oFFs PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 offset_x, png_uint_32 offset_y, int unit_type));
|
||||
extern void png_read_tIME PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_time *mod_time));
|
||||
extern void png_read_tEXt PNGARG((png_struct *png_ptr, png_info *info,
|
||||
char *key, char *text, png_uint_32 text_len));
|
||||
extern void png_read_zTXt PNGARG((png_struct *png_ptr, png_info *info,
|
||||
char *key, char *text, png_uint_32 text_len, int compression));
|
||||
|
||||
void
|
||||
png_build_gamma_table PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* combine a row of data, dealing with alpha, etc. if requested */
|
||||
extern void png_combine_row PNGARG((png_struct *png_ptr, png_byte *row,
|
||||
int mask));
|
||||
/* expand an interlaced row */
|
||||
extern void png_do_read_interlace PNGARG((png_row_info *row_info,
|
||||
png_byte *row, int pass));
|
||||
/* grab pixels out of a row for an interlaced pass */
|
||||
extern void png_do_write_interlace PNGARG((png_row_info *row_info,
|
||||
png_byte *row, int pass));
|
||||
|
||||
/* unfilter a row */
|
||||
extern void png_read_filter_row PNGARG((png_row_info *row_info,
|
||||
png_byte *row, png_byte *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_info *row_info,
|
||||
png_byte *row, png_byte *prev_row));
|
||||
/* finish a row while reading, dealing with interlacing passes, etc. */
|
||||
extern void png_read_finish_row PNGARG((png_struct *png_ptr));
|
||||
/* initialize the row buffers, etc. */
|
||||
extern void png_read_start_row PNGARG((png_struct *png_ptr));
|
||||
|
||||
/* these are the functions that do the transformations */
|
||||
extern void png_do_read_rgbx PNGARG((png_row_info *row_info,
|
||||
png_byte *row));
|
||||
extern void png_do_write_rgbx PNGARG((png_row_info *row_info,
|
||||
png_byte *row));
|
||||
extern void png_do_read_xrgb PNGARG((png_row_info *row_info,
|
||||
png_byte *row));
|
||||
extern void png_do_write_xrgb PNGARG((png_row_info *row_info,
|
||||
png_byte *row));
|
||||
extern void png_do_swap PNGARG((png_row_info *row_info, png_byte *row));
|
||||
extern void png_do_unpack PNGARG((png_row_info *row_info, png_byte *row));
|
||||
extern void png_do_unshift PNGARG((png_row_info *row_info, png_byte *row,
|
||||
png_color_8 *sig_bits));
|
||||
extern void png_do_invert PNGARG((png_row_info *row_info, png_byte *row));
|
||||
extern void png_do_gray_to_rgb PNGARG((png_row_info *row_info,
|
||||
png_byte *row));
|
||||
extern void png_do_chop PNGARG((png_row_info *row_info, png_byte *row));
|
||||
extern void png_do_dither PNGARG((png_row_info *row_info,
|
||||
png_byte *row, png_byte *palette_lookup, png_byte *dither_lookup));
|
||||
extern void png_do_bgr PNGARG((png_row_info *row_info, png_byte *row));
|
||||
extern void png_do_pack PNGARG((png_row_info *row_info,
|
||||
png_byte *row, png_byte bit_depth));
|
||||
extern void png_do_shift PNGARG((png_row_info *row_info, png_byte *row,
|
||||
png_color_8 *bit_depth));
|
||||
extern void png_do_background PNGARG((png_row_info *row_info, png_byte *row,
|
||||
png_color_16 *trans_values, png_color_16 *background,
|
||||
png_color_16 *background_1,
|
||||
png_byte *gamma_table, png_byte *gamma_from_1, png_byte *gamma_to_1,
|
||||
png_uint_16 **gamma_16, png_uint_16 **gamma_16_from_1,
|
||||
png_uint_16 **gamma_16_to_1, int gamma_shift));
|
||||
extern void png_do_gamma PNGARG((png_row_info *row_info, png_byte *row,
|
||||
png_byte *gamma_table, png_uint_16 **gamma_16_table,
|
||||
int gamma_shift));
|
||||
extern void png_do_expand_palette PNGARG((png_row_info *row_info,
|
||||
png_byte *row, png_color *palette, png_byte *trans, int num_trans));
|
||||
extern void png_do_expand PNGARG((png_row_info *row_info,
|
||||
png_byte *row, png_color_16 *trans_value));
|
||||
|
||||
/* unpack 16 and 32 bit values from a string */
|
||||
extern png_uint_32 png_get_uint_32 PNGARG((png_byte *buf));
|
||||
extern png_uint_16 png_get_uint_16 PNGARG((png_byte *buf));
|
||||
|
||||
/* read bytes into buf, and update png_ptr->crc */
|
||||
extern void png_crc_read PNGARG((png_struct *png_ptr, png_byte *buf,
|
||||
png_uint_32 length));
|
||||
/* skip length bytes, and update png_ptr->crc */
|
||||
extern void png_crc_skip PNGARG((png_struct *png_ptr, png_uint_32 length));
|
||||
|
||||
/* the following decodes the appropriate chunks, and does error correction,
|
||||
then calls the appropriate callback for the chunk if it is valid */
|
||||
|
||||
/* decode the IHDR chunk */
|
||||
extern void png_handle_IHDR PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 length));
|
||||
extern void png_handle_PLTE PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 length));
|
||||
extern void png_handle_gAMA PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 length));
|
||||
extern void png_handle_sBIT PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 length));
|
||||
extern void png_handle_cHRM PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 length));
|
||||
extern void png_handle_tRNS PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 length));
|
||||
extern void png_handle_bKGD PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 length));
|
||||
extern void png_handle_hIST PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 length));
|
||||
extern void png_handle_pHYs PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 length));
|
||||
extern void png_handle_oFFs PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 length));
|
||||
extern void png_handle_tIME PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 length));
|
||||
extern void png_handle_tEXt PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 length));
|
||||
extern void png_handle_zTXt PNGARG((png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 length));
|
||||
|
||||
/* handle the transformations for reading and writing */
|
||||
extern void png_do_read_transformations PNGARG((png_struct *png_ptr));
|
||||
extern void png_do_write_transformations PNGARG((png_struct *png_ptr));
|
||||
|
||||
extern void png_init_read_transformations PNGARG((png_struct *png_ptr));
|
||||
|
||||
|
||||
#endif /* PNG_INTERNAL */
|
||||
|
||||
/* do not put anything past this line */
|
||||
#endif /* _PNG_H */
|
|
@ -0,0 +1,44 @@
|
|||
pngchange.txt - changes for libpng
|
||||
|
||||
version 0.2
|
||||
added reader into png.h
|
||||
fixed small problems in stub file
|
||||
version 0.3
|
||||
added pull reader
|
||||
split up pngwrite.c to several files
|
||||
added pnglib.txt
|
||||
added example.c
|
||||
cleaned up writer, adding a few new tranformations
|
||||
fixed some bugs in writer
|
||||
interfaced with zlib 0.5
|
||||
added K&R support
|
||||
added check for 64 KB blocks for 16 bit machines
|
||||
version 0.4
|
||||
cleaned up code and commented code
|
||||
simplified time handling into png_time
|
||||
created png_color_16 and png_color_8 to handle color needs
|
||||
cleaned up color type defines
|
||||
fixed various bugs
|
||||
made various names more consistant
|
||||
interfaced with zlib 0.71
|
||||
cleaned up zTXt reader and writer (using zlib's Reset functions)
|
||||
split transformations into pngrtran.c and pngwtran.c
|
||||
version 0.5
|
||||
interfaced with zlib 0.8
|
||||
fixed many reading and writing bugs
|
||||
saved using 3 spaces instead of tabs
|
||||
version 0.6
|
||||
added png_large_malloc() and png_large_free()
|
||||
added png_size_t
|
||||
cleaned up some compiler warnings
|
||||
added png_start_read_image()
|
||||
version 0.7
|
||||
cleaned up lots of bugs
|
||||
finished dithering and other stuff
|
||||
added test program
|
||||
changed name from pnglib to libpng
|
||||
version 0.71
|
||||
changed pngtest.png for zlib 0.93
|
||||
fixed error in libpng.txt and example.c
|
||||
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
/* pngrcb.c - callbacks while reading a png file
|
||||
|
||||
libpng 1.0 beta 1 - version 0.71
|
||||
For conditions of distribution and use, see copyright notice in png.h
|
||||
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
|
||||
June 26, 1995
|
||||
*/
|
||||
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
void
|
||||
png_read_IHDR(png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 width, png_uint_32 height, int bit_depth,
|
||||
int color_type, int compression_type, int filter_type,
|
||||
int interlace_type)
|
||||
{
|
||||
if (!png_ptr || !info)
|
||||
return;
|
||||
|
||||
info->width = width;
|
||||
info->height = height;
|
||||
info->bit_depth = bit_depth;
|
||||
info->color_type = color_type;
|
||||
info->compression_type = compression_type;
|
||||
info->filter_type = filter_type;
|
||||
info->interlace_type = interlace_type;
|
||||
if (info->color_type == PNG_COLOR_TYPE_PALETTE)
|
||||
info->channels = 1;
|
||||
else if (info->color_type & PNG_COLOR_MASK_COLOR)
|
||||
info->channels = 3;
|
||||
else
|
||||
info->channels = 1;
|
||||
if (info->color_type & PNG_COLOR_MASK_ALPHA)
|
||||
info->channels++;
|
||||
info->pixel_depth = info->channels * info->bit_depth;
|
||||
info->rowbytes = ((info->width * info->pixel_depth + 7) >> 3);
|
||||
}
|
||||
|
||||
void
|
||||
png_read_PLTE(png_struct *png_ptr, png_info *info,
|
||||
png_color *palette, int num)
|
||||
{
|
||||
if (!png_ptr || !info)
|
||||
return;
|
||||
|
||||
info->palette = palette;
|
||||
info->num_palette = num;
|
||||
info->valid |= PNG_INFO_PLTE;
|
||||
}
|
||||
|
||||
void
|
||||
png_read_gAMA(png_struct *png_ptr, png_info *info, float gamma)
|
||||
{
|
||||
if (!png_ptr || !info)
|
||||
return;
|
||||
|
||||
info->gamma = gamma;
|
||||
info->valid |= PNG_INFO_gAMA;
|
||||
}
|
||||
|
||||
void
|
||||
png_read_sBIT(png_struct *png_ptr, png_info *info,
|
||||
png_color_8 *sig_bit)
|
||||
{
|
||||
if (!png_ptr || !info)
|
||||
return;
|
||||
|
||||
memcpy(&(info->sig_bit), sig_bit, sizeof (png_color_8));
|
||||
info->valid |= PNG_INFO_sBIT;
|
||||
}
|
||||
|
||||
void
|
||||
png_read_cHRM(png_struct *png_ptr, png_info *info,
|
||||
float white_x, float white_y, float red_x, float red_y,
|
||||
float green_x, float green_y, float blue_x, float blue_y)
|
||||
{
|
||||
if (!png_ptr || !info)
|
||||
return;
|
||||
|
||||
info->x_white = white_x;
|
||||
info->y_white = white_y;
|
||||
info->x_red = red_x;
|
||||
info->y_red = red_y;
|
||||
info->x_green = green_x;
|
||||
info->y_green = green_y;
|
||||
info->x_blue = blue_x;
|
||||
info->y_blue = blue_y;
|
||||
info->valid |= PNG_INFO_cHRM;
|
||||
}
|
||||
|
||||
void
|
||||
png_read_tRNS(png_struct *png_ptr, png_info *info,
|
||||
png_byte *trans, int num_trans, png_color_16 *trans_values)
|
||||
{
|
||||
if (!png_ptr || !info)
|
||||
return;
|
||||
|
||||
if (trans)
|
||||
{
|
||||
info->trans = trans;
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(&(info->trans_values), trans_values,
|
||||
sizeof(png_color_16));
|
||||
}
|
||||
info->num_trans = num_trans;
|
||||
info->valid |= PNG_INFO_tRNS;
|
||||
}
|
||||
|
||||
void
|
||||
png_read_bKGD(png_struct *png_ptr, png_info *info,
|
||||
png_color_16 *background)
|
||||
{
|
||||
if (!png_ptr || !info)
|
||||
return;
|
||||
|
||||
memcpy(&(info->background), background, sizeof(png_color_16));
|
||||
info->valid |= PNG_INFO_bKGD;
|
||||
}
|
||||
|
||||
void
|
||||
png_read_hIST(png_struct *png_ptr, png_info *info, png_uint_16 *hist)
|
||||
{
|
||||
if (!png_ptr || !info)
|
||||
return;
|
||||
|
||||
info->hist = hist;
|
||||
info->valid |= PNG_INFO_hIST;
|
||||
}
|
||||
|
||||
void
|
||||
png_read_pHYs(png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 res_x, png_uint_32 res_y, int unit_type)
|
||||
{
|
||||
if (!png_ptr || !info)
|
||||
return;
|
||||
|
||||
info->x_pixels_per_unit = res_x;
|
||||
info->y_pixels_per_unit = res_y;
|
||||
info->phys_unit_type = unit_type;
|
||||
info->valid |= PNG_INFO_pHYs;
|
||||
}
|
||||
|
||||
void
|
||||
png_read_oFFs(png_struct *png_ptr, png_info *info,
|
||||
png_uint_32 offset_x, png_uint_32 offset_y, int unit_type)
|
||||
{
|
||||
if (!png_ptr || !info)
|
||||
return;
|
||||
|
||||
info->x_offset = offset_x;
|
||||
info->y_offset = offset_y;
|
||||
info->offset_unit_type = unit_type;
|
||||
info->valid |= PNG_INFO_oFFs;
|
||||
}
|
||||
|
||||
void
|
||||
png_read_tIME(png_struct *png_ptr, png_info *info,
|
||||
png_time *mod_time)
|
||||
{
|
||||
if (!png_ptr || !info)
|
||||
return;
|
||||
|
||||
memcpy(&(info->mod_time), mod_time, sizeof (png_time));
|
||||
info->valid |= PNG_INFO_tIME;
|
||||
}
|
||||
|
||||
void
|
||||
png_read_zTXt(png_struct *png_ptr, png_info *info,
|
||||
char *key, char *text, png_uint_32 text_len, int compression)
|
||||
{
|
||||
if (!png_ptr || !info)
|
||||
return;
|
||||
|
||||
if (info->max_text <= info->num_text)
|
||||
{
|
||||
if (info->text)
|
||||
{
|
||||
info->max_text = info->num_text + 16;
|
||||
info->text = (png_text *)png_realloc(png_ptr,
|
||||
info->text,
|
||||
info->max_text * sizeof (png_text));
|
||||
}
|
||||
else
|
||||
{
|
||||
info->max_text = info->num_text + 16;
|
||||
info->text = (png_text *)png_malloc(png_ptr,
|
||||
info->max_text * sizeof (png_text));
|
||||
info->num_text = 0;
|
||||
}
|
||||
}
|
||||
|
||||
info->text[info->num_text].key = key;
|
||||
info->text[info->num_text].text = text;
|
||||
info->text[info->num_text].text_length = text_len;
|
||||
info->text[info->num_text].compression = compression;
|
||||
info->num_text++;
|
||||
}
|
||||
|
||||
void
|
||||
png_read_tEXt(png_struct *png_ptr, png_info *info,
|
||||
char *key, char *text, png_uint_32 text_len)
|
||||
{
|
||||
if (!png_ptr || !info)
|
||||
return;
|
||||
|
||||
png_read_zTXt(png_ptr, info, key, text, text_len, -1);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,642 @@
|
|||
|
||||
/* pngread.c - read a png file
|
||||
|
||||
libpng 1.0 beta 1 - version 0.71
|
||||
For conditions of distribution and use, see copyright notice in png.h
|
||||
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
|
||||
June 26, 1995
|
||||
*/
|
||||
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
/* initialize png structure for reading, and allocate any memory needed */
|
||||
void
|
||||
png_read_init(png_struct *png_ptr)
|
||||
{
|
||||
jmp_buf tmp_jmp;
|
||||
|
||||
memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
|
||||
memset(png_ptr, 0, sizeof (png_struct));
|
||||
memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
|
||||
|
||||
png_ptr->zbuf_size = PNG_ZBUF_SIZE;
|
||||
png_ptr->zbuf = png_large_malloc(png_ptr, png_ptr->zbuf_size);
|
||||
png_ptr->zstream = &(png_ptr->zstream_struct);
|
||||
png_ptr->zstream->zalloc = png_zalloc;
|
||||
png_ptr->zstream->zfree = png_zfree;
|
||||
png_ptr->zstream->opaque = (voidp)png_ptr;
|
||||
inflateInit(png_ptr->zstream);
|
||||
png_ptr->zstream->next_out = png_ptr->zbuf;
|
||||
png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
|
||||
}
|
||||
|
||||
/* read the information before the actual image data. */
|
||||
void
|
||||
png_read_info(png_struct *png_ptr, png_info *info)
|
||||
{
|
||||
png_byte chunk_start[8];
|
||||
png_uint_32 length;
|
||||
|
||||
png_read_data(png_ptr, chunk_start, 8);
|
||||
if (memcmp(chunk_start, png_sig, 8))
|
||||
png_error(png_ptr, "Not a Png File");
|
||||
|
||||
while (1)
|
||||
{
|
||||
png_uint_32 crc;
|
||||
|
||||
png_read_data(png_ptr, chunk_start, 8);
|
||||
length = png_get_uint_32(chunk_start);
|
||||
png_reset_crc(png_ptr);
|
||||
png_calculate_crc(png_ptr, chunk_start + 4, 4);
|
||||
if (!memcmp(chunk_start + 4, png_IHDR, 4))
|
||||
{
|
||||
if (png_ptr->mode != PNG_BEFORE_IHDR)
|
||||
png_error(png_ptr, "Out of Place IHDR");
|
||||
|
||||
png_handle_IHDR(png_ptr, info, length);
|
||||
png_ptr->mode = PNG_HAVE_IHDR;
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_PLTE, 4))
|
||||
{
|
||||
if (png_ptr->mode != PNG_HAVE_IHDR)
|
||||
png_error(png_ptr, "Missing IHDR");
|
||||
|
||||
png_handle_PLTE(png_ptr, info, length);
|
||||
png_ptr->mode = PNG_HAVE_PLTE;
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_gAMA, 4))
|
||||
{
|
||||
if (png_ptr->mode != PNG_HAVE_IHDR)
|
||||
png_error(png_ptr, "Out of Place PLTE");
|
||||
|
||||
png_handle_gAMA(png_ptr, info, length);
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_sBIT, 4))
|
||||
{
|
||||
if (png_ptr->mode != PNG_HAVE_IHDR)
|
||||
png_error(png_ptr, "Out of Place sBIT");
|
||||
|
||||
png_handle_sBIT(png_ptr, info, length);
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_cHRM, 4))
|
||||
{
|
||||
if (png_ptr->mode != PNG_HAVE_IHDR)
|
||||
png_error(png_ptr, "Out of Place cHRM");
|
||||
|
||||
png_handle_cHRM(png_ptr, info, length);
|
||||
}
|
||||
else if (!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);
|
||||
}
|
||||
else if (!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);
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_hIST, 4))
|
||||
{
|
||||
if (png_ptr->mode != PNG_HAVE_PLTE)
|
||||
png_error(png_ptr, "Out of Place hIST");
|
||||
|
||||
png_handle_hIST(png_ptr, info, length);
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_IDAT, 4))
|
||||
{
|
||||
png_ptr->idat_size = length;
|
||||
png_ptr->mode = PNG_HAVE_IDAT;
|
||||
break;
|
||||
}
|
||||
else if (!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);
|
||||
}
|
||||
else if (!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);
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_tIME, 4))
|
||||
{
|
||||
if (png_ptr->mode == PNG_BEFORE_IHDR ||
|
||||
png_ptr->mode == PNG_AFTER_IEND)
|
||||
png_error(png_ptr, "Out of Place tIME");
|
||||
|
||||
png_handle_tIME(png_ptr, info, length);
|
||||
}
|
||||
else if (!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);
|
||||
}
|
||||
else if (!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);
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_IEND, 4))
|
||||
{
|
||||
png_error(png_ptr, "No Image in File");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isupper(chunk_start[4]))
|
||||
png_error(png_ptr, "Unknown Critical Chunk");
|
||||
|
||||
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))
|
||||
png_error(png_ptr, "Bad CRC value");
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize palette, background, etc, after transformations
|
||||
are set, but before any reading takes place. This allows
|
||||
the user to obtail a gamma corrected palette, for example.
|
||||
If the user doesn't call this, we will do it ourselves. */
|
||||
void
|
||||
png_start_read_image(png_struct *png_ptr)
|
||||
{
|
||||
png_read_start_row(png_ptr);
|
||||
}
|
||||
|
||||
void
|
||||
png_read_row(png_struct *png_ptr, png_byte *row, png_byte *dsp_row)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!(png_ptr->row_init))
|
||||
png_read_start_row(png_ptr);
|
||||
|
||||
/* if interlaced and we do not need a new row, combine row and return */
|
||||
if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
|
||||
{
|
||||
switch (png_ptr->pass)
|
||||
{
|
||||
case 0:
|
||||
if (png_ptr->row_number & 7)
|
||||
{
|
||||
if (dsp_row)
|
||||
png_combine_row(png_ptr, dsp_row,
|
||||
png_pass_dsp_mask[png_ptr->pass]);
|
||||
png_read_finish_row(png_ptr);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if ((png_ptr->row_number & 7) || png_ptr->width < 5)
|
||||
{
|
||||
if (dsp_row)
|
||||
png_combine_row(png_ptr, dsp_row,
|
||||
png_pass_dsp_mask[png_ptr->pass]);
|
||||
png_read_finish_row(png_ptr);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if ((png_ptr->row_number & 7) != 4)
|
||||
{
|
||||
if (dsp_row && (png_ptr->row_number & 4))
|
||||
png_combine_row(png_ptr, dsp_row,
|
||||
png_pass_dsp_mask[png_ptr->pass]);
|
||||
png_read_finish_row(png_ptr);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if ((png_ptr->row_number & 3) || png_ptr->width < 3)
|
||||
{
|
||||
if (dsp_row)
|
||||
png_combine_row(png_ptr, dsp_row,
|
||||
png_pass_dsp_mask[png_ptr->pass]);
|
||||
png_read_finish_row(png_ptr);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if ((png_ptr->row_number & 3) != 2)
|
||||
{
|
||||
if (dsp_row && (png_ptr->row_number & 2))
|
||||
png_combine_row(png_ptr, dsp_row,
|
||||
png_pass_dsp_mask[png_ptr->pass]);
|
||||
png_read_finish_row(png_ptr);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if ((png_ptr->row_number & 1) || png_ptr->width < 2)
|
||||
{
|
||||
if (dsp_row)
|
||||
png_combine_row(png_ptr, dsp_row,
|
||||
png_pass_dsp_mask[png_ptr->pass]);
|
||||
png_read_finish_row(png_ptr);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if (!(png_ptr->row_number & 1))
|
||||
{
|
||||
png_read_finish_row(png_ptr);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
do
|
||||
{
|
||||
if (!(png_ptr->zstream->avail_in))
|
||||
{
|
||||
while (!png_ptr->idat_size)
|
||||
{
|
||||
png_byte buf[4];
|
||||
png_uint_32 crc;
|
||||
|
||||
png_read_data(png_ptr, buf, 4);
|
||||
crc = png_get_uint_32(buf);
|
||||
if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
|
||||
(png_ptr->crc & 0xffffffffL))
|
||||
png_error(png_ptr, "Bad CRC value");
|
||||
|
||||
png_read_data(png_ptr, buf, 4);
|
||||
png_ptr->idat_size = png_get_uint_32(buf);
|
||||
png_reset_crc(png_ptr);
|
||||
|
||||
png_crc_read(png_ptr, buf, 4);
|
||||
if (memcmp(buf, png_IDAT, 4))
|
||||
png_error(png_ptr, "Not enough image data");
|
||||
|
||||
}
|
||||
png_ptr->zstream->avail_in = (uInt)png_ptr->zbuf_size;
|
||||
png_ptr->zstream->next_in = png_ptr->zbuf;
|
||||
if (png_ptr->zbuf_size > png_ptr->idat_size)
|
||||
png_ptr->zstream->avail_in = (uInt)png_ptr->idat_size;
|
||||
png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream->avail_in);
|
||||
png_ptr->idat_size -= png_ptr->zstream->avail_in;
|
||||
}
|
||||
ret = inflate(png_ptr->zstream, Z_PARTIAL_FLUSH);
|
||||
if (ret == Z_STREAM_END)
|
||||
{
|
||||
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;
|
||||
break;
|
||||
}
|
||||
if (ret != Z_OK)
|
||||
png_error(png_ptr, "Compression 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;
|
||||
png_ptr->row_info.bit_depth = png_ptr->bit_depth;
|
||||
png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
|
||||
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]));
|
||||
|
||||
memcpy(png_ptr->prev_row, png_ptr->row_buf, (png_size_t)png_ptr->rowbytes + 1);
|
||||
|
||||
if (png_ptr->transformations)
|
||||
png_do_read_transformations(png_ptr);
|
||||
|
||||
/* blow up interlaced rows to full size */
|
||||
if (png_ptr->interlaced &&
|
||||
(png_ptr->transformations & PNG_INTERLACE))
|
||||
{
|
||||
if (png_ptr->pass < 6)
|
||||
png_do_read_interlace(&(png_ptr->row_info),
|
||||
png_ptr->row_buf + 1, png_ptr->pass);
|
||||
|
||||
if (dsp_row)
|
||||
png_combine_row(png_ptr, dsp_row,
|
||||
png_pass_dsp_mask[png_ptr->pass]);
|
||||
if (row)
|
||||
png_combine_row(png_ptr, row,
|
||||
png_pass_mask[png_ptr->pass]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (row)
|
||||
png_combine_row(png_ptr, row, 0xff);
|
||||
if (dsp_row)
|
||||
png_combine_row(png_ptr, dsp_row, 0xff);
|
||||
}
|
||||
png_read_finish_row(png_ptr);
|
||||
}
|
||||
|
||||
/* read a one or more rows of image data. If the image is interlaced,
|
||||
and png_set_interlace_handling() has been called, the rows need to
|
||||
to contain the contents of the rows from the previous pass. If
|
||||
the image has alpha or transparency, and png_handle_alpha() has been
|
||||
called, the rows contents must be initialized to the contents of the
|
||||
screen. row holds the actual image, and pixels are placed in it
|
||||
as they arrive. If the image is displayed after each pass, it will
|
||||
appear to "sparkle" in. display_row can be used to display a
|
||||
"chunky" progressive image, with finer detail added as it becomes
|
||||
available. If you do not want this "chunky" display, you may pass
|
||||
NULL for display_rows. If you do not want the sparkle display, and
|
||||
you have not called png_handle_alpha(), you may pass NULL for rows.
|
||||
If you have called png_handle_alpha(), and the image has either an
|
||||
alpha channel or a transparency chunk, you must provide a buffer for
|
||||
rows. In this case, you do not have to provide a display_rows buffer
|
||||
also, but you may. If the image is not interlaced, or if you have
|
||||
not called png_set_interlace_handling(), the display_row buffer will
|
||||
be ignored, so pass NULL to it. */
|
||||
void
|
||||
png_read_rows(png_struct *png_ptr, png_byte **row,
|
||||
png_byte **display_row, png_uint_32 num_rows)
|
||||
{
|
||||
png_uint_32 i;
|
||||
png_byte **rp;
|
||||
png_byte **dp;
|
||||
|
||||
rp = row;
|
||||
dp = display_row;
|
||||
for (i = 0; i < num_rows; i++)
|
||||
{
|
||||
png_byte *rptr;
|
||||
png_byte *dptr;
|
||||
|
||||
if (rp)
|
||||
rptr = *rp;
|
||||
else
|
||||
rptr = NULL;
|
||||
if (dp)
|
||||
dptr = *dp;
|
||||
else
|
||||
dptr = NULL;
|
||||
png_read_row(png_ptr, rptr, dptr);
|
||||
if (row)
|
||||
rp++;
|
||||
if (display_row)
|
||||
dp++;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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() */
|
||||
void
|
||||
png_read_image(png_struct *png_ptr, png_byte **image)
|
||||
{
|
||||
png_uint_32 i;
|
||||
int pass, j;
|
||||
png_byte **rp;
|
||||
|
||||
pass = png_set_interlace_handling(png_ptr);
|
||||
for (j = 0; j < pass; j++)
|
||||
{
|
||||
rp = image;
|
||||
for (i = 0; i < png_ptr->height; i++)
|
||||
{
|
||||
png_read_row(png_ptr, *rp, NULL);
|
||||
rp++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* read the end of the png file. Will not read past the end of the
|
||||
file, will verify the end is accurate, and will read any comments
|
||||
or time information at the end of the file, if info is not NULL. */
|
||||
void
|
||||
png_read_end(png_struct *png_ptr, png_info *info)
|
||||
{
|
||||
png_byte chunk_start[8];
|
||||
png_uint_32 length;
|
||||
png_uint_32 crc;
|
||||
|
||||
png_read_data(png_ptr, chunk_start, 4);
|
||||
crc = png_get_uint_32(chunk_start);
|
||||
if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
|
||||
(png_ptr->crc & 0xffffffffL))
|
||||
png_error(png_ptr, "Bad CRC value");
|
||||
|
||||
do
|
||||
{
|
||||
png_read_data(png_ptr, chunk_start, 8);
|
||||
length = png_get_uint_32(chunk_start);
|
||||
png_reset_crc(png_ptr);
|
||||
png_calculate_crc(png_ptr, chunk_start + 4, 4);
|
||||
|
||||
if (!memcmp(chunk_start + 4, png_IHDR, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_PLTE, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_gAMA, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_sBIT, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_cHRM, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_tRNS, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_bKGD, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_hIST, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_IDAT, 4))
|
||||
{
|
||||
if (length > 0 || png_ptr->mode != PNG_AT_LAST_IDAT)
|
||||
png_error(png_ptr, "too many IDAT's found");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_pHYs, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_oFFs, 4))
|
||||
{
|
||||
png_error(png_ptr, "invalid chunk after IDAT");
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_tIME, 4))
|
||||
{
|
||||
if (png_ptr->mode == PNG_BEFORE_IHDR ||
|
||||
png_ptr->mode == PNG_AFTER_IEND)
|
||||
png_error(png_ptr, "Out of Place tIME");
|
||||
|
||||
if (info)
|
||||
png_handle_tIME(png_ptr, info, length);
|
||||
else
|
||||
png_crc_skip(png_ptr, length);
|
||||
}
|
||||
else if (!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");
|
||||
|
||||
if (info)
|
||||
png_handle_tEXt(png_ptr, info, length);
|
||||
else
|
||||
png_crc_skip(png_ptr, length);
|
||||
}
|
||||
else if (!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");
|
||||
|
||||
if (info)
|
||||
png_handle_zTXt(png_ptr, info, length);
|
||||
else
|
||||
png_crc_skip(png_ptr, length);
|
||||
}
|
||||
else if (!memcmp(chunk_start + 4, png_IEND, 4))
|
||||
{
|
||||
png_ptr->mode = PNG_AFTER_IEND;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isupper(chunk_start[4]))
|
||||
png_error(png_ptr, "Unknown Critical Chunk");
|
||||
|
||||
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))
|
||||
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);
|
||||
}
|
||||
|
||||
/* free all memory used by the read */
|
||||
void
|
||||
png_read_destroy(png_struct *png_ptr, png_info *info, png_info *end_info)
|
||||
{
|
||||
int i;
|
||||
jmp_buf tmp_jmp;
|
||||
|
||||
if (info)
|
||||
{
|
||||
if (info->palette != png_ptr->palette)
|
||||
png_free(png_ptr, info->palette);
|
||||
if (info->trans != png_ptr->trans)
|
||||
png_free(png_ptr, info->trans);
|
||||
if (info->hist != png_ptr->hist)
|
||||
png_free(png_ptr, info->hist);
|
||||
for (i = 0; i < info->num_text; i++)
|
||||
{
|
||||
png_large_free(png_ptr, info->text[i].key);
|
||||
}
|
||||
|
||||
png_free(png_ptr, info->text);
|
||||
memset(info, 0, sizeof(png_info));
|
||||
}
|
||||
|
||||
if (end_info)
|
||||
{
|
||||
for (i = 0; i < end_info->num_text; i++)
|
||||
{
|
||||
png_large_free(png_ptr, end_info->text[i].key);
|
||||
}
|
||||
|
||||
png_free(png_ptr, end_info->text);
|
||||
memset(end_info, 0, sizeof(png_info));
|
||||
}
|
||||
|
||||
png_large_free(png_ptr, png_ptr->zbuf);
|
||||
png_large_free(png_ptr, png_ptr->row_buf);
|
||||
png_large_free(png_ptr, png_ptr->prev_row);
|
||||
png_large_free(png_ptr, png_ptr->palette_lookup);
|
||||
png_free(png_ptr, png_ptr->dither_index);
|
||||
png_free(png_ptr, png_ptr->gamma_table);
|
||||
png_free(png_ptr, png_ptr->gamma_from_1);
|
||||
png_free(png_ptr, png_ptr->gamma_to_1);
|
||||
if (png_ptr->gamma_16_table)
|
||||
{
|
||||
for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
|
||||
{
|
||||
png_free(png_ptr, png_ptr->gamma_16_table[i]);
|
||||
}
|
||||
}
|
||||
png_free(png_ptr, png_ptr->gamma_16_table);
|
||||
if (png_ptr->gamma_16_from_1)
|
||||
{
|
||||
for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
|
||||
{
|
||||
png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
|
||||
}
|
||||
}
|
||||
png_free(png_ptr, png_ptr->gamma_16_from_1);
|
||||
if (png_ptr->gamma_16_to_1)
|
||||
{
|
||||
for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
|
||||
{
|
||||
png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
|
||||
}
|
||||
}
|
||||
png_free(png_ptr, png_ptr->gamma_16_to_1);
|
||||
png_free(png_ptr, png_ptr->trans);
|
||||
png_free(png_ptr, png_ptr->hist);
|
||||
if (!png_ptr->user_palette)
|
||||
png_free(png_ptr, png_ptr->palette);
|
||||
|
||||
inflateEnd(png_ptr->zstream);
|
||||
|
||||
memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
|
||||
memset(png_ptr, 0, sizeof (png_struct));
|
||||
memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,387 @@
|
|||
|
||||
/* pngstub.c - stub functions for i/o and memory allocation
|
||||
|
||||
libpng 1.0 beta 1 - version 0.71
|
||||
For conditions of distribution and use, see copyright notice in png.h
|
||||
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
|
||||
June 26, 1995
|
||||
|
||||
This file provides a location for all input/output, memory location,
|
||||
and error handling. Users which need special handling in these areas
|
||||
are expected to modify the code in this file to meet their needs. See
|
||||
the instructions at each function. */
|
||||
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
/* Write the data to whatever output you are using. The default
|
||||
routine writes to a file pointer. If you need to write to something
|
||||
else, this is the place to do it. We suggest saving the old code
|
||||
for future use, possibly in a #define. Note that this routine sometimes
|
||||
gets called with very small lengths, so you should implement some kind
|
||||
of simple buffering if you are using unbuffered writes. This should
|
||||
never be asked to write more then 64K on a 16 bit machine. The cast
|
||||
to png_size_t is there for insurance, but if you are having problems
|
||||
with it, you can take it out. Just be sure to cast length to whatever
|
||||
fwrite needs in that spot if you don't have a function prototype for
|
||||
it. */
|
||||
void
|
||||
png_write_data(png_struct *png_ptr, png_byte *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");
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the data from whatever input you are using. The default
|
||||
routine reads from a file pointer. If you need to read from something
|
||||
else, this is the place to do it. We suggest saving the old code
|
||||
for future use. Note that this routine sometimes gets called with
|
||||
very small lengths, so you should implement some kind of simple
|
||||
buffering if you are using unbuffered reads. This should
|
||||
never be asked to read more then 64K on a 16 bit machine. The cast
|
||||
to png_size_t is there for insurance, but if you are having problems
|
||||
with it, you can take it out. Just be sure to cast length to whatever
|
||||
fread needs in that spot if you don't have a function prototype for
|
||||
it. */
|
||||
void
|
||||
png_read_data(png_struct *png_ptr, png_byte *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");
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the input/output for the png file. If you change
|
||||
the read and write routines, you will probably need to change
|
||||
this routine (or write your own). If you change the parameters
|
||||
of this routine, remember to change png.h also. */
|
||||
void
|
||||
png_init_io(png_struct *png_ptr, FILE *fp)
|
||||
{
|
||||
png_ptr->fp = fp;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
/* Borland compilers have this habit of not giving you 64K chunks
|
||||
that start on the segment in DOS mode. This has not been observed
|
||||
in Windows, and of course it doesn't matter in 32 bit mode, as there
|
||||
are no segments. Now libpng doesn't need that much memory normally,
|
||||
but zlib does, so we have to normalize it, if necessary. It would be
|
||||
better if zlib worked in less then 64K, but it doesn't, so we
|
||||
have to deal with it. Truely, we are misusing farmalloc here,
|
||||
as it is designed for use with huge pointers, which don't care
|
||||
about segments. So we allocate a large amount of memory, and
|
||||
divvy off segments when needed.
|
||||
*/
|
||||
#ifdef __TURBOC__
|
||||
#ifndef __WIN32__
|
||||
|
||||
/* NUM_SEG is the number of segments allocated at once */
|
||||
#define NUM_SEG 4
|
||||
typedef struct borland_seg_struct
|
||||
{
|
||||
void *mem_ptr;
|
||||
void *seg_ptr[NUM_SEG];
|
||||
int seg_used[NUM_SEG];
|
||||
int num_used;
|
||||
} borland_seg;
|
||||
|
||||
borland_seg *save_array;
|
||||
int num_save_array;
|
||||
int max_save_array;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void *
|
||||
png_large_malloc(png_struct *png_ptr, png_uint_32 size)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
#ifdef PNG_MAX_MALLOC_64K
|
||||
if (size > (png_uint_32)65536L)
|
||||
png_error(png_ptr, "Cannot Allocate > 64K");
|
||||
#endif
|
||||
|
||||
#ifdef __TURBOC__
|
||||
# ifdef __WIN32__
|
||||
ret = farmalloc(size);
|
||||
# else
|
||||
|
||||
if (size == 65536L)
|
||||
{
|
||||
unsigned long offset;
|
||||
if (!save_array)
|
||||
{
|
||||
ret = farmalloc(size);
|
||||
offset = (unsigned long)(ret);
|
||||
offset &= 0xffffL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = (void *)0;
|
||||
}
|
||||
if (save_array || offset)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
if (ret)
|
||||
farfree(ret);
|
||||
ret = (void *)0;
|
||||
|
||||
if (!save_array)
|
||||
{
|
||||
unsigned long offset;
|
||||
png_byte huge *ptr;
|
||||
int i;
|
||||
|
||||
num_save_array = 1;
|
||||
save_array = malloc(num_save_array * sizeof (borland_seg));
|
||||
if (!save_array)
|
||||
png_error(png_ptr, "Out of Memory");
|
||||
save_array->mem_ptr = farmalloc(
|
||||
(unsigned long)(NUM_SEG) * 65536L + 65528L);
|
||||
if (!save_array->mem_ptr)
|
||||
png_error(png_ptr, "Out of Memory");
|
||||
offset = (unsigned long)(ret);
|
||||
offset &= 0xffffL;
|
||||
ptr = save_array->mem_ptr;
|
||||
if (offset)
|
||||
ptr += 65536L - offset;
|
||||
for (i = 0; i < NUM_SEG; i++, ptr += 65536L)
|
||||
{
|
||||
save_array->seg_ptr[i] = ptr;
|
||||
save_array->seg_used[i] = 0;
|
||||
}
|
||||
save_array->num_used = 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_save_array; i++)
|
||||
{
|
||||
for (j = 0; j < NUM_SEG; j++)
|
||||
{
|
||||
if (!save_array[i].seg_used[j])
|
||||
{
|
||||
ret = save_array[i].seg_ptr[j];
|
||||
save_array[i].seg_used[j] = 1;
|
||||
save_array[i].num_used++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
unsigned long offset;
|
||||
png_byte huge *ptr;
|
||||
|
||||
save_array = realloc(save_array,
|
||||
(num_save_array + 1) * sizeof (borland_seg));
|
||||
if (!save_array)
|
||||
png_error(png_ptr, "Out of Memory");
|
||||
save_array[num_save_array].mem_ptr = farmalloc(
|
||||
(unsigned long)(NUM_SEG) * 65536L + 65528L);
|
||||
if (!save_array[num_save_array].mem_ptr)
|
||||
png_error(png_ptr, "Out of Memory");
|
||||
offset = (unsigned long)(ret);
|
||||
offset &= 0xffffL;
|
||||
ptr = save_array[num_save_array].mem_ptr;
|
||||
if (offset)
|
||||
ptr += 65536L - offset;
|
||||
for (i = 0; i < NUM_SEG; i++, ptr += 65536L)
|
||||
{
|
||||
save_array[num_save_array].seg_ptr[i] = ptr;
|
||||
save_array[num_save_array].seg_used[i] = 0;
|
||||
}
|
||||
ret = save_array[num_save_array].seg_ptr[0];
|
||||
save_array[num_save_array].seg_used[0] = 1;
|
||||
save_array[num_save_array].num_used = 1;
|
||||
num_save_array++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = farmalloc(size);
|
||||
}
|
||||
|
||||
# endif /* __WIN32__ */
|
||||
#else /* __TURBOC__ */
|
||||
# ifdef _MSC_VER
|
||||
ret = halloc(size, 1);
|
||||
# else
|
||||
/* everybody else, so normal malloc should do it. */
|
||||
ret = malloc(size);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
png_error(png_ptr, "Out of Memory");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* free a pointer allocated by png_large_malloc(). In the default
|
||||
configuration, png_ptr is not used, but is passed in case it
|
||||
is needed. If ptr is NULL, return without taking any action. */
|
||||
void
|
||||
png_large_free(png_struct *png_ptr, void *ptr)
|
||||
{
|
||||
if (!png_ptr)
|
||||
return;
|
||||
|
||||
if (ptr != (void *)0)
|
||||
{
|
||||
#ifdef __TURBOC__
|
||||
# ifndef __WIN32__
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < num_save_array; i++)
|
||||
{
|
||||
for (j = 0; j < NUM_SEG; j++)
|
||||
{
|
||||
if (ptr == save_array[i].seg_ptr[j])
|
||||
{
|
||||
printf("freeing pointer: i, j: %d, %d\n", i, j);
|
||||
save_array[i].seg_used[j] = 0;
|
||||
ptr = 0;
|
||||
save_array[i].num_used--;
|
||||
if (!save_array[i].num_used)
|
||||
{
|
||||
int k;
|
||||
printf("freeing array: %d\n", i);
|
||||
num_save_array--;
|
||||
farfree(save_array[i].mem_ptr);
|
||||
for (k = i; k < num_save_array; k++)
|
||||
save_array[k] = save_array[k + 1];
|
||||
if (!num_save_array)
|
||||
{
|
||||
free(save_array);
|
||||
save_array = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ptr)
|
||||
break;
|
||||
}
|
||||
|
||||
# endif
|
||||
if (ptr)
|
||||
farfree(ptr);
|
||||
#else
|
||||
# ifdef _MSC_VER
|
||||
hfree(ptr);
|
||||
# else
|
||||
free(ptr);
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate memory. This is called for smallish blocks only It
|
||||
should not get anywhere near 64K. */
|
||||
void *
|
||||
png_malloc(png_struct *png_ptr, png_uint_32 size)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
if (!png_ptr)
|
||||
return ((void *)0);
|
||||
|
||||
#ifdef PNG_MAX_MALLOC_64K
|
||||
if (size > (png_uint_32)65536L)
|
||||
png_error(png_ptr, "Cannot Allocate > 64K");
|
||||
#endif
|
||||
|
||||
ret = malloc((png_size_t)size);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
png_error(png_ptr, "Out of Memory");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reallocate memory. This will not get near 64K on a
|
||||
even marginally reasonable file. */
|
||||
void *
|
||||
png_realloc(png_struct *png_ptr, void *ptr, png_uint_32 size)
|
||||
{
|
||||
void *ret;
|
||||
|
||||
if (!png_ptr)
|
||||
return ((void *)0);
|
||||
|
||||
#ifdef PNG_MAX_MALLOC_64K
|
||||
if (size > (png_uint_32)65536L)
|
||||
png_error(png_ptr, "Cannot Allocate > 64K");
|
||||
#endif
|
||||
|
||||
ret = realloc(ptr, (png_size_t)size);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
png_error(png_ptr, "Out of Memory");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* free a pointer allocated by png_malloc(). In the default
|
||||
configuration, png_ptr is not used, but is passed incase it
|
||||
is needed. If ptr is NULL, return without taking any action. */
|
||||
void
|
||||
png_free(png_struct *png_ptr, void *ptr)
|
||||
{
|
||||
if (!png_ptr)
|
||||
return;
|
||||
|
||||
if (ptr != (void *)0)
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
/* This function is called whenever there is an error. Replace with
|
||||
however you wish to handle the error. Note that this function
|
||||
MUST NOT return, or the program will crash */
|
||||
void
|
||||
png_error(png_struct *png_ptr, char *message)
|
||||
{
|
||||
fprintf(stderr, "libpng error: %s\n", message);
|
||||
|
||||
longjmp(png_ptr->jmpbuf, 1);
|
||||
}
|
||||
|
||||
/* This function is called when there is a warning, but the library
|
||||
thinks it can continue anyway. You don't have to do anything here
|
||||
if you don't want to. In the default configuration, png_ptr is
|
||||
not used, but it is passed in case it may be useful. */
|
||||
void
|
||||
png_warning(png_struct *png_ptr, char *message)
|
||||
{
|
||||
if (!png_ptr)
|
||||
return;
|
||||
|
||||
fprintf(stderr, "libpng warning: %s\n", message);
|
||||
}
|
||||
|
|
@ -0,0 +1,180 @@
|
|||
/* pngtest.c - a simple test program to test libpng
|
||||
|
||||
libpng 1.0 beta 1 - version 0.71
|
||||
For conditions of distribution and use, see copyright notice in png.h
|
||||
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
|
||||
June 26, 1995
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "png.h"
|
||||
|
||||
#ifdef __TURBOC__
|
||||
#include <mem.h>
|
||||
#endif
|
||||
|
||||
/* defined so I can write to a file on gui/windowing platforms */
|
||||
#define STDERR stderr
|
||||
|
||||
/* 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;
|
||||
|
||||
char inbuf[256], outbuf[256];
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *fpin, *fpout;
|
||||
png_byte *row_buf;
|
||||
png_uint_32 rowbytes;
|
||||
png_uint_32 y;
|
||||
int channels, num_pass, pass;
|
||||
|
||||
row_buf = (png_byte *)0;
|
||||
|
||||
fpin = fopen(inname, "rb");
|
||||
if (!fpin)
|
||||
{
|
||||
fprintf(STDERR, "Could not find input file %s\n", inname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fpout = fopen(outname, "wb");
|
||||
if (!fpin)
|
||||
{
|
||||
fprintf(STDERR, "could not open output file %s\n", outname);
|
||||
fclose(fpin);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setjmp(read_ptr.jmpbuf))
|
||||
{
|
||||
fprintf(STDERR, "libpng read error\n");
|
||||
fclose(fpin);
|
||||
fclose(fpout);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setjmp(write_ptr.jmpbuf))
|
||||
{
|
||||
fprintf(STDERR, "libpng write error\n");
|
||||
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_read_info(&read_ptr, &info_ptr);
|
||||
png_write_info(&write_ptr, &info_ptr);
|
||||
|
||||
if ((info_ptr.color_type & 3) == 2)
|
||||
channels = 3;
|
||||
else
|
||||
channels = 1;
|
||||
if (info_ptr.color_type & 4)
|
||||
channels++;
|
||||
|
||||
rowbytes = ((info_ptr.width * info_ptr.bit_depth * channels + 7) >> 3);
|
||||
row_buf = (png_byte *)malloc((size_t)rowbytes);
|
||||
if (!row_buf)
|
||||
{
|
||||
fprintf(STDERR, "no memory to allocate row buffer\n");
|
||||
png_read_destroy(&read_ptr, &info_ptr, (png_info *)0);
|
||||
png_write_destroy(&write_ptr);
|
||||
fclose(fpin);
|
||||
fclose(fpout);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (info_ptr.interlace_type)
|
||||
{
|
||||
num_pass = png_set_interlace_handling(&read_ptr);
|
||||
num_pass = png_set_interlace_handling(&write_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
num_pass = 1;
|
||||
}
|
||||
|
||||
for (pass = 0; pass < num_pass; pass++)
|
||||
{
|
||||
for (y = 0; y < info_ptr.height; y++)
|
||||
{
|
||||
png_read_rows(&read_ptr, &row_buf, (png_byte **)0, 1);
|
||||
png_write_rows(&write_ptr, &row_buf, 1);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
fclose(fpin);
|
||||
fclose(fpout);
|
||||
|
||||
free(row_buf);
|
||||
|
||||
fpin = fopen(inname, "rb");
|
||||
|
||||
if (!fpin)
|
||||
{
|
||||
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);
|
||||
fclose(fpin);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
int num_in, num_out;
|
||||
|
||||
num_in = fread(inbuf, 1, 256, fpin);
|
||||
num_out = fread(outbuf, 1, 256, fpout);
|
||||
|
||||
if (num_in != num_out)
|
||||
{
|
||||
fprintf(STDERR, "files are of a different size\n");
|
||||
fclose(fpin);
|
||||
fclose(fpout);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!num_in)
|
||||
break;
|
||||
|
||||
if (memcmp(inbuf, outbuf, num_in))
|
||||
{
|
||||
fprintf(STDERR, "files are different\n");
|
||||
fclose(fpin);
|
||||
fclose(fpout);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fpin);
|
||||
fclose(fpout);
|
||||
fprintf(STDERR, "libpng passes test\n");
|
||||
|
||||
return 0;
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 7.1 KiB |
|
@ -0,0 +1,22 @@
|
|||
pngtodo.txt - list of things to do for libpng
|
||||
|
||||
allow user to #define out unused transformations
|
||||
medium memory model support
|
||||
overlaying one image on top of another
|
||||
optional palette creation
|
||||
histogram creation
|
||||
text conversion between different code types
|
||||
cHRM transformation
|
||||
support for other chunks being defined (sCAl, the gIF series,
|
||||
and others that people come up with).
|
||||
push reader
|
||||
pull writer
|
||||
better dithering
|
||||
keep up with public chunks
|
||||
other compression libraries
|
||||
more exotic interlace handling
|
||||
better filtering
|
||||
C++ wrapper
|
||||
other languages
|
||||
comments of > 64K
|
||||
|
|
@ -0,0 +1,192 @@
|
|||
|
||||
/* pngtrans.c - transforms the data in a row
|
||||
routines used by both readers and writers
|
||||
|
||||
libpng 1.0 beta 1 - version 0.71
|
||||
For conditions of distribution and use, see copyright notice in png.h
|
||||
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
|
||||
June 26, 1995
|
||||
*/
|
||||
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
/* turn on bgr to rgb mapping */
|
||||
void
|
||||
png_set_bgr(png_struct *png_ptr)
|
||||
{
|
||||
png_ptr->transformations |= PNG_BGR;
|
||||
}
|
||||
|
||||
/* turn on 16 bit byte swapping */
|
||||
void
|
||||
png_set_swap(png_struct *png_ptr)
|
||||
{
|
||||
if (png_ptr->bit_depth == 16)
|
||||
png_ptr->transformations |= PNG_SWAP_BYTES;
|
||||
}
|
||||
|
||||
/* turn on pixel packing */
|
||||
void
|
||||
png_set_packing(png_struct *png_ptr)
|
||||
{
|
||||
if (png_ptr->bit_depth < 8)
|
||||
{
|
||||
png_ptr->transformations |= PNG_PACK;
|
||||
png_ptr->usr_bit_depth = 8;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
png_set_shift(png_struct *png_ptr, png_color_8 *true_bits)
|
||||
{
|
||||
png_ptr->transformations |= PNG_SHIFT;
|
||||
png_ptr->shift = *true_bits;
|
||||
}
|
||||
|
||||
int
|
||||
png_set_interlace_handling(png_struct *png_ptr)
|
||||
{
|
||||
if (png_ptr->interlaced)
|
||||
{
|
||||
png_ptr->transformations |= PNG_INTERLACE;
|
||||
return 7;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
png_set_rgbx(png_struct *png_ptr)
|
||||
{
|
||||
png_ptr->transformations |= PNG_RGBA;
|
||||
if (png_ptr->color_type == PNG_COLOR_TYPE_RGB &&
|
||||
png_ptr->bit_depth == 8)
|
||||
png_ptr->usr_channels = 4;
|
||||
}
|
||||
|
||||
void
|
||||
png_set_xrgb(png_struct *png_ptr)
|
||||
{
|
||||
png_ptr->transformations |= PNG_XRGB;
|
||||
if (png_ptr->color_type == PNG_COLOR_TYPE_RGB &&
|
||||
png_ptr->bit_depth == 8)
|
||||
png_ptr->usr_channels = 4;
|
||||
}
|
||||
|
||||
void
|
||||
png_set_invert_mono(png_struct *png_ptr)
|
||||
{
|
||||
png_ptr->transformations |= PNG_INVERT_MONO;
|
||||
}
|
||||
|
||||
/* invert monocrome grayscale data */
|
||||
void
|
||||
png_do_invert(png_row_info *row_info, png_byte *row)
|
||||
{
|
||||
if (row && row_info && row_info->bit_depth == 1 &&
|
||||
row_info->color_type == PNG_COLOR_TYPE_GRAY)
|
||||
{
|
||||
png_byte *rp;
|
||||
png_uint_32 i;
|
||||
|
||||
for (i = 0, rp = row;
|
||||
i < row_info->rowbytes;
|
||||
i++, rp++)
|
||||
{
|
||||
*rp = ~(*rp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* swaps byte order on 16 bit depth images */
|
||||
void
|
||||
png_do_swap(png_row_info *row_info, png_byte *row)
|
||||
{
|
||||
if (row && row_info && row_info->bit_depth == 16)
|
||||
{
|
||||
png_byte *rp, t;
|
||||
png_uint_32 i;
|
||||
|
||||
for (i = 0, rp = row;
|
||||
i < row_info->width * row_info->channels;
|
||||
i++, rp += 2)
|
||||
{
|
||||
t = *rp;
|
||||
*rp = *(rp + 1);
|
||||
*(rp + 1) = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* swaps red and blue */
|
||||
void
|
||||
png_do_bgr(png_row_info *row_info, png_byte *row)
|
||||
{
|
||||
if (row && row_info && (row_info->color_type & 2))
|
||||
{
|
||||
if (row_info->color_type == 2 && row_info->bit_depth == 8)
|
||||
{
|
||||
png_byte *rp, t;
|
||||
png_uint_32 i;
|
||||
|
||||
for (i = 0, rp = row;
|
||||
i < row_info->width;
|
||||
i++, rp += 3)
|
||||
{
|
||||
t = *rp;
|
||||
*rp = *(rp + 2);
|
||||
*(rp + 2) = t;
|
||||
}
|
||||
}
|
||||
else if (row_info->color_type == 6 && row_info->bit_depth == 8)
|
||||
{
|
||||
png_byte *rp, t;
|
||||
png_uint_32 i;
|
||||
|
||||
for (i = 0, rp = row;
|
||||
i < row_info->width;
|
||||
i++, rp += 4)
|
||||
{
|
||||
t = *rp;
|
||||
*rp = *(rp + 2);
|
||||
*(rp + 2) = t;
|
||||
}
|
||||
}
|
||||
else if (row_info->color_type == 2 && row_info->bit_depth == 16)
|
||||
{
|
||||
png_byte *rp, t[2];
|
||||
png_uint_32 i;
|
||||
|
||||
for (i = 0, rp = row;
|
||||
i < row_info->width;
|
||||
i++, rp += 6)
|
||||
{
|
||||
t[0] = *rp;
|
||||
t[1] = *(rp + 1);
|
||||
*rp = *(rp + 4);
|
||||
*(rp + 1) = *(rp + 5);
|
||||
*(rp + 4) = t[0];
|
||||
*(rp + 5) = t[1];
|
||||
}
|
||||
}
|
||||
else if (row_info->color_type == 6 && row_info->bit_depth == 16)
|
||||
{
|
||||
png_byte *rp, t[2];
|
||||
png_uint_32 i;
|
||||
|
||||
for (i = 0, rp = row;
|
||||
i < row_info->width;
|
||||
i++, rp += 8)
|
||||
{
|
||||
t[0] = *rp;
|
||||
t[1] = *(rp + 1);
|
||||
*rp = *(rp + 4);
|
||||
*(rp + 1) = *(rp + 5);
|
||||
*(rp + 4) = t[0];
|
||||
*(rp + 5) = t[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,408 @@
|
|||
|
||||
/* pngwrite.c - general routines to write a png file
|
||||
|
||||
libpng 1.0 beta 1 - version 0.71
|
||||
For conditions of distribution and use, see copyright notice in png.h
|
||||
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
|
||||
June 26, 1995
|
||||
*/
|
||||
|
||||
/* get internal access to png.h */
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
/* Writes all the png information. This is the suggested way to use
|
||||
the library. If you have a new chunk to add, make a function to
|
||||
write it, and put it in the correct location here. If you want
|
||||
the chunk written after the image data, put it in png_write_end().
|
||||
I strongly encurage you to supply a PNG_INFO_ flag, and check
|
||||
info->valid before writing the chunk, as that will keep the code
|
||||
from breaking if you want to just write a plain png file.
|
||||
If you have long comments, I suggest writing them in png_write_end(),
|
||||
and compressing them. */
|
||||
void
|
||||
png_write_info(png_struct *png_ptr, png_info *info)
|
||||
{
|
||||
png_write_sig(png_ptr); /* write PNG signature */
|
||||
/* write IHDR information. */
|
||||
png_write_IHDR(png_ptr, info->width, info->height, info->bit_depth,
|
||||
info->color_type, info->compression_type, info->filter_type,
|
||||
info->interlace_type);
|
||||
/* the rest of these check to see if the valid field has the appropriate
|
||||
flag set, and if it does, writes the chunk. */
|
||||
if (info->valid & PNG_INFO_gAMA)
|
||||
png_write_gAMA(png_ptr, info->gamma);
|
||||
if (info->valid & PNG_INFO_sBIT)
|
||||
png_write_sBIT(png_ptr, &(info->sig_bit), info->color_type);
|
||||
if (info->valid & PNG_INFO_cHRM)
|
||||
png_write_cHRM(png_ptr,
|
||||
info->x_white, info->y_white,
|
||||
info->x_red, info->y_red,
|
||||
info->x_green, info->y_green,
|
||||
info->x_blue, info->y_blue);
|
||||
if (info->valid & PNG_INFO_PLTE)
|
||||
png_write_PLTE(png_ptr, info->palette, info->num_palette);
|
||||
if (info->valid & PNG_INFO_tRNS)
|
||||
png_write_tRNS(png_ptr, info->trans, &(info->trans_values),
|
||||
info->num_trans, info->color_type);
|
||||
if (info->valid & PNG_INFO_bKGD)
|
||||
png_write_bKGD(png_ptr, &(info->background), info->color_type);
|
||||
if (info->valid & PNG_INFO_hIST)
|
||||
png_write_hIST(png_ptr, info->hist, info->num_palette);
|
||||
if (info->valid & PNG_INFO_pHYs)
|
||||
png_write_pHYs(png_ptr, info->x_pixels_per_unit,
|
||||
info->y_pixels_per_unit, info->phys_unit_type);
|
||||
if (info->valid & PNG_INFO_oFFs)
|
||||
png_write_oFFs(png_ptr, info->x_offset, info->y_offset,
|
||||
info->offset_unit_type);
|
||||
if (info->valid & PNG_INFO_tIME)
|
||||
png_write_tIME(png_ptr, &(info->mod_time));
|
||||
/* Check to see if we need to write text chunks */
|
||||
if (info->num_text)
|
||||
{
|
||||
int i; /* local counter */
|
||||
|
||||
/* loop through the text chunks */
|
||||
for (i = 0; i < info->num_text; i++)
|
||||
{
|
||||
/* if chunk is compressed */
|
||||
if (info->text[i].compression >= 0)
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* write uncompressed chunk */
|
||||
png_write_tEXt(png_ptr, info->text[i].key,
|
||||
info->text[i].text, info->text[i].text_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* writes the end of the png file. If you don't want to write comments or
|
||||
time information, you can pass NULL for info. If you already wrote these
|
||||
in png_write_info(), do not write them again here. If you have long
|
||||
comments, I suggest writing them here, and compressing them. */
|
||||
void
|
||||
png_write_end(png_struct *png_ptr, png_info *info)
|
||||
{
|
||||
/* see if user wants us to write information chunks */
|
||||
if (info)
|
||||
{
|
||||
/* check to see if user has supplied a time chunk */
|
||||
if (info->valid & PNG_INFO_tIME)
|
||||
png_write_tIME(png_ptr, &(info->mod_time));
|
||||
/* check to see if we need to write comment chunks */
|
||||
if (info->num_text)
|
||||
{
|
||||
int i; /* local index variable */
|
||||
|
||||
/* loop through comment chunks */
|
||||
for (i = 0; i < info->num_text; i++)
|
||||
{
|
||||
/* check to see if comment is to be compressed */
|
||||
if (info->text[i].compression >= 0)
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* write uncompressed chunk */
|
||||
png_write_tEXt(png_ptr, info->text[i].key,
|
||||
info->text[i].text, info->text[i].text_length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* write end of png file */
|
||||
png_write_IEND(png_ptr);
|
||||
}
|
||||
|
||||
/* initialize the info structure */
|
||||
void
|
||||
png_info_init(png_info *info)
|
||||
{
|
||||
/* set everything to 0 */
|
||||
memset(info, 0, sizeof (png_info));
|
||||
}
|
||||
|
||||
void
|
||||
png_convert_from_struct_tm(png_time *ptime, struct tm *ttime)
|
||||
{
|
||||
ptime->year = 1900 + ttime->tm_year;
|
||||
ptime->month = ttime->tm_mon + 1;
|
||||
ptime->day = ttime->tm_mday;
|
||||
ptime->hour = ttime->tm_hour;
|
||||
ptime->minute = ttime->tm_min;
|
||||
ptime->second = ttime->tm_sec;
|
||||
}
|
||||
|
||||
void
|
||||
png_convert_from_time_t(png_time *ptime, time_t ttime)
|
||||
{
|
||||
struct tm *tbuf;
|
||||
|
||||
tbuf = gmtime(&ttime);
|
||||
png_convert_from_struct_tm(ptime, tbuf);
|
||||
}
|
||||
|
||||
/* initialize png structure, and allocate any memory needed */
|
||||
void
|
||||
png_write_init(png_struct *png_ptr)
|
||||
{
|
||||
jmp_buf tmp_jmp; /* to save current jump buffer */
|
||||
|
||||
/* save jump buffer */
|
||||
memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
|
||||
/* reset all variables to 0 */
|
||||
memset(png_ptr, 0, sizeof (png_struct));
|
||||
/* restore jump buffer */
|
||||
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);
|
||||
/* initialize zlib */
|
||||
png_ptr->zstream = &(png_ptr->zstream_struct);
|
||||
png_ptr->zstream->zalloc = png_zalloc;
|
||||
png_ptr->zstream->zfree = png_zfree;
|
||||
png_ptr->zstream->opaque = (voidp)png_ptr;
|
||||
deflateInit(png_ptr->zstream, Z_BEST_COMPRESSION);
|
||||
png_ptr->zstream->next_out = png_ptr->zbuf;
|
||||
png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
|
||||
}
|
||||
|
||||
/* write a few rows of image data. If the image is interlaced,
|
||||
either you will have to write the 7 sub images, or, if you
|
||||
have called png_set_interlace_handling(), you will have to
|
||||
"write" the image seven times */
|
||||
void
|
||||
png_write_rows(png_struct *png_ptr, png_byte **row,
|
||||
png_uint_32 num_rows)
|
||||
{
|
||||
png_uint_32 i; /* row counter */
|
||||
png_byte **rp; /* row pointer */
|
||||
|
||||
/* loop through the rows */
|
||||
for (i = 0, rp = row; i < num_rows; i++, rp++)
|
||||
{
|
||||
png_write_row(png_ptr, *rp);
|
||||
}
|
||||
}
|
||||
|
||||
/* write the image. You only need to call this function once, even
|
||||
if you are writing an interlaced image. */
|
||||
void
|
||||
png_write_image(png_struct *png_ptr, png_byte **image)
|
||||
{
|
||||
png_uint_32 i; /* row index */
|
||||
int pass, num_pass; /* pass variables */
|
||||
png_byte **rp; /* points to current row */
|
||||
|
||||
/* intialize interlace handling. If image is not interlaced,
|
||||
this will set pass to 1 */
|
||||
num_pass = png_set_interlace_handling(png_ptr);
|
||||
/* loop through passes */
|
||||
for (pass = 0; pass < num_pass; pass++)
|
||||
{
|
||||
/* loop through image */
|
||||
for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
|
||||
{
|
||||
png_write_row(png_ptr, *rp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* write a row of image data */
|
||||
void
|
||||
png_write_row(png_struct *png_ptr, png_byte *row)
|
||||
{
|
||||
/* initialize transformations and other stuff if first time */
|
||||
if (png_ptr->row_number == 0 && png_ptr->pass == 0)
|
||||
{
|
||||
png_write_start_row(png_ptr);
|
||||
}
|
||||
|
||||
/* if interlaced and not interested in row, return */
|
||||
if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
|
||||
{
|
||||
switch (png_ptr->pass)
|
||||
{
|
||||
case 0:
|
||||
if (png_ptr->row_number & 7)
|
||||
{
|
||||
png_write_finish_row(png_ptr);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if ((png_ptr->row_number & 7) || png_ptr->width < 5)
|
||||
{
|
||||
png_write_finish_row(png_ptr);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if ((png_ptr->row_number & 7) != 4)
|
||||
{
|
||||
png_write_finish_row(png_ptr);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
if ((png_ptr->row_number & 3) || png_ptr->width < 3)
|
||||
{
|
||||
png_write_finish_row(png_ptr);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if ((png_ptr->row_number & 3) != 2)
|
||||
{
|
||||
png_write_finish_row(png_ptr);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if ((png_ptr->row_number & 1) || png_ptr->width < 2)
|
||||
{
|
||||
png_write_finish_row(png_ptr);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
if (!(png_ptr->row_number & 1))
|
||||
{
|
||||
png_write_finish_row(png_ptr);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* set up row info for transformations */
|
||||
png_ptr->row_info.color_type = png_ptr->color_type;
|
||||
png_ptr->row_info.width = png_ptr->usr_width;
|
||||
png_ptr->row_info.channels = png_ptr->usr_channels;
|
||||
png_ptr->row_info.bit_depth = png_ptr->usr_bit_depth;
|
||||
png_ptr->row_info.pixel_depth = png_ptr->row_info.bit_depth *
|
||||
png_ptr->row_info.channels;
|
||||
png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
|
||||
(png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
|
||||
|
||||
/* copy users row into buffer, leaving room for filter byte */
|
||||
memcpy(png_ptr->row_buf + 1, row, (png_size_t)png_ptr->row_info.rowbytes);
|
||||
|
||||
/* handle interlacing */
|
||||
if (png_ptr->interlaced && png_ptr->pass < 6 &&
|
||||
(png_ptr->transformations & PNG_INTERLACE))
|
||||
{
|
||||
png_do_write_interlace(&(png_ptr->row_info),
|
||||
png_ptr->row_buf + 1, png_ptr->pass);
|
||||
/* this should always get caught above, but still ... */
|
||||
if (!(png_ptr->row_info.width))
|
||||
{
|
||||
png_write_finish_row(png_ptr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle other transformations */
|
||||
if (png_ptr->transformations)
|
||||
png_do_write_transformations(png_ptr);
|
||||
|
||||
/* filter rows that have been proved to help */
|
||||
if (png_ptr->bit_depth >= 8 && png_ptr->color_type != 3)
|
||||
{
|
||||
/* save row to previous row */
|
||||
memcpy(png_ptr->save_row, png_ptr->row_buf,
|
||||
(png_size_t)png_ptr->row_info.rowbytes + 1);
|
||||
|
||||
/* 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_byte *tptr;
|
||||
|
||||
tptr = png_ptr->prev_row;
|
||||
png_ptr->prev_row = png_ptr->save_row;
|
||||
png_ptr->save_row = 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;
|
||||
|
||||
#ifdef zlibinout
|
||||
/* temp zlib problem */
|
||||
{
|
||||
extern FILE *fpzlibin;
|
||||
|
||||
fwrite(png_ptr->row_buf, 1, png_ptr->zstream->avail_in, fpzlibin);
|
||||
}
|
||||
/* end temp zlib problem */
|
||||
#endif
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* free any memory used in png struct */
|
||||
void
|
||||
png_write_destroy(png_struct *png_ptr)
|
||||
{
|
||||
jmp_buf tmp_jmp; /* save jump buffer */
|
||||
|
||||
/* free any memory zlib uses */
|
||||
deflateEnd(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);
|
||||
/* reset structure */
|
||||
memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
|
||||
memset(png_ptr, 0, sizeof (png_struct));
|
||||
memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
|
||||
}
|
||||
|
|
@ -0,0 +1,331 @@
|
|||
|
||||
/* pngwtran.c - transforms the data in a row for png writers
|
||||
|
||||
libpng 1.0 beta 1 - version 0.71
|
||||
For conditions of distribution and use, see copyright notice in png.h
|
||||
Copyright (c) 1995 Guy Eric Schalnat, Group 42, Inc.
|
||||
June 26, 1995
|
||||
*/
|
||||
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
/* transform the data according to the users wishes. The order of
|
||||
transformations is significant. */
|
||||
void
|
||||
png_do_write_transformations(png_struct *png_ptr)
|
||||
{
|
||||
if (png_ptr->transformations & PNG_RGBA)
|
||||
png_do_write_rgbx(&(png_ptr->row_info), png_ptr->row_buf + 1);
|
||||
if (png_ptr->transformations & PNG_XRGB)
|
||||
png_do_write_xrgb(&(png_ptr->row_info), png_ptr->row_buf + 1);
|
||||
if (png_ptr->transformations & PNG_PACK)
|
||||
png_do_pack(&(png_ptr->row_info), png_ptr->row_buf + 1,
|
||||
png_ptr->bit_depth);
|
||||
if (png_ptr->transformations & PNG_SHIFT)
|
||||
png_do_shift(&(png_ptr->row_info), png_ptr->row_buf + 1,
|
||||
&(png_ptr->shift));
|
||||
if (png_ptr->transformations & PNG_SWAP_BYTES)
|
||||
png_do_swap(&(png_ptr->row_info), png_ptr->row_buf + 1);
|
||||
if (png_ptr->transformations & PNG_BGR)
|
||||
png_do_bgr(&(png_ptr->row_info), png_ptr->row_buf + 1);
|
||||
if (png_ptr->transformations & PNG_INVERT_MONO)
|
||||
png_do_invert(&(png_ptr->row_info), png_ptr->row_buf + 1);
|
||||
}
|
||||
|
||||
/* pack pixels into bytes. Pass the true bit depth in bit_depth. The
|
||||
row_info bit depth should be 8 (one pixel per byte). The channels
|
||||
should be 1 (this only happens on grayscale and paletted images) */
|
||||
void
|
||||
png_do_pack(png_row_info *row_info, png_byte *row, png_byte bit_depth)
|
||||
{
|
||||
if (row_info && row && row_info->bit_depth == 8 &&
|
||||
row_info->channels == 1)
|
||||
{
|
||||
switch (bit_depth)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
png_byte *sp;
|
||||
png_byte *dp;
|
||||
int mask;
|
||||
png_int_32 i;
|
||||
int v;
|
||||
|
||||
sp = row;
|
||||
dp = row;
|
||||
mask = 0x80;
|
||||
v = 0;
|
||||
for (i = 0; i < row_info->width; i++)
|
||||
{
|
||||
if (*sp)
|
||||
v |= mask;
|
||||
sp++;
|
||||
if (mask > 1)
|
||||
mask >>= 1;
|
||||
else
|
||||
{
|
||||
mask = 0x80;
|
||||
*dp = v;
|
||||
dp++;
|
||||
v = 0;
|
||||
}
|
||||
}
|
||||
if (mask != 0x80)
|
||||
*dp = v;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
png_byte *sp;
|
||||
png_byte *dp;
|
||||
int shift;
|
||||
png_int_32 i;
|
||||
int v;
|
||||
png_byte value;
|
||||
|
||||
sp = row;
|
||||
dp = row;
|
||||
shift = 6;
|
||||
v = 0;
|
||||
for (i = 0; i < row_info->width; i++)
|
||||
{
|
||||
value = *sp & 0x3;
|
||||
v |= (value << shift);
|
||||
if (shift == 0)
|
||||
{
|
||||
shift = 6;
|
||||
*dp = v;
|
||||
dp++;
|
||||
v = 0;
|
||||
}
|
||||
else
|
||||
shift -= 2;
|
||||
sp++;
|
||||
}
|
||||
if (shift != 6)
|
||||
*dp = v;
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
png_byte *sp;
|
||||
png_byte *dp;
|
||||
int shift;
|
||||
png_int_32 i;
|
||||
int v;
|
||||
png_byte value;
|
||||
|
||||
sp = row;
|
||||
dp = row;
|
||||
shift = 4;
|
||||
v = 0;
|
||||
for (i = 0; i < row_info->width; i++)
|
||||
{
|
||||
value = *sp & 0xf;
|
||||
v |= (value << shift);
|
||||
|
||||
if (shift == 0)
|
||||
{
|
||||
shift = 4;
|
||||
*dp = v;
|
||||
dp++;
|
||||
v = 0;
|
||||
}
|
||||
else
|
||||
shift -= 4;
|
||||
|
||||
sp++;
|
||||
}
|
||||
if (shift != 4)
|
||||
*dp = v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
row_info->bit_depth = bit_depth;
|
||||
row_info->pixel_depth = bit_depth * row_info->channels;
|
||||
row_info->rowbytes =
|
||||
((row_info->width * row_info->pixel_depth + 7) >> 3);
|
||||
}
|
||||
}
|
||||
|
||||
/* shift pixel values to take advantage of whole range. Pass the
|
||||
true number of bits in bit_depth. The row should be packed
|
||||
according to row_info->bit_depth. Thus, if you had a row of
|
||||
bit depth 4, but the pixels only had values from 0 to 7, you
|
||||
would pass 3 as bit_depth, and this routine would translate the
|
||||
data to 0 to 15. */
|
||||
void
|
||||
png_do_shift(png_row_info *row_info, png_byte *row, png_color_8 *bit_depth)
|
||||
{
|
||||
if (row && row_info &&
|
||||
row_info->color_type != PNG_COLOR_TYPE_PALETTE)
|
||||
{
|
||||
int shift_start[4], shift_dec[4];
|
||||
int channels;
|
||||
|
||||
channels = 0;
|
||||
if (row_info->color_type & PNG_COLOR_MASK_COLOR)
|
||||
{
|
||||
shift_start[channels] = row_info->bit_depth - bit_depth->red;
|
||||
shift_dec[channels] = bit_depth->red;
|
||||
channels++;
|
||||
shift_start[channels] = row_info->bit_depth - bit_depth->green;
|
||||
shift_dec[channels] = bit_depth->green;
|
||||
channels++;
|
||||
shift_start[channels] = row_info->bit_depth - bit_depth->blue;
|
||||
shift_dec[channels] = bit_depth->blue;
|
||||
channels++;
|
||||
}
|
||||
else
|
||||
{
|
||||
shift_start[channels] = row_info->bit_depth - bit_depth->gray;
|
||||
shift_dec[channels] = bit_depth->gray;
|
||||
channels++;
|
||||
}
|
||||
if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
|
||||
{
|
||||
shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
|
||||
shift_dec[channels] = bit_depth->alpha;
|
||||
channels++;
|
||||
}
|
||||
|
||||
/* with low row dephts, could only be grayscale, so one channel */
|
||||
if (row_info->bit_depth < 8)
|
||||
{
|
||||
png_byte *bp;
|
||||
png_uint_32 i;
|
||||
int j;
|
||||
png_byte mask;
|
||||
|
||||
if (bit_depth->gray == 1 && row_info->bit_depth == 2)
|
||||
mask = 0x55;
|
||||
else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
|
||||
mask = 0x11;
|
||||
else
|
||||
mask = 0xff;
|
||||
|
||||
for (bp = row, i = 0; i < row_info->rowbytes; i++, bp++)
|
||||
{
|
||||
int v;
|
||||
|
||||
v = *bp;
|
||||
*bp = 0;
|
||||
for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
|
||||
{
|
||||
if (j > 0)
|
||||
*bp |= (png_byte)((v << j) & 0xff);
|
||||
else
|
||||
*bp |= (png_byte)((v >> (-j)) & mask);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (row_info->bit_depth == 8)
|
||||
{
|
||||
png_byte *bp;
|
||||
png_uint_32 i;
|
||||
int j;
|
||||
|
||||
for (bp = row, i = 0; i < row_info->width; i++)
|
||||
{
|
||||
int c;
|
||||
|
||||
for (c = 0; c < channels; c++, bp++)
|
||||
{
|
||||
int v;
|
||||
|
||||
v = *bp;
|
||||
*bp = 0;
|
||||
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
|
||||
{
|
||||
if (j > 0)
|
||||
*bp |= (png_byte)((v << j) & 0xff);
|
||||
else
|
||||
*bp |= (png_byte)((v >> (-j)) & 0xff);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
png_byte *bp;
|
||||
png_uint_32 i;
|
||||
int j;
|
||||
|
||||
for (bp = row, i = 0;
|
||||
i < row_info->width * row_info->channels;
|
||||
i++)
|
||||
{
|
||||
int c;
|
||||
|
||||
for (c = 0; c < channels; c++, bp += 2)
|
||||
{
|
||||
png_uint_16 value, v;
|
||||
|
||||
v = ((png_uint_16)(*bp) << 8) + (png_uint_16)(*(bp + 1));
|
||||
value = 0;
|
||||
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
|
||||
{
|
||||
if (j > 0)
|
||||
value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
|
||||
else
|
||||
value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
|
||||
}
|
||||
*bp = value >> 8;
|
||||
*(bp + 1) = value & 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* remove filler byte after rgb */
|
||||
void
|
||||
png_do_write_rgbx(png_row_info *row_info, png_byte *row)
|
||||
{
|
||||
if (row && row_info && row_info->color_type == PNG_COLOR_TYPE_RGB &&
|
||||
row_info->bit_depth == 8)
|
||||
{
|
||||
png_byte *sp, *dp;
|
||||
png_uint_32 i;
|
||||
|
||||
for (i = 1, sp = row + 4, dp = row + 3;
|
||||
i < row_info->width;
|
||||
i++)
|
||||
{
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
sp++;
|
||||
}
|
||||
row_info->channels = 3;
|
||||
row_info->pixel_depth = 24;
|
||||
row_info->rowbytes = row_info->width * 3;
|
||||
}
|
||||
}
|
||||
|
||||
/* remove filler byte before rgb */
|
||||
void
|
||||
png_do_write_xrgb(png_row_info *row_info, png_byte *row)
|
||||
{
|
||||
if (row && row_info && row_info->color_type == PNG_COLOR_TYPE_RGB &&
|
||||
row_info->bit_depth == 8)
|
||||
{
|
||||
png_byte *sp, *dp;
|
||||
png_uint_32 i;
|
||||
|
||||
for (i = 0, sp = row, dp = row;
|
||||
i < row_info->width;
|
||||
i++)
|
||||
{
|
||||
sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
*dp++ = *sp++;
|
||||
}
|
||||
row_info->channels = 3;
|
||||
row_info->pixel_depth = 24;
|
||||
row_info->rowbytes = row_info->width * 3;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,79 @@
|
|||
readme.txt - for libpng 0.71
|
||||
|
||||
This is the first beta version of libpng 1.0. By beta, I mean that
|
||||
all the code for 1.0 is there, and it works on all the machines
|
||||
I have running all the tests I have devised. However, there is
|
||||
always one more bug (at least), and I don't have many #define's in
|
||||
the code (yet) for various platforms that I do not have. Also, I'd
|
||||
like to see if I can get the code to compile with as few warnings
|
||||
as possible. Finally, as people use my code, they may have
|
||||
suggestions for additions that will make pnglib easier to port.
|
||||
|
||||
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 make file, but you will probably have to modify it
|
||||
for your own needs. I'm using Borland C++, running large memory
|
||||
model on Windows 3.11, but it should work on almost anything. Support
|
||||
for medium memory model is planned, but is not in 1.0 (probably in 1.1).
|
||||
|
||||
You will need zlib 0.93 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
|
||||
|
||||
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
|
||||
be available at the same place you picked up libpng. If it is
|
||||
not there, try ftp.uu.net in the /graphics/png directory.
|
||||
|
||||
This code is currently being archived at ftp.uu.net in the
|
||||
/graphics/png directory, and at ftp.group42.com in the /pub/png
|
||||
directory, and on CompuServe, Lib 20 (PNG) at GO GRAPHSUP.
|
||||
If you can't find it in any of those places, e-mail me, and I'll
|
||||
tell you where it is.
|
||||
|
||||
If you have any code changes, requests, problems, etc., please e-mail
|
||||
them to me. Also, I'd appreciate any make files or project files,
|
||||
and any modifications you needed to make to get libpng to compile,
|
||||
along with a #define variable to tell what compiler/system you are on.
|
||||
If you needed to add transformations to libpng, or wish libpng would
|
||||
provide the image in a different way, drop me a note (and code, if
|
||||
possible), so I can consider supporting the transformation.
|
||||
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:
|
||||
|
||||
internet: schalnat&group42.com
|
||||
CompuServe: 75501,1625
|
||||
|
||||
Please do not send me 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
|
||||
in the PNG specification that is related to using libpng, send it
|
||||
to me. Send me any questions that start with "I was using libpng,
|
||||
and ...". If in doubt, send questions to me. I'll bounce them
|
||||
to others, if necessary.
|
||||
|
||||
Please do not send suggestions on how to change PNG. We have
|
||||
been discussing PNG for 6 months now, and it is official and
|
||||
finished. If you have suggestions for libpng, however, I'll
|
||||
gladly listen. Even if your suggestion is not used for version
|
||||
1.0, it may be used later.
|
||||
|
||||
Good luck, and happy coding.
|
||||
|
||||
-Guy Eric Schalnat
|
||||
Group 42, Inc.
|
||||
Internet: schalnat@group42.com
|
||||
CompuServe: 75501,1625
|
||||
Web: www.group42.com
|
||||
FTP: ftp.group42.com
|
||||
|
Reference in New Issue