[libpng16] Added color-map support to simplified API.

This is an initial version for review; the documentation has not yet been
updated.
This commit is contained in:
John Bowler 2012-01-23 22:43:22 -06:00 committed by Glenn Randers-Pehrson
parent 2312167d51
commit 5bc90389bf
8 changed files with 2239 additions and 458 deletions

View File

@ -114,6 +114,8 @@ Version 1.6.0beta06 [January 24, 2012]
changes some of the macro definitions in png.h, app code changes some of the macro definitions in png.h, app code
may need corresponding changes. may need corresponding changes.
Increased the formatted warning buffer to 192 bytes. Increased the formatted warning buffer to 192 bytes.
Added color-map support to simplified API. This is an initial version for
review; the documentation has not yet been updated.
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

@ -3865,6 +3865,8 @@ Version 1.6.0beta06 [January 24, 2012]
changes some of the macro definitions in png.h, app code changes some of the macro definitions in png.h, app code
may need corresponding changes. may need corresponding changes.
Increased the formatted warning buffer to 192 bytes. Increased the formatted warning buffer to 192 bytes.
Added color-map support to simplified API. This is an initial version for
review; the documentation has not yet been updated.
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

222
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.6.0beta06 - January 16, 2012 * libpng version 1.6.0beta06 - January 24, 2012
* Copyright (c) 1998-2012 Glenn Randers-Pehrson * Copyright (c) 1998-2012 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@ -11,7 +11,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.89c, June 1996, through 0.96, May 1997: Andreas Dilger * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
* libpng versions 0.97, January 1998, through 1.6.0beta06 - January 16, 2012: Glenn * libpng versions 0.97, January 1998, through 1.6.0beta06 - January 24, 2012: Glenn
* See also "Contributing Authors", below. * See also "Contributing Authors", below.
* *
* Note about libpng version numbers: * Note about libpng version numbers:
@ -198,7 +198,7 @@
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* *
* libpng versions 1.2.6, August 15, 2004, through 1.6.0beta06, January 16, 2012, are * libpng versions 1.2.6, August 15, 2004, through 1.6.0beta06, January 24, 2012, are
* Copyright (c) 2004, 2006-2012 Glenn Randers-Pehrson, and are * Copyright (c) 2004, 2006-2012 Glenn Randers-Pehrson, and are
* distributed according to the same disclaimer and license as libpng-1.2.5 * distributed according to the same disclaimer and license as libpng-1.2.5
* with the following individual added to the list of Contributing Authors: * with the following individual added to the list of Contributing Authors:
@ -310,7 +310,7 @@
* Y2K compliance in libpng: * Y2K compliance in libpng:
* ========================= * =========================
* *
* January 16, 2012 * January 24, 2012
* *
* 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.
@ -376,7 +376,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.6.0beta06" #define PNG_LIBPNG_VER_STRING "1.6.0beta06"
#define PNG_HEADER_VERSION_STRING \ #define PNG_HEADER_VERSION_STRING \
" libpng version 1.6.0beta06 - January 16, 2012\n" " libpng version 1.6.0beta06 - January 24, 2012\n"
#define PNG_LIBPNG_VER_SONUM 16 #define PNG_LIBPNG_VER_SONUM 16
#define PNG_LIBPNG_VER_DLLNUM 16 #define PNG_LIBPNG_VER_DLLNUM 16
@ -2636,48 +2636,47 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i));
* *
* To read a PNG file using the simplified API: * To read a PNG file using the simplified API:
* *
* 1) Declare a 'png_image' structure (see below) on the stack and memset() it * 1) Declare a 'png_image' structure (see below) on the stack and set the
* to all zero. * version field to PNG_IMAGE_VERSION.
* 2) Call the appropriate png_image_begin_read... function. * 2) Call the appropriate png_image_begin_read... function.
* 3) Set the png_image 'format' member to the required sample format. * 3) Set the png_image 'format' member to the required sample format.
* 4) [Optionally] Call png_image_read_colormap to read the image color-map and * 4) Allocate a buffer for the image and, if required, the color-map.
* request return of a color-mapped image. * 5) Call png_image_finish_read to read the image and, if required, the
* 5) Allocate a buffer for the image. * color-map into your buffers.
* 6) Call png_image_finish_read to read the image into your buffer.
* *
* There are no restrictions on the format of the PNG input itself; all valid * There are no restrictions on the format of the PNG input itself; all valid
* color types, bit depths, and interlace methods are acceptable, and the * color types, bit depths, and interlace methods are acceptable, and the
* input image is transformed as necessary to the requested in-memory format * input image is transformed as necessary to the requested in-memory format
* during the png_image_finish_read() step. The only caveat is that if you * during the png_image_finish_read() step. The only caveat is that if you
* request a color-mapped image from a PNG that was not originally color-mapped * request a color-mapped image from a PNG that is full-color or makes
* the transformation is extremely lossy and the result may look terrible. * complex use of an alpha channel the transformation is extremely lossy and the
* result may look terrible.
* *
* To write a PNG file using the simplified API: * To write a PNG file using the simplified API:
* *
* 1) Declare a 'png_image' structure on the stack and memset() it to all zero. * 1) Declare a 'png_image' structure on the stack and memset() it to all zero.
* 2) Initialize the members of the structure that describe the image, setting * 2) Initialize the members of the structure that describe the image, setting
* the 'format' member to the format of the image samples. * the 'format' member to the format of the image samples.
* 3) [Optionally] call png_image_write_colormap to set the image color-map if * 3) Call the appropriate png_image_write... function with a pointer to the
* the data to be written is color-mapped. * image and, if necessary, the color-map to write the PNG data.
* 4) Call the appropriate png_image_write... function with a pointer to the
* image to write the PNG data.
* *
* png_image is a structure that describes the in-memory format of an image * png_image is a structure that describes the in-memory format of an image
* when it is being read or define the in-memory format of an image that you * when it is being read or defines the in-memory format of an image that you
* need to write: * need to write:
*/ */
#define PNG_IMAGE_VERSION 1
typedef struct png_control *png_controlp; typedef struct png_control *png_controlp;
typedef struct typedef struct
{ {
png_controlp opaque; /* Initialize to NULL, free with png_image_free */
png_uint_32 version; /* Set to PNG_IMAGE_VERSION */
png_uint_32 width; /* Image width in pixels (columns) */ png_uint_32 width; /* Image width in pixels (columns) */
png_uint_32 height; /* Image height in pixels (rows) */ png_uint_32 height; /* Image height in pixels (rows) */
png_uint_32 format; /* Image format as defined below */ png_uint_32 format; /* Image format as defined below */
png_uint_32 flags; /* A bit mask containing informational flags */ png_uint_32 flags; /* A bit mask containing informational flags */
png_controlp opaque; /* Initialize to NULL, free with png_image_free */ png_uint_32 colormap_entries;
/* Number of entries in the color-map */
/* The following is only used for write; initialize it to NULL */
png_const_bytep colormap; /* A pointer to the application color-map */
/* In the event of an error or warning the following field will be set to a /* In the event of an error or warning the following field will be set to a
* non-zero value and the 'message' field will contain a '\0' terminated * non-zero value and the 'message' field will contain a '\0' terminated
@ -2706,15 +2705,15 @@ typedef struct
char message[64]; char message[64];
} png_image, *png_imagep; } png_image, *png_imagep;
/* The pixels (samples) of the image have one to four channels whose components /* The samples of the image have one to four channels whose components have
* have original values in the range 0 to 1.0: * original values in the range 0 to 1.0:
* *
* 1: A single gray or luminance channel (G). * 1: A single gray or luminance channel (G).
* 2: A gray/luminance channel and an alpha channel (GA). * 2: A gray/luminance channel and an alpha channel (GA).
* 3: Three red, green, blue color channels (RGB). * 3: Three red, green, blue color channels (RGB).
* 4: Three color channels and an alpha channel (RGBA). * 4: Three color channels and an alpha channel (RGBA).
* *
* The channels are encoded in one of two ways: * The components are encoded in one of two ways:
* *
* a) As a small integer, value 0..255, contained in a single byte. For the * a) As a small integer, value 0..255, contained in a single byte. For the
* alpha channel the original value is simply value/255. For the color or * alpha channel the original value is simply value/255. For the color or
@ -2735,22 +2734,24 @@ typedef struct
* channel: the color/gray channels are scaled (pre-multiplied) by the alpha * channel: the color/gray channels are scaled (pre-multiplied) by the alpha
* value. * value.
* *
* When a color-mapped image is used as a result of calling * The samples are either contained directly in the image data, between 1 and 8
* png_image_read_colormap or png_image_write_colormap the channels are encoded * bytes per pixel according to the encoding, or are held in a color-map indexed
* in the color-map and the descriptions above apply to the color-map entries. * by bytes in the image data. In the case of a color-map the color-map entries
* The image data is encoded as small integers, value 0..255, that index the * are individual samples, encoded as above, and the image data has one byte per
* entries in the color-map. One integer (one byte) is stored for each pixel. * pixel to select the relevant sample from the color-map.
*/ */
/* PNG_FORMAT_* /* PNG_FORMAT_*
* *
* #defines to be used in png_image::format. Each #define identifies a * #defines to be used in png_image::format. Each #define identifies a
* particular layout of channel data and, if present, alpha values. There are * particular layout of sample data and, if present, alpha values. There are
* separate defines for each of the two channel encodings. * separate defines for each of the two component encodings.
* *
* A format is built up using single bit flag values. Not all combinations are * A format is built up using single bit flag values. All combinations are
* valid: use the bit flag values below for testing a format returned by the * valid. Formats can be built up from the flag values or you can use one of
* read APIs, but set formats from the derived values. * the predefined values below. When testing formats always use the FORMAT_FLAG
* macros to test for individual features - future versions of the library may
* add new flags.
* *
* When reading or writing color-mapped images the format should be set to the * When reading or writing color-mapped images the format should be set to the
* format of the entries in the color-map then png_image_{read,write}_colormap * format of the entries in the color-map then png_image_{read,write}_colormap
@ -2762,14 +2763,15 @@ typedef struct
* compiled out it is because libpng does not have the required support. It is * compiled out it is because libpng does not have the required support. It is
* possible, however, for the libpng configuration to enable the format on just * possible, however, for the libpng configuration to enable the format on just
* read or just write; in that case you may see an error at run time. You can * read or just write; in that case you may see an error at run time. You can
* guard against this by checking for the definition of: * guard against this by checking for the definition of the appropriate
* "_SUPPORTED" macro, one of:
* *
* PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED * PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED
*/ */
#define PNG_FORMAT_FLAG_ALPHA 0x01U /* format with an alpha channel */ #define PNG_FORMAT_FLAG_ALPHA 0x01U /* format with an alpha channel */
#define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */ #define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */
#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2 byte channels else 1 byte */ #define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2 byte channels else 1 byte */
#define PNG_FORMAT_FLAG_COLORMAP 0x08U /* libpng use only */ #define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */
#ifdef PNG_FORMAT_BGR_SUPPORTED #ifdef PNG_FORMAT_BGR_SUPPORTED
# define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */ # define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */
@ -2779,13 +2781,9 @@ typedef struct
# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ # define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */
#endif #endif
/* Supported formats are as follows. Future versions of libpng may support more /* Commonly used formats have predefined macros.
* formats; for compatibility with older versions simply check if the format
* macro is defined using #ifdef. These defines describe the in-memory layout
* of the components of the pixels of the image or, for color-mapped images, the
* layout of the entries of the color-map.
* *
* First the single byte formats: * First the single byte (sRGB) formats:
*/ */
#define PNG_FORMAT_GRAY 0 #define PNG_FORMAT_GRAY 0
#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA #define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA
@ -2798,9 +2796,7 @@ typedef struct
#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST) #define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST)
/* Then the linear 2-byte formats. When naming these "Y" is used to /* Then the linear 2-byte formats. When naming these "Y" is used to
* indicate a luminance (gray) channel. The component order within the pixel * indicate a luminance (gray) channel.
* is always the same - there is no provision for swapping the order of the
* components in the linear format.
*/ */
#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR #define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR
#define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA) #define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA)
@ -2808,13 +2804,17 @@ typedef struct
#define PNG_FORMAT_LINEAR_RGB_ALPHA \ #define PNG_FORMAT_LINEAR_RGB_ALPHA \
(PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA) (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA)
/* Color-mapped formats are obtained by calling png_image_{read,write}_colormap, /* With color-mapped formats the image data is one byte for each pixel, the byte
* as appropriate after setting png_image::format to the format of the color-map * is an index into the color-map which is formatted as above. To obtain a
* to be read or written. Applications may check the value of * color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP
* PNG_FORMAT_FLAG_COLORMAP to see if they have called the colormap API. The * to one of the above definitions, or you can use one of the definitions below.
* format of the color-map may be extracted using the following macro.
*/ */
#define PNG_FORMAT_OF_COLORMAP(fmt) ((fmt) & ~PNG_FORMAT_FLAG_COLORMAP) #define PNG_FORMAT_RGB_COLORMAP (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP)
#define PNG_FORMAT_BGR_COLORMAP (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP)
#define PNG_FORMAT_RGBA_COLORMAP (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP)
#define PNG_FORMAT_ARGB_COLORMAP (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP)
#define PNG_FORMAT_BGRA_COLORMAP (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP)
#define PNG_FORMAT_ABGR_COLORMAP (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP)
/* PNG_IMAGE macros /* PNG_IMAGE macros
* *
@ -2822,9 +2822,9 @@ typedef struct
* structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the * structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the
* actual image sample values - either the entries in the color-map or the * actual image sample values - either the entries in the color-map or the
* pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values * pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values
* for the pixels and will always return 1 after a call to * for the pixels and will always return 1 for color-mapped formats. The
* png_image_{read,write}_colormap. The remaining macros return information * remaining macros return information about the rows in the image and the
* about the rows in the image and the complete image. * complete image.
* *
* NOTE: All the macros that take a png_image::format parameter are compile time * NOTE: All the macros that take a png_image::format parameter are compile time
* constants if the format parameter is, itself, a constant. Therefore these * constants if the format parameter is, itself, a constant. Therefore these
@ -2841,7 +2841,7 @@ typedef struct
#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\ #define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\
((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1) ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1)
/* Return the size in bytes of a single component of a pixel or color-map /* Return the size in bytes of a single component of a pixel or color-map
* entry (as appropriate) in the image. * entry (as appropriate) in the image: 1 or 2.
*/ */
#define PNG_IMAGE_SAMPLE_SIZE(fmt)\ #define PNG_IMAGE_SAMPLE_SIZE(fmt)\
@ -2851,11 +2851,19 @@ typedef struct
* one byte in size), otherwise it is the size of one image pixel. * one byte in size), otherwise it is the size of one image pixel.
*/ */
#define PNG_IMAGE_COLORMAP_SIZE(fmt) (PNG_IMAGE_SAMPLE_SIZE(format) * 256) #define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\
/* The size of the color-map required by the format; this is the size of the (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256)
* color-map buffer passed to the png_image_{read,write}_colormap APIs, it is /* The maximum size of the color-map required by the format expressed in a
* a fixed number determined by the format so can easily be allocated on the * count of components. This can be used to compile-time allocate a
* stack if necessary. * color-map:
*
* png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)];
*
* png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)];
*
* Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the
* information from one of the png_image_begin_read_ APIs and dynamically
* allocate the required memory.
*/ */
/* Corresponding information about the pixels */ /* Corresponding information about the pixels */
@ -2898,6 +2906,14 @@ typedef struct
* the row stride is the minimum stride required for the image. * the row stride is the minimum stride required for the image.
*/ */
#define PNG_IMAGE_COLORMAP_SIZE(image)\
(PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries)
/* Return the size, in bytes, of the color-map of this image. If the image
* format is not a color-map format this will return a size sufficient for
* 256 entries in the given format; check PNG_IMAGE_FORMAT_FLAG_COLORMAP if
* you don't want to allocate a color-map in this case.
*/
/* PNG_IMAGE_FLAG_* /* PNG_IMAGE_FLAG_*
* *
* Flags containing additional information about the image are held in the * Flags containing additional information about the image are held in the
@ -2908,13 +2924,6 @@ typedef struct
* correspond to the red, green and blue end-points defined by sRGB. * correspond to the red, green and blue end-points defined by sRGB.
*/ */
#define PNG_IMAGE_FLAG_COLORMAP 0x02
/* The PNG is color-mapped. If this flag is set png_image_read_colormap
* can be used without further loss of image information. If it is not set
* png_image_read_colormap will cause significant loss if the image has any
* colors (if PNG_FORMAT_FLAG_COLOR is set).
*/
#ifdef PNG_SIMPLIFIED_READ_SUPPORTED #ifdef PNG_SIMPLIFIED_READ_SUPPORTED
/* READ APIs /* READ APIs
* --------- * ---------
@ -2938,28 +2947,9 @@ PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image,
png_const_voidp memory, png_size_t size)); png_const_voidp memory, png_size_t size));
/* The PNG header is read from the given memory buffer. */ /* The PNG header is read from the given memory buffer. */
PNG_EXPORT(242, int, png_image_read_colormap, (png_imagep image,
png_bytep colormap, png_colorp background));
/* Set the png_image to read a color-mapped image. image->format must be set
* to the format required for the color-map, typically PNG_FORMAT_RGBA or
* just PNG_FORMAT_RGB if an alpha channel is to be removed.
*
* The color-map is filled in and the actual number of valid entries
* returned, 0 is returned on error. A subsequent call to
* png_image_finish_read will return the color-mapped image data; one byte
* per pixel.
*
* background is used as described below to remove alpha or transparency
* information from an 8-bit color-map by compositing onto a solid color.
*
* If background is NULL *and* PNG_FORMAT_RGB is requested *and* the input
* has an alpha channel then the call will currently FAIL, however, in the
* future, libpng may be extended to composite onto the buffer in this case
* too.
*/
PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image,
png_colorp background, void *buffer, png_int_32 row_stride)); png_colorp background, void *buffer, png_int_32 row_stride,
void *colormap));
/* Finish reading the image into the supplied buffer and clean up the /* Finish reading the image into the supplied buffer and clean up the
* png_image structure. * png_image structure.
* *
@ -2974,12 +2964,22 @@ PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image,
* onto the buffer. The value is an sRGB color to use for the background, * onto the buffer. The value is an sRGB color to use for the background,
* for grayscale output the green channel is used. * for grayscale output the green channel is used.
* *
* If png_image_read_colormap has been called the value of background must be * background must be supplied when an alpha channel must be removed from a
* the same as that passed to the colormap call or the resultant image pixels * single byte color-mapped output format, in other words if:
* are implementation defined and may vary between libpng minor releases. *
* 1) The original format from png_image_begin_read_from_* had
* PNG_FORMAT_FLAG_ALPHA set.
* 2) The format set by the application does not.
* 3) The format set by the application has PNG_FORMAT_FLAG_COLORMAP set and
* PNG_FORMAT_FLAG_LINEAR *not* set.
* *
* For linear output removing the alpha channel is always done by compositing * For linear output removing the alpha channel is always done by compositing
* on black. * on black and background is ignored.:
*
* colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must
* be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE.
* image->colormap_entries will be updated to the actual number of entries
* written to the colormap; this may be less than the original value.
*/ */
PNG_EXPORT(238, void, png_image_free, (png_imagep image)); PNG_EXPORT(238, void, png_image_free, (png_imagep image));
@ -2992,42 +2992,38 @@ PNG_EXPORT(238, void, png_image_free, (png_imagep image));
/* 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
* be written: * be written. To do this use memset to set the whole structure to 0 then
* initialize fields describing your image.
* *
* version: must be set to PNG_IMAGE_VERSION
* opaque: must be initialized to NULL * opaque: must be initialized to NULL
* colormap: must be initialized to NULL
* width: image width in pixels * width: image width in pixels
* height: image height in rows * height: image height in rows
* format: the format of the data you wish to write * format: the format of the data (image and color-map) you wish to write
* flags: set to 0 unless one of the defined flags applies; set * flags: set to 0 unless one of the defined flags applies; set
* PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB * PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB
* 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)
*/ */
PNG_EXPORT(243, int, png_image_write_colormap, (png_imagep image,
png_const_bytep colormap));
/* Optionally write a color-mapped image. 'format' must be set to the format
* of the data in the color-map and must not be changed after the call. The
* colormap *pointer* is retained, the color-map data itself is not copied;
* the data must not be freed until after the called to png_image_write_*
*/
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)); png_int_32 row_stride, const void *colormap));
/* Write the image to the named file. */ /* Write the image to the named file. */
PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, 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));
/* Write the image to the given (FILE*). */ /* Write the image to the given (FILE*). */
/* With all write APIs if image is in one of the linear formats with 16-bit data /* With both write APIs if image is in one of the linear formats with 16-bit
* then setting convert_to_8_bit will cause the output to be an 8-bit PNG gamma * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG
* 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.
* *
* With color-mapped data png_image_write_colormap must be called. The palette * With color-mapped data formats the colormap parameter point to a color-map
* may contain linear (16-bit) entries, these will be converted to sRGB values * with at least image->colormap_entries encoded in the specified format. If
* regardless of the setting of convert_to_8_bit. * the format is linear the written PNG color-map will be converted to sRGB
* regardless of the convert_to_8_bit flag.
* *
* 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
@ -3049,7 +3045,7 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
* scripts/symbols.def as well. * scripts/symbols.def as well.
*/ */
#ifdef PNG_EXPORT_LAST_ORDINAL #ifdef PNG_EXPORT_LAST_ORDINAL
PNG_EXPORT_LAST_ORDINAL(243); PNG_EXPORT_LAST_ORDINAL(241);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -519,20 +519,31 @@ typedef const png_uint_16p * png_const_uint_16pp;
#ifdef PNG_SIMPLIFIED_READ_SUPPORTED #ifdef PNG_SIMPLIFIED_READ_SUPPORTED
extern /*PRIVATE*/ PNG_CONST_DATA png_uint_16 png_sRGB_table[256]; extern /*PRIVATE*/ PNG_CONST_DATA png_uint_16 png_sRGB_table[256];
/* Convert from an sRGB encoded value 0..255 to a 16-bit linear value, /* Convert from an sRGB encoded value 0..255 to a 16-bit linear value,
* 0..65535. This table gives the closes 16-bit answers (no errors). * 0..65535. This table gives the closest 16-bit answers (no errors).
*/ */
#endif #endif
extern /*PRIVATE*/ PNG_CONST_DATA png_uint_16 png_sRGB_base[512]; extern /*PRIVATE*/ PNG_CONST_DATA png_uint_16 png_sRGB_base[512];
extern /*PRIVATE*/ PNG_CONST_DATA png_byte png_sRGB_delta[512]; extern /*PRIVATE*/ PNG_CONST_DATA png_byte png_sRGB_delta[512];
#define PNG_sRGB_FROM_LINEAR(linear) ((png_sRGB_base[(linear)>>15] +\ #define PNG_sRGB_FROM_LINEAR(linear) ((png_byte)((png_sRGB_base[(linear)>>15] +\
((((linear)&0x7fff)*png_sRGB_delta[(linear)>>15])>>12)) >> 8) ((((linear)&0x7fff)*png_sRGB_delta[(linear)>>15])>>12)) >> 8))
/* Given a value 'linear' in the range 0..255*65535 calculate the 8-bit sRGB /* Given a value 'linear' in the range 0..255*65535 calculate the 8-bit sRGB
* encoded value with maximum error 0.646365. Note that the input is not a * encoded value with maximum error 0.646365. Note that the input is not a
* 16-bit value; it has been multiplied by 255! */ * 16-bit value; it has been multiplied by 255! */
#endif /* PNG_SIMPLIFIED_READ/WRITE */ #endif /* PNG_SIMPLIFIED_READ/WRITE */
/* Added to libpng-1.6.0: scale a 16-bit value in the range 0..65535 to 0..255
* by dividing by 257 *with rounding*. This macro is exact for the given range.
* See the discourse in pngrtran.c png_do_scale_16_to_8. The values in the
* macro were established by experiment (modifying the added value). The macro
* has a second variant that takes a value already scaled by 255 and divides by
* 65535 - this has a maximum error of .502. Over the range 0..65535*65535 it
* only gives off-by-one errors and only for 0.5% (1 in 200) of the values.
*/
#define PNG_DIV65535(v24) (((v24) + 32895) >> 16)
#define PNG_DIV257(v16) PNG_DIV65535((png_uint_32)(v16) * 255)
/* Added to libpng-1.2.6 JB */ /* Added to libpng-1.2.6 JB */
#define PNG_ROWBYTES(pixel_bits, width) \ #define PNG_ROWBYTES(pixel_bits, width) \
((pixel_bits) >= 8 ? \ ((pixel_bits) >= 8 ? \
@ -1633,6 +1644,9 @@ typedef struct png_control
unsigned int owned_file :1; /* We own the file in io_ptr */ unsigned int owned_file :1; /* We own the file in io_ptr */
} png_control; } png_control;
/* This is used to name an sPLT written by the simplified API. */
#define LIBPNG_SPLT_NAME "libpng " PNG_LIBPNG_VER_STRING
/* Return the pointer to the jmp_buf from a png_control: necessary because C /* Return the pointer to the jmp_buf from a png_control: necessary because C
* does not reveal the type of the elements of jmp_buf. * does not reveal the type of the elements of jmp_buf.
*/ */

