mirror of
https://git.code.sf.net/p/libpng/code.git
synced 2025-07-10 18:04:09 +02:00
Merge branch 'libpng16-simple-memory-II' of git://github.com/jbowler/libpng-1 into libpng16
This commit is contained in:
@@ -307,7 +307,7 @@ compare_16bit(int v1, int v2, int error_limit, int multiple_algorithms)
|
|||||||
}
|
}
|
||||||
#endif /* unused */
|
#endif /* unused */
|
||||||
|
|
||||||
#define READ_FILE 1 /* else memory */
|
#define USE_FILE 1 /* else memory */
|
||||||
#define USE_STDIO 2 /* else use file name */
|
#define USE_STDIO 2 /* else use file name */
|
||||||
#define STRICT 4 /* fail on warnings too */
|
#define STRICT 4 /* fail on warnings too */
|
||||||
#define VERBOSE 8
|
#define VERBOSE 8
|
||||||
@@ -320,7 +320,7 @@ compare_16bit(int v1, int v2, int error_limit, int multiple_algorithms)
|
|||||||
static void
|
static void
|
||||||
print_opts(png_uint_32 opts)
|
print_opts(png_uint_32 opts)
|
||||||
{
|
{
|
||||||
if (opts & READ_FILE)
|
if (opts & USE_FILE)
|
||||||
printf(" --file");
|
printf(" --file");
|
||||||
if (opts & USE_STDIO)
|
if (opts & USE_STDIO)
|
||||||
printf(" --stdio");
|
printf(" --stdio");
|
||||||
@@ -3008,14 +3008,14 @@ read_file(Image *image, png_uint_32 format, png_const_colorp background)
|
|||||||
static int
|
static int
|
||||||
read_one_file(Image *image)
|
read_one_file(Image *image)
|
||||||
{
|
{
|
||||||
if (!(image->opts & READ_FILE) || (image->opts & USE_STDIO))
|
if (!(image->opts & USE_FILE) || (image->opts & USE_STDIO))
|
||||||
{
|
{
|
||||||
/* memory or stdio. */
|
/* memory or stdio. */
|
||||||
FILE *f = fopen(image->file_name, "rb");
|
FILE *f = fopen(image->file_name, "rb");
|
||||||
|
|
||||||
if (f != NULL)
|
if (f != NULL)
|
||||||
{
|
{
|
||||||
if (image->opts & READ_FILE)
|
if (image->opts & USE_FILE)
|
||||||
image->input_file = f;
|
image->input_file = f;
|
||||||
|
|
||||||
else /* memory */
|
else /* memory */
|
||||||
@@ -3096,6 +3096,7 @@ write_one_file(Image *output, Image *image, int convert_to_8bit)
|
|||||||
|
|
||||||
if (image->opts & USE_STDIO)
|
if (image->opts & USE_STDIO)
|
||||||
{
|
{
|
||||||
|
#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
|
||||||
#ifndef __COVERITY__
|
#ifndef __COVERITY__
|
||||||
FILE *f = tmpfile();
|
FILE *f = tmpfile();
|
||||||
#else
|
#else
|
||||||
@@ -3158,10 +3159,14 @@ write_one_file(Image *output, Image *image, int convert_to_8bit)
|
|||||||
|
|
||||||
else
|
else
|
||||||
return logerror(image, "tmpfile", ": open: ", strerror(errno));
|
return logerror(image, "tmpfile", ": open: ", strerror(errno));
|
||||||
|
#else /* SIMPLIFIED_WRITE_STDIO */
|
||||||
|
return logerror(image, "tmpfile", ": open: unsupported", "");
|
||||||
|
#endif /* SIMPLIFIED_WRITE_STDIO */
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else if (image->opts & USE_FILE)
|
||||||
{
|
{
|
||||||
|
#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
|
||||||
static int counter = 0;
|
static int counter = 0;
|
||||||
char name[32];
|
char name[32];
|
||||||
|
|
||||||
@@ -3181,6 +3186,48 @@ write_one_file(Image *output, Image *image, int convert_to_8bit)
|
|||||||
|
|
||||||
else
|
else
|
||||||
return logerror(image, name, ": write failed", "");
|
return logerror(image, name, ": write failed", "");
|
||||||
|
#else /* SIMPLIFIED_WRITE_STDIO */
|
||||||
|
return logerror(image, "stdio", ": open: unsupported", "");
|
||||||
|
#endif /* SIMPLIFIED_WRITE_STDIO */
|
||||||
|
}
|
||||||
|
|
||||||
|
else /* use memory */
|
||||||
|
{
|
||||||
|
png_alloc_size_t size;
|
||||||
|
|
||||||
|
if (png_image_write_get_memory_size(image->image, size, convert_to_8bit,
|
||||||
|
image->buffer+16, (png_int_32)image->stride, image->colormap))
|
||||||
|
{
|
||||||
|
/* This is non-fatal: */
|
||||||
|
if (size > PNG_IMAGE_PNG_SIZE_MAX(image->image))
|
||||||
|
logerror(image, "memory", ": PNG_IMAGE_SIZE_MAX wrong", "");
|
||||||
|
|
||||||
|
initimage(output, image->opts, "memory", image->stride_extra);
|
||||||
|
output->input_memory = malloc(size);
|
||||||
|
|
||||||
|
if (output->input_memory != NULL)
|
||||||
|
{
|
||||||
|
output->input_memory_size = size;
|
||||||
|
|
||||||
|
if (png_image_write_to_memory(&image->image, output->input_memory,
|
||||||
|
&output->input_memory_size, convert_to_8bit, image->buffer+16,
|
||||||
|
(png_int_32)image->stride, image->colormap))
|
||||||
|
{
|
||||||
|
/* This is also non-fatal (maybe): */
|
||||||
|
if (size != output->input_memory_size)
|
||||||
|
logerror(image, "memory", ": memory size wrong", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return logerror(image, "memory", ": write failed", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return logerror(image, "memory", ": out of memory", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return logerror(image, "memory", ": get size:", "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 'output' has an initialized temporary image, read this back in and compare
|
/* 'output' has an initialized temporary image, read this back in and compare
|
||||||
@@ -3421,12 +3468,12 @@ main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
else if (strcmp(arg, "--file") == 0)
|
else if (strcmp(arg, "--file") == 0)
|
||||||
# ifdef PNG_STDIO_SUPPORTED
|
# ifdef PNG_STDIO_SUPPORTED
|
||||||
opts |= READ_FILE;
|
opts |= USE_FILE;
|
||||||
# else
|
# else
|
||||||
return 77; /* skipped: no support */
|
return 77; /* skipped: no support */
|
||||||
# endif
|
# endif
|
||||||
else if (strcmp(arg, "--memory") == 0)
|
else if (strcmp(arg, "--memory") == 0)
|
||||||
opts &= ~READ_FILE;
|
opts &= ~USE_FILE;
|
||||||
else if (strcmp(arg, "--stdio") == 0)
|
else if (strcmp(arg, "--stdio") == 0)
|
||||||
# ifdef PNG_STDIO_SUPPORTED
|
# ifdef PNG_STDIO_SUPPORTED
|
||||||
opts |= USE_STDIO;
|
opts |= USE_STDIO;
|
||||||
|
|||||||
113
png.h
113
png.h
@@ -2889,12 +2889,19 @@ typedef struct
|
|||||||
* is the minimum 'row stride', the minimum count of components between each
|
* is the minimum 'row stride', the minimum count of components between each
|
||||||
* row. For a color-mapped image this is the minimum number of bytes in a
|
* row. For a color-mapped image this is the minimum number of bytes in a
|
||||||
* row.
|
* row.
|
||||||
|
*
|
||||||
|
* WARNING: this macro overflows for some images with more than one component
|
||||||
|
* and very large image widths. libpng will refuse to process an image where
|
||||||
|
* this macro would overflow.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\
|
#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\
|
||||||
(PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride))
|
(PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride))
|
||||||
/* Return the size, in bytes, of an image buffer given a png_image and a row
|
/* Return the size, in bytes, of an image buffer given a png_image and a row
|
||||||
* stride - the number of components to leave space for in each row.
|
* stride - the number of components to leave space for in each row.
|
||||||
|
*
|
||||||
|
* WARNING: this macro overflows a 32-bit integer for some large PNG images,
|
||||||
|
* libpng will refuse to process an image where such an overflow would occur.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PNG_IMAGE_SIZE(image)\
|
#define PNG_IMAGE_SIZE(image)\
|
||||||
@@ -3015,7 +3022,6 @@ PNG_EXPORT(238, void, png_image_free, (png_imagep image));
|
|||||||
#endif /* SIMPLIFIED_READ */
|
#endif /* SIMPLIFIED_READ */
|
||||||
|
|
||||||
#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
|
#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
|
||||||
#ifdef PNG_STDIO_SUPPORTED
|
|
||||||
/* WRITE APIS
|
/* WRITE APIS
|
||||||
* ----------
|
* ----------
|
||||||
* For write you must initialize a png_image structure to describe the image to
|
* For write you must initialize a png_image structure to describe the image to
|
||||||
@@ -3032,6 +3038,7 @@ PNG_EXPORT(238, void, png_image_free, (png_imagep image));
|
|||||||
* values do not correspond to the colors in sRGB.
|
* values do not correspond to the colors in sRGB.
|
||||||
* colormap_entries: set to the number of entries in the color-map (0 to 256)
|
* colormap_entries: set to the number of entries in the color-map (0 to 256)
|
||||||
*/
|
*/
|
||||||
|
#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
|
||||||
PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image,
|
PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image,
|
||||||
const char *file, int convert_to_8bit, const void *buffer,
|
const char *file, int convert_to_8bit, const void *buffer,
|
||||||
png_int_32 row_stride, const void *colormap));
|
png_int_32 row_stride, const void *colormap));
|
||||||
@@ -3041,8 +3048,9 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
|
|||||||
int convert_to_8_bit, const void *buffer, png_int_32 row_stride,
|
int convert_to_8_bit, const void *buffer, png_int_32 row_stride,
|
||||||
const void *colormap));
|
const void *colormap));
|
||||||
/* Write the image to the given (FILE*). */
|
/* Write the image to the given (FILE*). */
|
||||||
|
#endif /* SIMPLIFIED_WRITE_STDIO */
|
||||||
|
|
||||||
/* With both write APIs if image is in one of the linear formats with 16-bit
|
/* With all write APIs if image is in one of the linear formats with 16-bit
|
||||||
* data then setting convert_to_8_bit will cause the output to be an 8-bit PNG
|
* data then setting convert_to_8_bit will cause the output to be an 8-bit PNG
|
||||||
* gamma encoded according to the sRGB specification, otherwise a 16-bit linear
|
* gamma encoded according to the sRGB specification, otherwise a 16-bit linear
|
||||||
* encoded PNG file is written.
|
* encoded PNG file is written.
|
||||||
@@ -3054,13 +3062,102 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
|
|||||||
*
|
*
|
||||||
* With all APIs row_stride is handled as in the read APIs - it is the spacing
|
* With all APIs row_stride is handled as in the read APIs - it is the spacing
|
||||||
* from one row to the next in component sized units (1 or 2 bytes) and if
|
* from one row to the next in component sized units (1 or 2 bytes) and if
|
||||||
* negative indicates a bottom-up row layout in the buffer. If row_stride is zero,
|
* negative indicates a bottom-up row layout in the buffer. If row_stride is
|
||||||
* libpng will calculate it for you from the image width and number of channels.
|
* zero, libpng will calculate it for you from the image width and number of
|
||||||
|
* channels.
|
||||||
*
|
*
|
||||||
* Note that the write API does not support interlacing, sub-8-bit pixels, indexed
|
* Note that the write API does not support interlacing, sub-8-bit pixels or
|
||||||
* PNG (color_type 3) or most ancillary chunks.
|
* st ancillary chunks. If you need to write text chunks (e.g. for copyright
|
||||||
|
* notices) you need to use one of the other APIs.
|
||||||
*/
|
*/
|
||||||
#endif /* STDIO */
|
|
||||||
|
PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory,
|
||||||
|
png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit,
|
||||||
|
const void *buffer, png_int_32 row_stride, const void *colormap));
|
||||||
|
/* Write the image to the given memory buffer. The function both writes the
|
||||||
|
* whole PNG data stream to *memory and updates *memory_bytes with the count
|
||||||
|
* of bytes written.
|
||||||
|
*
|
||||||
|
* 'memory' may be NULL. In this case *memory_bytes is not read however on
|
||||||
|
* success the number of bytes which would have been written will still be
|
||||||
|
* stored in *memory_bytes. On failure *memory_bytes will contain 0.
|
||||||
|
*
|
||||||
|
* If 'memory' is not NULL it must point to memory[*memory_bytes] of
|
||||||
|
* writeable memory.
|
||||||
|
*
|
||||||
|
* If the function returns success memory[*memory_bytes] (if 'memory' is not
|
||||||
|
* NULL) contains the written PNG data. *memory_bytes will always be less
|
||||||
|
* than or equal to the original value.
|
||||||
|
*
|
||||||
|
* If the function returns false and *memory_bytes was not changed an error
|
||||||
|
* occured during write. If *memory_bytes was changed, or is not 0 if
|
||||||
|
* 'memory' was NULL, the write would have succeeded but for the memory
|
||||||
|
* buffer being too small. *memory_bytes contains the required number of
|
||||||
|
* bytes and will be bigger that the original value.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\
|
||||||
|
row_stride, colormap)\
|
||||||
|
png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\
|
||||||
|
row_stride, colormap)
|
||||||
|
/* Return the amount of memory in 'size' required to compress this image.
|
||||||
|
* The png_image structure 'image' must be filled in as in the above
|
||||||
|
* function and must not be changed before the actual write call, the buffer
|
||||||
|
* and all other parameters must also be indentical to that in the final
|
||||||
|
* write call. The 'size' variable need not be initialized.
|
||||||
|
*
|
||||||
|
* NOTE: the macro returns true/false, if false is returned 'size' will be
|
||||||
|
* set to zero and the write failed and probably will fail if tried again.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* You can pre-allocate the buffer by making sure it is of sufficient size
|
||||||
|
* regardless of the amount of compression achieved. The buffer size will
|
||||||
|
* always be bigger than the original image and it will never be filled. The
|
||||||
|
* following macros are provided to assist in allocating the buffer.
|
||||||
|
*/
|
||||||
|
#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height)
|
||||||
|
/* The number of uncompressed bytes in the PNG byte encoding of the image;
|
||||||
|
* uncompressing the PNG IDAT data will give this number of bytes.
|
||||||
|
*
|
||||||
|
* NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this
|
||||||
|
* macro can because of the extra bytes used in the PNG byte encoding. You
|
||||||
|
* need to avoid this macro if your image size approaches 2^30 in width or
|
||||||
|
* height. The same goes for the remainder of these macros; they all produce
|
||||||
|
* bigger numbers than the actual in-memory image size.
|
||||||
|
*/
|
||||||
|
#ifndef PNG_ZLIB_MAX_SIZE
|
||||||
|
# define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U)
|
||||||
|
/* An upper bound on the number of compressed bytes given 'b' uncompressed
|
||||||
|
* bytes. This is based on deflateBounds() in zlib; different
|
||||||
|
* implementations of zlib compression may conceivable produce more data so
|
||||||
|
* if your zlib implementation is not zlib itself redefine this macro
|
||||||
|
* appropriately.
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\
|
||||||
|
PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image))
|
||||||
|
/* An upper bound on the size of the data in the PNG IDAT chunks. */
|
||||||
|
|
||||||
|
#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\
|
||||||
|
((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\
|
||||||
|
(((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\
|
||||||
|
12U+PNG_IMAGE_COLORMAP_SIZE(image)/*PLTE+tRNS data*/+\
|
||||||
|
(((image).format&PNG_FORMAT_FLAG_ALPHA)?12U/*tRNS*/:0U):0U)+\
|
||||||
|
12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size))
|
||||||
|
/* A helper for the following macro; if your compiler cannot handle the
|
||||||
|
* following macro use this one with the result of
|
||||||
|
* PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most
|
||||||
|
* compilers should handle this just fine.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PNG_IMAGE_PNG_SIZE_MAX(image)\
|
||||||
|
PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image))
|
||||||
|
/* An upper bound on the total length of the PNG data stream for 'image'.
|
||||||
|
* The result is of type png_alloc_size_t, on 32-bit systems this may
|
||||||
|
* overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will
|
||||||
|
* run out of buffer space but return a corrected size which should work.
|
||||||
|
*/
|
||||||
#endif /* SIMPLIFIED_WRITE */
|
#endif /* SIMPLIFIED_WRITE */
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* END OF SIMPLIFIED API
|
* END OF SIMPLIFIED API
|
||||||
@@ -3118,7 +3215,7 @@ PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option,
|
|||||||
* one to use is one more than this.)
|
* one to use is one more than this.)
|
||||||
*/
|
*/
|
||||||
#ifdef PNG_EXPORT_LAST_ORDINAL
|
#ifdef PNG_EXPORT_LAST_ORDINAL
|
||||||
PNG_EXPORT_LAST_ORDINAL(244);
|
PNG_EXPORT_LAST_ORDINAL(245);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
102
pngread.c
102
pngread.c
@@ -4071,58 +4071,84 @@ png_image_finish_read(png_imagep image, png_const_colorp background,
|
|||||||
{
|
{
|
||||||
if (image != NULL && image->version == PNG_IMAGE_VERSION)
|
if (image != NULL && image->version == PNG_IMAGE_VERSION)
|
||||||
{
|
{
|
||||||
png_uint_32 check;
|
/* Check for row_stride overflow. This check is not performed on the
|
||||||
|
* original PNG format because it may not occur in the output PNG format
|
||||||
|
* and libpng deals with the issues of reading the original.
|
||||||
|
*/
|
||||||
|
const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
|
||||||
|
|
||||||
if (row_stride == 0)
|
if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */
|
||||||
row_stride = PNG_IMAGE_ROW_STRIDE(*image);
|
|
||||||
|
|
||||||
if (row_stride < 0)
|
|
||||||
check = -row_stride;
|
|
||||||
|
|
||||||
else
|
|
||||||
check = row_stride;
|
|
||||||
|
|
||||||
if (image->opaque != NULL && buffer != NULL &&
|
|
||||||
check >= PNG_IMAGE_ROW_STRIDE(*image))
|
|
||||||
{
|
{
|
||||||
if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
|
png_uint_32 check;
|
||||||
(image->colormap_entries > 0 && colormap != NULL))
|
const png_uint_32 png_row_stride = image->width * channels;
|
||||||
|
|
||||||
|
if (row_stride == 0)
|
||||||
|
row_stride = (png_int_32)/*SAFE*/png_row_stride;
|
||||||
|
|
||||||
|
if (row_stride < 0)
|
||||||
|
check = -row_stride;
|
||||||
|
|
||||||
|
else
|
||||||
|
check = row_stride;
|
||||||
|
|
||||||
|
if (image->opaque != NULL && buffer != NULL && check >= png_row_stride)
|
||||||
{
|
{
|
||||||
int result;
|
/* Now check for overflow of the image buffer calculation; this
|
||||||
png_image_read_control display;
|
* limits the whole image size to 32 bits for API compatibility with
|
||||||
|
* the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
|
||||||
memset(&display, 0, (sizeof display));
|
|
||||||
display.image = image;
|
|
||||||
display.buffer = buffer;
|
|
||||||
display.row_stride = row_stride;
|
|
||||||
display.colormap = colormap;
|
|
||||||
display.background = background;
|
|
||||||
display.local_row = NULL;
|
|
||||||
|
|
||||||
/* Choose the correct 'end' routine; for the color-map case all the
|
|
||||||
* setup has already been done.
|
|
||||||
*/
|
*/
|
||||||
if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
|
if (image->height <= 0xFFFFFFFF/png_row_stride)
|
||||||
result =
|
{
|
||||||
png_safe_execute(image, png_image_read_colormap, &display) &&
|
if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
|
||||||
png_safe_execute(image, png_image_read_colormapped, &display);
|
(image->colormap_entries > 0 && colormap != NULL))
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
png_image_read_control display;
|
||||||
|
|
||||||
|
memset(&display, 0, (sizeof display));
|
||||||
|
display.image = image;
|
||||||
|
display.buffer = buffer;
|
||||||
|
display.row_stride = row_stride;
|
||||||
|
display.colormap = colormap;
|
||||||
|
display.background = background;
|
||||||
|
display.local_row = NULL;
|
||||||
|
|
||||||
|
/* Choose the correct 'end' routine; for the color-map case
|
||||||
|
* all the setup has already been done.
|
||||||
|
*/
|
||||||
|
if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
|
||||||
|
result = png_safe_execute(image,
|
||||||
|
png_image_read_colormap, &display) &&
|
||||||
|
png_safe_execute(image,
|
||||||
|
png_image_read_colormapped, &display);
|
||||||
|
|
||||||
|
else
|
||||||
|
result =
|
||||||
|
png_safe_execute(image,
|
||||||
|
png_image_read_direct, &display);
|
||||||
|
|
||||||
|
png_image_free(image);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return png_image_error(image,
|
||||||
|
"png_image_finish_read[color-map]: no color-map");
|
||||||
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
result =
|
return png_image_error(image,
|
||||||
png_safe_execute(image, png_image_read_direct, &display);
|
"png_image_finish_read: image too large");
|
||||||
|
|
||||||
png_image_free(image);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
return png_image_error(image,
|
return png_image_error(image,
|
||||||
"png_image_finish_read[color-map]: no color-map");
|
"png_image_finish_read: invalid argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
return png_image_error(image,
|
return png_image_error(image,
|
||||||
"png_image_finish_read: invalid argument");
|
"png_image_finish_read: row_stride too large");
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (image != NULL)
|
else if (image != NULL)
|
||||||
|
|||||||
171
pngwrite.c
171
pngwrite.c
@@ -12,9 +12,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "pngpriv.h"
|
#include "pngpriv.h"
|
||||||
#if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
|
#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
|
||||||
# include <errno.h>
|
# include <errno.h>
|
||||||
#endif
|
#endif /* SIMPLIFIED_WRITE_STDIO */
|
||||||
|
|
||||||
#ifdef PNG_WRITE_SUPPORTED
|
#ifdef PNG_WRITE_SUPPORTED
|
||||||
|
|
||||||
@@ -1452,7 +1452,6 @@ png_write_png(png_structrp png_ptr, png_inforp info_ptr,
|
|||||||
|
|
||||||
|
|
||||||
#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
|
#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
|
||||||
# ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */
|
|
||||||
/* Initialize the write structure - general purpose utility. */
|
/* Initialize the write structure - general purpose utility. */
|
||||||
static int
|
static int
|
||||||
png_image_write_init(png_imagep image)
|
png_image_write_init(png_imagep image)
|
||||||
@@ -1504,6 +1503,10 @@ typedef struct
|
|||||||
png_const_voidp first_row;
|
png_const_voidp first_row;
|
||||||
ptrdiff_t row_bytes;
|
ptrdiff_t row_bytes;
|
||||||
png_voidp local_row;
|
png_voidp local_row;
|
||||||
|
/* Byte count for memory writing */
|
||||||
|
png_bytep memory;
|
||||||
|
png_alloc_size_t memory_bytes; /* not used for STDIO */
|
||||||
|
png_alloc_size_t output_bytes; /* running total */
|
||||||
} png_image_write_control;
|
} png_image_write_control;
|
||||||
|
|
||||||
/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
|
/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
|
||||||
@@ -1931,9 +1934,43 @@ png_image_write_main(png_voidp argument)
|
|||||||
png_set_benign_errors(png_ptr, 0/*error*/);
|
png_set_benign_errors(png_ptr, 0/*error*/);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
/* Default the 'row_stride' parameter if required. */
|
/* Default the 'row_stride' parameter if required, also check the row stride
|
||||||
if (display->row_stride == 0)
|
* and total image size to ensure that they are within the system limits.
|
||||||
display->row_stride = PNG_IMAGE_ROW_STRIDE(*image);
|
*/
|
||||||
|
{
|
||||||
|
const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
|
||||||
|
|
||||||
|
if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */
|
||||||
|
{
|
||||||
|
png_uint_32 check;
|
||||||
|
const png_uint_32 png_row_stride = image->width * channels;
|
||||||
|
|
||||||
|
if (display->row_stride == 0)
|
||||||
|
display->row_stride = (png_int_32)/*SAFE*/png_row_stride;
|
||||||
|
|
||||||
|
if (display->row_stride < 0)
|
||||||
|
check = -display->row_stride;
|
||||||
|
|
||||||
|
else
|
||||||
|
check = display->row_stride;
|
||||||
|
|
||||||
|
if (check >= png_row_stride)
|
||||||
|
{
|
||||||
|
/* Now check for overflow of the image buffer calculation; this
|
||||||
|
* limits the whole image size to 32 bits for API compatibility with
|
||||||
|
* the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
|
||||||
|
*/
|
||||||
|
if (image->height > 0xFFFFFFFF/png_row_stride)
|
||||||
|
png_error(image->opaque->png_ptr, "memory image too large");
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
png_error(image->opaque->png_ptr, "supplied row stride too small");
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
png_error(image->opaque->png_ptr, "image row stride too large");
|
||||||
|
}
|
||||||
|
|
||||||
/* Set the required transforms then write the rows in the correct order. */
|
/* Set the required transforms then write the rows in the correct order. */
|
||||||
if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0)
|
if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0)
|
||||||
@@ -2110,6 +2147,122 @@ png_image_write_main(png_voidp argument)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void (PNGCBAPI
|
||||||
|
image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data,
|
||||||
|
png_size_t size)
|
||||||
|
{
|
||||||
|
png_image_write_control *display = png_voidcast(png_image_write_control*,
|
||||||
|
png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/);
|
||||||
|
const png_alloc_size_t ob = display->output_bytes;
|
||||||
|
|
||||||
|
/* Check for overflow; this should never happen: */
|
||||||
|
if (size <= ((png_alloc_size_t)-1) - ob)
|
||||||
|
{
|
||||||
|
/* I don't think libpng ever does this, but just in case: */
|
||||||
|
if (size > 0)
|
||||||
|
{
|
||||||
|
if (display->memory_bytes >= ob+size) /* writing */
|
||||||
|
memcpy(display->memory+ob, data, size);
|
||||||
|
|
||||||
|
/* Always update the size: */
|
||||||
|
display->output_bytes = ob+size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
png_error(png_ptr, "png_image_write_to_memory: PNG too big");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void (PNGCBAPI
|
||||||
|
image_memory_flush)(png_structp png_ptr)
|
||||||
|
{
|
||||||
|
PNG_UNUSED(png_ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
png_image_write_memory(png_voidp argument)
|
||||||
|
{
|
||||||
|
png_image_write_control *display = png_voidcast(png_image_write_control*,
|
||||||
|
argument);
|
||||||
|
|
||||||
|
/* The rest of the memory-specific init and write_main in an error protected
|
||||||
|
* environment. This case needs to use callbacks for the write operations
|
||||||
|
* since libpng has no built in support for writing to memory.
|
||||||
|
*/
|
||||||
|
png_set_write_fn(display->image->opaque->png_ptr, display/*io_ptr*/,
|
||||||
|
image_memory_write, image_memory_flush);
|
||||||
|
|
||||||
|
return png_image_write_main(display);
|
||||||
|
}
|
||||||
|
|
||||||
|
int PNGAPI
|
||||||
|
png_image_write_to_memory(png_imagep image, void *memory,
|
||||||
|
png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
|
||||||
|
const void *buffer, png_int_32 row_stride, const void *colormap)
|
||||||
|
{
|
||||||
|
/* Write the image to the given buffer, or count the bytes if it is NULL */
|
||||||
|
if (image != NULL && image->version == PNG_IMAGE_VERSION)
|
||||||
|
{
|
||||||
|
if (memory_bytes != NULL && buffer != NULL)
|
||||||
|
{
|
||||||
|
/* This is to give the caller an easier error detection in the NULL
|
||||||
|
* case and guard against uninitialized variable problems:
|
||||||
|
*/
|
||||||
|
if (memory == NULL)
|
||||||
|
*memory_bytes = 0;
|
||||||
|
|
||||||
|
if (png_image_write_init(image) != 0)
|
||||||
|
{
|
||||||
|
png_image_write_control display;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
memset(&display, 0, (sizeof display));
|
||||||
|
display.image = image;
|
||||||
|
display.buffer = buffer;
|
||||||
|
display.row_stride = row_stride;
|
||||||
|
display.colormap = colormap;
|
||||||
|
display.convert_to_8bit = convert_to_8bit;
|
||||||
|
display.memory = png_voidcast(png_bytep, memory);
|
||||||
|
display.memory_bytes = *memory_bytes;
|
||||||
|
display.output_bytes = 0;
|
||||||
|
|
||||||
|
result = png_safe_execute(image, png_image_write_memory, &display);
|
||||||
|
png_image_free(image);
|
||||||
|
|
||||||
|
/* write_memory returns true even if we ran out of buffer. */
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
/* On out-of-buffer this function returns '0' but still updates
|
||||||
|
* memory_bytes:
|
||||||
|
*/
|
||||||
|
if (memory != NULL && display.output_bytes > *memory_bytes)
|
||||||
|
result = 0;
|
||||||
|
|
||||||
|
*memory_bytes = display.output_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return png_image_error(image,
|
||||||
|
"png_image_write_to_memory: invalid argument");
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (image != NULL)
|
||||||
|
return png_image_error(image,
|
||||||
|
"png_image_write_to_memory: incorrect PNG_IMAGE_VERSION");
|
||||||
|
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
|
||||||
int PNGAPI
|
int PNGAPI
|
||||||
png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
|
png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
|
||||||
const void *buffer, png_int_32 row_stride, const void *colormap)
|
const void *buffer, png_int_32 row_stride, const void *colormap)
|
||||||
@@ -2117,7 +2270,7 @@ png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
|
|||||||
/* Write the image to the given (FILE*). */
|
/* Write the image to the given (FILE*). */
|
||||||
if (image != NULL && image->version == PNG_IMAGE_VERSION)
|
if (image != NULL && image->version == PNG_IMAGE_VERSION)
|
||||||
{
|
{
|
||||||
if (file != NULL)
|
if (file != NULL && buffer != NULL)
|
||||||
{
|
{
|
||||||
if (png_image_write_init(image) != 0)
|
if (png_image_write_init(image) != 0)
|
||||||
{
|
{
|
||||||
@@ -2167,7 +2320,7 @@ png_image_write_to_file(png_imagep image, const char *file_name,
|
|||||||
/* Write the image to the named file. */
|
/* Write the image to the named file. */
|
||||||
if (image != NULL && image->version == PNG_IMAGE_VERSION)
|
if (image != NULL && image->version == PNG_IMAGE_VERSION)
|
||||||
{
|
{
|
||||||
if (file_name != NULL)
|
if (file_name != NULL && buffer != NULL)
|
||||||
{
|
{
|
||||||
FILE *fp = fopen(file_name, "wb");
|
FILE *fp = fopen(file_name, "wb");
|
||||||
|
|
||||||
@@ -2225,6 +2378,6 @@ png_image_write_to_file(png_imagep image, const char *file_name,
|
|||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
# endif /* STDIO */
|
#endif /* SIMPLIFIED_WRITE_STDIO */
|
||||||
#endif /* SIMPLIFIED_WRITE */
|
#endif /* SIMPLIFIED_WRITE */
|
||||||
#endif /* WRITE */
|
#endif /* WRITE */
|
||||||
|
|||||||
@@ -873,9 +873,12 @@ option SIMPLIFIED_READ_BGR enables FORMAT_BGR,
|
|||||||
|
|
||||||
# Write:
|
# Write:
|
||||||
option SIMPLIFIED_WRITE,
|
option SIMPLIFIED_WRITE,
|
||||||
requires WRITE STDIO, SETJMP, WRITE_SWAP, WRITE_PACK,
|
requires WRITE, SETJMP, WRITE_SWAP, WRITE_PACK,
|
||||||
WRITE_tRNS, WRITE_gAMA, WRITE_sRGB, WRITE_cHRM
|
WRITE_tRNS, WRITE_gAMA, WRITE_sRGB, WRITE_cHRM
|
||||||
|
|
||||||
|
# 1.6.22: allow simplified write without stdio support:
|
||||||
|
option SIMPLIFIED_WRITE_STDIO requires SIMPLIFIED_WRITE STDIO
|
||||||
|
|
||||||
option SIMPLIFIED_WRITE_AFIRST enables FORMAT_AFIRST,
|
option SIMPLIFIED_WRITE_AFIRST enables FORMAT_AFIRST,
|
||||||
requires SIMPLIFIED_WRITE WRITE_SWAP_ALPHA
|
requires SIMPLIFIED_WRITE WRITE_SWAP_ALPHA
|
||||||
|
|
||||||
|
|||||||
@@ -109,6 +109,7 @@
|
|||||||
#define PNG_SIMPLIFIED_READ_SUPPORTED
|
#define PNG_SIMPLIFIED_READ_SUPPORTED
|
||||||
#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
|
#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
|
||||||
#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
|
#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
|
||||||
|
#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
|
||||||
#define PNG_SIMPLIFIED_WRITE_SUPPORTED
|
#define PNG_SIMPLIFIED_WRITE_SUPPORTED
|
||||||
#define PNG_STDIO_SUPPORTED
|
#define PNG_STDIO_SUPPORTED
|
||||||
#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
|
#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
|
||||||
|
|||||||
@@ -249,3 +249,4 @@ EXPORTS
|
|||||||
png_set_check_for_invalid_index @242
|
png_set_check_for_invalid_index @242
|
||||||
png_get_palette_max @243
|
png_get_palette_max @243
|
||||||
png_set_option @244
|
png_set_option @244
|
||||||
|
png_image_write_to_memory @245
|
||||||
|
|||||||
Reference in New Issue
Block a user