[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
may need corresponding changes.
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
(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
may need corresponding changes.
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
(subscription required; visit

230
png.h
View File

@ -1,7 +1,7 @@
/* 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
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@ -11,7 +11,7 @@
* Authors and maintainers:
* 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.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.
*
* Note about libpng version numbers:
@ -198,7 +198,7 @@
*
* 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
* distributed according to the same disclaimer and license as libpng-1.2.5
* with the following individual added to the list of Contributing Authors:
@ -310,7 +310,7 @@
* Y2K compliance in libpng:
* =========================
*
* January 16, 2012
* January 24, 2012
*
* Since the PNG Development group is an ad-hoc body, we can't make
* an official declaration.
@ -376,7 +376,7 @@
/* Version information for png.h - this should match the version in png.c */
#define PNG_LIBPNG_VER_STRING "1.6.0beta06"
#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_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:
*
* 1) Declare a 'png_image' structure (see below) on the stack and memset() it
* to all zero.
* 1) Declare a 'png_image' structure (see below) on the stack and set the
* version field to PNG_IMAGE_VERSION.
* 2) Call the appropriate png_image_begin_read... function.
* 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
* request return of a color-mapped image.
* 5) Allocate a buffer for the image.
* 6) Call png_image_finish_read to read the image into your buffer.
* 4) Allocate a buffer for the image and, if required, the color-map.
* 5) Call png_image_finish_read to read the image and, if required, the
* color-map into your buffers.
*
* 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
* 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
* request a color-mapped image from a PNG that was not originally color-mapped
* the transformation is extremely lossy and the result may look terrible.
* request a color-mapped image from a PNG that is full-color or makes
* 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:
*
* 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
* the 'format' member to the format of the image samples.
* 3) [Optionally] call png_image_write_colormap to set the image color-map if
* the data to be written is color-mapped.
* 4) Call the appropriate png_image_write... function with a pointer to the
* image to write the PNG data.
* 3) Call the appropriate png_image_write... function with a pointer to the
* image and, if necessary, the color-map to write the PNG data.
*
* 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:
*/
#define PNG_IMAGE_VERSION 1
typedef struct png_control *png_controlp;
typedef struct
{
png_uint_32 width; /* Image width in pixels (columns) */
png_uint_32 height; /* Image height in pixels (rows) */
png_uint_32 format; /* Image format as defined below */
png_uint_32 flags; /* A bit mask containing informational flags */
png_controlp opaque; /* Initialize to NULL, free with png_image_free */
/* The following is only used for write; initialize it to NULL */
png_const_bytep colormap; /* A pointer to the application color-map */
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 height; /* Image height in pixels (rows) */
png_uint_32 format; /* Image format as defined below */
png_uint_32 flags; /* A bit mask containing informational flags */
png_uint_32 colormap_entries;
/* Number of entries in the color-map */
/* 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
@ -2706,15 +2705,15 @@ typedef struct
char message[64];
} png_image, *png_imagep;
/* The pixels (samples) of the image have one to four channels whose components
* have original values in the range 0 to 1.0:
/* The samples of the image have one to four channels whose components have
* original values in the range 0 to 1.0:
*
* 1: A single gray or luminance channel (G).
* 2: A gray/luminance channel and an alpha channel (GA).
* 3: Three red, green, blue color channels (RGB).
* 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
* 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
* value.
*
* When a color-mapped image is used as a result of calling
* png_image_read_colormap or png_image_write_colormap the channels are encoded
* in the color-map and the descriptions above apply to the color-map entries.
* The image data is encoded as small integers, value 0..255, that index the
* entries in the color-map. One integer (one byte) is stored for each pixel.
* The samples are either contained directly in the image data, between 1 and 8
* bytes per pixel according to the encoding, or are held in a color-map indexed
* by bytes in the image data. In the case of a color-map the color-map entries
* are individual samples, encoded as above, and the image data has one byte per
* pixel to select the relevant sample from the color-map.
*/
/* PNG_FORMAT_*
*
* #defines to be used in png_image::format. Each #define identifies a
* particular layout of channel data and, if present, alpha values. There are
* separate defines for each of the two channel encodings.
* particular layout of sample data and, if present, alpha values. There are
* separate defines for each of the two component encodings.
*
* A format is built up using single bit flag values. Not all combinations are
* valid: use the bit flag values below for testing a format returned by the
* read APIs, but set formats from the derived values.
* A format is built up using single bit flag values. All combinations are
* valid. Formats can be built up from the flag values or you can use one of
* 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
* 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
* 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
* 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
*/
#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_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
# 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 */
#endif
/* Supported formats are as follows. Future versions of libpng may support more
* 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.
/* Commonly used formats have predefined macros.
*
* First the single byte formats:
* First the single byte (sRGB) formats:
*/
#define PNG_FORMAT_GRAY 0
#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)
/* Then the linear 2-byte formats. When naming these "Y" is used to
* indicate a luminance (gray) channel. The component order within the pixel
* is always the same - there is no provision for swapping the order of the
* components in the linear format.
* indicate a luminance (gray) channel.
*/
#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR
#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 \
(PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA)
/* Color-mapped formats are obtained by calling png_image_{read,write}_colormap,
* as appropriate after setting png_image::format to the format of the color-map
* to be read or written. Applications may check the value of
* PNG_FORMAT_FLAG_COLORMAP to see if they have called the colormap API. The
* format of the color-map may be extracted using the following macro.
/* With color-mapped formats the image data is one byte for each pixel, the byte
* is an index into the color-map which is formatted as above. To obtain a
* color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP
* to one of the above definitions, or you can use one of the definitions below.
*/
#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
*
@ -2822,9 +2822,9 @@ typedef struct
* structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to 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
* for the pixels and will always return 1 after a call to
* png_image_{read,write}_colormap. The remaining macros return information
* about the rows in the image and the complete image.
* for the pixels and will always return 1 for color-mapped formats. The
* remaining macros return information about the rows in the image and the
* complete image.
*
* 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
@ -2841,7 +2841,7 @@ typedef struct
#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\
((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1)
/* 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)\
@ -2851,11 +2851,19 @@ typedef struct
* 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)
/* The size of the color-map required by the format; this is the size of the
* color-map buffer passed to the png_image_{read,write}_colormap APIs, it is
* a fixed number determined by the format so can easily be allocated on the
* stack if necessary.
#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\
(PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256)
/* The maximum size of the color-map required by the format expressed in a
* count of components. This can be used to compile-time allocate a
* 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 */
@ -2898,6 +2906,14 @@ typedef struct
* 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_*
*
* 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.
*/
#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
/* 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));
/* 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_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
* 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,
* for grayscale output the green channel is used.
*
* If png_image_read_colormap has been called the value of background must be
* the same as that passed to the colormap call or the resultant image pixels
* are implementation defined and may vary between libpng minor releases.
* background must be supplied when an alpha channel must be removed from a
* single byte color-mapped output format, in other words if:
*
* 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
* 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));
@ -2992,42 +2992,38 @@ PNG_EXPORT(238, void, png_image_free, (png_imagep image));
/* WRITE APIS
* ----------
* 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
* colormap: must be initialized to NULL
* width: image width in pixels
* 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
* PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB
* 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,
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. */
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*). */
/* 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 gamma
* encoded according to the sRGB specification, otherwise a 16-bit linear
/* With both 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
* gamma encoded according to the sRGB specification, otherwise a 16-bit linear
* encoded PNG file is written.
*
* With color-mapped data png_image_write_colormap must be called. The palette
* may contain linear (16-bit) entries, these will be converted to sRGB values
* regardless of the setting of convert_to_8_bit.
* With color-mapped data formats the colormap parameter point to a color-map
* with at least image->colormap_entries encoded in the specified format. If
* 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
* 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.
*/
#ifdef PNG_EXPORT_LAST_ORDINAL
PNG_EXPORT_LAST_ORDINAL(243);
PNG_EXPORT_LAST_ORDINAL(241);
#endif
#ifdef __cplusplus

View File

@ -519,20 +519,31 @@ typedef const png_uint_16p * png_const_uint_16pp;
#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
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,
* 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
extern /*PRIVATE*/ PNG_CONST_DATA png_uint_16 png_sRGB_base[512];
extern /*PRIVATE*/ PNG_CONST_DATA png_byte png_sRGB_delta[512];
#define PNG_sRGB_FROM_LINEAR(linear) ((png_sRGB_base[(linear)>>15] +\
((((linear)&0x7fff)*png_sRGB_delta[(linear)>>15])>>12)) >> 8)
#define PNG_sRGB_FROM_LINEAR(linear) ((png_byte)((png_sRGB_base[(linear)>>15] +\
((((linear)&0x7fff)*png_sRGB_delta[(linear)>>15])>>12)) >> 8))
/* 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
* 16-bit value; it has been multiplied by 255! */
#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 */
#define PNG_ROWBYTES(pixel_bits, width) \
((pixel_bits) >= 8 ? \
@ -1622,17 +1633,20 @@ PNG_EXTERN void png_build_gamma_table PNGARG((png_structrp png_ptr,
/* The internal structure that png_image::opaque points to. */
typedef struct png_control
{
png_structp png_ptr;
png_infop info_ptr;
png_voidp error_buf; /* Always a jmp_buf at present. */
png_structp png_ptr;
png_infop info_ptr;
png_voidp error_buf; /* Always a jmp_buf at present. */
png_const_bytep memory; /* Memory buffer. */
png_size_t size; /* Size of the memory buffer. */
png_const_bytep memory; /* Memory buffer. */
png_size_t size; /* Size of the memory buffer. */
unsigned int for_write :1; /* Otherwise it is a read structure */
unsigned int owned_file :1; /* We own the file in io_ptr */
unsigned int for_write :1; /* Otherwise it is a read structure */
unsigned int owned_file :1; /* We own the file in io_ptr */
} 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
* does not reveal the type of the elements of jmp_buf.
*/

2083
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
* 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.green);
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");
}
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: */
typedef struct
{
@ -1594,6 +1568,7 @@ typedef struct
png_imagep image;
png_const_voidp buffer;
png_int_32 row_stride;
png_const_voidp colormap;
int convert_to_8bit;
/* Local variables: */
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
* is present it must be removed from the components, the components are then
* 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
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 */
{
png_uint_16 alpha = in_ptr[aindex];
png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
png_uint_32 reciprocal = 0;
int c;
/* Scale and write the alpha channel. See pngrtran.c
* png_do_scale_16_to_8 for a discussion of this calculation. The
* code here has machine native values, so use:
*
* (V * 255 + 32895) >> 16
*/
out_ptr[aindex] = (png_byte)((alpha * 255 + 32895) >> 16);
/* Scale and write the alpha channel. */
out_ptr[aindex] = alphabyte;
/* Calculate a reciprocal. 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.
*/
if (alpha > 0 && alpha < 65535)
reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
if (alphabyte > 0 && alphabyte < 255)
reciprocal = UNP_RECIPROCAL(alpha);
c = channels;
do /* always at least one channel */
{
/* 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;
}
*out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
while (--c > 0);
/* Skip to next component (skip the intervening alpha channel) */
@ -1846,6 +1829,151 @@ png_write_image_8bit(png_voidp argument)
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
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_uint_32 format = image->format;
int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0; /* input */
int alpha = (format & PNG_FORMAT_FLAG_ALPHA) != 0;
int write_16bit = linear && !display->convert_to_8bit;
int colormap = (format & PNG_FORMAT_FLAG_COLORMAP) != 0;
int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR) != 0; /* input */
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. */
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. */
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
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
* write an interlaced image.
*/
if (write_16bit)
{
/* 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
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);
format &= ~PNG_FORMAT_FLAG_BGR;
}
@ -1932,15 +2078,21 @@ png_image_write_main(png_voidp argument)
# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
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);
format &= ~PNG_FORMAT_FLAG_AFIRST;
}
# 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. */
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");
{
@ -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
* 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_get_rowbytes(png_ptr, info_ptr)));
@ -2003,10 +2155,10 @@ png_image_write_main(png_voidp argument)
int PNGAPI
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*). */
if (image != NULL)
if (image != NULL || image->version != PNG_IMAGE_VERSION)
{
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.buffer = buffer;
display.row_stride = row_stride;
display.colormap = colormap;
display.convert_to_8bit = convert_to_8bit;
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
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. */
if (image != NULL)
if (image != NULL || image->version != PNG_IMAGE_VERSION)
{
if (file_name != NULL)
{
@ -2059,7 +2213,7 @@ png_image_write_to_file(png_imagep image, const char *file_name,
if (fp != NULL)
{
if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
row_stride))
row_stride, colormap))
{
int error; /* from fflush/fclose */

View File

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