[libpng17] Update CHANGES and ANNOUNCE about pngcp; sync timepng.c with libpng16

This commit is contained in:
John Bowler 2016-05-06 19:09:58 -05:00 committed by Glenn Randers-Pehrson
parent 4cc89fb733
commit a70f5053de
5 changed files with 410 additions and 105 deletions

View File

@ -1,5 +1,5 @@
Libpng 1.7.0beta80 - May 5, 2016 Libpng 1.7.0beta80 - May 6, 2016
This is not intended to be a public release. It will be replaced This is not intended to be a public release. It will be replaced
within a few weeks by a public version or by another test version. within a few weeks by a public version or by another test version.
@ -1264,9 +1264,10 @@ Version 1.7.0beta79 [March 9, 2016]
(Robert C. Seacord). Various other flags in png.h made unsigned as well. (Robert C. Seacord). Various other flags in png.h made unsigned as well.
Fixed some misleading indentation (Krishnaraj Bhat). Fixed some misleading indentation (Krishnaraj Bhat).
Version 1.7.0beta80 [May 5, 2016] Version 1.7.0beta80 [May 6, 2016]
Fixed typo (missing underscore) in #define PNG_READ_16_TO_8_SUPPORTED Fixed typo (missing underscore) in #define PNG_READ_16_TO_8_SUPPORTED
Bug report by (Y.Ohashik). Bug report by (Y.Ohashik).
Quieted two Coverity issues in contrib/libtests/timepng.c.
Write code update (John Bowler): Write code update (John Bowler):
Implemented better defaulting of zlib settings based on image properties. Implemented better defaulting of zlib settings based on image properties.
Replaced pngtest.png with one compressed with the new zlib settings. Replaced pngtest.png with one compressed with the new zlib settings.
@ -1283,6 +1284,11 @@ Version 1.7.0beta80 [May 5, 2016]
There are minimal API changes beyond removal of the selection options. There are minimal API changes beyond removal of the selection options.
Work is still to be done to investigate a filter selection mechanism that Work is still to be done to investigate a filter selection mechanism that
is at least as good as the previous one. is at least as good as the previous one.
Minor write bug-fixes, remove unimplemented code. A debug() assert
fired if windowBits was set to 8 for the Huffman only and no-compression
cases. This commit changes it to do some extra checking. Removed
unreachable code in pz_default_settings and eliminated a spurious
warning in pngcp for small files.
Send comments/corrections/commendations to png-mng-implement at lists.sf.net Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit (subscription required; visit

View File

@ -5564,9 +5564,10 @@ Version 1.7.0beta79 [March 9, 2016]
(Robert C. Seacord). Various other flags in png.h made unsigned as well. (Robert C. Seacord). Various other flags in png.h made unsigned as well.
Fixed some misleading indentation (Krishnaraj Bhat). Fixed some misleading indentation (Krishnaraj Bhat).
Version 1.7.0beta80 [May 5, 2016] Version 1.7.0beta80 [May 6, 2016]
Fixed typo (missing underscore) in #define PNG_READ_16_TO_8_SUPPORTED Fixed typo (missing underscore) in #define PNG_READ_16_TO_8_SUPPORTED
Bug report by (Y.Ohashik). Bug report by (Y.Ohashik).
Quieted two Coverity issues in contrib/libtests/timepng.c.
Write code update (John Bowler): Write code update (John Bowler):
Implemented better defaulting of zlib settings based on image properties. Implemented better defaulting of zlib settings based on image properties.
Replaced pngtest.png with one compressed with the new zlib settings. Replaced pngtest.png with one compressed with the new zlib settings.
@ -5583,6 +5584,11 @@ Version 1.7.0beta80 [May 5, 2016]
There are minimal API changes beyond removal of the selection options. There are minimal API changes beyond removal of the selection options.
Work is still to be done to investigate a filter selection mechanism that Work is still to be done to investigate a filter selection mechanism that
is at least as good as the previous one. is at least as good as the previous one.
Minor write bug-fixes, remove unimplemented code. A debug() assert
fired if windowBits was set to 8 for the Huffman only and no-compression
cases. This commit changes it to do some extra checking. Removed
unreachable code in pz_default_settings and eliminated a spurious
warning in pngcp for small files.
Send comments/corrections/commendations to png-mng-implement at lists.sf.net Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit (subscription required; visit

View File

@ -1199,7 +1199,7 @@ getsearchopts(struct display *dp, const char *opt_str, int *value)
else if (opt == OPTIND(dp, windowBits)) else if (opt == OPTIND(dp, windowBits))
{ {
/* Changing windowBits for strategies that do not search the window is /* Changing windowBits for strategies that do not search the window is
* pointless. Huffman-only does not search, RLE only searchs backwards * pointless. Huffman-only does not search, RLE only searches backwards
* one byte, so given that the maximum string length is 258, a windowBits * one byte, so given that the maximum string length is 258, a windowBits
* of 9 is always sufficient. * of 9 is always sufficient.
*/ */

View File

@ -1,8 +1,8 @@
/* timepng.c /* timepng.c
* *
* Copyright (c) 2013 John Cunningham Bowler * Copyright (c) 2013,2016 John Cunningham Bowler
* *
* Last changed in libpng 1.6.1 [March 28, 2013] * Last changed in libpng 1.6.22 [(PENDING RELEASE)]
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -10,15 +10,17 @@
* *
* Load an arbitrary number of PNG files (from the command line, or, if there * Load an arbitrary number of PNG files (from the command line, or, if there
* are no arguments on the command line, from stdin) then run a time test by * are no arguments on the command line, from stdin) then run a time test by
* reading each file by row. The test does nothing with the read result and * reading each file by row or by image (possibly with transforms in the latter
* does no transforms. The only output is a time as a floating point number of * case). The only output is a time as a floating point number of seconds with
* seconds with 9 decimal digits. * 9 decimal digits.
*/ */
#define _POSIX_C_SOURCE 199309L /* for clock_gettime */ #define _POSIX_C_SOURCE 199309L /* for clock_gettime */
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <errno.h>
#include <limits.h>
#include <time.h> #include <time.h>
@ -35,36 +37,61 @@
# include "../../png.h" # include "../../png.h"
#endif #endif
static int read_png(FILE *fp) /* The following is to support direct compilation of this file as C++ */
#ifdef __cplusplus
# define voidcast(type, value) static_cast<type>(value)
#else
# define voidcast(type, value) (value)
#endif /* __cplusplus */
#if ((defined(PNG_SEQUENTIAL_READ_SUPPORTED)) && defined(PNG_STDIO_SUPPORTED)\
&& defined(PNG_EASY_ACCESS_SUPPORTED) && defined(PNG_INFO_IMAGE_SUPPORTED))
typedef struct
{ {
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0); FILE *input;
png_infop info_ptr = NULL; FILE *output;
png_bytep row = NULL, display = NULL; } io_data;
if (png_ptr == NULL) static PNG_CALLBACK(void, read_and_copy,
return 0; (png_structp png_ptr, png_bytep buffer, png_size_t cb))
{
io_data *io = (io_data*)png_get_io_ptr(png_ptr);
if (setjmp(png_jmpbuf(png_ptr))) if (fread(buffer, cb, 1, io->input) != 1)
png_error(png_ptr, strerror(errno));
if (fwrite(buffer, cb, 1, io->output) != 1)
{ {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL); perror("temporary file");
if (row != NULL) free(row); fprintf(stderr, "temporary file PNG write failed\n");
if (display != NULL) free(display); exit(1);
return 0;
} }
}
png_init_io(png_ptr, fp); static void read_by_row(png_structp png_ptr, png_infop info_ptr,
FILE *write_ptr, FILE *read_ptr)
{
/* These don't get freed on error, this is fine; the program immediately
* exits.
*/
png_bytep row = NULL, display = NULL;
io_data io_copy;
info_ptr = png_create_info_struct(png_ptr); if (write_ptr != NULL)
if (info_ptr == NULL) {
png_error(png_ptr, "OOM allocating info structure"); /* Set up for a copy to the temporary file: */
io_copy.input = read_ptr;
io_copy.output = write_ptr;
png_set_read_fn(png_ptr, &io_copy, read_and_copy);
}
png_read_info(png_ptr, info_ptr); png_read_info(png_ptr, info_ptr);
{ {
png_size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr); png_size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);
row = malloc(rowbytes); row = voidcast(png_bytep,malloc(rowbytes));
display = malloc(rowbytes); display = voidcast(png_bytep,malloc(rowbytes));
if (row == NULL || display == NULL) if (row == NULL || display == NULL)
png_error(png_ptr, "OOM allocating row buffers"); png_error(png_ptr, "OOM allocating row buffers");
@ -81,7 +108,8 @@ static int read_png(FILE *fp)
png_uint_32 y = height; png_uint_32 y = height;
/* NOTE: this trashes the row each time; interlace handling won't /* NOTE: this trashes the row each time; interlace handling won't
* work, but this avoids memory thrashing for speed testing. * work, but this avoids memory thrashing for speed testing and is
* somewhat representative of an application that works row-by-row.
*/ */
while (y-- > 0) while (y-- > 0)
png_read_row(png_ptr, row, display); png_read_row(png_ptr, row, display);
@ -91,9 +119,51 @@ static int read_png(FILE *fp)
/* Make sure to read to the end of the file: */ /* Make sure to read to the end of the file: */
png_read_end(png_ptr, info_ptr); png_read_end(png_ptr, info_ptr);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
/* Free this up: */
free(row); free(row);
free(display); free(display);
}
static PNG_CALLBACK(void, no_warnings, (png_structp png_ptr,
png_const_charp warning))
{
(void)png_ptr;
(void)warning;
}
static int read_png(FILE *fp, png_int_32 transforms, FILE *write_file)
{
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,
no_warnings);
png_infop info_ptr = NULL;
if (png_ptr == NULL)
return 0;
if (setjmp(png_jmpbuf(png_ptr)))
{
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return 0;
}
# ifdef PNG_BENIGN_ERRORS_SUPPORTED
png_set_benign_errors(png_ptr, 1/*allowed*/);
# endif
png_init_io(png_ptr, fp);
info_ptr = png_create_info_struct(png_ptr);
if (info_ptr == NULL)
png_error(png_ptr, "OOM allocating info structure");
if (transforms < 0)
read_by_row(png_ptr, info_ptr, write_file, fp);
else
png_read_png(png_ptr, info_ptr, transforms, NULL/*params*/);
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return 1; return 1;
} }
@ -108,7 +178,7 @@ static int mytime(struct timespec *t)
return 0; return 0;
} }
static int perform_one_test(FILE *fp, int nfiles) static int perform_one_test(FILE *fp, int nfiles, png_int_32 transforms)
{ {
int i; int i;
struct timespec before, after; struct timespec before, after;
@ -120,7 +190,7 @@ static int perform_one_test(FILE *fp, int nfiles)
{ {
for (i=0; i<nfiles; ++i) for (i=0; i<nfiles; ++i)
{ {
if (read_png(fp)) if (read_png(fp, transforms, NULL/*write*/))
{ {
if (ferror(fp)) if (ferror(fp))
{ {
@ -184,120 +254,343 @@ static int add_one_file(FILE *fp, char *name)
if (ip != NULL) if (ip != NULL)
{ {
int ch; /* Read the file using libpng; this detects errors and also deals with
for (;;) * files which contain data beyond the end of the file.
*/
int ok = 0;
fpos_t pos;
if (fgetpos(fp, &pos))
{ {
ch = getc(ip); /* Fatal error reading the start: */
if (ch == EOF) break; perror("temporary file");
putc(ch, fp); fprintf(stderr, "temporary file fgetpos error\n");
exit(1);
} }
if (ferror(ip)) if (read_png(ip, -1/*by row*/, fp/*output*/))
{ {
perror(name); if (ferror(ip))
fprintf(stderr, "%s: read error\n", name); {
return 0; perror(name);
fprintf(stderr, "%s: read error\n", name);
}
else
ok = 1; /* read ok */
} }
else
fprintf(stderr, "%s: file not added\n", name);
(void)fclose(ip); (void)fclose(ip);
/* An error in the output is fatal; exit immediately: */
if (ferror(fp)) if (ferror(fp))
{ {
perror("temporary file"); perror("temporary file");
fprintf(stderr, "temporary file write error\n"); fprintf(stderr, "temporary file write error\n");
return 0; exit(1);
}
if (ok)
return 1;
/* Did not read the file successfully, simply rewind the temporary
* file. This must happen after the ferror check above to avoid clearing
* the error.
*/
if (fsetpos(fp, &pos))
{
perror("temporary file");
fprintf(stderr, "temporary file fsetpos error\n");
exit(1);
} }
} }
else else
{ {
/* file open error: */
perror(name); perror(name);
fprintf(stderr, "%s: open failed\n", name); fprintf(stderr, "%s: open failed\n", name);
return 0;
} }
return 1; return 0; /* file not added */
}
static void
usage(FILE *fp)
{
if (fp != NULL) fclose(fp);
fprintf(stderr,
"Usage:\n"
" timepng --assemble <assembly> {files}\n"
" Read the files into <assembly>, output the count. Options are ignored.\n"
" timepng --dissemble <assembly> <count> [options]\n"
" Time <count> files from <assembly>, additional files may not be given.\n"
" Otherwise:\n"
" Read the files into a temporary file and time the decode\n"
"Transforms:\n"
" --by-image: read by image with png_read_png\n"
" --<transform>: implies by-image, use PNG_TRANSFORM_<transform>\n"
" Otherwise: read by row using png_read_row (to a single row buffer)\n"
/* ISO C90 string length max 509 */);fprintf(stderr,
"{files}:\n"
" PNG files to copy into the assembly and time. Invalid files are skipped\n"
" with appropriate error messages. If no files are given the list of files\n"
" is read from stdin with each file name terminated by a newline\n"
"Output:\n"
" For --assemble the output is the name of the assembly file followed by the\n"
" count of the files it contains; the arguments for --dissemble. Otherwise\n"
" the output is the total decode time in seconds.\n");
exit(99);
} }
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int ok = 0; int ok = 0;
FILE *fp = tmpfile(); int err = 0;
int nfiles = 0;
int transforms = -1; /* by row */
const char *assembly = NULL;
FILE *fp;
if (fp != NULL) if (argc > 2 && strcmp(argv[1], "--assemble") == 0)
{ {
int err = 0; /* Just build the test file, argv[2] is the file name. */
int nfiles = 0; assembly = argv[2];
fp = fopen(assembly, "wb");
if (argc > 1) if (fp == NULL)
{ {
int i; perror(assembly);
fprintf(stderr, "timepng --assemble %s: could not open for write\n",
assembly);
usage(NULL);
}
for (i=1; i<argc; ++i) argv += 2;
argc -= 2;
}
else if (argc > 3 && strcmp(argv[1], "--dissemble") == 0)
{
fp = fopen(argv[2], "rb");
if (fp == NULL)
{
perror(argv[2]);
fprintf(stderr, "timepng --dissemble %s: could not open for read\n",
argv[2]);
usage(NULL);
}
nfiles = atoi(argv[3]);
if (nfiles <= 0)
{
fprintf(stderr,
"timepng --dissemble <file> <count>: %s is not a count\n",
argv[3]);
exit(99);
}
#ifdef __COVERITY__
else
{
nfiles &= PNG_UINT_31_MAX;
}
#endif
argv += 3;
argc -= 3;
}
else /* Else use a temporary file */
{
#ifndef __COVERITY__
fp = tmpfile();
#else
/* Experimental. Coverity says tmpfile() is insecure because it
* generates predictable names.
*
* It is possible to satisfy Coverity by using mkstemp(); however,
* any platform supporting mkstemp() undoubtedly has a secure tmpfile()
* implementation as well, and doesn't need the fix. Note that
* the fix won't work on platforms that don't support mkstemp().
*
* https://www.securecoding.cert.org/confluence/display/c/
* FIO21-C.+Do+not+create+temporary+files+in+shared+directories
* says that most historic implementations of tmpfile() provide
* only a limited number of possible temporary file names
* (usually 26) before file names are recycled. That article also
* provides a secure solution that unfortunately depends upon mkstemp().
*/
char tmpfile[] = "timepng-XXXXXX";
int filedes;
umask(0177);
filedes = mkstemp(tmpfile);
if (filedes < 0)
fp = NULL;
else
{
fp = fdopen(filedes,"w+");
/* Hide the filename immediately and ensure that the file does
* not exist after the program ends
*/
(void) unlink(tmpfile);
}
#endif
if (fp == NULL)
{
perror("tmpfile");
fprintf(stderr, "timepng: could not open the temporary file\n");
exit(1); /* not a user error */
}
}
/* Handle the transforms: */
while (argc > 1 && argv[1][0] == '-' && argv[1][1] == '-')
{
const char *opt = *++argv + 2;
--argc;
/* Transforms turn on the by-image processing and maybe set some
* transforms:
*/
if (transforms == -1)
transforms = PNG_TRANSFORM_IDENTITY;
if (strcmp(opt, "by-image") == 0)
{
/* handled above */
}
# define OPT(name) else if (strcmp(opt, #name) == 0)\
transforms |= PNG_TRANSFORM_ ## name
OPT(STRIP_16);
OPT(STRIP_ALPHA);
OPT(PACKING);
OPT(PACKSWAP);
OPT(EXPAND);
OPT(INVERT_MONO);
OPT(SHIFT);
OPT(BGR);
OPT(SWAP_ALPHA);
OPT(SWAP_ENDIAN);
OPT(INVERT_ALPHA);
OPT(STRIP_FILLER);
OPT(STRIP_FILLER_BEFORE);
OPT(STRIP_FILLER_AFTER);
OPT(GRAY_TO_RGB);
OPT(EXPAND_16);
OPT(SCALE_16);
else
{
fprintf(stderr, "timepng %s: unrecognized transform\n", opt);
usage(fp);
}
}
/* Handle the files: */
if (argc > 1 && nfiles > 0)
usage(fp); /* Additional files not valid with --dissemble */
else if (argc > 1)
{
int i;
for (i=1; i<argc; ++i)
{
if (nfiles == INT_MAX)
{ {
if (add_one_file(fp, argv[i])) fprintf(stderr, "%s: skipped, too many files\n", argv[i]);
break;
}
else if (add_one_file(fp, argv[i]))
++nfiles;
}
}
else if (nfiles == 0) /* Read from stdin withoout --dissemble */
{
char filename[FILENAME_MAX+1];
while (fgets(filename, FILENAME_MAX+1, stdin))
{
size_t len = strlen(filename);
if (filename[len-1] == '\n')
{
filename[len-1] = 0;
if (nfiles == INT_MAX)
{
fprintf(stderr, "%s: skipped, too many files\n", filename);
break;
}
else if (add_one_file(fp, filename))
++nfiles; ++nfiles;
}
else
{
fprintf(stderr, "timepng: file name too long: ...%s\n",
filename+len-32);
err = 1;
break;
}
}
if (ferror(stdin))
{
fprintf(stderr, "timepng: stdin: read error\n");
err = 1;
}
}
/* Perform the test, or produce the --assemble output: */
if (!err)
{
if (nfiles > 0)
{
if (assembly != NULL)
{
if (fflush(fp) && !ferror(fp) && fclose(fp))
{
perror(assembly);
fprintf(stderr, "%s: close failed\n", assembly);
}
else else
{ {
err = 1; printf("%s %d\n", assembly, nfiles);
break; fflush(stdout);
ok = !ferror(stdout);
} }
} }
else
{
ok = perform_one_test(fp, nfiles, transforms);
(void)fclose(fp);
}
} }
else else
{ usage(fp);
char filename[FILENAME_MAX+1];
while (fgets(filename, FILENAME_MAX+1, stdin))
{
size_t len = strlen(filename);
if (filename[len-1] == '\n')
{
filename[len-1] = 0;
if (add_one_file(fp, filename))
++nfiles;
else
{
err = 1;
break;
}
}
else
{
fprintf(stderr, "timepng: truncated file name ...%s\n",
filename+len-32);
err = 1;
break;
}
}
if (ferror(stdin))
{
fprintf(stderr, "timepng: stdin: read error\n");
err = 1;
}
}
if (!err)
{
if (nfiles > 0)
ok = perform_one_test(fp, nfiles);
else
fprintf(stderr, "usage: timepng {files} or ls files | timepng\n");
}
(void)fclose(fp);
} }
else else
fprintf(stderr, "timepng: could not open temporary file\n"); (void)fclose(fp);
/* Exit code 0 on success. */ /* Exit code 0 on success. */
return ok == 0; return ok == 0;
} }
#else /* !sufficient support */
int main(void) { return 77; }
#endif /* !sufficient support */

10
png.h
View File

@ -1,7 +1,7 @@
/* png.h - header file for PNG reference library /* png.h - header file for PNG reference library
* *
* libpng version 1.7.0beta80, May 5, 2016 * libpng version 1.7.0beta80, May 6, 2016
* *
* Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
@ -12,7 +12,7 @@
* Authors and maintainers: * Authors and maintainers:
* libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
* libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
* libpng versions 0.97, January 1998, through 1.7.0beta80, May 5, 2016: * libpng versions 0.97, January 1998, through 1.7.0beta80, May 6, 2016:
* Glenn Randers-Pehrson. * Glenn Randers-Pehrson.
* See also "Contributing Authors", below. * See also "Contributing Authors", below.
*/ */
@ -25,7 +25,7 @@
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* *
* libpng versions 1.0.7, July 1, 2000, through 1.7.0beta80, May 5, 2016, are * libpng versions 1.0.7, July 1, 2000, through 1.7.0beta80, May 6, 2016, are
* Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are * Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are
* derived from libpng-1.0.6, and are distributed according to the same * derived from libpng-1.0.6, and are distributed according to the same
* disclaimer and license as libpng-1.0.6 with the following individuals * disclaimer and license as libpng-1.0.6 with the following individuals
@ -218,7 +218,7 @@
* Y2K compliance in libpng: * Y2K compliance in libpng:
* ========================= * =========================
* *
* May 5, 2016 * May 6, 2016
* *
* Since the PNG Development group is an ad-hoc body, we can't make * Since the PNG Development group is an ad-hoc body, we can't make
* an official declaration. * an official declaration.
@ -288,7 +288,7 @@
/* Version information for png.h - this should match the version in png.c */ /* Version information for png.h - this should match the version in png.c */
#define PNG_LIBPNG_VER_STRING "1.7.0beta80" #define PNG_LIBPNG_VER_STRING "1.7.0beta80"
#define PNG_HEADER_VERSION_STRING \ #define PNG_HEADER_VERSION_STRING \
" libpng version 1.7.0beta80 - May 5, 2016\n" " libpng version 1.7.0beta80 - May 6, 2016\n"
#define PNG_LIBPNG_VER_SONUM 17 #define PNG_LIBPNG_VER_SONUM 17
#define PNG_LIBPNG_VER_DLLNUM 17 #define PNG_LIBPNG_VER_DLLNUM 17