1859
pngread.c

File diff suppressed because it is too large Load Diff

View File

@ -1454,7 +1454,7 @@ png_init_read_transformations(png_structrp png_ptr)
* NOTE: this discards the low 16 bits of the user supplied background * NOTE: this discards the low 16 bits of the user supplied background
* color, but until expand_16 works properly there is no choice! * color, but until expand_16 works properly there is no choice!
*/ */
# define CHOP(x) (x)=((png_uint_16)(((png_uint_32)(x)*255+32895) >> 16)) # define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x))
CHOP(png_ptr->background.red); CHOP(png_ptr->background.red);
CHOP(png_ptr->background.green); CHOP(png_ptr->background.green);
CHOP(png_ptr->background.blue); CHOP(png_ptr->background.blue);

View File

@ -1561,32 +1561,6 @@ png_image_write_init(png_imagep image)
return png_image_error(image, "png_image_read: out of memory"); return png_image_error(image, "png_image_read: out of memory");
} }
int PNGAPI
png_image_write_colormap(png_imagep image, png_const_bytep colormap)
{
if (image != NULL)
{
if (colormap != NULL)
{
if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0)
{
image->colormap = colormap; /* alias, caller must preserve */
image->format |= PNG_FORMAT_FLAG_COLORMAP;
}
else
return png_image_error(image,
"png_image_write_colormap: colormap already set");
}
else
return png_image_error(image,
"png_image_write_colormap: invalid argument");
}
return 0;
}
/* Arguments to png_image_write_main: */ /* Arguments to png_image_write_main: */
typedef struct typedef struct
{ {
@ -1594,6 +1568,7 @@ typedef struct
png_imagep image; png_imagep image;
png_const_voidp buffer; png_const_voidp buffer;
png_int_32 row_stride; png_int_32 row_stride;
png_const_voidp colormap;
int convert_to_8bit; int convert_to_8bit;
/* Local variables: */ /* Local variables: */
png_const_voidp first_row; png_const_voidp first_row;
@ -1708,7 +1683,58 @@ png_write_image_16bit(png_voidp argument)
/* Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel /* Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel
* is present it must be removed from the components, the components are then * is present it must be removed from the components, the components are then
* written in sRGB encoding. No components are added or removed. * written in sRGB encoding. No components are added or removed.
*
* Calculate an alpha reciprocal to reverse pre-multiplication. As above the
* calculation can be done to 15 bits of accuracy; however, the output needs to
* be scaled in the range 0..255*65535, so include that scaling here.
*/ */
#define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha)
static png_byte
png_unpremultiply(png_uint_32 component, png_uint_32 alpha,
png_uint_32 reciprocal/*from the above macro*/)
{
/* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
* is represented as some other value there is more likely to be a
* discontinuity which will probably damage compression when moving from a
* fully transparent area to a nearly transparent one. (The assumption here
* is that opaque areas tend not to be 0 intensity.)
*
* There is a rounding problem here; if alpha is less than 128 it will end up
* as 0 when scaled to 8 bits. To avoid introducing spurious colors into the
* output change for this too.
*/
if (component >= alpha || alpha < 128)
return 255;
/* component<alpha, so component/alpha is less than one and
* component*reciprocal is less than 2^31.
*/
else if (component > 0)
{
/* The test is that alpha/257 (rounded) is less than 255, the first value
* that becomes 255 is 65407.
* NOTE: this must agree with the PNG_DIV257 macro (which must, therefore,
* be exact!) [Could also test reciprocal != 0]
*/
if (alpha < 65407)
{
component *= reciprocal;
component += 64; /* round to nearest */
component >>= 7;
}
else
component *= 255;
/* Convert the component to sRGB. */
return (png_byte)PNG_sRGB_FROM_LINEAR(component);
}
else
return 0;
}
static int static int
png_write_image_8bit(png_voidp argument) png_write_image_8bit(png_voidp argument)
{ {
@ -1749,62 +1775,19 @@ png_write_image_8bit(png_voidp argument)
if (aindex != 0) while (out_ptr < row_end) /* Alpha channel case */ if (aindex != 0) while (out_ptr < row_end) /* Alpha channel case */
{ {
png_uint_16 alpha = in_ptr[aindex]; png_uint_16 alpha = in_ptr[aindex];
png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
png_uint_32 reciprocal = 0; png_uint_32 reciprocal = 0;
int c; int c;
/* Scale and write the alpha channel. See pngrtran.c /* Scale and write the alpha channel. */
* png_do_scale_16_to_8 for a discussion of this calculation. The out_ptr[aindex] = alphabyte;
* code here has machine native values, so use:
*
* (V * 255 + 32895) >> 16
*/
out_ptr[aindex] = (png_byte)((alpha * 255 + 32895) >> 16);
/* Calculate a reciprocal. As above the calculation can be done to if (alphabyte > 0 && alphabyte < 255)
* 15 bits of accuracy, however the output needs to be scaled in the reciprocal = UNP_RECIPROCAL(alpha);
* range 0..255*65535, so include that scaling here.
*/
if (alpha > 0 && alpha < 65535)
reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
c = channels; c = channels;
do /* always at least one channel */ do /* always at least one channel */
{ *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
/* Need 32 bit accuracy in the sRGB tables */
png_uint_32 component = *in_ptr++;
/* The following gives 1.0 for an alpha of 0, which is fine,
* otherwise if 0/0 is represented as some other value there is
* more likely to be a discontinuity which will probably damage
* compression when moving from a fully transparent area to a
* nearly transparent one. (The assumption here is that opaque
* areas tend not to be 0 intensity.)
*/
if (component >= alpha)
*out_ptr++ = 255;
/* component<alpha, so component/alpha is less than one and
* component*reciprocal is less than 2^31.
*/
else if (component > 0)
{
if (alpha < 65535)
{
component *= reciprocal;
component += 64; /* round to nearest */
component >>= 7;
}
else
component *= 255;
/* Convert the component to sRGB. */
*out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component);
}
else
*out_ptr++ = 0;
}
while (--c > 0); while (--c > 0);
/* Skip to next component (skip the intervening alpha channel) */ /* Skip to next component (skip the intervening alpha channel) */
@ -1846,6 +1829,151 @@ png_write_image_8bit(png_voidp argument)
return 1; return 1;
} }
static void
png_image_set_PLTE(png_image_write_control *display)
{
const png_imagep image = display->image;
const void *cmap = display->colormap;
const int entries = image->colormap_entries > 256 ? 256 :
(int)image->colormap_entries;
/* NOTE: the caller must check for cmap != NULL and entries != 0 */
const png_uint_32 format = image->format;
const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format);
# ifdef PNG_FORMAT_BGR_SUPPORTED
const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
(format & PNG_FORMAT_FLAG_ALPHA) != 0;
# else
# define afirst 0
# endif
# ifdef PNG_FORMAT_BGR_SUPPORTED
const int bgr = (format & PNG_FORMAT_FLAG_BGR) ? 2 : 0;
# else
# define bgr 0
# endif
int i, num_trans;
png_color palette[256];
png_byte tRNS[256];
memset(tRNS, 255, sizeof tRNS);
memset(palette, 0, sizeof palette);
for (i=num_trans=0; i<entries; ++i)
{
/* This gets automatically converted to sRGB with reversal of the
* pre-multiplication if the color-map has an alpha channel.
*/
if (format & PNG_FORMAT_FLAG_LINEAR)
{
png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap);
entry += i * channels;
if (channels & 1) /* no alpha */
{
if (channels >= 3) /* RGB */
{
palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
entry[(2 ^ bgr)]);
palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
entry[1]);
palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
entry[bgr]);
}
else /* Gray */
palette[i].blue = palette[i].red = palette[i].green =
(png_byte)PNG_sRGB_FROM_LINEAR(255 * *entry);
}
else /* alpha */
{
png_uint_16 alpha = entry[afirst ? 0 : channels-1];
png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
png_uint_32 reciprocal = 0;
/* Calculate a reciprocal, as in the png_write_image_8bit code above
* this is designed to produce a value scaled to 255*65535 when
* divided by 128 (i.e. asr 7).
*/
if (alphabyte > 0 && alphabyte < 255)
reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
tRNS[i] = alphabyte;
if (alphabyte < 255)
num_trans = i+1;
if (channels >= 3) /* RGB */
{
palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)],
alpha, reciprocal);
palette[i].green = png_unpremultiply(entry[afirst + 1], alpha,
reciprocal);
palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha,
reciprocal);
}
else /* gray */
palette[i].blue = palette[i].red = palette[i].green =
png_unpremultiply(entry[afirst], alpha, reciprocal);
}
}
else /* Color-map has sRGB values */
{
png_const_bytep entry = png_voidcast(png_const_bytep, cmap);
entry += i * channels;
switch (channels)
{
case 4:
tRNS[i] = entry[afirst ? 0 : 3];
if (tRNS[i] < 255)
num_trans = i+1;
/* FALL THROUGH */
case 3:
palette[i].blue = entry[afirst + (2 ^ bgr)];
palette[i].green = entry[afirst + 1];
palette[i].red = entry[afirst + bgr];
break;
case 2:
tRNS[i] = entry[1 ^ afirst];
if (tRNS[i] < 255)
num_trans = i+1;
/* FALL THROUGH */
case 1:
palette[i].blue = palette[i].red = palette[i].green =
entry[afirst];
break;
default:
break;
}
}
}
# ifdef afirst
# undef afirst
# endif
# ifdef bgr
# undef bgr
# endif
png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette,
entries);
if (num_trans > 0)
png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS,
num_trans, NULL);
image->colormap_entries = entries;
}
static int static int
png_image_write_main(png_voidp argument) png_image_write_main(png_voidp argument)
{ {
@ -1856,9 +1984,10 @@ png_image_write_main(png_voidp argument)
png_inforp info_ptr = image->opaque->info_ptr; png_inforp info_ptr = image->opaque->info_ptr;
png_uint_32 format = image->format; png_uint_32 format = image->format;
int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0; /* input */ int colormap = (format & PNG_FORMAT_FLAG_COLORMAP) != 0;
int alpha = (format & PNG_FORMAT_FLAG_ALPHA) != 0; int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR) != 0; /* input */
int write_16bit = linear && !display->convert_to_8bit; int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA) != 0;
int write_16bit = linear && !colormap && !display->convert_to_8bit;
/* Default the 'row_stride' parameter if required. */ /* Default the 'row_stride' parameter if required. */
if (display->row_stride == 0) if (display->row_stride == 0)
@ -1866,7 +1995,23 @@ png_image_write_main(png_voidp argument)
/* 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) if (format & PNG_FORMAT_FLAG_COLORMAP)
return png_image_error(image, "png_image_write: colormap NYI"); {
if (display->colormap != NULL && image->colormap_entries > 0)
{
png_uint_32 entries = image->colormap_entries;
png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)),
PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
png_image_set_PLTE(display);
}
else
png_error(image->opaque->png_ptr,
"no color-map for color-mapped image");
}
else else
png_set_IHDR(png_ptr, info_ptr, image->width, image->height, png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
@ -1880,6 +2025,7 @@ png_image_write_main(png_voidp argument)
* must still be called before. Just set the color space information, never * must still be called before. Just set the color space information, never
* write an interlaced image. * write an interlaced image.
*/ */
if (write_16bit) if (write_16bit)
{ {
/* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */ /* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */
@ -1923,7 +2069,7 @@ png_image_write_main(png_voidp argument)
# ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED # ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
if (format & PNG_FORMAT_FLAG_BGR) if (format & PNG_FORMAT_FLAG_BGR)
{ {
if (format & PNG_FORMAT_FLAG_COLOR) if (!colormap && (format & PNG_FORMAT_FLAG_COLOR) != 0)
png_set_bgr(png_ptr); png_set_bgr(png_ptr);
format &= ~PNG_FORMAT_FLAG_BGR; format &= ~PNG_FORMAT_FLAG_BGR;
} }
@ -1932,15 +2078,21 @@ png_image_write_main(png_voidp argument)
# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED # ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
if (format & PNG_FORMAT_FLAG_AFIRST) if (format & PNG_FORMAT_FLAG_AFIRST)
{ {
if (format & PNG_FORMAT_FLAG_ALPHA) if (!colormap && (format & PNG_FORMAT_FLAG_ALPHA) != 0)
png_set_swap_alpha(png_ptr); png_set_swap_alpha(png_ptr);
format &= ~PNG_FORMAT_FLAG_AFIRST; format &= ~PNG_FORMAT_FLAG_AFIRST;
} }
# endif # endif
/* If there are 16 or fewer color-map entries we wrote a lower bit depth
* above, but the application data is still byte packed.
*/
if (colormap && image->colormap_entries <= 16)
png_set_packing(png_ptr);
/* That should have handled all (both) the transforms. */ /* That should have handled all (both) the transforms. */
if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR | if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR |
PNG_FORMAT_FLAG_ALPHA)) != 0) PNG_FORMAT_FLAG_ALPHA | PNG_FORMAT_FLAG_COLORMAP)) != 0)
png_error(png_ptr, "png_write_image: unsupported transformation"); png_error(png_ptr, "png_write_image: unsupported transformation");
{ {
@ -1961,7 +2113,7 @@ png_image_write_main(png_voidp argument)
* before it is written. This only applies when the input is 16-bit and * before it is written. This only applies when the input is 16-bit and
* either there is an alpha channel or it is converted to 8-bit. * either there is an alpha channel or it is converted to 8-bit.
*/ */
if ((linear && alpha) || display->convert_to_8bit) if ((linear && alpha) || (!colormap && display->convert_to_8bit))
{ {
png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
png_get_rowbytes(png_ptr, info_ptr))); png_get_rowbytes(png_ptr, info_ptr)));
@ -2003,10 +2155,10 @@ png_image_write_main(png_voidp argument)
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 *buffer, png_int_32 row_stride, const void *colormap)
{ {
/* Write the image to the given (FILE*). */ /* Write the image to the given (FILE*). */
if (image != NULL) if (image != NULL || image->version != PNG_IMAGE_VERSION)
{ {
if (file != NULL) if (file != NULL)
{ {
@ -2025,6 +2177,7 @@ png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
display.image = image; display.image = image;
display.buffer = buffer; display.buffer = buffer;
display.row_stride = row_stride; display.row_stride = row_stride;
display.colormap = colormap;
display.convert_to_8bit = convert_to_8bit; display.convert_to_8bit = convert_to_8bit;
result = png_safe_execute(image, png_image_write_main, &display); result = png_safe_execute(image, png_image_write_main, &display);
@ -2047,10 +2200,11 @@ png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
int PNGAPI int PNGAPI
png_image_write_to_file(png_imagep image, const char *file_name, png_image_write_to_file(png_imagep image, const char *file_name,
int convert_to_8bit, const void *buffer, png_int_32 row_stride) int convert_to_8bit, const void *buffer, png_int_32 row_stride,
const void *colormap)
{ {
/* Write the image to the named file. */ /* Write the image to the named file. */
if (image != NULL) if (image != NULL || image->version != PNG_IMAGE_VERSION)
{ {
if (file_name != NULL) if (file_name != NULL)
{ {
@ -2059,7 +2213,7 @@ png_image_write_to_file(png_imagep image, const char *file_name,
if (fp != NULL) if (fp != NULL)
{ {
if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer, if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
row_stride)) row_stride, colormap))
{ {
int error; /* from fflush/fclose */ int error; /* from fflush/fclose */

View File

@ -247,5 +247,3 @@ EXPORTS
png_image_write_to_file @239 png_image_write_to_file @239
png_image_write_to_stdio @240 png_image_write_to_stdio @240
png_convert_to_rfc1123_buffer @241 png_convert_to_rfc1123_buffer @241
png_image_read_colormap @242
png_image_write_colormap @243