From 45ceb74df29bfb775e09eb74ce3d470bc777df4a Mon Sep 17 00:00:00 2001 From: FunkyFr3sh Date: Mon, 12 Nov 2018 06:31:02 +0100 Subject: [PATCH] use lodepng for screenshots --- Makefile | 8 +- cnc-ddraw.vcxproj | 6 +- cnc-ddraw.vcxproj.filters | 18 +- ddraw.rc | 2 +- inc/lodepng.h | 1924 +++++++++++ inc/png.h | 2699 --------------- inc/pngconf.h | 1540 --------- inc/zconf.h | 428 --- inc/zlib.h | 1613 --------- lib/libpng14.a | Bin 210758 -> 0 bytes lib/libz.a | Bin 95182 -> 0 bytes src/lodepng.c | 6853 +++++++++++++++++++++++++++++++++++++ src/screenshot.c | 171 +- 13 files changed, 8814 insertions(+), 6448 deletions(-) create mode 100644 inc/lodepng.h delete mode 100644 inc/png.h delete mode 100644 inc/pngconf.h delete mode 100644 inc/zconf.h delete mode 100644 inc/zlib.h delete mode 100644 lib/libpng14.a delete mode 100644 lib/libz.a create mode 100644 src/lodepng.c diff --git a/Makefile b/Makefile index 48198f4..0e5b398 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,7 @@ CC=gcc WINDRES=windres -CFLAGS=-DHAVE_LIBPNG -Iinc -Wall -Wl,--enable-stdcall-fixup -s -LIBS=lib/libpng14.a lib/libz.a -lgdi32 -lwinmm - -#CFLAGS=-Iinc -Wall -Wl,--enable-stdcall-fixup -O3 -s -#LIBS=-lgdi32 -lwinmm +CFLAGS=-Iinc -Wall -Wl,--enable-stdcall-fixup -s +LIBS=-lgdi32 -lwinmm FILES = src/debug.c \ src/main.c \ @@ -17,6 +14,7 @@ FILES = src/debug.c \ src/render_d3d9.c \ src/screenshot.c \ src/settings.c \ + src/lodepng.c \ src/opengl.c all: diff --git a/cnc-ddraw.vcxproj b/cnc-ddraw.vcxproj index 0dba751..79127ec 100644 --- a/cnc-ddraw.vcxproj +++ b/cnc-ddraw.vcxproj @@ -13,6 +13,7 @@ + @@ -28,6 +29,7 @@ + @@ -36,11 +38,7 @@ - - - - diff --git a/cnc-ddraw.vcxproj.filters b/cnc-ddraw.vcxproj.filters index 8756909..13536df 100644 --- a/cnc-ddraw.vcxproj.filters +++ b/cnc-ddraw.vcxproj.filters @@ -51,6 +51,9 @@ Source Files + + Source Files + @@ -68,21 +71,9 @@ Header Files - - Header Files - - - Header Files - Header Files - - Header Files - - - Header Files - Header Files @@ -101,6 +92,9 @@ Header Files + + Header Files + diff --git a/ddraw.rc b/ddraw.rc index 495881e..e976c5d 100644 --- a/ddraw.rc +++ b/ddraw.rc @@ -4,7 +4,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 2 #define VERSION_BUILD 4 -#define VERSION_REVISION 2 +#define VERSION_REVISION 3 #define VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION #define VERSION_STRING ver_str(VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD, VERSION_REVISION) diff --git a/inc/lodepng.h b/inc/lodepng.h new file mode 100644 index 0000000..2780e09 --- /dev/null +++ b/inc/lodepng.h @@ -0,0 +1,1924 @@ +/* +LodePNG version 20180910 + +Copyright (c) 2005-2018 Lode Vandevenne + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*/ + +#ifndef LODEPNG_H +#define LODEPNG_H + +#include /*for size_t*/ + +extern const char* LODEPNG_VERSION_STRING; + +/* +The following #defines are used to create code sections. They can be disabled +to disable code sections, which can give faster compile time and smaller binary. +The "NO_COMPILE" defines are designed to be used to pass as defines to the +compiler command to disable them without modifying this header, e.g. +-DLODEPNG_NO_COMPILE_ZLIB for gcc. +In addition to those below, you can also define LODEPNG_NO_COMPILE_CRC to +allow implementing a custom lodepng_crc32. +*/ +/*deflate & zlib. If disabled, you must specify alternative zlib functions in +the custom_zlib field of the compress and decompress settings*/ +#ifndef LODEPNG_NO_COMPILE_ZLIB +#define LODEPNG_COMPILE_ZLIB +#endif +/*png encoder and png decoder*/ +#ifndef LODEPNG_NO_COMPILE_PNG +#define LODEPNG_COMPILE_PNG +#endif +/*deflate&zlib decoder and png decoder*/ +#ifndef LODEPNG_NO_COMPILE_DECODER +#define LODEPNG_COMPILE_DECODER +#endif +/*deflate&zlib encoder and png encoder*/ +#ifndef LODEPNG_NO_COMPILE_ENCODER +#define LODEPNG_COMPILE_ENCODER +#endif +/*the optional built in harddisk file loading and saving functions*/ +#ifndef LODEPNG_NO_COMPILE_DISK +#define LODEPNG_COMPILE_DISK +#endif +/*support for chunks other than IHDR, IDAT, PLTE, tRNS, IEND: ancillary and unknown chunks*/ +#ifndef LODEPNG_NO_COMPILE_ANCILLARY_CHUNKS +#define LODEPNG_COMPILE_ANCILLARY_CHUNKS +#endif +/*ability to convert error numerical codes to English text string*/ +#ifndef LODEPNG_NO_COMPILE_ERROR_TEXT +#define LODEPNG_COMPILE_ERROR_TEXT +#endif +/*Compile the default allocators (C's free, malloc and realloc). If you disable this, +you can define the functions lodepng_free, lodepng_malloc and lodepng_realloc in your +source files with custom allocators.*/ +#ifndef LODEPNG_NO_COMPILE_ALLOCATORS +#define LODEPNG_COMPILE_ALLOCATORS +#endif +/*compile the C++ version (you can disable the C++ wrapper here even when compiling for C++)*/ +#ifdef __cplusplus +#ifndef LODEPNG_NO_COMPILE_CPP +#define LODEPNG_COMPILE_CPP +#endif +#endif + +#ifdef LODEPNG_COMPILE_CPP +#include +#include +#endif /*LODEPNG_COMPILE_CPP*/ + +#ifdef LODEPNG_COMPILE_PNG +/*The PNG color types (also used for raw).*/ +typedef enum LodePNGColorType +{ + LCT_GREY = 0, /*greyscale: 1,2,4,8,16 bit*/ + LCT_RGB = 2, /*RGB: 8,16 bit*/ + LCT_PALETTE = 3, /*palette: 1,2,4,8 bit*/ + LCT_GREY_ALPHA = 4, /*greyscale with alpha: 8,16 bit*/ + LCT_RGBA = 6 /*RGB with alpha: 8,16 bit*/ +} LodePNGColorType; + +#ifdef LODEPNG_COMPILE_DECODER +/* +Converts PNG data in memory to raw pixel data. +out: Output parameter. Pointer to buffer that will contain the raw pixel data. + After decoding, its size is w * h * (bytes per pixel) bytes larger than + initially. Bytes per pixel depends on colortype and bitdepth. + Must be freed after usage with free(*out). + Note: for 16-bit per channel colors, uses big endian format like PNG does. +w: Output parameter. Pointer to width of pixel data. +h: Output parameter. Pointer to height of pixel data. +in: Memory buffer with the PNG file. +insize: size of the in buffer. +colortype: the desired color type for the raw output image. See explanation on PNG color types. +bitdepth: the desired bit depth for the raw output image. See explanation on PNG color types. +Return value: LodePNG error code (0 means no error). +*/ +unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, + const unsigned char* in, size_t insize, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_decode_memory, but always decodes to 32-bit RGBA raw image*/ +unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, + const unsigned char* in, size_t insize); + +/*Same as lodepng_decode_memory, but always decodes to 24-bit RGB raw image*/ +unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, + const unsigned char* in, size_t insize); + +#ifdef LODEPNG_COMPILE_DISK +/* +Load PNG from disk, from file with given name. +Same as the other decode functions, but instead takes a filename as input. +*/ +unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, + const char* filename, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_decode_file, but always decodes to 32-bit RGBA raw image.*/ +unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, + const char* filename); + +/*Same as lodepng_decode_file, but always decodes to 24-bit RGB raw image.*/ +unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, + const char* filename); +#endif /*LODEPNG_COMPILE_DISK*/ +#endif /*LODEPNG_COMPILE_DECODER*/ + + +#ifdef LODEPNG_COMPILE_ENCODER +/* +Converts raw pixel data into a PNG image in memory. The colortype and bitdepth + of the output PNG image cannot be chosen, they are automatically determined + by the colortype, bitdepth and content of the input pixel data. + Note: for 16-bit per channel colors, needs big endian format like PNG does. +out: Output parameter. Pointer to buffer that will contain the PNG image data. + Must be freed after usage with free(*out). +outsize: Output parameter. Pointer to the size in bytes of the out buffer. +image: The raw pixel data to encode. The size of this buffer should be + w * h * (bytes per pixel), bytes per pixel depends on colortype and bitdepth. +w: width of the raw pixel data in pixels. +h: height of the raw pixel data in pixels. +colortype: the color type of the raw input image. See explanation on PNG color types. +bitdepth: the bit depth of the raw input image. See explanation on PNG color types. +Return value: LodePNG error code (0 means no error). +*/ +unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_encode_memory, but always encodes from 32-bit RGBA raw image.*/ +unsigned lodepng_encode32(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h); + +/*Same as lodepng_encode_memory, but always encodes from 24-bit RGB raw image.*/ +unsigned lodepng_encode24(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h); + +#ifdef LODEPNG_COMPILE_DISK +/* +Converts raw pixel data into a PNG file on disk. +Same as the other encode functions, but instead takes a filename as output. +NOTE: This overwrites existing files without warning! +*/ +unsigned lodepng_encode_file(const char* filename, + const unsigned char* image, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth); + +/*Same as lodepng_encode_file, but always encodes from 32-bit RGBA raw image.*/ +unsigned lodepng_encode32_file(const char* filename, + const unsigned char* image, unsigned w, unsigned h); + +/*Same as lodepng_encode_file, but always encodes from 24-bit RGB raw image.*/ +unsigned lodepng_encode24_file(const char* filename, + const unsigned char* image, unsigned w, unsigned h); +#endif /*LODEPNG_COMPILE_DISK*/ +#endif /*LODEPNG_COMPILE_ENCODER*/ + + +#ifdef LODEPNG_COMPILE_CPP +namespace lodepng +{ +#ifdef LODEPNG_COMPILE_DECODER +/*Same as lodepng_decode_memory, but decodes to an std::vector. The colortype +is the format to output the pixels to. Default is RGBA 8-bit per channel.*/ +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const unsigned char* in, size_t insize, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const std::vector& in, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#ifdef LODEPNG_COMPILE_DISK +/* +Converts PNG file from disk to raw pixel data in memory. +Same as the other decode functions, but instead takes a filename as input. +*/ +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const std::string& filename, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_DECODER */ + +#ifdef LODEPNG_COMPILE_ENCODER +/*Same as lodepng_encode_memory, but encodes to an std::vector. colortype +is that of the raw input data. The output PNG color type will be auto chosen.*/ +unsigned encode(std::vector& out, + const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#ifdef LODEPNG_COMPILE_DISK +/* +Converts 32-bit RGBA raw pixel data into a PNG file on disk. +Same as the other encode functions, but instead takes a filename as output. +NOTE: This overwrites existing files without warning! +*/ +unsigned encode(const std::string& filename, + const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +unsigned encode(const std::string& filename, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype = LCT_RGBA, unsigned bitdepth = 8); +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_ENCODER */ +} /* namespace lodepng */ +#endif /*LODEPNG_COMPILE_CPP*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +#ifdef LODEPNG_COMPILE_ERROR_TEXT +/*Returns an English description of the numerical error code.*/ +const char* lodepng_error_text(unsigned code); +#endif /*LODEPNG_COMPILE_ERROR_TEXT*/ + +#ifdef LODEPNG_COMPILE_DECODER +/*Settings for zlib decompression*/ +typedef struct LodePNGDecompressSettings LodePNGDecompressSettings; +struct LodePNGDecompressSettings +{ + /* Check LodePNGDecoderSettings for more ignorable errors such as ignore_crc */ + unsigned ignore_adler32; /*if 1, continue and don't give an error message if the Adler32 checksum is corrupted*/ + + /*use custom zlib decoder instead of built in one (default: null)*/ + unsigned (*custom_zlib)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGDecompressSettings*); + /*use custom deflate decoder instead of built in one (default: null) + if custom_zlib is used, custom_deflate is ignored since only the built in + zlib function will call custom_deflate*/ + unsigned (*custom_inflate)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGDecompressSettings*); + + const void* custom_context; /*optional custom settings for custom functions*/ +}; + +extern const LodePNGDecompressSettings lodepng_default_decompress_settings; +void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/* +Settings for zlib compression. Tweaking these settings tweaks the balance +between speed and compression ratio. +*/ +typedef struct LodePNGCompressSettings LodePNGCompressSettings; +struct LodePNGCompressSettings /*deflate = compress*/ +{ + /*LZ77 related settings*/ + unsigned btype; /*the block type for LZ (0, 1, 2 or 3, see zlib standard). Should be 2 for proper compression.*/ + unsigned use_lz77; /*whether or not to use LZ77. Should be 1 for proper compression.*/ + unsigned windowsize; /*must be a power of two <= 32768. higher compresses more but is slower. Default value: 2048.*/ + unsigned minmatch; /*mininum lz77 length. 3 is normally best, 6 can be better for some PNGs. Default: 0*/ + unsigned nicematch; /*stop searching if >= this length found. Set to 258 for best compression. Default: 128*/ + unsigned lazymatching; /*use lazy matching: better compression but a bit slower. Default: true*/ + + /*use custom zlib encoder instead of built in one (default: null)*/ + unsigned (*custom_zlib)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGCompressSettings*); + /*use custom deflate encoder instead of built in one (default: null) + if custom_zlib is used, custom_deflate is ignored since only the built in + zlib function will call custom_deflate*/ + unsigned (*custom_deflate)(unsigned char**, size_t*, + const unsigned char*, size_t, + const LodePNGCompressSettings*); + + const void* custom_context; /*optional custom settings for custom functions*/ +}; + +extern const LodePNGCompressSettings lodepng_default_compress_settings; +void lodepng_compress_settings_init(LodePNGCompressSettings* settings); +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_PNG +/* +Color mode of an image. Contains all information required to decode the pixel +bits to RGBA colors. This information is the same as used in the PNG file +format, and is used both for PNG and raw image data in LodePNG. +*/ +typedef struct LodePNGColorMode +{ + /*header (IHDR)*/ + LodePNGColorType colortype; /*color type, see PNG standard or documentation further in this header file*/ + unsigned bitdepth; /*bits per sample, see PNG standard or documentation further in this header file*/ + + /* + palette (PLTE and tRNS) + + Dynamically allocated with the colors of the palette, including alpha. + When encoding a PNG, to store your colors in the palette of the LodePNGColorMode, first use + lodepng_palette_clear, then for each color use lodepng_palette_add. + If you encode an image without alpha with palette, don't forget to put value 255 in each A byte of the palette. + + When decoding, by default you can ignore this palette, since LodePNG already + fills the palette colors in the pixels of the raw RGBA output. + + The palette is only supported for color type 3. + */ + unsigned char* palette; /*palette in RGBARGBA... order. When allocated, must be either 0, or have size 1024*/ + size_t palettesize; /*palette size in number of colors (amount of bytes is 4 * palettesize)*/ + + /* + transparent color key (tRNS) + + This color uses the same bit depth as the bitdepth value in this struct, which can be 1-bit to 16-bit. + For greyscale PNGs, r, g and b will all 3 be set to the same. + + When decoding, by default you can ignore this information, since LodePNG sets + pixels with this key to transparent already in the raw RGBA output. + + The color key is only supported for color types 0 and 2. + */ + unsigned key_defined; /*is a transparent color key given? 0 = false, 1 = true*/ + unsigned key_r; /*red/greyscale component of color key*/ + unsigned key_g; /*green component of color key*/ + unsigned key_b; /*blue component of color key*/ +} LodePNGColorMode; + +/*init, cleanup and copy functions to use with this struct*/ +void lodepng_color_mode_init(LodePNGColorMode* info); +void lodepng_color_mode_cleanup(LodePNGColorMode* info); +/*return value is error code (0 means no error)*/ +unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source); +/* Makes a temporary LodePNGColorMode that does not need cleanup (no palette) */ +LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth); + +void lodepng_palette_clear(LodePNGColorMode* info); +/*add 1 color to the palette*/ +unsigned lodepng_palette_add(LodePNGColorMode* info, + unsigned char r, unsigned char g, unsigned char b, unsigned char a); + +/*get the total amount of bits per pixel, based on colortype and bitdepth in the struct*/ +unsigned lodepng_get_bpp(const LodePNGColorMode* info); +/*get the amount of color channels used, based on colortype in the struct. +If a palette is used, it counts as 1 channel.*/ +unsigned lodepng_get_channels(const LodePNGColorMode* info); +/*is it a greyscale type? (only colortype 0 or 4)*/ +unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info); +/*has it got an alpha channel? (only colortype 2 or 6)*/ +unsigned lodepng_is_alpha_type(const LodePNGColorMode* info); +/*has it got a palette? (only colortype 3)*/ +unsigned lodepng_is_palette_type(const LodePNGColorMode* info); +/*only returns true if there is a palette and there is a value in the palette with alpha < 255. +Loops through the palette to check this.*/ +unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info); +/* +Check if the given color info indicates the possibility of having non-opaque pixels in the PNG image. +Returns true if the image can have translucent or invisible pixels (it still be opaque if it doesn't use such pixels). +Returns false if the image can only have opaque pixels. +In detail, it returns true only if it's a color type with alpha, or has a palette with non-opaque values, +or if "key_defined" is true. +*/ +unsigned lodepng_can_have_alpha(const LodePNGColorMode* info); +/*Returns the byte size of a raw image buffer with given width, height and color mode*/ +size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color); + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +/*The information of a Time chunk in PNG.*/ +typedef struct LodePNGTime +{ + unsigned year; /*2 bytes used (0-65535)*/ + unsigned month; /*1-12*/ + unsigned day; /*1-31*/ + unsigned hour; /*0-23*/ + unsigned minute; /*0-59*/ + unsigned second; /*0-60 (to allow for leap seconds)*/ +} LodePNGTime; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +/*Information about the PNG image, except pixels, width and height.*/ +typedef struct LodePNGInfo +{ + /*header (IHDR), palette (PLTE) and transparency (tRNS) chunks*/ + unsigned compression_method;/*compression method of the original file. Always 0.*/ + unsigned filter_method; /*filter method of the original file*/ + unsigned interlace_method; /*interlace method of the original file: 0=none, 1=Adam7*/ + LodePNGColorMode color; /*color type and bits, palette and transparency of the PNG file*/ + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /* + Suggested background color chunk (bKGD) + + This uses the same color mode and bit depth as the PNG (except no alpha channel), + with values truncated to the bit depth in the unsigned integer. + + For greyscale and palette PNGs, the value is stored in background_r. The values + in background_g and background_b are then unused. + + So when decoding, you may get these in a different color mode than the one you requested + for the raw pixels. + + When encoding with auto_convert, you must use the color model defined in info_png.color for + these values. The encoder normally ignores info_png.color when auto_convert is on, but will + use it to interpret these values (and convert copies of them to its chosen color model). + + When encoding, avoid setting this to an expensive color, such as a non-grey value + when the image is grey, or the compression will be worse since it will be forced to + write the PNG with a more expensive color mode (when auto_convert is on). + + The decoder does not use this background color to edit the color of pixels. This is a + completely optional metadata feature. + */ + unsigned background_defined; /*is a suggested background color given?*/ + unsigned background_r; /*red/grey/palette component of suggested background color*/ + unsigned background_g; /*green component of suggested background color*/ + unsigned background_b; /*blue component of suggested background color*/ + + /* + non-international text chunks (tEXt and zTXt) + + The char** arrays each contain num strings. The actual messages are in + text_strings, while text_keys are keywords that give a short description what + the actual text represents, e.g. Title, Author, Description, or anything else. + + All the string fields below including keys, names and language tags are null terminated. + The PNG specification uses null characters for the keys, names and tags, and forbids null + characters to appear in the main text which is why we can use null termination everywhere here. + + A keyword is minimum 1 character and maximum 79 characters long. It's + discouraged to use a single line length longer than 79 characters for texts. + + Don't allocate these text buffers yourself. Use the init/cleanup functions + correctly and use lodepng_add_text and lodepng_clear_text. + */ + size_t text_num; /*the amount of texts in these char** buffers (there may be more texts in itext)*/ + char** text_keys; /*the keyword of a text chunk (e.g. "Comment")*/ + char** text_strings; /*the actual text*/ + + /* + international text chunks (iTXt) + Similar to the non-international text chunks, but with additional strings + "langtags" and "transkeys". + */ + size_t itext_num; /*the amount of international texts in this PNG*/ + char** itext_keys; /*the English keyword of the text chunk (e.g. "Comment")*/ + char** itext_langtags; /*language tag for this text's language, ISO/IEC 646 string, e.g. ISO 639 language tag*/ + char** itext_transkeys; /*keyword translated to the international language - UTF-8 string*/ + char** itext_strings; /*the actual international text - UTF-8 string*/ + + /*time chunk (tIME)*/ + unsigned time_defined; /*set to 1 to make the encoder generate a tIME chunk*/ + LodePNGTime time; + + /*phys chunk (pHYs)*/ + unsigned phys_defined; /*if 0, there is no pHYs chunk and the values below are undefined, if 1 else there is one*/ + unsigned phys_x; /*pixels per unit in x direction*/ + unsigned phys_y; /*pixels per unit in y direction*/ + unsigned phys_unit; /*may be 0 (unknown unit) or 1 (metre)*/ + + /* + Color profile related chunks: gAMA, cHRM, sRGB, iCPP + + LodePNG does not apply any color conversions on pixels in the encoder or decoder and does not interpret these color + profile values. It merely passes on the information. If you wish to use color profiles and convert colors, please + use these values with a color management library. + + See the PNG, ICC and sRGB specifications for more information about the meaning of these values. + */ + + /* gAMA chunk: optional, overridden by sRGB or iCCP if those are present. */ + unsigned gama_defined; /* Whether a gAMA chunk is present (0 = not present, 1 = present). */ + unsigned gama_gamma; /* Gamma exponent times 100000 */ + + /* cHRM chunk: optional, overridden by sRGB or iCCP if those are present. */ + unsigned chrm_defined; /* Whether a cHRM chunk is present (0 = not present, 1 = present). */ + unsigned chrm_white_x; /* White Point x times 100000 */ + unsigned chrm_white_y; /* White Point y times 100000 */ + unsigned chrm_red_x; /* Red x times 100000 */ + unsigned chrm_red_y; /* Red y times 100000 */ + unsigned chrm_green_x; /* Green x times 100000 */ + unsigned chrm_green_y; /* Green y times 100000 */ + unsigned chrm_blue_x; /* Blue x times 100000 */ + unsigned chrm_blue_y; /* Blue y times 100000 */ + + /* + sRGB chunk: optional. May not appear at the same time as iCCP. + If gAMA is also present gAMA must contain value 45455. + If cHRM is also present cHRM must contain respectively 31270,32900,64000,33000,30000,60000,15000,6000. + */ + unsigned srgb_defined; /* Whether an sRGB chunk is present (0 = not present, 1 = present). */ + unsigned srgb_intent; /* Rendering intent: 0=perceptual, 1=rel. colorimetric, 2=saturation, 3=abs. colorimetric */ + + /* + iCCP chunk: optional. May not appear at the same time as sRGB. + + LodePNG does not parse or use the ICC profile (except its color space header field for an edge case), a + separate library to handle the ICC data (not included in LodePNG) format is needed to use it for color + management and conversions. + + For encoding, if iCCP is present, gAMA and cHRM are recommended to be added as well with values that match the ICC + profile as closely as possible, if you wish to do this you should provide the correct values for gAMA and cHRM and + enable their '_defined' flags since LodePNG will not automatically compute them from the ICC profile. + + For encoding, the ICC profile is required by the PNG specification to be an "RGB" profile for non-grey + PNG color types and a "GRAY" profile for grey PNG color types. If you disable auto_convert, you must ensure + the ICC profile type matches your requested color type, else the encoder gives an error. If auto_convert is + enabled (the default), and the ICC profile is not a good match for the pixel data, this will result in an encoder + error if the pixel data has non-grey pixels for a GRAY profile, or a silent less-optimal compression of the pixel + data if the pixels could be encoded as greyscale but the ICC profile is RGB. + + To avoid this do not set an ICC profile in the image unless there is a good reason for it, and when doing so + make sure you compute it carefully to avoid the above problems. + */ + unsigned iccp_defined; /* Whether an iCCP chunk is present (0 = not present, 1 = present). */ + char* iccp_name; /* Null terminated string with profile name, 1-79 bytes */ + /* + The ICC profile in iccp_profile_size bytes. + Don't allocate this buffer yourself. Use the init/cleanup functions + correctly and use lodepng_set_icc and lodepng_clear_icc. + */ + unsigned char* iccp_profile; + unsigned iccp_profile_size; /* The size of iccp_profile in bytes */ + + /* End of color profile related chunks */ + + + /* + unknown chunks: chunks not known by LodePNG, passed on byte for byte. + + There are 3 buffers, one for each position in the PNG where unknown chunks can appear. + Each buffer contains all unknown chunks for that position consecutively. + The 3 positions are: + 0: between IHDR and PLTE, 1: between PLTE and IDAT, 2: between IDAT and IEND. + + For encoding, do not store critical chunks or known chunks that are enabled with a "_defined" flag + above in here, since the encoder will blindly follow this and could then encode an invalid PNG file + (such as one with two IHDR chunks or the disallowed combination of sRGB with iCCP). But do use + this if you wish to store an ancillary chunk that is not supported by LodePNG (such as sPLT or hIST), + or any non-standard PNG chunk. + + Do not allocate or traverse this data yourself. Use the chunk traversing functions declared + later, such as lodepng_chunk_next and lodepng_chunk_append, to read/write this struct. + */ + unsigned char* unknown_chunks_data[3]; + size_t unknown_chunks_size[3]; /*size in bytes of the unknown chunks, given for protection*/ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} LodePNGInfo; + +/*init, cleanup and copy functions to use with this struct*/ +void lodepng_info_init(LodePNGInfo* info); +void lodepng_info_cleanup(LodePNGInfo* info); +/*return value is error code (0 means no error)*/ +unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source); + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str); /*push back both texts at once*/ +void lodepng_clear_text(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/ + +unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag, + const char* transkey, const char* str); /*push back the 4 texts of 1 chunk at once*/ +void lodepng_clear_itext(LodePNGInfo* info); /*use this to clear the itexts again after you filled them in*/ + +/*replaces if exists*/ +unsigned lodepng_set_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size); +void lodepng_clear_icc(LodePNGInfo* info); /*use this to clear the texts again after you filled them in*/ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +/* +Converts raw buffer from one color type to another color type, based on +LodePNGColorMode structs to describe the input and output color type. +See the reference manual at the end of this header file to see which color conversions are supported. +return value = LodePNG error code (0 if all went ok, an error if the conversion isn't supported) +The out buffer must have size (w * h * bpp + 7) / 8, where bpp is the bits per pixel +of the output color type (lodepng_get_bpp). +For < 8 bpp images, there should not be padding bits at the end of scanlines. +For 16-bit per channel colors, uses big endian format like PNG does. +Return value is LodePNG error code +*/ +unsigned lodepng_convert(unsigned char* out, const unsigned char* in, + const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in, + unsigned w, unsigned h); + +#ifdef LODEPNG_COMPILE_DECODER +/* +Settings for the decoder. This contains settings for the PNG and the Zlib +decoder, but not the Info settings from the Info structs. +*/ +typedef struct LodePNGDecoderSettings +{ + LodePNGDecompressSettings zlibsettings; /*in here is the setting to ignore Adler32 checksums*/ + + /* Check LodePNGDecompressSettings for more ignorable errors such as ignore_adler32 */ + unsigned ignore_crc; /*ignore CRC checksums*/ + unsigned ignore_critical; /*ignore unknown critical chunks*/ + unsigned ignore_end; /*ignore issues at end of file if possible (missing IEND chunk, too large chunk, ...)*/ + /* TODO: make a system involving warnings with levels and a strict mode instead. Other potentially recoverable + errors: srgb rendering intent value, size of content of ancillary chunks, more than 79 characters for some + strings, placement/combination rules for ancillary chunks, crc of unknown chunks, allowed characters + in string keys, etc... */ + + unsigned color_convert; /*whether to convert the PNG to the color type you want. Default: yes*/ + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + unsigned read_text_chunks; /*if false but remember_unknown_chunks is true, they're stored in the unknown chunks*/ + /*store all bytes from unknown chunks in the LodePNGInfo (off by default, useful for a png editor)*/ + unsigned remember_unknown_chunks; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} LodePNGDecoderSettings; + +void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/*automatically use color type with less bits per pixel if losslessly possible. Default: AUTO*/ +typedef enum LodePNGFilterStrategy +{ + /*every filter at zero*/ + LFS_ZERO, + /*Use filter that gives minimum sum, as described in the official PNG filter heuristic.*/ + LFS_MINSUM, + /*Use the filter type that gives smallest Shannon entropy for this scanline. Depending + on the image, this is better or worse than minsum.*/ + LFS_ENTROPY, + /* + Brute-force-search PNG filters by compressing each filter for each scanline. + Experimental, very slow, and only rarely gives better compression than MINSUM. + */ + LFS_BRUTE_FORCE, + /*use predefined_filters buffer: you specify the filter type for each scanline*/ + LFS_PREDEFINED +} LodePNGFilterStrategy; + +/*Gives characteristics about the integer RGBA colors of the image (count, alpha channel usage, bit depth, ...), +which helps decide which color model to use for encoding. +Used internally by default if "auto_convert" is enabled. Public because it's useful for custom algorithms. +NOTE: This is not related to the ICC color profile, search "iccp_profile" instead to find the ICC/chromacity/... +fields in this header file.*/ +typedef struct LodePNGColorProfile +{ + unsigned colored; /*not greyscale*/ + unsigned key; /*image is not opaque and color key is possible instead of full alpha*/ + unsigned short key_r; /*key values, always as 16-bit, in 8-bit case the byte is duplicated, e.g. 65535 means 255*/ + unsigned short key_g; + unsigned short key_b; + unsigned alpha; /*image is not opaque and alpha channel or alpha palette required*/ + unsigned numcolors; /*amount of colors, up to 257. Not valid if bits == 16.*/ + unsigned char palette[1024]; /*Remembers up to the first 256 RGBA colors, in no particular order*/ + unsigned bits; /*bits per channel (not for palette). 1,2 or 4 for greyscale only. 16 if 16-bit per channel required.*/ + size_t numpixels; +} LodePNGColorProfile; + +void lodepng_color_profile_init(LodePNGColorProfile* profile); + +/*Get a LodePNGColorProfile of the image. The profile must already have been inited. +NOTE: This is not related to the ICC color profile, search "iccp_profile" instead to find the ICC/chromacity/... +fields in this header file.*/ +unsigned lodepng_get_color_profile(LodePNGColorProfile* profile, + const unsigned char* image, unsigned w, unsigned h, + const LodePNGColorMode* mode_in); +/*The function LodePNG uses internally to decide the PNG color with auto_convert. +Chooses an optimal color model, e.g. grey if only grey pixels, palette if < 256 colors, ...*/ +unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out, + const unsigned char* image, unsigned w, unsigned h, + const LodePNGColorMode* mode_in); + +/*Settings for the encoder.*/ +typedef struct LodePNGEncoderSettings +{ + LodePNGCompressSettings zlibsettings; /*settings for the zlib encoder, such as window size, ...*/ + + unsigned auto_convert; /*automatically choose output PNG color type. Default: true*/ + + /*If true, follows the official PNG heuristic: if the PNG uses a palette or lower than + 8 bit depth, set all filters to zero. Otherwise use the filter_strategy. Note that to + completely follow the official PNG heuristic, filter_palette_zero must be true and + filter_strategy must be LFS_MINSUM*/ + unsigned filter_palette_zero; + /*Which filter strategy to use when not using zeroes due to filter_palette_zero. + Set filter_palette_zero to 0 to ensure always using your chosen strategy. Default: LFS_MINSUM*/ + LodePNGFilterStrategy filter_strategy; + /*used if filter_strategy is LFS_PREDEFINED. In that case, this must point to a buffer with + the same length as the amount of scanlines in the image, and each value must <= 5. You + have to cleanup this buffer, LodePNG will never free it. Don't forget that filter_palette_zero + must be set to 0 to ensure this is also used on palette or low bitdepth images.*/ + const unsigned char* predefined_filters; + + /*force creating a PLTE chunk if colortype is 2 or 6 (= a suggested palette). + If colortype is 3, PLTE is _always_ created.*/ + unsigned force_palette; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*add LodePNG identifier and version as a text chunk, for debugging*/ + unsigned add_id; + /*encode text chunks as zTXt chunks instead of tEXt chunks, and use compression in iTXt chunks*/ + unsigned text_compression; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} LodePNGEncoderSettings; + +void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings); +#endif /*LODEPNG_COMPILE_ENCODER*/ + + +#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) +/*The settings, state and information for extended encoding and decoding.*/ +typedef struct LodePNGState +{ +#ifdef LODEPNG_COMPILE_DECODER + LodePNGDecoderSettings decoder; /*the decoding settings*/ +#endif /*LODEPNG_COMPILE_DECODER*/ +#ifdef LODEPNG_COMPILE_ENCODER + LodePNGEncoderSettings encoder; /*the encoding settings*/ +#endif /*LODEPNG_COMPILE_ENCODER*/ + LodePNGColorMode info_raw; /*specifies the format in which you would like to get the raw pixel buffer*/ + LodePNGInfo info_png; /*info of the PNG image obtained after decoding*/ + unsigned error; +#ifdef LODEPNG_COMPILE_CPP + /* For the lodepng::State subclass. */ + virtual ~LodePNGState(){} +#endif +} LodePNGState; + +/*init, cleanup and copy functions to use with this struct*/ +void lodepng_state_init(LodePNGState* state); +void lodepng_state_cleanup(LodePNGState* state); +void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source); +#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */ + +#ifdef LODEPNG_COMPILE_DECODER +/* +Same as lodepng_decode_memory, but uses a LodePNGState to allow custom settings and +getting much more information about the PNG image and color mode. +*/ +unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize); + +/* +Read the PNG header, but not the actual data. This returns only the information +that is in the IHDR chunk of the PNG, such as width, height and color type. The +information is placed in the info_png field of the LodePNGState. +*/ +unsigned lodepng_inspect(unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize); +#endif /*LODEPNG_COMPILE_DECODER*/ + +/* +Reads one metadata chunk (other than IHDR) of the PNG file and outputs what it +read in the state. Returns error code on failure. +Use lodepng_inspect first with a new state, then e.g. lodepng_chunk_find_const +to find the desired chunk type, and if non null use lodepng_inspect_chunk (with +chunk_pointer - start_of_file as pos). +Supports most metadata chunks from the PNG standard (gAMA, bKGD, tEXt, ...). +Ignores unsupported, unknown, non-metadata or IHDR chunks (without error). +Requirements: &in[pos] must point to start of a chunk, must use regular +lodepng_inspect first since format of most other chunks depends on IHDR, and if +there is a PLTE chunk, that one must be inspected before tRNS or bKGD. +*/ +unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos, + const unsigned char* in, size_t insize); + +#ifdef LODEPNG_COMPILE_ENCODER +/*This function allocates the out buffer with standard malloc and stores the size in *outsize.*/ +unsigned lodepng_encode(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h, + LodePNGState* state); +#endif /*LODEPNG_COMPILE_ENCODER*/ + +/* +The lodepng_chunk functions are normally not needed, except to traverse the +unknown chunks stored in the LodePNGInfo struct, or add new ones to it. +It also allows traversing the chunks of an encoded PNG file yourself. + +The chunk pointer always points to the beginning of the chunk itself, that is +the first byte of the 4 length bytes. + +In the PNG file format, chunks have the following format: +-4 bytes length: length of the data of the chunk in bytes (chunk itself is 12 bytes longer) +-4 bytes chunk type (ASCII a-z,A-Z only, see below) +-length bytes of data (may be 0 bytes if length was 0) +-4 bytes of CRC, computed on chunk name + data + +The first chunk starts at the 8th byte of the PNG file, the entire rest of the file +exists out of concatenated chunks with the above format. + +PNG standard chunk ASCII naming conventions: +-First byte: uppercase = critical, lowercase = ancillary +-Second byte: uppercase = public, lowercase = private +-Third byte: must be uppercase +-Fourth byte: uppercase = unsafe to copy, lowercase = safe to copy +*/ + +/* +Gets the length of the data of the chunk. Total chunk length has 12 bytes more. +There must be at least 4 bytes to read from. If the result value is too large, +it may be corrupt data. +*/ +unsigned lodepng_chunk_length(const unsigned char* chunk); + +/*puts the 4-byte type in null terminated string*/ +void lodepng_chunk_type(char type[5], const unsigned char* chunk); + +/*check if the type is the given type*/ +unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type); + +/*0: it's one of the critical chunk types, 1: it's an ancillary chunk (see PNG standard)*/ +unsigned char lodepng_chunk_ancillary(const unsigned char* chunk); + +/*0: public, 1: private (see PNG standard)*/ +unsigned char lodepng_chunk_private(const unsigned char* chunk); + +/*0: the chunk is unsafe to copy, 1: the chunk is safe to copy (see PNG standard)*/ +unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk); + +/*get pointer to the data of the chunk, where the input points to the header of the chunk*/ +unsigned char* lodepng_chunk_data(unsigned char* chunk); +const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk); + +/*returns 0 if the crc is correct, 1 if it's incorrect (0 for OK as usual!)*/ +unsigned lodepng_chunk_check_crc(const unsigned char* chunk); + +/*generates the correct CRC from the data and puts it in the last 4 bytes of the chunk*/ +void lodepng_chunk_generate_crc(unsigned char* chunk); + +/* +Iterate to next chunks, allows iterating through all chunks of the PNG file. +Input must be at the beginning of a chunk (result of a previous lodepng_chunk_next call, +or the 8th byte of a PNG file which always has the first chunk), or alternatively may +point to the first byte of the PNG file (which is not a chunk but the magic header, the +function will then skip over it and return the first real chunk). +Expects at least 8 readable bytes of memory in the input pointer. +Will output pointer to the start of the next chunk or the end of the file if there +is no more chunk after this. Start this process at the 8th byte of the PNG file. +In a non-corrupt PNG file, the last chunk should have name "IEND". +*/ +unsigned char* lodepng_chunk_next(unsigned char* chunk); +const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk); + +/*Finds the first chunk with the given type in the range [chunk, end), or returns NULL if not found.*/ +unsigned char* lodepng_chunk_find(unsigned char* chunk, const unsigned char* end, const char type[5]); +const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]); + +/* +Appends chunk to the data in out. The given chunk should already have its chunk header. +The out variable and outlength are updated to reflect the new reallocated buffer. +Returns error code (0 if it went ok) +*/ +unsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk); + +/* +Appends new chunk to out. The chunk to append is given by giving its length, type +and data separately. The type is a 4-letter string. +The out variable and outlength are updated to reflect the new reallocated buffer. +Returne error code (0 if it went ok) +*/ +unsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length, + const char* type, const unsigned char* data); + + +/*Calculate CRC32 of buffer*/ +unsigned lodepng_crc32(const unsigned char* buf, size_t len); +#endif /*LODEPNG_COMPILE_PNG*/ + + +#ifdef LODEPNG_COMPILE_ZLIB +/* +This zlib part can be used independently to zlib compress and decompress a +buffer. It cannot be used to create gzip files however, and it only supports the +part of zlib that is required for PNG, it does not support dictionaries. +*/ + +#ifdef LODEPNG_COMPILE_DECODER +/*Inflate a buffer. Inflate is the decompression step of deflate. Out buffer must be freed after use.*/ +unsigned lodepng_inflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings); + +/* +Decompresses Zlib data. Reallocates the out buffer and appends the data. The +data must be according to the zlib specification. +Either, *out must be NULL and *outsize must be 0, or, *out must be a valid +buffer and *outsize its size in bytes. out must be freed by user after usage. +*/ +unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/* +Compresses data with Zlib. Reallocates the out buffer and appends the data. +Zlib adds a small header and trailer around the deflate data. +The data is output in the format of the zlib specification. +Either, *out must be NULL and *outsize must be 0, or, *out must be a valid +buffer and *outsize its size in bytes. out must be freed by user after usage. +*/ +unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings); + +/* +Find length-limited Huffman code for given frequencies. This function is in the +public interface only for tests, it's used internally by lodepng_deflate. +*/ +unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies, + size_t numcodes, unsigned maxbitlen); + +/*Compress a buffer with deflate. See RFC 1951. Out buffer must be freed after use.*/ +unsigned lodepng_deflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings); + +#endif /*LODEPNG_COMPILE_ENCODER*/ +#endif /*LODEPNG_COMPILE_ZLIB*/ + +#ifdef LODEPNG_COMPILE_DISK +/* +Load a file from disk into buffer. The function allocates the out buffer, and +after usage you should free it. +out: output parameter, contains pointer to loaded buffer. +outsize: output parameter, size of the allocated out buffer +filename: the path to the file to load +return value: error code (0 means ok) +*/ +unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename); + +/* +Save a file from buffer to disk. Warning, if it exists, this function overwrites +the file without warning! +buffer: the buffer to write +buffersize: size of the buffer to write +filename: the path to the file to save to +return value: error code (0 means ok) +*/ +unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename); +#endif /*LODEPNG_COMPILE_DISK*/ + +#ifdef LODEPNG_COMPILE_CPP +/* The LodePNG C++ wrapper uses std::vectors instead of manually allocated memory buffers. */ +namespace lodepng +{ +#ifdef LODEPNG_COMPILE_PNG +class State : public LodePNGState +{ + public: + State(); + State(const State& other); + virtual ~State(); + State& operator=(const State& other); +}; + +#ifdef LODEPNG_COMPILE_DECODER +/* Same as other lodepng::decode, but using a State for more settings and information. */ +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const unsigned char* in, size_t insize); +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const std::vector& in); +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER +/* Same as other lodepng::encode, but using a State for more settings and information. */ +unsigned encode(std::vector& out, + const unsigned char* in, unsigned w, unsigned h, + State& state); +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + State& state); +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_DISK +/* +Load a file from disk into an std::vector. +return value: error code (0 means ok) +*/ +unsigned load_file(std::vector& buffer, const std::string& filename); + +/* +Save the binary data in an std::vector to a file on disk. The file is overwritten +without warning. +*/ +unsigned save_file(const std::vector& buffer, const std::string& filename); +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_PNG */ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_DECODER +/* Zlib-decompress an unsigned char buffer */ +unsigned decompress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings); + +/* Zlib-decompress an std::vector */ +unsigned decompress(std::vector& out, const std::vector& in, + const LodePNGDecompressSettings& settings = lodepng_default_decompress_settings); +#endif /* LODEPNG_COMPILE_DECODER */ + +#ifdef LODEPNG_COMPILE_ENCODER +/* Zlib-compress an unsigned char buffer */ +unsigned compress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGCompressSettings& settings = lodepng_default_compress_settings); + +/* Zlib-compress an std::vector */ +unsigned compress(std::vector& out, const std::vector& in, + const LodePNGCompressSettings& settings = lodepng_default_compress_settings); +#endif /* LODEPNG_COMPILE_ENCODER */ +#endif /* LODEPNG_COMPILE_ZLIB */ +} /* namespace lodepng */ +#endif /*LODEPNG_COMPILE_CPP*/ + +/* +TODO: +[.] test if there are no memory leaks or security exploits - done a lot but needs to be checked often +[.] check compatibility with various compilers - done but needs to be redone for every newer version +[X] converting color to 16-bit per channel types +[X] support color profile chunk types (but never let them touch RGB values by default) +[ ] support all public PNG chunk types +[ ] make sure encoder generates no chunks with size > (2^31)-1 +[ ] partial decoding (stream processing) +[X] let the "isFullyOpaque" function check color keys and transparent palettes too +[X] better name for the variables "codes", "codesD", "codelengthcodes", "clcl" and "lldl" +[ ] don't stop decoding on errors like 69, 57, 58 (make warnings) +[ ] make warnings like: oob palette, checksum fail, data after iend, wrong/unknown crit chunk, no null terminator in text, ... +[ ] errors with line numbers (and version) +[ ] let the C++ wrapper catch exceptions coming from the standard library and return LodePNG error codes +[ ] allow user to provide custom color conversion functions, e.g. for premultiplied alpha, padding bits or not, ... +[ ] allow user to give data (void*) to custom allocator +*/ + +#endif /*LODEPNG_H inclusion guard*/ + +/* +LodePNG Documentation +--------------------- + +0. table of contents +-------------------- + + 1. about + 1.1. supported features + 1.2. features not supported + 2. C and C++ version + 3. security + 4. decoding + 5. encoding + 6. color conversions + 6.1. PNG color types + 6.2. color conversions + 6.3. padding bits + 6.4. A note about 16-bits per channel and endianness + 7. error values + 8. chunks and PNG editing + 9. compiler support + 10. examples + 10.1. decoder C++ example + 10.2. decoder C example + 11. state settings reference + 12. changes + 13. contact information + + +1. about +-------- + +PNG is a file format to store raster images losslessly with good compression, +supporting different color types and alpha channel. + +LodePNG is a PNG codec according to the Portable Network Graphics (PNG) +Specification (Second Edition) - W3C Recommendation 10 November 2003. + +The specifications used are: + +*) Portable Network Graphics (PNG) Specification (Second Edition): + http://www.w3.org/TR/2003/REC-PNG-20031110 +*) RFC 1950 ZLIB Compressed Data Format version 3.3: + http://www.gzip.org/zlib/rfc-zlib.html +*) RFC 1951 DEFLATE Compressed Data Format Specification ver 1.3: + http://www.gzip.org/zlib/rfc-deflate.html + +The most recent version of LodePNG can currently be found at +http://lodev.org/lodepng/ + +LodePNG works both in C (ISO C90) and C++, with a C++ wrapper that adds +extra functionality. + +LodePNG exists out of two files: +-lodepng.h: the header file for both C and C++ +-lodepng.c(pp): give it the name lodepng.c or lodepng.cpp (or .cc) depending on your usage + +If you want to start using LodePNG right away without reading this doc, get the +examples from the LodePNG website to see how to use it in code, or check the +smaller examples in chapter 13 here. + +LodePNG is simple but only supports the basic requirements. To achieve +simplicity, the following design choices were made: There are no dependencies +on any external library. There are functions to decode and encode a PNG with +a single function call, and extended versions of these functions taking a +LodePNGState struct allowing to specify or get more information. By default +the colors of the raw image are always RGB or RGBA, no matter what color type +the PNG file uses. To read and write files, there are simple functions to +convert the files to/from buffers in memory. + +This all makes LodePNG suitable for loading textures in games, demos and small +programs, ... It's less suitable for full fledged image editors, loading PNGs +over network (it requires all the image data to be available before decoding can +begin), life-critical systems, ... + +1.1. supported features +----------------------- + +The following features are supported by the decoder: + +*) decoding of PNGs with any color type, bit depth and interlace mode, to a 24- or 32-bit color raw image, + or the same color type as the PNG +*) encoding of PNGs, from any raw image to 24- or 32-bit color, or the same color type as the raw image +*) Adam7 interlace and deinterlace for any color type +*) loading the image from harddisk or decoding it from a buffer from other sources than harddisk +*) support for alpha channels, including RGBA color model, translucent palettes and color keying +*) zlib decompression (inflate) +*) zlib compression (deflate) +*) CRC32 and ADLER32 checksums +*) handling of unknown chunks, allowing making a PNG editor that stores custom and unknown chunks. +*) the following chunks are supported (generated/interpreted) by both encoder and decoder: + IHDR: header information + PLTE: color palette + IDAT: pixel data + IEND: the final chunk + tRNS: transparency for palettized images + tEXt: textual information + zTXt: compressed textual information + iTXt: international textual information + bKGD: suggested background color + pHYs: physical dimensions + tIME: modification time + +1.2. features not supported +--------------------------- + +The following features are _not_ supported: + +*) some features needed to make a conformant PNG-Editor might be still missing. +*) partial loading/stream processing. All data must be available and is processed in one call. +*) The following public chunks are not supported but treated as unknown chunks by LodePNG + cHRM, gAMA, iCCP, sRGB, sBIT, hIST, sPLT + Some of these are not supported on purpose: LodePNG wants to provide the RGB values + stored in the pixels, not values modified by system dependent gamma or color models. + + +2. C and C++ version +-------------------- + +The C version uses buffers allocated with alloc that you need to free() +yourself. You need to use init and cleanup functions for each struct whenever +using a struct from the C version to avoid exploits and memory leaks. + +The C++ version has extra functions with std::vectors in the interface and the +lodepng::State class which is a LodePNGState with constructor and destructor. + +These files work without modification for both C and C++ compilers because all +the additional C++ code is in "#ifdef __cplusplus" blocks that make C-compilers +ignore it, and the C code is made to compile both with strict ISO C90 and C++. + +To use the C++ version, you need to rename the source file to lodepng.cpp +(instead of lodepng.c), and compile it with a C++ compiler. + +To use the C version, you need to rename the source file to lodepng.c (instead +of lodepng.cpp), and compile it with a C compiler. + + +3. Security +----------- + +Even if carefully designed, it's always possible that LodePNG contains possible +exploits. If you discover one, please let me know, and it will be fixed. + +When using LodePNG, care has to be taken with the C version of LodePNG, as well +as the C-style structs when working with C++. The following conventions are used +for all C-style structs: + +-if a struct has a corresponding init function, always call the init function when making a new one +-if a struct has a corresponding cleanup function, call it before the struct disappears to avoid memory leaks +-if a struct has a corresponding copy function, use the copy function instead of "=". + The destination must also be inited already. + + +4. Decoding +----------- + +Decoding converts a PNG compressed image to a raw pixel buffer. + +Most documentation on using the decoder is at its declarations in the header +above. For C, simple decoding can be done with functions such as +lodepng_decode32, and more advanced decoding can be done with the struct +LodePNGState and lodepng_decode. For C++, all decoding can be done with the +various lodepng::decode functions, and lodepng::State can be used for advanced +features. + +When using the LodePNGState, it uses the following fields for decoding: +*) LodePNGInfo info_png: it stores extra information about the PNG (the input) in here +*) LodePNGColorMode info_raw: here you can say what color mode of the raw image (the output) you want to get +*) LodePNGDecoderSettings decoder: you can specify a few extra settings for the decoder to use + +LodePNGInfo info_png +-------------------- + +After decoding, this contains extra information of the PNG image, except the actual +pixels, width and height because these are already gotten directly from the decoder +functions. + +It contains for example the original color type of the PNG image, text comments, +suggested background color, etc... More details about the LodePNGInfo struct are +at its declaration documentation. + +LodePNGColorMode info_raw +------------------------- + +When decoding, here you can specify which color type you want +the resulting raw image to be. If this is different from the colortype of the +PNG, then the decoder will automatically convert the result. This conversion +always works, except if you want it to convert a color PNG to greyscale or to +a palette with missing colors. + +By default, 32-bit color is used for the result. + +LodePNGDecoderSettings decoder +------------------------------ + +The settings can be used to ignore the errors created by invalid CRC and Adler32 +chunks, and to disable the decoding of tEXt chunks. + +There's also a setting color_convert, true by default. If false, no conversion +is done, the resulting data will be as it was in the PNG (after decompression) +and you'll have to puzzle the colors of the pixels together yourself using the +color type information in the LodePNGInfo. + + +5. Encoding +----------- + +Encoding converts a raw pixel buffer to a PNG compressed image. + +Most documentation on using the encoder is at its declarations in the header +above. For C, simple encoding can be done with functions such as +lodepng_encode32, and more advanced decoding can be done with the struct +LodePNGState and lodepng_encode. For C++, all encoding can be done with the +various lodepng::encode functions, and lodepng::State can be used for advanced +features. + +Like the decoder, the encoder can also give errors. However it gives less errors +since the encoder input is trusted, the decoder input (a PNG image that could +be forged by anyone) is not trusted. + +When using the LodePNGState, it uses the following fields for encoding: +*) LodePNGInfo info_png: here you specify how you want the PNG (the output) to be. +*) LodePNGColorMode info_raw: here you say what color type of the raw image (the input) has +*) LodePNGEncoderSettings encoder: you can specify a few settings for the encoder to use + +LodePNGInfo info_png +-------------------- + +When encoding, you use this the opposite way as when decoding: for encoding, +you fill in the values you want the PNG to have before encoding. By default it's +not needed to specify a color type for the PNG since it's automatically chosen, +but it's possible to choose it yourself given the right settings. + +The encoder will not always exactly match the LodePNGInfo struct you give, +it tries as close as possible. Some things are ignored by the encoder. The +encoder uses, for example, the following settings from it when applicable: +colortype and bitdepth, text chunks, time chunk, the color key, the palette, the +background color, the interlace method, unknown chunks, ... + +When encoding to a PNG with colortype 3, the encoder will generate a PLTE chunk. +If the palette contains any colors for which the alpha channel is not 255 (so +there are translucent colors in the palette), it'll add a tRNS chunk. + +LodePNGColorMode info_raw +------------------------- + +You specify the color type of the raw image that you give to the input here, +including a possible transparent color key and palette you happen to be using in +your raw image data. + +By default, 32-bit color is assumed, meaning your input has to be in RGBA +format with 4 bytes (unsigned chars) per pixel. + +LodePNGEncoderSettings encoder +------------------------------ + +The following settings are supported (some are in sub-structs): +*) auto_convert: when this option is enabled, the encoder will +automatically choose the smallest possible color mode (including color key) that +can encode the colors of all pixels without information loss. +*) btype: the block type for LZ77. 0 = uncompressed, 1 = fixed huffman tree, + 2 = dynamic huffman tree (best compression). Should be 2 for proper + compression. +*) use_lz77: whether or not to use LZ77 for compressed block types. Should be + true for proper compression. +*) windowsize: the window size used by the LZ77 encoder (1 - 32768). Has value + 2048 by default, but can be set to 32768 for better, but slow, compression. +*) force_palette: if colortype is 2 or 6, you can make the encoder write a PLTE + chunk if force_palette is true. This can used as suggested palette to convert + to by viewers that don't support more than 256 colors (if those still exist) +*) add_id: add text chunk "Encoder: LodePNG " to the image. +*) text_compression: default 1. If 1, it'll store texts as zTXt instead of tEXt chunks. + zTXt chunks use zlib compression on the text. This gives a smaller result on + large texts but a larger result on small texts (such as a single program name). + It's all tEXt or all zTXt though, there's no separate setting per text yet. + + +6. color conversions +-------------------- + +An important thing to note about LodePNG, is that the color type of the PNG, and +the color type of the raw image, are completely independent. By default, when +you decode a PNG, you get the result as a raw image in the color type you want, +no matter whether the PNG was encoded with a palette, greyscale or RGBA color. +And if you encode an image, by default LodePNG will automatically choose the PNG +color type that gives good compression based on the values of colors and amount +of colors in the image. It can be configured to let you control it instead as +well, though. + +To be able to do this, LodePNG does conversions from one color mode to another. +It can convert from almost any color type to any other color type, except the +following conversions: RGB to greyscale is not supported, and converting to a +palette when the palette doesn't have a required color is not supported. This is +not supported on purpose: this is information loss which requires a color +reduction algorithm that is beyong the scope of a PNG encoder (yes, RGB to grey +is easy, but there are multiple ways if you want to give some channels more +weight). + +By default, when decoding, you get the raw image in 32-bit RGBA or 24-bit RGB +color, no matter what color type the PNG has. And by default when encoding, +LodePNG automatically picks the best color model for the output PNG, and expects +the input image to be 32-bit RGBA or 24-bit RGB. So, unless you want to control +the color format of the images yourself, you can skip this chapter. + +6.1. PNG color types +-------------------- + +A PNG image can have many color types, ranging from 1-bit color to 64-bit color, +as well as palettized color modes. After the zlib decompression and unfiltering +in the PNG image is done, the raw pixel data will have that color type and thus +a certain amount of bits per pixel. If you want the output raw image after +decoding to have another color type, a conversion is done by LodePNG. + +The PNG specification gives the following color types: + +0: greyscale, bit depths 1, 2, 4, 8, 16 +2: RGB, bit depths 8 and 16 +3: palette, bit depths 1, 2, 4 and 8 +4: greyscale with alpha, bit depths 8 and 16 +6: RGBA, bit depths 8 and 16 + +Bit depth is the amount of bits per pixel per color channel. So the total amount +of bits per pixel is: amount of channels * bitdepth. + +6.2. color conversions +---------------------- + +As explained in the sections about the encoder and decoder, you can specify +color types and bit depths in info_png and info_raw to change the default +behaviour. + +If, when decoding, you want the raw image to be something else than the default, +you need to set the color type and bit depth you want in the LodePNGColorMode, +or the parameters colortype and bitdepth of the simple decoding function. + +If, when encoding, you use another color type than the default in the raw input +image, you need to specify its color type and bit depth in the LodePNGColorMode +of the raw image, or use the parameters colortype and bitdepth of the simple +encoding function. + +If, when encoding, you don't want LodePNG to choose the output PNG color type +but control it yourself, you need to set auto_convert in the encoder settings +to false, and specify the color type you want in the LodePNGInfo of the +encoder (including palette: it can generate a palette if auto_convert is true, +otherwise not). + +If the input and output color type differ (whether user chosen or auto chosen), +LodePNG will do a color conversion, which follows the rules below, and may +sometimes result in an error. + +To avoid some confusion: +-the decoder converts from PNG to raw image +-the encoder converts from raw image to PNG +-the colortype and bitdepth in LodePNGColorMode info_raw, are those of the raw image +-the colortype and bitdepth in the color field of LodePNGInfo info_png, are those of the PNG +-when encoding, the color type in LodePNGInfo is ignored if auto_convert + is enabled, it is automatically generated instead +-when decoding, the color type in LodePNGInfo is set by the decoder to that of the original + PNG image, but it can be ignored since the raw image has the color type you requested instead +-if the color type of the LodePNGColorMode and PNG image aren't the same, a conversion + between the color types is done if the color types are supported. If it is not + supported, an error is returned. If the types are the same, no conversion is done. +-even though some conversions aren't supported, LodePNG supports loading PNGs from any + colortype and saving PNGs to any colortype, sometimes it just requires preparing + the raw image correctly before encoding. +-both encoder and decoder use the same color converter. + +Non supported color conversions: +-color to greyscale: no error is thrown, but the result will look ugly because +only the red channel is taken +-anything to palette when that palette does not have that color in it: in this +case an error is thrown + +Supported color conversions: +-anything to 8-bit RGB, 8-bit RGBA, 16-bit RGB, 16-bit RGBA +-any grey or grey+alpha, to grey or grey+alpha +-anything to a palette, as long as the palette has the requested colors in it +-removing alpha channel +-higher to smaller bitdepth, and vice versa + +If you want no color conversion to be done (e.g. for speed or control): +-In the encoder, you can make it save a PNG with any color type by giving the +raw color mode and LodePNGInfo the same color mode, and setting auto_convert to +false. +-In the decoder, you can make it store the pixel data in the same color type +as the PNG has, by setting the color_convert setting to false. Settings in +info_raw are then ignored. + +The function lodepng_convert does the color conversion. It is available in the +interface but normally isn't needed since the encoder and decoder already call +it. + +6.3. padding bits +----------------- + +In the PNG file format, if a less than 8-bit per pixel color type is used and the scanlines +have a bit amount that isn't a multiple of 8, then padding bits are used so that each +scanline starts at a fresh byte. But that is NOT true for the LodePNG raw input and output. +The raw input image you give to the encoder, and the raw output image you get from the decoder +will NOT have these padding bits, e.g. in the case of a 1-bit image with a width +of 7 pixels, the first pixel of the second scanline will the the 8th bit of the first byte, +not the first bit of a new byte. + +6.4. A note about 16-bits per channel and endianness +---------------------------------------------------- + +LodePNG uses unsigned char arrays for 16-bit per channel colors too, just like +for any other color format. The 16-bit values are stored in big endian (most +significant byte first) in these arrays. This is the opposite order of the +little endian used by x86 CPU's. + +LodePNG always uses big endian because the PNG file format does so internally. +Conversions to other formats than PNG uses internally are not supported by +LodePNG on purpose, there are myriads of formats, including endianness of 16-bit +colors, the order in which you store R, G, B and A, and so on. Supporting and +converting to/from all that is outside the scope of LodePNG. + +This may mean that, depending on your use case, you may want to convert the big +endian output of LodePNG to little endian with a for loop. This is certainly not +always needed, many applications and libraries support big endian 16-bit colors +anyway, but it means you cannot simply cast the unsigned char* buffer to an +unsigned short* buffer on x86 CPUs. + + +7. error values +--------------- + +All functions in LodePNG that return an error code, return 0 if everything went +OK, or a non-zero code if there was an error. + +The meaning of the LodePNG error values can be retrieved with the function +lodepng_error_text: given the numerical error code, it returns a description +of the error in English as a string. + +Check the implementation of lodepng_error_text to see the meaning of each code. + + +8. chunks and PNG editing +------------------------- + +If you want to add extra chunks to a PNG you encode, or use LodePNG for a PNG +editor that should follow the rules about handling of unknown chunks, or if your +program is able to read other types of chunks than the ones handled by LodePNG, +then that's possible with the chunk functions of LodePNG. + +A PNG chunk has the following layout: + +4 bytes length +4 bytes type name +length bytes data +4 bytes CRC + +8.1. iterating through chunks +----------------------------- + +If you have a buffer containing the PNG image data, then the first chunk (the +IHDR chunk) starts at byte number 8 of that buffer. The first 8 bytes are the +signature of the PNG and are not part of a chunk. But if you start at byte 8 +then you have a chunk, and can check the following things of it. + +NOTE: none of these functions check for memory buffer boundaries. To avoid +exploits, always make sure the buffer contains all the data of the chunks. +When using lodepng_chunk_next, make sure the returned value is within the +allocated memory. + +unsigned lodepng_chunk_length(const unsigned char* chunk): + +Get the length of the chunk's data. The total chunk length is this length + 12. + +void lodepng_chunk_type(char type[5], const unsigned char* chunk): +unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type): + +Get the type of the chunk or compare if it's a certain type + +unsigned char lodepng_chunk_critical(const unsigned char* chunk): +unsigned char lodepng_chunk_private(const unsigned char* chunk): +unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk): + +Check if the chunk is critical in the PNG standard (only IHDR, PLTE, IDAT and IEND are). +Check if the chunk is private (public chunks are part of the standard, private ones not). +Check if the chunk is safe to copy. If it's not, then, when modifying data in a critical +chunk, unsafe to copy chunks of the old image may NOT be saved in the new one if your +program doesn't handle that type of unknown chunk. + +unsigned char* lodepng_chunk_data(unsigned char* chunk): +const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk): + +Get a pointer to the start of the data of the chunk. + +unsigned lodepng_chunk_check_crc(const unsigned char* chunk): +void lodepng_chunk_generate_crc(unsigned char* chunk): + +Check if the crc is correct or generate a correct one. + +unsigned char* lodepng_chunk_next(unsigned char* chunk): +const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk): + +Iterate to the next chunk. This works if you have a buffer with consecutive chunks. Note that these +functions do no boundary checking of the allocated data whatsoever, so make sure there is enough +data available in the buffer to be able to go to the next chunk. + +unsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk): +unsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length, + const char* type, const unsigned char* data): + +These functions are used to create new chunks that are appended to the data in *out that has +length *outlength. The append function appends an existing chunk to the new data. The create +function creates a new chunk with the given parameters and appends it. Type is the 4-letter +name of the chunk. + +8.2. chunks in info_png +----------------------- + +The LodePNGInfo struct contains fields with the unknown chunk in it. It has 3 +buffers (each with size) to contain 3 types of unknown chunks: +the ones that come before the PLTE chunk, the ones that come between the PLTE +and the IDAT chunks, and the ones that come after the IDAT chunks. +It's necessary to make the distionction between these 3 cases because the PNG +standard forces to keep the ordering of unknown chunks compared to the critical +chunks, but does not force any other ordering rules. + +info_png.unknown_chunks_data[0] is the chunks before PLTE +info_png.unknown_chunks_data[1] is the chunks after PLTE, before IDAT +info_png.unknown_chunks_data[2] is the chunks after IDAT + +The chunks in these 3 buffers can be iterated through and read by using the same +way described in the previous subchapter. + +When using the decoder to decode a PNG, you can make it store all unknown chunks +if you set the option settings.remember_unknown_chunks to 1. By default, this +option is off (0). + +The encoder will always encode unknown chunks that are stored in the info_png. +If you need it to add a particular chunk that isn't known by LodePNG, you can +use lodepng_chunk_append or lodepng_chunk_create to the chunk data in +info_png.unknown_chunks_data[x]. + +Chunks that are known by LodePNG should not be added in that way. E.g. to make +LodePNG add a bKGD chunk, set background_defined to true and add the correct +parameters there instead. + + +9. compiler support +------------------- + +No libraries other than the current standard C library are needed to compile +LodePNG. For the C++ version, only the standard C++ library is needed on top. +Add the files lodepng.c(pp) and lodepng.h to your project, include +lodepng.h where needed, and your program can read/write PNG files. + +It is compatible with C90 and up, and C++03 and up. + +If performance is important, use optimization when compiling! For both the +encoder and decoder, this makes a large difference. + +Make sure that LodePNG is compiled with the same compiler of the same version +and with the same settings as the rest of the program, or the interfaces with +std::vectors and std::strings in C++ can be incompatible. + +CHAR_BITS must be 8 or higher, because LodePNG uses unsigned chars for octets. + +*) gcc and g++ + +LodePNG is developed in gcc so this compiler is natively supported. It gives no +warnings with compiler options "-Wall -Wextra -pedantic -ansi", with gcc and g++ +version 4.7.1 on Linux, 32-bit and 64-bit. + +*) Clang + +Fully supported and warning-free. + +*) Mingw + +The Mingw compiler (a port of gcc for Windows) should be fully supported by +LodePNG. + +*) Visual Studio and Visual C++ Express Edition + +LodePNG should be warning-free with warning level W4. Two warnings were disabled +with pragmas though: warning 4244 about implicit conversions, and warning 4996 +where it wants to use a non-standard function fopen_s instead of the standard C +fopen. + +Visual Studio may want "stdafx.h" files to be included in each source file and +give an error "unexpected end of file while looking for precompiled header". +This is not standard C++ and will not be added to the stock LodePNG. You can +disable it for lodepng.cpp only by right clicking it, Properties, C/C++, +Precompiled Headers, and set it to Not Using Precompiled Headers there. + +NOTE: Modern versions of VS should be fully supported, but old versions, e.g. +VS6, are not guaranteed to work. + +*) Compilers on Macintosh + +LodePNG has been reported to work both with gcc and LLVM for Macintosh, both for +C and C++. + +*) Other Compilers + +If you encounter problems on any compilers, feel free to let me know and I may +try to fix it if the compiler is modern and standards complient. + + +10. examples +------------ + +This decoder example shows the most basic usage of LodePNG. More complex +examples can be found on the LodePNG website. + +10.1. decoder C++ example +------------------------- + +#include "lodepng.h" +#include + +int main(int argc, char *argv[]) +{ + const char* filename = argc > 1 ? argv[1] : "test.png"; + + //load and decode + std::vector image; + unsigned width, height; + unsigned error = lodepng::decode(image, width, height, filename); + + //if there's an error, display it + if(error) std::cout << "decoder error " << error << ": " << lodepng_error_text(error) << std::endl; + + //the pixels are now in the vector "image", 4 bytes per pixel, ordered RGBARGBA..., use it as texture, draw it, ... +} + +10.2. decoder C example +----------------------- + +#include "lodepng.h" + +int main(int argc, char *argv[]) +{ + unsigned error; + unsigned char* image; + size_t width, height; + const char* filename = argc > 1 ? argv[1] : "test.png"; + + error = lodepng_decode32_file(&image, &width, &height, filename); + + if(error) printf("decoder error %u: %s\n", error, lodepng_error_text(error)); + + / * use image here * / + + free(image); + return 0; +} + +11. state settings reference +---------------------------- + +A quick reference of some settings to set on the LodePNGState + +For decoding: + +state.decoder.zlibsettings.ignore_adler32: ignore ADLER32 checksums +state.decoder.zlibsettings.custom_...: use custom inflate function +state.decoder.ignore_crc: ignore CRC checksums +state.decoder.ignore_critical: ignore unknown critical chunks +state.decoder.ignore_end: ignore missing IEND chunk. May fail if this corruption causes other errors +state.decoder.color_convert: convert internal PNG color to chosen one +state.decoder.read_text_chunks: whether to read in text metadata chunks +state.decoder.remember_unknown_chunks: whether to read in unknown chunks +state.info_raw.colortype: desired color type for decoded image +state.info_raw.bitdepth: desired bit depth for decoded image +state.info_raw....: more color settings, see struct LodePNGColorMode +state.info_png....: no settings for decoder but ouput, see struct LodePNGInfo + +For encoding: + +state.encoder.zlibsettings.btype: disable compression by setting it to 0 +state.encoder.zlibsettings.use_lz77: use LZ77 in compression +state.encoder.zlibsettings.windowsize: tweak LZ77 windowsize +state.encoder.zlibsettings.minmatch: tweak min LZ77 length to match +state.encoder.zlibsettings.nicematch: tweak LZ77 match where to stop searching +state.encoder.zlibsettings.lazymatching: try one more LZ77 matching +state.encoder.zlibsettings.custom_...: use custom deflate function +state.encoder.auto_convert: choose optimal PNG color type, if 0 uses info_png +state.encoder.filter_palette_zero: PNG filter strategy for palette +state.encoder.filter_strategy: PNG filter strategy to encode with +state.encoder.force_palette: add palette even if not encoding to one +state.encoder.add_id: add LodePNG identifier and version as a text chunk +state.encoder.text_compression: use compressed text chunks for metadata +state.info_raw.colortype: color type of raw input image you provide +state.info_raw.bitdepth: bit depth of raw input image you provide +state.info_raw: more color settings, see struct LodePNGColorMode +state.info_png.color.colortype: desired color type if auto_convert is false +state.info_png.color.bitdepth: desired bit depth if auto_convert is false +state.info_png.color....: more color settings, see struct LodePNGColorMode +state.info_png....: more PNG related settings, see struct LodePNGInfo + + +12. changes +----------- + +The version number of LodePNG is the date of the change given in the format +yyyymmdd. + +Some changes aren't backwards compatible. Those are indicated with a (!) +symbol. + +*) 10 sep 2018: added way to inspect metadata chunks without full decoding. +*) 19 aug 2018 (!): fixed color mode bKGD is encoded with and made it use + palette index in case of palette. +*) 10 aug 2018 (!): added support for gAMA, cHRM, sRGB and iCCP chunks. This + change is backwards compatible unless you relied on unknown_chunks for those. +*) 11 jun 2018: less restrictive check for pixel size integer overflow +*) 14 jan 2018: allow optionally ignoring a few more recoverable errors +*) 17 sep 2017: fix memory leak for some encoder input error cases +*) 27 nov 2016: grey+alpha auto color model detection bugfix +*) 18 apr 2016: Changed qsort to custom stable sort (for platforms w/o qsort). +*) 09 apr 2016: Fixed colorkey usage detection, and better file loading (within + the limits of pure C90). +*) 08 dec 2015: Made load_file function return error if file can't be opened. +*) 24 okt 2015: Bugfix with decoding to palette output. +*) 18 apr 2015: Boundary PM instead of just package-merge for faster encoding. +*) 23 aug 2014: Reduced needless memory usage of decoder. +*) 28 jun 2014: Removed fix_png setting, always support palette OOB for + simplicity. Made ColorProfile public. +*) 09 jun 2014: Faster encoder by fixing hash bug and more zeros optimization. +*) 22 dec 2013: Power of two windowsize required for optimization. +*) 15 apr 2013: Fixed bug with LAC_ALPHA and color key. +*) 25 mar 2013: Added an optional feature to ignore some PNG errors (fix_png). +*) 11 mar 2013 (!): Bugfix with custom free. Changed from "my" to "lodepng_" + prefix for the custom allocators and made it possible with a new #define to + use custom ones in your project without needing to change lodepng's code. +*) 28 jan 2013: Bugfix with color key. +*) 27 okt 2012: Tweaks in text chunk keyword length error handling. +*) 8 okt 2012 (!): Added new filter strategy (entropy) and new auto color mode. + (no palette). Better deflate tree encoding. New compression tweak settings. + Faster color conversions while decoding. Some internal cleanups. +*) 23 sep 2012: Reduced warnings in Visual Studio a little bit. +*) 1 sep 2012 (!): Removed #define's for giving custom (de)compression functions + and made it work with function pointers instead. +*) 23 jun 2012: Added more filter strategies. Made it easier to use custom alloc + and free functions and toggle #defines from compiler flags. Small fixes. +*) 6 may 2012 (!): Made plugging in custom zlib/deflate functions more flexible. +*) 22 apr 2012 (!): Made interface more consistent, renaming a lot. Removed + redundant C++ codec classes. Reduced amount of structs. Everything changed, + but it is cleaner now imho and functionality remains the same. Also fixed + several bugs and shrunk the implementation code. Made new samples. +*) 6 nov 2011 (!): By default, the encoder now automatically chooses the best + PNG color model and bit depth, based on the amount and type of colors of the + raw image. For this, autoLeaveOutAlphaChannel replaced by auto_choose_color. +*) 9 okt 2011: simpler hash chain implementation for the encoder. +*) 8 sep 2011: lz77 encoder lazy matching instead of greedy matching. +*) 23 aug 2011: tweaked the zlib compression parameters after benchmarking. + A bug with the PNG filtertype heuristic was fixed, so that it chooses much + better ones (it's quite significant). A setting to do an experimental, slow, + brute force search for PNG filter types is added. +*) 17 aug 2011 (!): changed some C zlib related function names. +*) 16 aug 2011: made the code less wide (max 120 characters per line). +*) 17 apr 2011: code cleanup. Bugfixes. Convert low to 16-bit per sample colors. +*) 21 feb 2011: fixed compiling for C90. Fixed compiling with sections disabled. +*) 11 dec 2010: encoding is made faster, based on suggestion by Peter Eastman + to optimize long sequences of zeros. +*) 13 nov 2010: added LodePNG_InfoColor_hasPaletteAlpha and + LodePNG_InfoColor_canHaveAlpha functions for convenience. +*) 7 nov 2010: added LodePNG_error_text function to get error code description. +*) 30 okt 2010: made decoding slightly faster +*) 26 okt 2010: (!) changed some C function and struct names (more consistent). + Reorganized the documentation and the declaration order in the header. +*) 08 aug 2010: only changed some comments and external samples. +*) 05 jul 2010: fixed bug thanks to warnings in the new gcc version. +*) 14 mar 2010: fixed bug where too much memory was allocated for char buffers. +*) 02 sep 2008: fixed bug where it could create empty tree that linux apps could + read by ignoring the problem but windows apps couldn't. +*) 06 jun 2008: added more error checks for out of memory cases. +*) 26 apr 2008: added a few more checks here and there to ensure more safety. +*) 06 mar 2008: crash with encoding of strings fixed +*) 02 feb 2008: support for international text chunks added (iTXt) +*) 23 jan 2008: small cleanups, and #defines to divide code in sections +*) 20 jan 2008: support for unknown chunks allowing using LodePNG for an editor. +*) 18 jan 2008: support for tIME and pHYs chunks added to encoder and decoder. +*) 17 jan 2008: ability to encode and decode compressed zTXt chunks added + Also various fixes, such as in the deflate and the padding bits code. +*) 13 jan 2008: Added ability to encode Adam7-interlaced images. Improved + filtering code of encoder. +*) 07 jan 2008: (!) changed LodePNG to use ISO C90 instead of C++. A + C++ wrapper around this provides an interface almost identical to before. + Having LodePNG be pure ISO C90 makes it more portable. The C and C++ code + are together in these files but it works both for C and C++ compilers. +*) 29 dec 2007: (!) changed most integer types to unsigned int + other tweaks +*) 30 aug 2007: bug fixed which makes this Borland C++ compatible +*) 09 aug 2007: some VS2005 warnings removed again +*) 21 jul 2007: deflate code placed in new namespace separate from zlib code +*) 08 jun 2007: fixed bug with 2- and 4-bit color, and small interlaced images +*) 04 jun 2007: improved support for Visual Studio 2005: crash with accessing + invalid std::vector element [0] fixed, and level 3 and 4 warnings removed +*) 02 jun 2007: made the encoder add a tag with version by default +*) 27 may 2007: zlib and png code separated (but still in the same file), + simple encoder/decoder functions added for more simple usage cases +*) 19 may 2007: minor fixes, some code cleaning, new error added (error 69), + moved some examples from here to lodepng_examples.cpp +*) 12 may 2007: palette decoding bug fixed +*) 24 apr 2007: changed the license from BSD to the zlib license +*) 11 mar 2007: very simple addition: ability to encode bKGD chunks. +*) 04 mar 2007: (!) tEXt chunk related fixes, and support for encoding + palettized PNG images. Plus little interface change with palette and texts. +*) 03 mar 2007: Made it encode dynamic Huffman shorter with repeat codes. + Fixed a bug where the end code of a block had length 0 in the Huffman tree. +*) 26 feb 2007: Huffman compression with dynamic trees (BTYPE 2) now implemented + and supported by the encoder, resulting in smaller PNGs at the output. +*) 27 jan 2007: Made the Adler-32 test faster so that a timewaste is gone. +*) 24 jan 2007: gave encoder an error interface. Added color conversion from any + greyscale type to 8-bit greyscale with or without alpha. +*) 21 jan 2007: (!) Totally changed the interface. It allows more color types + to convert to and is more uniform. See the manual for how it works now. +*) 07 jan 2007: Some cleanup & fixes, and a few changes over the last days: + encode/decode custom tEXt chunks, separate classes for zlib & deflate, and + at last made the decoder give errors for incorrect Adler32 or Crc. +*) 01 jan 2007: Fixed bug with encoding PNGs with less than 8 bits per channel. +*) 29 dec 2006: Added support for encoding images without alpha channel, and + cleaned out code as well as making certain parts faster. +*) 28 dec 2006: Added "Settings" to the encoder. +*) 26 dec 2006: The encoder now does LZ77 encoding and produces much smaller files now. + Removed some code duplication in the decoder. Fixed little bug in an example. +*) 09 dec 2006: (!) Placed output parameters of public functions as first parameter. + Fixed a bug of the decoder with 16-bit per color. +*) 15 okt 2006: Changed documentation structure +*) 09 okt 2006: Encoder class added. It encodes a valid PNG image from the + given image buffer, however for now it's not compressed. +*) 08 sep 2006: (!) Changed to interface with a Decoder class +*) 30 jul 2006: (!) LodePNG_InfoPng , width and height are now retrieved in different + way. Renamed decodePNG to decodePNGGeneric. +*) 29 jul 2006: (!) Changed the interface: image info is now returned as a + struct of type LodePNG::LodePNG_Info, instead of a vector, which was a bit clumsy. +*) 28 jul 2006: Cleaned the code and added new error checks. + Corrected terminology "deflate" into "inflate". +*) 23 jun 2006: Added SDL example in the documentation in the header, this + example allows easy debugging by displaying the PNG and its transparency. +*) 22 jun 2006: (!) Changed way to obtain error value. Added + loadFile function for convenience. Made decodePNG32 faster. +*) 21 jun 2006: (!) Changed type of info vector to unsigned. + Changed position of palette in info vector. Fixed an important bug that + happened on PNGs with an uncompressed block. +*) 16 jun 2006: Internally changed unsigned into unsigned where + needed, and performed some optimizations. +*) 07 jun 2006: (!) Renamed functions to decodePNG and placed them + in LodePNG namespace. Changed the order of the parameters. Rewrote the + documentation in the header. Renamed files to lodepng.cpp and lodepng.h +*) 22 apr 2006: Optimized and improved some code +*) 07 sep 2005: (!) Changed to std::vector interface +*) 12 aug 2005: Initial release (C++, decoder only) + + +13. contact information +----------------------- + +Feel free to contact me with suggestions, problems, comments, ... concerning +LodePNG. If you encounter a PNG image that doesn't work properly with this +decoder, feel free to send it and I'll use it to find and fix the problem. + +My email address is (puzzle the account and domain together with an @ symbol): +Domain: gmail dot com. +Account: lode dot vandevenne. + + +Copyright (c) 2005-2018 Lode Vandevenne +*/ diff --git a/inc/png.h b/inc/png.h deleted file mode 100644 index 805be12..0000000 --- a/inc/png.h +++ /dev/null @@ -1,2699 +0,0 @@ - -/* png.h - header file for PNG reference library - * - * libpng version 1.4.4 - September 23, 2010 - * Copyright (c) 1998-2010 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.) - * - * This code is released under the libpng license (See LICENSE, below) - * - * 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.4.4 - September 23, 2010: Glenn - * See also "Contributing Authors", below. - * - * Note about libpng version numbers: - * - * Due to various miscommunications, unforeseen code incompatibilities - * and occasional factors outside the authors' control, version numbering - * on the library has not always been consistent and straightforward. - * The following table summarizes matters since version 0.89c, which was - * the first widely used release: - * - * source png.h png.h shared-lib - * version string int version - * ------- ------ ----- ---------- - * 0.89c "1.0 beta 3" 0.89 89 1.0.89 - * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] - * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] - * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] - * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] - * 0.97c 0.97 97 2.0.97 - * 0.98 0.98 98 2.0.98 - * 0.99 0.99 98 2.0.99 - * 0.99a-m 0.99 99 2.0.99 - * 1.00 1.00 100 2.1.0 [100 should be 10000] - * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] - * 1.0.1 png.h string is 10001 2.1.0 - * 1.0.1a-e identical to the 10002 from here on, the shared library - * 1.0.2 source version) 10002 is 2.V where V is the source code - * 1.0.2a-b 10003 version, except as noted. - * 1.0.3 10003 - * 1.0.3a-d 10004 - * 1.0.4 10004 - * 1.0.4a-f 10005 - * 1.0.5 (+ 2 patches) 10005 - * 1.0.5a-d 10006 - * 1.0.5e-r 10100 (not source compatible) - * 1.0.5s-v 10006 (not binary compatible) - * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) - * 1.0.6d-f 10007 (still binary incompatible) - * 1.0.6g 10007 - * 1.0.6h 10007 10.6h (testing xy.z so-numbering) - * 1.0.6i 10007 10.6i - * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) - * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) - * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) - * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) - * 1.0.7 1 10007 (still compatible) - * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 - * 1.0.8rc1 1 10008 2.1.0.8rc1 - * 1.0.8 1 10008 2.1.0.8 - * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 - * 1.0.9rc1 1 10009 2.1.0.9rc1 - * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 - * 1.0.9rc2 1 10009 2.1.0.9rc2 - * 1.0.9 1 10009 2.1.0.9 - * 1.0.10beta1 1 10010 2.1.0.10beta1 - * 1.0.10rc1 1 10010 2.1.0.10rc1 - * 1.0.10 1 10010 2.1.0.10 - * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 - * 1.0.11rc1 1 10011 2.1.0.11rc1 - * 1.0.11 1 10011 2.1.0.11 - * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 - * 1.0.12rc1 2 10012 2.1.0.12rc1 - * 1.0.12 2 10012 2.1.0.12 - * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) - * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 - * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 - * 1.2.0rc1 3 10200 3.1.2.0rc1 - * 1.2.0 3 10200 3.1.2.0 - * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 - * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 - * 1.2.1 3 10201 3.1.2.1 - * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 - * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 - * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 - * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 - * 1.0.13 10 10013 10.so.0.1.0.13 - * 1.2.2 12 10202 12.so.0.1.2.2 - * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 - * 1.2.3 12 10203 12.so.0.1.2.3 - * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 - * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 - * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 - * 1.0.14 10 10014 10.so.0.1.0.14 - * 1.2.4 13 10204 12.so.0.1.2.4 - * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 - * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 - * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 - * 1.0.15 10 10015 10.so.0.1.0.15 - * 1.2.5 13 10205 12.so.0.1.2.5 - * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 - * 1.0.16 10 10016 10.so.0.1.0.16 - * 1.2.6 13 10206 12.so.0.1.2.6 - * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 - * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 - * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 - * 1.0.17 10 10017 12.so.0.1.0.17 - * 1.2.7 13 10207 12.so.0.1.2.7 - * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 - * 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5 - * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 - * 1.0.18 10 10018 12.so.0.1.0.18 - * 1.2.8 13 10208 12.so.0.1.2.8 - * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 - * 1.2.9beta4-11 13 10209 12.so.0.9[.0] - * 1.2.9rc1 13 10209 12.so.0.9[.0] - * 1.2.9 13 10209 12.so.0.9[.0] - * 1.2.10beta1-7 13 10210 12.so.0.10[.0] - * 1.2.10rc1-2 13 10210 12.so.0.10[.0] - * 1.2.10 13 10210 12.so.0.10[.0] - * 1.4.0beta1-5 14 10400 14.so.0.0[.0] - * 1.2.11beta1-4 13 10211 12.so.0.11[.0] - * 1.4.0beta7-8 14 10400 14.so.0.0[.0] - * 1.2.11 13 10211 12.so.0.11[.0] - * 1.2.12 13 10212 12.so.0.12[.0] - * 1.4.0beta9-14 14 10400 14.so.0.0[.0] - * 1.2.13 13 10213 12.so.0.13[.0] - * 1.4.0beta15-36 14 10400 14.so.0.0[.0] - * 1.4.0beta37-87 14 10400 14.so.14.0[.0] - * 1.4.0rc01 14 10400 14.so.14.0[.0] - * 1.4.0beta88-109 14 10400 14.so.14.0[.0] - * 1.4.0rc02-08 14 10400 14.so.14.0[.0] - * 1.4.0 14 10400 14.so.14.0[.0] - * 1.4.1beta01-03 14 10401 14.so.14.1[.0] - * 1.4.1rc01 14 10401 14.so.14.1[.0] - * 1.4.1beta04-12 14 10401 14.so.14.1[.0] - * 1.4.1rc02-04 14 10401 14.so.14.1[.0] - * 1.4.1 14 10401 14.so.14.1[.0] - * 1.4.2beta01 14 10402 14.so.14.2[.0] - * 1.4.2rc02-06 14 10402 14.so.14.2[.0] - * 1.4.2 14 10402 14.so.14.2[.0] - * 1.4.3beta01-05 14 10403 14.so.14.3[.0] - * 1.4.3rc01-03 14 10403 14.so.14.3[.0] - * 1.4.3 14 10403 14.so.14.3[.0] - * 1.4.4beta01-08 14 10404 14.so.14.4[.0] - * 1.4.4rc01-06 14 10404 14.so.14.4[.0] - * - * Henceforth the source version will match the shared-library major - * and minor numbers; the shared-library major version number will be - * used for changes in backward compatibility, as it is intended. The - * PNG_LIBPNG_VER macro, which is not used within libpng but is available - * for applications, is an unsigned integer of the form xyyzz corresponding - * to the source version x.y.z (leading zeros in y and z). Beta versions - * were given the previous public release number plus a letter, until - * version 1.0.6j; from then on they were given the upcoming public - * release number plus "betaNN" or "rcN". - * - * Binary incompatibility exists only when applications make direct access - * to the info_ptr or png_ptr members through png.h, and the compiled - * application is loaded with a different version of the library. - * - * DLLNUM will change each time there are forward or backward changes - * in binary compatibility (e.g., when a new feature is added). - * - * See libpng.txt or libpng.3 for more information. The PNG specification - * is available as a W3C Recommendation and as an ISO Specification, - * defines should NOT be changed. - */ -#define PNG_INFO_gAMA 0x0001 -#define PNG_INFO_sBIT 0x0002 -#define PNG_INFO_cHRM 0x0004 -#define PNG_INFO_PLTE 0x0008 -#define PNG_INFO_tRNS 0x0010 -#define PNG_INFO_bKGD 0x0020 -#define PNG_INFO_hIST 0x0040 -#define PNG_INFO_pHYs 0x0080 -#define PNG_INFO_oFFs 0x0100 -#define PNG_INFO_tIME 0x0200 -#define PNG_INFO_pCAL 0x0400 -#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ -#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ -#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ -#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ -#define PNG_INFO_IDAT 0x8000L /* ESR, 1.0.6 */ - -/* This is used for the transformation routines, as some of them - * change these values for the row. It also should enable using - * the routines for other purposes. - */ -typedef struct png_row_info_struct -{ - png_uint_32 width; /* width of row */ - png_size_t rowbytes; /* number of bytes in row */ - png_byte color_type; /* color type of row */ - png_byte bit_depth; /* bit depth of row */ - png_byte channels; /* number of channels (1, 2, 3, or 4) */ - png_byte pixel_depth; /* bits per pixel (depth * channels) */ -} png_row_info; - -typedef png_row_info FAR * png_row_infop; -typedef png_row_info FAR * FAR * png_row_infopp; - -/* These are the function types for the I/O functions and for the functions - * that allow the user to override the default I/O functions with his or her - * own. The png_error_ptr type should match that of user-supplied warning - * and error functions, while the png_rw_ptr type should match that of the - * user read/write data functions. - */ -typedef struct png_struct_def png_struct; -typedef png_struct FAR * png_structp; - -typedef void (PNGAPI *png_error_ptr) PNGARG((png_structp, png_const_charp)); -typedef void (PNGAPI *png_rw_ptr) PNGARG((png_structp, png_bytep, png_size_t)); -typedef void (PNGAPI *png_flush_ptr) PNGARG((png_structp)); -typedef void (PNGAPI *png_read_status_ptr) PNGARG((png_structp, png_uint_32, - int)); -typedef void (PNGAPI *png_write_status_ptr) PNGARG((png_structp, png_uint_32, - int)); - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -typedef void (PNGAPI *png_progressive_info_ptr) PNGARG((png_structp, - png_infop)); -typedef void (PNGAPI *png_progressive_end_ptr) PNGARG((png_structp, png_infop)); -typedef void (PNGAPI *png_progressive_row_ptr) PNGARG((png_structp, png_bytep, - png_uint_32, int)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -typedef void (PNGAPI *png_user_transform_ptr) PNGARG((png_structp, - png_row_infop, png_bytep)); -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -typedef int (PNGAPI *png_user_chunk_ptr) PNGARG((png_structp, - png_unknown_chunkp)); -#endif -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED -typedef void (PNGAPI *png_unknown_chunk_ptr) PNGARG((png_structp)); -#endif -#ifdef PNG_SETJMP_SUPPORTED -/* This must match the function definition in , and the - * application must include this before png.h to obtain the definition - * of jmp_buf. - */ -typedef void (PNGAPI *png_longjmp_ptr) PNGARG((jmp_buf, int)); -#endif - -/* Transform masks for the high-level interface */ -#define PNG_TRANSFORM_IDENTITY 0x0000 /* read and write */ -#define PNG_TRANSFORM_STRIP_16 0x0001 /* read only */ -#define PNG_TRANSFORM_STRIP_ALPHA 0x0002 /* read only */ -#define PNG_TRANSFORM_PACKING 0x0004 /* read and write */ -#define PNG_TRANSFORM_PACKSWAP 0x0008 /* read and write */ -#define PNG_TRANSFORM_EXPAND 0x0010 /* read only */ -#define PNG_TRANSFORM_INVERT_MONO 0x0020 /* read and write */ -#define PNG_TRANSFORM_SHIFT 0x0040 /* read and write */ -#define PNG_TRANSFORM_BGR 0x0080 /* read and write */ -#define PNG_TRANSFORM_SWAP_ALPHA 0x0100 /* read and write */ -#define PNG_TRANSFORM_SWAP_ENDIAN 0x0200 /* read and write */ -#define PNG_TRANSFORM_INVERT_ALPHA 0x0400 /* read and write */ -#define PNG_TRANSFORM_STRIP_FILLER 0x0800 /* write only */ -/* Added to libpng-1.2.34 */ -#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER -#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */ -/* Added to libpng-1.4.0 */ -#define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ - -/* Flags for MNG supported features */ -#define PNG_FLAG_MNG_EMPTY_PLTE 0x01 -#define PNG_FLAG_MNG_FILTER_64 0x04 -#define PNG_ALL_MNG_FEATURES 0x05 - -typedef png_voidp (*png_malloc_ptr) PNGARG((png_structp, png_alloc_size_t)); -typedef void (*png_free_ptr) PNGARG((png_structp, png_voidp)); - -/* The structure that holds the information to read and write PNG files. - * The only people who need to care about what is inside of this are the - * people who will be modifying the library for their own special needs. - * It should NOT be accessed directly by an application, except to store - * the jmp_buf. - */ - -struct png_struct_def -{ -#ifdef PNG_SETJMP_SUPPORTED - jmp_buf jmpbuf PNG_DEPSTRUCT; /* used in png_error */ - png_longjmp_ptr longjmp_fn PNG_DEPSTRUCT;/* setjmp non-local goto - function. */ -#endif - png_error_ptr error_fn PNG_DEPSTRUCT; /* function for printing - errors and aborting */ - png_error_ptr warning_fn PNG_DEPSTRUCT; /* function for printing - warnings */ - png_voidp error_ptr PNG_DEPSTRUCT; /* user supplied struct for - error functions */ - png_rw_ptr write_data_fn PNG_DEPSTRUCT; /* function for writing - output data */ - png_rw_ptr read_data_fn PNG_DEPSTRUCT; /* function for reading - input data */ - png_voidp io_ptr PNG_DEPSTRUCT; /* ptr to application struct - for I/O functions */ - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED - png_user_transform_ptr read_user_transform_fn PNG_DEPSTRUCT; /* user read - transform */ -#endif - -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED - png_user_transform_ptr write_user_transform_fn PNG_DEPSTRUCT; /* user write - transform */ -#endif - -/* These were added in libpng-1.0.2 */ -#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - png_voidp user_transform_ptr PNG_DEPSTRUCT; /* user supplied struct - for user transform */ - png_byte user_transform_depth PNG_DEPSTRUCT; /* bit depth of user - transformed pixels */ - png_byte user_transform_channels PNG_DEPSTRUCT; /* channels in user - transformed pixels */ -#endif -#endif - - png_uint_32 mode PNG_DEPSTRUCT; /* tells us where we are in - the PNG file */ - png_uint_32 flags PNG_DEPSTRUCT; /* flags indicating various - things to libpng */ - png_uint_32 transformations PNG_DEPSTRUCT; /* which transformations - to perform */ - - z_stream zstream PNG_DEPSTRUCT; /* pointer to decompression - structure (below) */ - png_bytep zbuf PNG_DEPSTRUCT; /* buffer for zlib */ - png_size_t zbuf_size PNG_DEPSTRUCT; /* size of zbuf */ - int zlib_level PNG_DEPSTRUCT; /* holds zlib compression level */ - int zlib_method PNG_DEPSTRUCT; /* holds zlib compression method */ - int zlib_window_bits PNG_DEPSTRUCT; /* holds zlib compression window - bits */ - int zlib_mem_level PNG_DEPSTRUCT; /* holds zlib compression memory - level */ - int zlib_strategy PNG_DEPSTRUCT; /* holds zlib compression - strategy */ - - png_uint_32 width PNG_DEPSTRUCT; /* width of image in pixels */ - png_uint_32 height PNG_DEPSTRUCT; /* height of image in pixels */ - png_uint_32 num_rows PNG_DEPSTRUCT; /* number of rows in current pass */ - png_uint_32 usr_width PNG_DEPSTRUCT; /* width of row at start of write */ - png_size_t rowbytes PNG_DEPSTRUCT; /* size of row in bytes */ -#if 0 /* Replaced with the following in libpng-1.4.1 */ - png_size_t irowbytes PNG_DEPSTRUCT; -#endif -/* Added in libpng-1.4.1 */ -#ifdef PNG_USER_LIMITS_SUPPORTED - /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk - * can occupy when decompressed. 0 means unlimited. - * We will change the typedef from png_size_t to png_alloc_size_t - * in libpng-1.6.0 - */ - png_alloc_size_t user_chunk_malloc_max PNG_DEPSTRUCT; -#endif - png_uint_32 iwidth PNG_DEPSTRUCT; /* width of current interlaced - row in pixels */ - png_uint_32 row_number PNG_DEPSTRUCT; /* current row in interlace pass */ - png_bytep prev_row PNG_DEPSTRUCT; /* buffer to save previous - (unfiltered) row */ - png_bytep row_buf PNG_DEPSTRUCT; /* buffer to save current - (unfiltered) row */ - png_bytep sub_row PNG_DEPSTRUCT; /* buffer to save "sub" row - when filtering */ - png_bytep up_row PNG_DEPSTRUCT; /* buffer to save "up" row - when filtering */ - png_bytep avg_row PNG_DEPSTRUCT; /* buffer to save "avg" row - when filtering */ - png_bytep paeth_row PNG_DEPSTRUCT; /* buffer to save "Paeth" row - when filtering */ - png_row_info row_info PNG_DEPSTRUCT; /* used for transformation - routines */ - - png_uint_32 idat_size PNG_DEPSTRUCT; /* current IDAT size for read */ - png_uint_32 crc PNG_DEPSTRUCT; /* current chunk CRC value */ - png_colorp palette PNG_DEPSTRUCT; /* palette from the input file */ - png_uint_16 num_palette PNG_DEPSTRUCT; /* number of color entries in - palette */ - png_uint_16 num_trans PNG_DEPSTRUCT; /* number of transparency values */ - png_byte chunk_name[5] PNG_DEPSTRUCT; /* null-terminated name of current - chunk */ - png_byte compression PNG_DEPSTRUCT; /* file compression type - (always 0) */ - png_byte filter PNG_DEPSTRUCT; /* file filter type (always 0) */ - png_byte interlaced PNG_DEPSTRUCT; /* PNG_INTERLACE_NONE, - PNG_INTERLACE_ADAM7 */ - png_byte pass PNG_DEPSTRUCT; /* current interlace pass (0 - 6) */ - png_byte do_filter PNG_DEPSTRUCT; /* row filter flags (see - PNG_FILTER_ below ) */ - png_byte color_type PNG_DEPSTRUCT; /* color type of file */ - png_byte bit_depth PNG_DEPSTRUCT; /* bit depth of file */ - png_byte usr_bit_depth PNG_DEPSTRUCT; /* bit depth of users row */ - png_byte pixel_depth PNG_DEPSTRUCT; /* number of bits per pixel */ - png_byte channels PNG_DEPSTRUCT; /* number of channels in file */ - png_byte usr_channels PNG_DEPSTRUCT; /* channels at start of write */ - png_byte sig_bytes PNG_DEPSTRUCT; /* magic bytes read/written from - start of file */ - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) - png_uint_16 filler PNG_DEPSTRUCT; /* filler bytes for pixel - expansion */ -#endif - -#ifdef PNG_bKGD_SUPPORTED - png_byte background_gamma_type PNG_DEPSTRUCT; -# ifdef PNG_FLOATING_POINT_SUPPORTED - float background_gamma PNG_DEPSTRUCT; -# endif - png_color_16 background PNG_DEPSTRUCT; /* background color in - screen gamma space */ -#ifdef PNG_READ_GAMMA_SUPPORTED - png_color_16 background_1 PNG_DEPSTRUCT; /* background normalized - to gamma 1.0 */ -#endif -#endif /* PNG_bKGD_SUPPORTED */ - -#ifdef PNG_WRITE_FLUSH_SUPPORTED - png_flush_ptr output_flush_fn PNG_DEPSTRUCT; /* Function for flushing - output */ - png_uint_32 flush_dist PNG_DEPSTRUCT; /* how many rows apart to flush, - 0 - no flush */ - png_uint_32 flush_rows PNG_DEPSTRUCT; /* number of rows written since - last flush */ -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - int gamma_shift PNG_DEPSTRUCT; /* number of "insignificant" bits - 16-bit gamma */ -#ifdef PNG_FLOATING_POINT_SUPPORTED - float gamma PNG_DEPSTRUCT; /* file gamma value */ - float screen_gamma PNG_DEPSTRUCT; /* screen gamma value - (display_exponent) */ -#endif -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep gamma_table PNG_DEPSTRUCT; /* gamma table for 8-bit - depth files */ - png_bytep gamma_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to screen */ - png_bytep gamma_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */ - png_uint_16pp gamma_16_table PNG_DEPSTRUCT; /* gamma table for 16-bit - depth files */ - png_uint_16pp gamma_16_from_1 PNG_DEPSTRUCT; /* converts from 1.0 to - screen */ - png_uint_16pp gamma_16_to_1 PNG_DEPSTRUCT; /* converts from file to 1.0 */ -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) - png_color_8 sig_bit PNG_DEPSTRUCT; /* significant bits in each - available channel */ -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) - png_color_8 shift PNG_DEPSTRUCT; /* shift for significant bit - tranformation */ -#endif - -#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ - || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep trans_alpha PNG_DEPSTRUCT; /* alpha values for - paletted files */ - png_color_16 trans_color PNG_DEPSTRUCT; /* transparent color for - non-paletted files */ -#endif - - png_read_status_ptr read_row_fn PNG_DEPSTRUCT; /* called after each - row is decoded */ - png_write_status_ptr write_row_fn PNG_DEPSTRUCT; /* called after each - row is encoded */ -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED - png_progressive_info_ptr info_fn PNG_DEPSTRUCT; /* called after header - data fully read */ - png_progressive_row_ptr row_fn PNG_DEPSTRUCT; /* called after each - prog. row is decoded */ - png_progressive_end_ptr end_fn PNG_DEPSTRUCT; /* called after image - is complete */ - png_bytep save_buffer_ptr PNG_DEPSTRUCT; /* current location in - save_buffer */ - png_bytep save_buffer PNG_DEPSTRUCT; /* buffer for previously - read data */ - png_bytep current_buffer_ptr PNG_DEPSTRUCT; /* current location in - current_buffer */ - png_bytep current_buffer PNG_DEPSTRUCT; /* buffer for recently - used data */ - png_uint_32 push_length PNG_DEPSTRUCT; /* size of current input - chunk */ - png_uint_32 skip_length PNG_DEPSTRUCT; /* bytes to skip in - input data */ - png_size_t save_buffer_size PNG_DEPSTRUCT; /* amount of data now - in save_buffer */ - png_size_t save_buffer_max PNG_DEPSTRUCT; /* total size of - save_buffer */ - png_size_t buffer_size PNG_DEPSTRUCT; /* total amount of - available input data */ - png_size_t current_buffer_size PNG_DEPSTRUCT; /* amount of data now - in current_buffer */ - int process_mode PNG_DEPSTRUCT; /* what push library - is currently doing */ - int cur_palette PNG_DEPSTRUCT; /* current push library - palette index */ - -# ifdef PNG_TEXT_SUPPORTED - png_size_t current_text_size PNG_DEPSTRUCT; /* current size of - text input data */ - png_size_t current_text_left PNG_DEPSTRUCT; /* how much text left - to read in input */ - png_charp current_text PNG_DEPSTRUCT; /* current text chunk - buffer */ - png_charp current_text_ptr PNG_DEPSTRUCT; /* current location - in current_text */ -# endif /* PNG_PROGRESSIVE_READ_SUPPORTED && PNG_TEXT_SUPPORTED */ - -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) -/* For the Borland special 64K segment handler */ - png_bytepp offset_table_ptr PNG_DEPSTRUCT; - png_bytep offset_table PNG_DEPSTRUCT; - png_uint_16 offset_table_number PNG_DEPSTRUCT; - png_uint_16 offset_table_count PNG_DEPSTRUCT; - png_uint_16 offset_table_count_free PNG_DEPSTRUCT; -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED - png_bytep palette_lookup PNG_DEPSTRUCT; /* lookup table for quantizing */ - png_bytep quantize_index PNG_DEPSTRUCT; /* index translation for palette - files */ -#endif - -#if defined(PNG_READ_QUANTIZE_SUPPORTED) || defined(PNG_hIST_SUPPORTED) - png_uint_16p hist PNG_DEPSTRUCT; /* histogram */ -#endif - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - png_byte heuristic_method PNG_DEPSTRUCT; /* heuristic for row - filter selection */ - png_byte num_prev_filters PNG_DEPSTRUCT; /* number of weights - for previous rows */ - png_bytep prev_filters PNG_DEPSTRUCT; /* filter type(s) of - previous row(s) */ - png_uint_16p filter_weights PNG_DEPSTRUCT; /* weight(s) for previous - line(s) */ - png_uint_16p inv_filter_weights PNG_DEPSTRUCT; /* 1/weight(s) for - previous line(s) */ - png_uint_16p filter_costs PNG_DEPSTRUCT; /* relative filter - calculation cost */ - png_uint_16p inv_filter_costs PNG_DEPSTRUCT; /* 1/relative filter - calculation cost */ -#endif - -#ifdef PNG_TIME_RFC1123_SUPPORTED - png_charp time_buffer PNG_DEPSTRUCT; /* String to hold RFC 1123 time text */ -#endif - -/* New members added in libpng-1.0.6 */ - - png_uint_32 free_me PNG_DEPSTRUCT; /* flags items libpng is - responsible for freeing */ - -#ifdef PNG_USER_CHUNKS_SUPPORTED - png_voidp user_chunk_ptr PNG_DEPSTRUCT; - png_user_chunk_ptr read_user_chunk_fn PNG_DEPSTRUCT; /* user read - chunk handler */ -#endif - -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED - int num_chunk_list PNG_DEPSTRUCT; - png_bytep chunk_list PNG_DEPSTRUCT; -#endif - -/* New members added in libpng-1.0.3 */ -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED - png_byte rgb_to_gray_status PNG_DEPSTRUCT; - /* These were changed from png_byte in libpng-1.0.6 */ - png_uint_16 rgb_to_gray_red_coeff PNG_DEPSTRUCT; - png_uint_16 rgb_to_gray_green_coeff PNG_DEPSTRUCT; - png_uint_16 rgb_to_gray_blue_coeff PNG_DEPSTRUCT; -#endif - -/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ -#if defined(PNG_MNG_FEATURES_SUPPORTED) || \ - defined(PNG_READ_EMPTY_PLTE_SUPPORTED) || \ - defined(PNG_WRITE_EMPTY_PLTE_SUPPORTED) -/* Changed from png_byte to png_uint_32 at version 1.2.0 */ - png_uint_32 mng_features_permitted PNG_DEPSTRUCT; -#endif - -/* New member added in libpng-1.0.7 */ -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_fixed_point int_gamma PNG_DEPSTRUCT; -#endif - -/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */ -#ifdef PNG_MNG_FEATURES_SUPPORTED - png_byte filter_type PNG_DEPSTRUCT; -#endif - -/* New members added in libpng-1.2.0 */ - -/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ -#ifdef PNG_USER_MEM_SUPPORTED - png_voidp mem_ptr PNG_DEPSTRUCT; /* user supplied struct for - mem functions */ - png_malloc_ptr malloc_fn PNG_DEPSTRUCT; /* function for - allocating memory */ - png_free_ptr free_fn PNG_DEPSTRUCT; /* function for - freeing memory */ -#endif - -/* New member added in libpng-1.0.13 and 1.2.0 */ - png_bytep big_row_buf PNG_DEPSTRUCT; /* buffer to save current - (unfiltered) row */ - -#ifdef PNG_READ_QUANTIZE_SUPPORTED -/* The following three members were added at version 1.0.14 and 1.2.4 */ - png_bytep quantize_sort PNG_DEPSTRUCT; /* working sort array */ - png_bytep index_to_palette PNG_DEPSTRUCT; /* where the original - index currently is - in the palette */ - png_bytep palette_to_index PNG_DEPSTRUCT; /* which original index - points to this - palette color */ -#endif - -/* New members added in libpng-1.0.16 and 1.2.6 */ - png_byte compression_type PNG_DEPSTRUCT; - -#ifdef PNG_USER_LIMITS_SUPPORTED - png_uint_32 user_width_max PNG_DEPSTRUCT; - png_uint_32 user_height_max PNG_DEPSTRUCT; - /* Added in libpng-1.4.0: Total number of sPLT, text, and unknown - * chunks that can be stored (0 means unlimited). - */ - png_uint_32 user_chunk_cache_max PNG_DEPSTRUCT; -#endif - -/* New member added in libpng-1.0.25 and 1.2.17 */ -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED - /* Storage for unknown chunk that the library doesn't recognize. */ - png_unknown_chunk unknown_chunk PNG_DEPSTRUCT; -#endif - -/* New members added in libpng-1.2.26 */ - png_uint_32 old_big_row_buf_size PNG_DEPSTRUCT; - png_uint_32 old_prev_row_size PNG_DEPSTRUCT; - -/* New member added in libpng-1.2.30 */ - png_charp chunkdata PNG_DEPSTRUCT; /* buffer for reading chunk data */ - -#ifdef PNG_IO_STATE_SUPPORTED -/* New member added in libpng-1.4.0 */ - png_uint_32 io_state PNG_DEPSTRUCT; -#endif -}; - - -/* This triggers a compiler error in png.c, if png.c and png.h - * do not agree upon the version number. - */ -typedef png_structp version_1_4_4; - -typedef png_struct FAR * FAR * png_structpp; - -/* Here are the function definitions most commonly used. This is not - * the place to find out how to use libpng. See libpng.txt for the - * full explanation, see example.c for the summary. This just provides - * a simple one line description of the use of each function. - */ - -/* Returns the version number of the library */ -PNG_EXPORT(png_uint_32,png_access_version_number) PNGARG((void)); - -/* Tell lib we have already handled the first magic bytes. - * Handling more than 8 bytes from the beginning of the file is an error. - */ -PNG_EXPORT(void,png_set_sig_bytes) PNGARG((png_structp png_ptr, - int num_bytes)); - -/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a - * PNG file. Returns zero if the supplied bytes match the 8-byte PNG - * signature, and non-zero otherwise. Having num_to_check == 0 or - * start > 7 will always fail (ie return non-zero). - */ -PNG_EXPORT(int,png_sig_cmp) PNGARG((png_bytep sig, png_size_t start, - png_size_t num_to_check)); - -/* Simple signature checking function. This is the same as calling - * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). - */ -#define png_check_sig(sig,n) !png_sig_cmp((sig), 0, (n)) - -/* Allocate and initialize png_ptr struct for reading, and any other memory. */ -PNG_EXPORT(png_structp,png_create_read_struct) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED; - -/* Allocate and initialize png_ptr struct for writing, and any other memory */ -PNG_EXPORT(png_structp,png_create_write_struct) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn)) PNG_ALLOCATED; - -PNG_EXPORT(png_size_t,png_get_compression_buffer_size) - PNGARG((png_structp png_ptr)); - -PNG_EXPORT(void,png_set_compression_buffer_size) - PNGARG((png_structp png_ptr, png_size_t size)); - -/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp - * match up. - */ -#ifdef PNG_SETJMP_SUPPORTED -/* This function returns the jmp_buf built in to *png_ptr. It must be - * supplied with an appropriate 'longjmp' function to use on that jmp_buf - * unless the default error function is overridden in which case NULL is - * acceptable. The size of the jmp_buf is checked against the actual size - * allocated by the library - the call will return NULL on a mismatch - * indicating an ABI mismatch. - */ -PNG_EXPORT(jmp_buf*, png_set_longjmp_fn) - PNGARG((png_structp png_ptr, png_longjmp_ptr longjmp_fn, size_t - jmp_buf_size)); -# define png_jmpbuf(png_ptr) \ - (*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf))) -#else -# define png_jmpbuf(png_ptr) \ - (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP) -#endif - -#ifdef PNG_READ_SUPPORTED -/* Reset the compression stream */ -PNG_EXPORT(int,png_reset_zstream) PNGARG((png_structp png_ptr)); -#endif - -/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ -#ifdef PNG_USER_MEM_SUPPORTED -PNG_EXPORT(png_structp,png_create_read_struct_2) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED; -PNG_EXPORT(png_structp,png_create_write_struct_2) - PNGARG((png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn)) PNG_ALLOCATED; -#endif - -/* Write the PNG file signature. */ -PNG_EXPORT(void,png_write_sig) PNGARG((png_structp png_ptr)); - -/* Write a PNG chunk - size, type, (optional) data, CRC. */ -PNG_EXPORT(void,png_write_chunk) PNGARG((png_structp png_ptr, - png_bytep chunk_name, png_bytep data, png_size_t length)); - -/* Write the start of a PNG chunk - length and chunk name. */ -PNG_EXPORT(void,png_write_chunk_start) PNGARG((png_structp png_ptr, - png_bytep chunk_name, png_uint_32 length)); - -/* Write the data of a PNG chunk started with png_write_chunk_start(). */ -PNG_EXPORT(void,png_write_chunk_data) PNGARG((png_structp png_ptr, - png_bytep data, png_size_t length)); - -/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ -PNG_EXPORT(void,png_write_chunk_end) PNGARG((png_structp png_ptr)); - -/* Allocate and initialize the info structure */ -PNG_EXPORT(png_infop,png_create_info_struct) - PNGARG((png_structp png_ptr)) PNG_ALLOCATED; - -PNG_EXPORT(void,png_info_init_3) PNGARG((png_infopp info_ptr, - png_size_t png_info_struct_size)); - -/* Writes all the PNG information before the image. */ -PNG_EXPORT(void,png_write_info_before_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr)); -PNG_EXPORT(void,png_write_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the information before the actual image data. */ -PNG_EXPORT(void,png_read_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif - -#ifdef PNG_TIME_RFC1123_SUPPORTED -PNG_EXPORT(png_charp,png_convert_to_rfc1123) - PNGARG((png_structp png_ptr, png_timep ptime)); -#endif - -#ifdef PNG_CONVERT_tIME_SUPPORTED -/* Convert from a struct tm to png_time */ -PNG_EXPORT(void,png_convert_from_struct_tm) PNGARG((png_timep ptime, - struct tm FAR * ttime)); - -/* Convert from time_t to png_time. Uses gmtime() */ -PNG_EXPORT(void,png_convert_from_time_t) PNGARG((png_timep ptime, - time_t ttime)); -#endif /* PNG_CONVERT_tIME_SUPPORTED */ - -#ifdef PNG_READ_EXPAND_SUPPORTED -/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ -PNG_EXPORT(void,png_set_expand) PNGARG((png_structp png_ptr)); -PNG_EXPORT(void,png_set_expand_gray_1_2_4_to_8) PNGARG((png_structp - png_ptr)); -PNG_EXPORT(void,png_set_palette_to_rgb) PNGARG((png_structp png_ptr)); -PNG_EXPORT(void,png_set_tRNS_to_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -/* Use blue, green, red order for pixels. */ -PNG_EXPORT(void,png_set_bgr) PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED -/* Expand the grayscale to 24-bit RGB if necessary. */ -PNG_EXPORT(void,png_set_gray_to_rgb) PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -/* Reduce RGB to grayscale. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXPORT(void,png_set_rgb_to_gray) PNGARG((png_structp png_ptr, - int error_action, double red, double green )); -#endif -PNG_EXPORT(void,png_set_rgb_to_gray_fixed) PNGARG((png_structp png_ptr, - int error_action, png_fixed_point red, png_fixed_point green )); -PNG_EXPORT(png_byte,png_get_rgb_to_gray_status) PNGARG((png_structp - png_ptr)); -#endif - -PNG_EXPORT(void,png_build_grayscale_palette) PNGARG((int bit_depth, - png_colorp palette)); - -#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED -PNG_EXPORT(void,png_set_strip_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -PNG_EXPORT(void,png_set_swap_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ - defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -PNG_EXPORT(void,png_set_invert_alpha) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ -PNG_EXPORT(void,png_set_filler) PNGARG((png_structp png_ptr, - png_uint_32 filler, int flags)); -/* The values of the PNG_FILLER_ defines should NOT be changed */ -#define PNG_FILLER_BEFORE 0 -#define PNG_FILLER_AFTER 1 -/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ -PNG_EXPORT(void,png_set_add_alpha) PNGARG((png_structp png_ptr, - png_uint_32 filler, int flags)); -#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */ - -#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* Swap bytes in 16-bit depth files. */ -PNG_EXPORT(void,png_set_swap) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) -/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ -PNG_EXPORT(void,png_set_packing) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ - defined(PNG_WRITE_PACKSWAP_SUPPORTED) -/* Swap packing order of pixels in bytes. */ -PNG_EXPORT(void,png_set_packswap) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) -/* Converts files to legal bit depths. */ -PNG_EXPORT(void,png_set_shift) PNGARG((png_structp png_ptr, - png_color_8p true_bits)); -#endif - -#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ - defined(PNG_WRITE_INTERLACING_SUPPORTED) -/* Have the code handle the interlacing. Returns the number of passes. */ -PNG_EXPORT(int,png_set_interlace_handling) PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -/* Invert monochrome files */ -PNG_EXPORT(void,png_set_invert_mono) PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_READ_BACKGROUND_SUPPORTED -/* Handle alpha and tRNS by replacing with a background color. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXPORT(void,png_set_background) PNGARG((png_structp png_ptr, - png_color_16p background_color, int background_gamma_code, - int need_expand, double background_gamma)); -#endif -#define PNG_BACKGROUND_GAMMA_UNKNOWN 0 -#define PNG_BACKGROUND_GAMMA_SCREEN 1 -#define PNG_BACKGROUND_GAMMA_FILE 2 -#define PNG_BACKGROUND_GAMMA_UNIQUE 3 -#endif - -#ifdef PNG_READ_16_TO_8_SUPPORTED -/* Strip the second byte of information from a 16-bit depth file. */ -PNG_EXPORT(void,png_set_strip_16) PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_READ_QUANTIZE_SUPPORTED -/* Turn on quantizing, and reduce the palette to the number of colors - * available. Prior to libpng-1.4.2, this was png_set_dither(). - */ -PNG_EXPORT(void,png_set_quantize) PNGARG((png_structp png_ptr, - png_colorp palette, int num_palette, int maximum_colors, - png_uint_16p histogram, int full_quantize)); -#endif -/* This migration aid will be removed from libpng-1.5.0 */ -#define png_set_dither png_set_quantize - -#ifdef PNG_READ_GAMMA_SUPPORTED -/* Handle gamma correction. Screen_gamma=(display_exponent) */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXPORT(void,png_set_gamma) PNGARG((png_structp png_ptr, - double screen_gamma, double default_file_gamma)); -#endif -#endif - - -#ifdef PNG_WRITE_FLUSH_SUPPORTED -/* Set how many lines between output flushes - 0 for no flushing */ -PNG_EXPORT(void,png_set_flush) PNGARG((png_structp png_ptr, int nrows)); -/* Flush the current PNG output buffer */ -PNG_EXPORT(void,png_write_flush) PNGARG((png_structp png_ptr)); -#endif - -/* Optional update palette with requested transformations */ -PNG_EXPORT(void,png_start_read_image) PNGARG((png_structp png_ptr)); - -/* Optional call to update the users info structure */ -PNG_EXPORT(void,png_read_update_info) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read one or more rows of image data. */ -PNG_EXPORT(void,png_read_rows) PNGARG((png_structp png_ptr, - png_bytepp row, png_bytepp display_row, png_uint_32 num_rows)); -#endif - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read a row of data. */ -PNG_EXPORT(void,png_read_row) PNGARG((png_structp png_ptr, - png_bytep row, - png_bytep display_row)); -#endif - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the whole image into memory at once. */ -PNG_EXPORT(void,png_read_image) PNGARG((png_structp png_ptr, - png_bytepp image)); -#endif - -/* Write a row of image data */ -PNG_EXPORT(void,png_write_row) PNGARG((png_structp png_ptr, - png_bytep row)); - -/* Write a few rows of image data */ -PNG_EXPORT(void,png_write_rows) PNGARG((png_structp png_ptr, - png_bytepp row, png_uint_32 num_rows)); - -/* Write the image data */ -PNG_EXPORT(void,png_write_image) PNGARG((png_structp png_ptr, - png_bytepp image)); - -/* Write the end of the PNG file. */ -PNG_EXPORT(void,png_write_end) PNGARG((png_structp png_ptr, - png_infop info_ptr)); - -#ifdef PNG_SEQUENTIAL_READ_SUPPORTED -/* Read the end of the PNG file. */ -PNG_EXPORT(void,png_read_end) PNGARG((png_structp png_ptr, - png_infop info_ptr)); -#endif - -/* Free any memory associated with the png_info_struct */ -PNG_EXPORT(void,png_destroy_info_struct) PNGARG((png_structp png_ptr, - png_infopp info_ptr_ptr)); - -/* Free any memory associated with the png_struct and the png_info_structs */ -PNG_EXPORT(void,png_destroy_read_struct) PNGARG((png_structpp - png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); - -/* Free any memory associated with the png_struct and the png_info_structs */ -PNG_EXPORT(void,png_destroy_write_struct) - PNGARG((png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)); - -/* Set the libpng method of handling chunk CRC errors */ -PNG_EXPORT(void,png_set_crc_action) PNGARG((png_structp png_ptr, - int crit_action, int ancil_action)); - -/* Values for png_set_crc_action() to say how to handle CRC errors in - * ancillary and critical chunks, and whether to use the data contained - * therein. Note that it is impossible to "discard" data in a critical - * chunk. For versions prior to 0.90, the action was always error/quit, - * whereas in version 0.90 and later, the action for CRC errors in ancillary - * chunks is warn/discard. These values should NOT be changed. - * - * value action:critical action:ancillary - */ -#define PNG_CRC_DEFAULT 0 /* error/quit warn/discard data */ -#define PNG_CRC_ERROR_QUIT 1 /* error/quit error/quit */ -#define PNG_CRC_WARN_DISCARD 2 /* (INVALID) warn/discard data */ -#define PNG_CRC_WARN_USE 3 /* warn/use data warn/use data */ -#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */ -#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */ - -/* These functions give the user control over the scan-line filtering in - * libpng and the compression methods used by zlib. These functions are - * mainly useful for testing, as the defaults should work with most users. - * Those users who are tight on memory or want faster performance at the - * expense of compression can modify them. See the compression library - * header file (zlib.h) for an explination of the compression functions. - */ - -/* Set the filtering method(s) used by libpng. Currently, the only valid - * value for "method" is 0. - */ -PNG_EXPORT(void,png_set_filter) PNGARG((png_structp png_ptr, int method, - int filters)); - -/* Flags for png_set_filter() to say which filters to use. The flags - * are chosen so that they don't conflict with real filter types - * below, in case they are supplied instead of the #defined constants. - * These values should NOT be changed. - */ -#define PNG_NO_FILTERS 0x00 -#define PNG_FILTER_NONE 0x08 -#define PNG_FILTER_SUB 0x10 -#define PNG_FILTER_UP 0x20 -#define PNG_FILTER_AVG 0x40 -#define PNG_FILTER_PAETH 0x80 -#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ - PNG_FILTER_AVG | PNG_FILTER_PAETH) - -/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. - * These defines should NOT be changed. - */ -#define PNG_FILTER_VALUE_NONE 0 -#define PNG_FILTER_VALUE_SUB 1 -#define PNG_FILTER_VALUE_UP 2 -#define PNG_FILTER_VALUE_AVG 3 -#define PNG_FILTER_VALUE_PAETH 4 -#define PNG_FILTER_VALUE_LAST 5 - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */ -/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ - * defines, either the default (minimum-sum-of-absolute-differences), or - * the experimental method (weighted-minimum-sum-of-absolute-differences). - * - * Weights are factors >= 1.0, indicating how important it is to keep the - * filter type consistent between rows. Larger numbers mean the current - * filter is that many times as likely to be the same as the "num_weights" - * previous filters. This is cumulative for each previous row with a weight. - * There needs to be "num_weights" values in "filter_weights", or it can be - * NULL if the weights aren't being specified. Weights have no influence on - * the selection of the first row filter. Well chosen weights can (in theory) - * improve the compression for a given image. - * - * Costs are factors >= 1.0 indicating the relative decoding costs of a - * filter type. Higher costs indicate more decoding expense, and are - * therefore less likely to be selected over a filter with lower computational - * costs. There needs to be a value in "filter_costs" for each valid filter - * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't - * setting the costs. Costs try to improve the speed of decompression without - * unduly increasing the compressed image size. - * - * A negative weight or cost indicates the default value is to be used, and - * values in the range [0.0, 1.0) indicate the value is to remain unchanged. - * The default values for both weights and costs are currently 1.0, but may - * change if good general weighting/cost heuristics can be found. If both - * the weights and costs are set to 1.0, this degenerates the WEIGHTED method - * to the UNWEIGHTED method, but with added encoding time/computation. - */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXPORT(void,png_set_filter_heuristics) PNGARG((png_structp png_ptr, - int heuristic_method, int num_weights, png_doublep filter_weights, - png_doublep filter_costs)); -#endif -#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */ - -/* Heuristic used for row filter selection. These defines should NOT be - * changed. - */ -#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ -#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ -#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ -#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ - -/* Set the library compression level. Currently, valid values range from - * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 - * (0 - no compression, 9 - "maximal" compression). Note that tests have - * shown that zlib compression levels 3-6 usually perform as well as level 9 - * for PNG images, and do considerably fewer caclulations. In the future, - * these values may not correspond directly to the zlib compression levels. - */ -PNG_EXPORT(void,png_set_compression_level) PNGARG((png_structp png_ptr, - int level)); - -PNG_EXPORT(void,png_set_compression_mem_level) - PNGARG((png_structp png_ptr, int mem_level)); - -PNG_EXPORT(void,png_set_compression_strategy) - PNGARG((png_structp png_ptr, int strategy)); - -PNG_EXPORT(void,png_set_compression_window_bits) - PNGARG((png_structp png_ptr, int window_bits)); - -PNG_EXPORT(void,png_set_compression_method) PNGARG((png_structp png_ptr, - int method)); - -/* These next functions are called for input/output, memory, and error - * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, - * and call standard C I/O routines such as fread(), fwrite(), and - * fprintf(). These functions can be made to use other I/O routines - * at run time for those applications that need to handle I/O in a - * different manner by calling png_set_???_fn(). See libpng.txt for - * more information. - */ - -#ifdef PNG_STDIO_SUPPORTED -/* Initialize the input/output for the PNG file to the default functions. */ -PNG_EXPORT(void,png_init_io) PNGARG((png_structp png_ptr, - png_FILE_p fp)); -#endif - -/* Replace the (error and abort), and warning functions with user - * supplied functions. If no messages are to be printed you must still - * write and use replacement functions. The replacement error_fn should - * still do a longjmp to the last setjmp location if you are using this - * method of error handling. If error_fn or warning_fn is NULL, the - * default function will be used. - */ - -PNG_EXPORT(void,png_set_error_fn) PNGARG((png_structp png_ptr, - png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); - -/* Return the user pointer associated with the error functions */ -PNG_EXPORT(png_voidp,png_get_error_ptr) PNGARG((png_structp png_ptr)); - -/* Replace the default data output functions with a user supplied one(s). - * If buffered output is not used, then output_flush_fn can be set to NULL. - * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time - * output_flush_fn will be ignored (and thus can be NULL). - * It is probably a mistake to use NULL for output_flush_fn if - * write_data_fn is not also NULL unless you have built libpng with - * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's - * default flush function, which uses the standard *FILE structure, will - * be used. - */ -PNG_EXPORT(void,png_set_write_fn) PNGARG((png_structp png_ptr, - png_voidp io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); - -/* Replace the default data input function with a user supplied one. */ -PNG_EXPORT(void,png_set_read_fn) PNGARG((png_structp png_ptr, - png_voidp io_ptr, png_rw_ptr read_data_fn)); - -/* Return the user pointer associated with the I/O functions */ -PNG_EXPORT(png_voidp,png_get_io_ptr) PNGARG((png_structp png_ptr)); - -PNG_EXPORT(void,png_set_read_status_fn) PNGARG((png_structp png_ptr, - png_read_status_ptr read_row_fn)); - -PNG_EXPORT(void,png_set_write_status_fn) PNGARG((png_structp png_ptr, - png_write_status_ptr write_row_fn)); - -#ifdef PNG_USER_MEM_SUPPORTED -/* Replace the default memory allocation functions with user supplied one(s). */ -PNG_EXPORT(void,png_set_mem_fn) PNGARG((png_structp png_ptr, - png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); -/* Return the user pointer associated with the memory functions */ -PNG_EXPORT(png_voidp,png_get_mem_ptr) PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED -PNG_EXPORT(void,png_set_read_user_transform_fn) PNGARG((png_structp - png_ptr, png_user_transform_ptr read_user_transform_fn)); -#endif - -#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED -PNG_EXPORT(void,png_set_write_user_transform_fn) PNGARG((png_structp - png_ptr, png_user_transform_ptr write_user_transform_fn)); -#endif - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -PNG_EXPORT(void,png_set_user_transform_info) PNGARG((png_structp - png_ptr, png_voidp user_transform_ptr, int user_transform_depth, - int user_transform_channels)); -/* Return the user pointer associated with the user transform functions */ -PNG_EXPORT(png_voidp,png_get_user_transform_ptr) - PNGARG((png_structp png_ptr)); -#endif - -#ifdef PNG_USER_CHUNKS_SUPPORTED -PNG_EXPORT(void,png_set_read_user_chunk_fn) PNGARG((png_structp png_ptr, - png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); -PNG_EXPORT(png_voidp,png_get_user_chunk_ptr) PNGARG((png_structp - png_ptr)); -#endif - -#ifdef PNG_PROGRESSIVE_READ_SUPPORTED -/* Sets the function callbacks for the push reader, and a pointer to a - * user-defined structure available to the callback functions. - */ -PNG_EXPORT(void,png_set_progressive_read_fn) PNGARG((png_structp png_ptr, - png_voidp progressive_ptr, - png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, - png_progressive_end_ptr end_fn)); - -/* Returns the user pointer associated with the push read functions */ -PNG_EXPORT(png_voidp,png_get_progressive_ptr) - PNGARG((png_structp png_ptr)); - -/* Function to be called when data becomes available */ -PNG_EXPORT(void,png_process_data) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep buffer, png_size_t buffer_size)); - -/* Function that combines rows. Not very much different than the - * png_combine_row() call. Is this even used????? - */ -PNG_EXPORT(void,png_progressive_combine_row) PNGARG((png_structp png_ptr, - png_bytep old_row, png_bytep new_row)); -#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ - -PNG_EXPORT(png_voidp,png_malloc) PNGARG((png_structp png_ptr, - png_alloc_size_t size)) PNG_ALLOCATED; -/* Added at libpng version 1.4.0 */ -PNG_EXPORT(png_voidp,png_calloc) PNGARG((png_structp png_ptr, - png_alloc_size_t size)) PNG_ALLOCATED; - -/* Added at libpng version 1.2.4 */ -PNG_EXPORT(png_voidp,png_malloc_warn) PNGARG((png_structp png_ptr, - png_alloc_size_t size)) PNG_ALLOCATED; - -/* Frees a pointer allocated by png_malloc() */ -PNG_EXPORT(void,png_free) PNGARG((png_structp png_ptr, png_voidp ptr)); - -/* Free data that was allocated internally */ -PNG_EXPORT(void,png_free_data) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 free_me, int num)); -/* Reassign responsibility for freeing existing data, whether allocated - * by libpng or by the application */ -PNG_EXPORT(void,png_data_freer) PNGARG((png_structp png_ptr, - png_infop info_ptr, int freer, png_uint_32 mask)); -/* Assignments for png_data_freer */ -#define PNG_DESTROY_WILL_FREE_DATA 1 -#define PNG_SET_WILL_FREE_DATA 1 -#define PNG_USER_WILL_FREE_DATA 2 -/* Flags for png_ptr->free_me and info_ptr->free_me */ -#define PNG_FREE_HIST 0x0008 -#define PNG_FREE_ICCP 0x0010 -#define PNG_FREE_SPLT 0x0020 -#define PNG_FREE_ROWS 0x0040 -#define PNG_FREE_PCAL 0x0080 -#define PNG_FREE_SCAL 0x0100 -#define PNG_FREE_UNKN 0x0200 -#define PNG_FREE_LIST 0x0400 -#define PNG_FREE_PLTE 0x1000 -#define PNG_FREE_TRNS 0x2000 -#define PNG_FREE_TEXT 0x4000 -#define PNG_FREE_ALL 0x7fff -#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ - -#ifdef PNG_USER_MEM_SUPPORTED -PNG_EXPORT(png_voidp,png_malloc_default) PNGARG((png_structp png_ptr, - png_alloc_size_t size)) PNG_ALLOCATED; -PNG_EXPORT(void,png_free_default) PNGARG((png_structp png_ptr, - png_voidp ptr)); -#endif - -#ifndef PNG_NO_ERROR_TEXT -/* Fatal error in PNG image of libpng - can't continue */ -PNG_EXPORT(void,png_error) PNGARG((png_structp png_ptr, - png_const_charp error_message)) PNG_NORETURN; - -/* The same, but the chunk name is prepended to the error string. */ -PNG_EXPORT(void,png_chunk_error) PNGARG((png_structp png_ptr, - png_const_charp error_message)) PNG_NORETURN; - -#else -/* Fatal error in PNG image of libpng - can't continue */ -PNG_EXPORT(void,png_err) PNGARG((png_structp png_ptr)) PNG_NORETURN; -#endif - -/* Non-fatal error in libpng. Can continue, but may have a problem. */ -PNG_EXPORT(void,png_warning) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); - -/* Non-fatal error in libpng, chunk name is prepended to message. */ -PNG_EXPORT(void,png_chunk_warning) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); - -#ifdef PNG_BENIGN_ERRORS_SUPPORTED -/* Benign error in libpng. Can continue, but may have a problem. - * User can choose whether to handle as a fatal error or as a warning. */ -PNG_EXPORT(void,png_benign_error) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); - -/* Same, chunk name is prepended to message. */ -PNG_EXPORT(void,png_chunk_benign_error) PNGARG((png_structp png_ptr, - png_const_charp warning_message)); - -PNG_EXPORT(void,png_set_benign_errors) PNGARG((png_structp - png_ptr, int allowed)); -#endif - -/* The png_set_ functions are for storing values in the png_info_struct. - * Similarly, the png_get_ calls are used to read values from the - * png_info_struct, either storing the parameters in the passed variables, or - * setting pointers into the png_info_struct where the data is stored. The - * png_get_ functions return a non-zero value if the data was available - * in info_ptr, or return zero and do not change any of the parameters if the - * data was not available. - * - * These functions should be used instead of directly accessing png_info - * to avoid problems with future changes in the size and internal layout of - * png_info_struct. - */ -/* Returns "flag" if chunk data is valid in info_ptr. */ -PNG_EXPORT(png_uint_32,png_get_valid) PNGARG((png_structp png_ptr, -png_infop info_ptr, png_uint_32 flag)); - -/* Returns number of bytes needed to hold a transformed row. */ -PNG_EXPORT(png_size_t,png_get_rowbytes) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#ifdef PNG_INFO_IMAGE_SUPPORTED -/* Returns row_pointers, which is an array of pointers to scanlines that was - * returned from png_read_png(). - */ -PNG_EXPORT(png_bytepp,png_get_rows) PNGARG((png_structp png_ptr, -png_infop info_ptr)); -/* Set row_pointers, which is an array of pointers to scanlines for use - * by png_write_png(). - */ -PNG_EXPORT(void,png_set_rows) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytepp row_pointers)); -#endif - -/* Returns number of color channels in image. */ -PNG_EXPORT(png_byte,png_get_channels) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#ifdef PNG_EASY_ACCESS_SUPPORTED -/* Returns image width in pixels. */ -PNG_EXPORT(png_uint_32, png_get_image_width) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image height in pixels. */ -PNG_EXPORT(png_uint_32, png_get_image_height) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image bit_depth. */ -PNG_EXPORT(png_byte, png_get_bit_depth) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image color_type. */ -PNG_EXPORT(png_byte, png_get_color_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image filter_type. */ -PNG_EXPORT(png_byte, png_get_filter_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image interlace_type. */ -PNG_EXPORT(png_byte, png_get_interlace_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image compression_type. */ -PNG_EXPORT(png_byte, png_get_compression_type) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns image resolution in pixels per meter, from pHYs chunk data. */ -PNG_EXPORT(png_uint_32, png_get_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -/* Returns pixel aspect ratio, computed from pHYs chunk data. */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXPORT(float, png_get_pixel_aspect_ratio) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -#endif - -/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ -PNG_EXPORT(png_int_32, png_get_x_offset_pixels) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -PNG_EXPORT(png_int_32, png_get_y_offset_pixels) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -PNG_EXPORT(png_int_32, png_get_x_offset_microns) PNGARG((png_structp -png_ptr, png_infop info_ptr)); -PNG_EXPORT(png_int_32, png_get_y_offset_microns) PNGARG((png_structp -png_ptr, png_infop info_ptr)); - -#endif /* PNG_EASY_ACCESS_SUPPORTED */ - -/* Returns pointer to signature string read from PNG header */ -PNG_EXPORT(png_bytep,png_get_signature) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#ifdef PNG_bKGD_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_bKGD) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_16p *background)); -#endif - -#ifdef PNG_bKGD_SUPPORTED -PNG_EXPORT(void,png_set_bKGD) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_16p background)); -#endif - -#ifdef PNG_cHRM_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_cHRM) PNGARG((png_structp png_ptr, - png_infop info_ptr, double *white_x, double *white_y, double *red_x, - double *red_y, double *green_x, double *green_y, double *blue_x, - double *blue_y)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_cHRM_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point *int_white_x, png_fixed_point - *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y, - png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point - *int_blue_x, png_fixed_point *int_blue_y)); -#endif -#endif - -#ifdef PNG_cHRM_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXPORT(void,png_set_cHRM) PNGARG((png_structp png_ptr, - png_infop info_ptr, double white_x, double white_y, double red_x, - double red_y, double green_x, double green_y, double blue_x, double blue_y)); -#endif -#ifdef PNG_FIXED_POINT_SUPPORTED -PNG_EXPORT(void,png_set_cHRM_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point int_white_x, png_fixed_point int_white_y, - png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point - int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x, - png_fixed_point int_blue_y)); -#endif -#endif - -#ifdef PNG_gAMA_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_gAMA) PNGARG((png_structp png_ptr, - png_infop info_ptr, double *file_gamma)); -#endif -PNG_EXPORT(png_uint_32,png_get_gAMA_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point *int_file_gamma)); -#endif - -#ifdef PNG_gAMA_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXPORT(void,png_set_gAMA) PNGARG((png_structp png_ptr, - png_infop info_ptr, double file_gamma)); -#endif -PNG_EXPORT(void,png_set_gAMA_fixed) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_fixed_point int_file_gamma)); -#endif - -#ifdef PNG_hIST_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_hIST) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_16p *hist)); -#endif - -#ifdef PNG_hIST_SUPPORTED -PNG_EXPORT(void,png_set_hIST) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_16p hist)); -#endif - -PNG_EXPORT(png_uint_32,png_get_IHDR) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 *width, png_uint_32 *height, - int *bit_depth, int *color_type, int *interlace_method, - int *compression_method, int *filter_method)); - -PNG_EXPORT(void,png_set_IHDR) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, - int color_type, int interlace_method, int compression_method, - int filter_method)); - -#ifdef PNG_oFFs_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_oFFs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, - int *unit_type)); -#endif - -#ifdef PNG_oFFs_SUPPORTED -PNG_EXPORT(void,png_set_oFFs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_int_32 offset_x, png_int_32 offset_y, - int unit_type)); -#endif - -#ifdef PNG_pCAL_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_pCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp *purpose, png_int_32 *X0, png_int_32 *X1, - int *type, int *nparams, png_charp *units, png_charpp *params)); -#endif - -#ifdef PNG_pCAL_SUPPORTED -PNG_EXPORT(void,png_set_pCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp purpose, png_int_32 X0, png_int_32 X1, - int type, int nparams, png_charp units, png_charpp params)); -#endif - -#ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_pHYs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); -#endif - -#ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(void,png_set_pHYs) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); -#endif - -PNG_EXPORT(png_uint_32,png_get_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_colorp *palette, int *num_palette)); - -PNG_EXPORT(void,png_set_PLTE) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_colorp palette, int num_palette)); - -#ifdef PNG_sBIT_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_sBIT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_8p *sig_bit)); -#endif - -#ifdef PNG_sBIT_SUPPORTED -PNG_EXPORT(void,png_set_sBIT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_color_8p sig_bit)); -#endif - -#ifdef PNG_sRGB_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_sRGB) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *intent)); -#endif - -#ifdef PNG_sRGB_SUPPORTED -PNG_EXPORT(void,png_set_sRGB) PNGARG((png_structp png_ptr, - png_infop info_ptr, int intent)); -PNG_EXPORT(void,png_set_sRGB_gAMA_and_cHRM) PNGARG((png_structp png_ptr, - png_infop info_ptr, int intent)); -#endif - -#ifdef PNG_iCCP_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_iCCP) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charpp name, int *compression_type, - png_charpp profile, png_uint_32 *proflen)); - /* Note to maintainer: profile should be png_bytepp */ -#endif - -#ifdef PNG_iCCP_SUPPORTED -PNG_EXPORT(void,png_set_iCCP) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_charp name, int compression_type, - png_charp profile, png_uint_32 proflen)); - /* Note to maintainer: profile should be png_bytep */ -#endif - -#ifdef PNG_sPLT_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_sPLT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_sPLT_tpp entries)); -#endif - -#ifdef PNG_sPLT_SUPPORTED -PNG_EXPORT(void,png_set_sPLT) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_sPLT_tp entries, int nentries)); -#endif - -#ifdef PNG_TEXT_SUPPORTED -/* png_get_text also returns the number of text chunks in *num_text */ -PNG_EXPORT(png_uint_32,png_get_text) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_textp *text_ptr, int *num_text)); -#endif - -/* Note while png_set_text() will accept a structure whose text, - * language, and translated keywords are NULL pointers, the structure - * returned by png_get_text will always contain regular - * zero-terminated C strings. They might be empty strings but - * they will never be NULL pointers. - */ - -#ifdef PNG_TEXT_SUPPORTED -PNG_EXPORT(void,png_set_text) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_textp text_ptr, int num_text)); -#endif - -#ifdef PNG_tIME_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_tIME) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_timep *mod_time)); -#endif - -#ifdef PNG_tIME_SUPPORTED -PNG_EXPORT(void,png_set_tIME) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_timep mod_time)); -#endif - -#ifdef PNG_tRNS_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_tRNS) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep *trans_alpha, int *num_trans, - png_color_16p *trans_color)); -#endif - -#ifdef PNG_tRNS_SUPPORTED -PNG_EXPORT(void,png_set_tRNS) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_bytep trans_alpha, int num_trans, - png_color_16p trans_color)); -#endif - -#ifdef PNG_tRNS_SUPPORTED -#endif - -#ifdef PNG_sCAL_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_sCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *unit, double *width, double *height)); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_sCAL_s) PNGARG((png_structp png_ptr, - png_infop info_ptr, int *unit, png_charpp swidth, png_charpp sheight)); -#endif -#endif -#endif /* PNG_sCAL_SUPPORTED */ - -#ifdef PNG_sCAL_SUPPORTED -#ifdef PNG_FLOATING_POINT_SUPPORTED -PNG_EXPORT(void,png_set_sCAL) PNGARG((png_structp png_ptr, - png_infop info_ptr, int unit, double width, double height)); -#else -#ifdef PNG_FIXED_POINT_SUPPORTED -PNG_EXPORT(void,png_set_sCAL_s) PNGARG((png_structp png_ptr, - png_infop info_ptr, int unit, png_charp swidth, png_charp sheight)); -#endif -#endif -#endif /* PNG_sCAL_SUPPORTED || PNG_WRITE_sCAL_SUPPORTED */ - -#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -/* Provide a list of chunks and how they are to be handled, if the built-in - handling or default unknown chunk handling is not desired. Any chunks not - listed will be handled in the default manner. The IHDR and IEND chunks - must not be listed. - keep = 0: follow default behaviour - = 1: do not keep - = 2: keep only if safe-to-copy - = 3: keep even if unsafe-to-copy -*/ -PNG_EXPORT(void, png_set_keep_unknown_chunks) PNGARG((png_structp - png_ptr, int keep, png_bytep chunk_list, int num_chunks)); -PNG_EXPORT(int,png_handle_as_unknown) PNGARG((png_structp png_ptr, png_bytep - chunk_name)); -#endif -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED -PNG_EXPORT(void, png_set_unknown_chunks) PNGARG((png_structp png_ptr, - png_infop info_ptr, png_unknown_chunkp unknowns, int num_unknowns)); -PNG_EXPORT(void, png_set_unknown_chunk_location) - PNGARG((png_structp png_ptr, png_infop info_ptr, int chunk, int location)); -PNG_EXPORT(png_uint_32,png_get_unknown_chunks) PNGARG((png_structp - png_ptr, png_infop info_ptr, png_unknown_chunkpp entries)); -#endif - -/* Png_free_data() will turn off the "valid" flag for anything it frees. - * If you need to turn it off for a chunk that your application has freed, - * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); - */ -PNG_EXPORT(void, png_set_invalid) PNGARG((png_structp png_ptr, - png_infop info_ptr, int mask)); - -#ifdef PNG_INFO_IMAGE_SUPPORTED -/* The "params" pointer is currently not used and is for future expansion. */ -PNG_EXPORT(void, png_read_png) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int transforms, - png_voidp params)); -PNG_EXPORT(void, png_write_png) PNGARG((png_structp png_ptr, - png_infop info_ptr, - int transforms, - png_voidp params)); -#endif - -PNG_EXPORT(png_charp,png_get_copyright) PNGARG((png_structp png_ptr)); -PNG_EXPORT(png_charp,png_get_header_ver) PNGARG((png_structp png_ptr)); -PNG_EXPORT(png_charp,png_get_header_version) PNGARG((png_structp - png_ptr)); -PNG_EXPORT(png_charp,png_get_libpng_ver) PNGARG((png_structp png_ptr)); - -#ifdef PNG_MNG_FEATURES_SUPPORTED -PNG_EXPORT(png_uint_32,png_permit_mng_features) PNGARG((png_structp - png_ptr, png_uint_32 mng_features_permitted)); -#endif - -/* For use in png_set_keep_unknown, added to version 1.2.6 */ -#define PNG_HANDLE_CHUNK_AS_DEFAULT 0 -#define PNG_HANDLE_CHUNK_NEVER 1 -#define PNG_HANDLE_CHUNK_IF_SAFE 2 -#define PNG_HANDLE_CHUNK_ALWAYS 3 - -/* Strip the prepended error numbers ("#nnn ") from error and warning - * messages before passing them to the error or warning handler. - */ -#ifdef PNG_ERROR_NUMBERS_SUPPORTED -PNG_EXPORT(void,png_set_strip_error_numbers) PNGARG((png_structp - png_ptr, png_uint_32 strip_mode)); -#endif - -/* Added in libpng-1.2.6 */ -#ifdef PNG_SET_USER_LIMITS_SUPPORTED -PNG_EXPORT(void,png_set_user_limits) PNGARG((png_structp - png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); -PNG_EXPORT(png_uint_32,png_get_user_width_max) PNGARG((png_structp - png_ptr)); -PNG_EXPORT(png_uint_32,png_get_user_height_max) PNGARG((png_structp - png_ptr)); -/* Added in libpng-1.4.0 */ -PNG_EXPORT(void,png_set_chunk_cache_max) PNGARG((png_structp - png_ptr, png_uint_32 user_chunk_cache_max)); -PNG_EXPORT(png_uint_32,png_get_chunk_cache_max) - PNGARG((png_structp png_ptr)); -/* Added in libpng-1.4.1 */ -PNG_EXPORT(void,png_set_chunk_malloc_max) PNGARG((png_structp - png_ptr, png_alloc_size_t user_chunk_cache_max)); -PNG_EXPORT(png_alloc_size_t,png_get_chunk_malloc_max) - PNGARG((png_structp png_ptr)); -#endif - -#if defined(PNG_INCH_CONVERSIONS) && defined(PNG_FLOATING_POINT_SUPPORTED) -PNG_EXPORT(png_uint_32,png_get_pixels_per_inch) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -PNG_EXPORT(png_uint_32,png_get_x_pixels_per_inch) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -PNG_EXPORT(png_uint_32,png_get_y_pixels_per_inch) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -PNG_EXPORT(float,png_get_x_offset_inches) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -PNG_EXPORT(float,png_get_y_offset_inches) PNGARG((png_structp png_ptr, -png_infop info_ptr)); - -#ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_pHYs_dpi) PNGARG((png_structp png_ptr, -png_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); -#endif /* PNG_pHYs_SUPPORTED */ -#endif /* PNG_INCH_CONVERSIONS && PNG_FLOATING_POINT_SUPPORTED */ - -/* Added in libpng-1.4.0 */ -#ifdef PNG_IO_STATE_SUPPORTED -PNG_EXPORT(png_uint_32,png_get_io_state) PNGARG((png_structp png_ptr)); - -PNG_EXPORT(png_bytep,png_get_io_chunk_name) - PNGARG((png_structp png_ptr)); - -/* The flags returned by png_get_io_state() are the following: */ -#define PNG_IO_NONE 0x0000 /* no I/O at this moment */ -#define PNG_IO_READING 0x0001 /* currently reading */ -#define PNG_IO_WRITING 0x0002 /* currently writing */ -#define PNG_IO_SIGNATURE 0x0010 /* currently at the file signature */ -#define PNG_IO_CHUNK_HDR 0x0020 /* currently at the chunk header */ -#define PNG_IO_CHUNK_DATA 0x0040 /* currently at the chunk data */ -#define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */ -#define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */ -#define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */ -#endif /* ?PNG_IO_STATE_SUPPORTED */ - -/* Maintainer: Put new public prototypes here ^, in libpng.3, and project - * defs - */ - -#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED -/* With these routines we avoid an integer divide, which will be slower on - * most machines. However, it does take more operations than the corresponding - * divide method, so it may be slower on a few RISC systems. There are two - * shifts (by 8 or 16 bits) and an addition, versus a single integer divide. - * - * Note that the rounding factors are NOT supposed to be the same! 128 and - * 32768 are correct for the NODIV code; 127 and 32767 are correct for the - * standard method. - * - * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ] - */ - - /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ - -# define png_composite(composite, fg, alpha, bg) \ - { png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ - * (png_uint_16)(alpha) \ - + (png_uint_16)(bg)*(png_uint_16)(255 \ - - (png_uint_16)(alpha)) + (png_uint_16)128); \ - (composite) = (png_byte)((temp + (temp >> 8)) >> 8); } - -# define png_composite_16(composite, fg, alpha, bg) \ - { png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ - * (png_uint_32)(alpha) \ - + (png_uint_32)(bg)*(png_uint_32)(65535L \ - - (png_uint_32)(alpha)) + (png_uint_32)32768L); \ - (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); } - -#else /* Standard method using integer division */ - -# define png_composite(composite, fg, alpha, bg) \ - (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \ - (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \ - (png_uint_16)127) / 255) - -# define png_composite_16(composite, fg, alpha, bg) \ - (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \ - (png_uint_32)(bg)*(png_uint_32)(65535L - (png_uint_32)(alpha)) + \ - (png_uint_32)32767) / (png_uint_32)65535L) -#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */ - -#ifdef PNG_USE_READ_MACROS -/* Inline macros to do direct reads of bytes from the input buffer. - * The png_get_int_32() routine assumes we are using two's complement - * format for negative values, which is almost certainly true. - */ -# define png_get_uint_32(buf) \ - (((png_uint_32)(*(buf)) << 24) + \ - ((png_uint_32)(*((buf) + 1)) << 16) + \ - ((png_uint_32)(*((buf) + 2)) << 8) + \ - ((png_uint_32)(*((buf) + 3)))) -# define png_get_uint_16(buf) \ - (((png_uint_32)(*(buf)) << 8) + \ - ((png_uint_32)(*((buf) + 1)))) -# define png_get_int_32(buf) \ - ((png_int_32)((*(buf) & 0x80) \ - ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffff)+1)) \ - : (png_int_32)png_get_uint_32(buf))) -#else -PNG_EXPORT(png_uint_32,png_get_uint_32) PNGARG((png_bytep buf)); -PNG_EXPORT(png_uint_16,png_get_uint_16) PNGARG((png_bytep buf)); -#ifdef PNG_GET_INT_32_SUPPORTED -PNG_EXPORT(png_int_32,png_get_int_32) PNGARG((png_bytep buf)); -#endif -#endif -PNG_EXPORT(png_uint_32,png_get_uint_31) - PNGARG((png_structp png_ptr, png_bytep buf)); -/* No png_get_int_16 -- may be added if there's a real need for it. */ - -/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ -PNG_EXPORT(void,png_save_uint_32) - PNGARG((png_bytep buf, png_uint_32 i)); -PNG_EXPORT(void,png_save_int_32) - PNGARG((png_bytep buf, png_int_32 i)); - -/* Place a 16-bit number into a buffer in PNG byte order. - * The parameter is declared unsigned int, not png_uint_16, - * just to avoid potential problems on pre-ANSI C compilers. - */ -PNG_EXPORT(void,png_save_uint_16) - PNGARG((png_bytep buf, unsigned int i)); -/* No png_save_int_16 -- may be added if there's a real need for it. */ - -/* ************************************************************************* */ - -/* Various modes of operation. Note that after an init, mode is set to - * zero automatically when the structure is created. - */ -#define PNG_HAVE_IHDR 0x01 -#define PNG_HAVE_PLTE 0x02 -#define PNG_HAVE_IDAT 0x04 -#define PNG_AFTER_IDAT 0x08 /* Have complete zlib datastream */ -#define PNG_HAVE_IEND 0x10 -#define PNG_HAVE_gAMA 0x20 -#define PNG_HAVE_cHRM 0x40 - -#ifdef __cplusplus -} -#endif - -#endif /* PNG_VERSION_INFO_ONLY */ -/* Do not put anything past this line */ -#endif /* PNG_H */ diff --git a/inc/pngconf.h b/inc/pngconf.h deleted file mode 100644 index 41b13e9..0000000 --- a/inc/pngconf.h +++ /dev/null @@ -1,1540 +0,0 @@ - -/* pngconf.h - machine configurable file for libpng - * - * libpng version 1.4.4 - September 23, 2010 - * For conditions of distribution and use, see copyright notice in png.h - * Copyright (c) 1998-2010 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.) - * - * This code is released under the libpng license. - * For conditions of distribution and use, see the disclaimer - * and license in png.h - * - */ - -/* Any machine specific code is near the front of this file, so if you - * are configuring libpng for a machine, you may want to read the section - * starting here down to where it starts to typedef png_color, png_text, - * and png_info. - */ - -#ifndef PNGCONF_H -#define PNGCONF_H - -#ifndef PNG_NO_LIMITS_H -# include -#endif - -/* Added at libpng-1.2.9 */ - -/* config.h is created by and PNG_CONFIGURE_LIBPNG is set by the "configure" - * script. - */ -#ifdef PNG_CONFIGURE_LIBPNG -# ifdef HAVE_CONFIG_H -# include "config.h" -# endif -#endif - -/* - * Added at libpng-1.2.8 - * - * PNG_USER_CONFIG has to be defined on the compiler command line. This - * includes the resource compiler for Windows DLL configurations. - */ -#ifdef PNG_USER_CONFIG -# include "pngusr.h" -# ifndef PNG_USER_PRIVATEBUILD -# define PNG_USER_PRIVATEBUILD -# endif -#endif - -/* - * If you create a private DLL you should define in "pngusr.h" the following: - * #define PNG_USER_PRIVATEBUILD - * e.g. #define PNG_USER_PRIVATEBUILD "Build by MyCompany for xyz reasons." - * #define PNG_USER_DLLFNAME_POSTFIX - * e.g. // private DLL "libpng14gx.dll" - * #define PNG_USER_DLLFNAME_POSTFIX "gx" - * - * The following macros are also at your disposal if you want to complete the - * DLL VERSIONINFO structure. - * - PNG_USER_VERSIONINFO_COMMENTS - * - PNG_USER_VERSIONINFO_COMPANYNAME - * - PNG_USER_VERSIONINFO_LEGALTRADEMARKS - */ - -#ifdef __STDC__ -# ifdef SPECIALBUILD -# pragma message("PNG_LIBPNG_SPECIALBUILD (and deprecated SPECIALBUILD)\ - are now LIBPNG reserved macros. Use PNG_USER_PRIVATEBUILD instead.") -# endif - -# ifdef PRIVATEBUILD -# pragma message("PRIVATEBUILD is deprecated.\ - Use PNG_USER_PRIVATEBUILD instead.") -# define PNG_USER_PRIVATEBUILD PRIVATEBUILD -# endif -#endif /* __STDC__ */ - -/* End of material added to libpng-1.2.8 */ - -#ifndef PNG_VERSION_INFO_ONLY - -/* This is the size of the compression buffer, and thus the size of - * an IDAT chunk. Make this whatever size you feel is best for your - * machine. One of these will be allocated per png_struct. When this - * is full, it writes the data to the disk, and does some other - * calculations. Making this an extremely small size will slow - * the library down, but you may want to experiment to determine - * where it becomes significant, if you are concerned with memory - * usage. Note that zlib allocates at least 32Kb also. For readers, - * this describes the size of the buffer available to read the data in. - * Unless this gets smaller than the size of a row (compressed), - * it should not make much difference how big this is. - */ - -#ifndef PNG_ZBUF_SIZE -# define PNG_ZBUF_SIZE 8192 -#endif - -/* Enable if you want a write-only libpng */ - -#ifndef PNG_NO_READ_SUPPORTED -# define PNG_READ_SUPPORTED -#endif - -/* Enable if you want a read-only libpng */ - -#ifndef PNG_NO_WRITE_SUPPORTED -# define PNG_WRITE_SUPPORTED -#endif - -/* Enabled in 1.4.0. */ -#ifdef PNG_ALLOW_BENIGN_ERRORS -# define png_benign_error png_warning -# define png_chunk_benign_error png_chunk_warning -#else -# ifndef PNG_BENIGN_ERRORS_SUPPORTED -# define png_benign_error png_error -# define png_chunk_benign_error png_chunk_error -# endif -#endif - -/* Added at libpng version 1.4.0 */ -#if !defined(PNG_NO_WARNINGS) && !defined(PNG_WARNINGS_SUPPORTED) -# define PNG_WARNINGS_SUPPORTED -#endif - -/* Added at libpng version 1.4.0 */ -#if !defined(PNG_NO_ERROR_TEXT) && !defined(PNG_ERROR_TEXT_SUPPORTED) -# define PNG_ERROR_TEXT_SUPPORTED -#endif - -/* Added at libpng version 1.4.0 */ -#if !defined(PNG_NO_CHECK_cHRM) && !defined(PNG_CHECK_cHRM_SUPPORTED) -# define PNG_CHECK_cHRM_SUPPORTED -#endif - -/* Added at libpng version 1.4.0 */ -#if !defined(PNG_NO_ALIGNED_MEMORY) && !defined(PNG_ALIGNED_MEMORY_SUPPORTED) -# define PNG_ALIGNED_MEMORY_SUPPORTED -#endif - -/* Enabled by default in 1.2.0. You can disable this if you don't need to - support PNGs that are embedded in MNG datastreams */ -#ifndef PNG_NO_MNG_FEATURES -# ifndef PNG_MNG_FEATURES_SUPPORTED -# define PNG_MNG_FEATURES_SUPPORTED -# endif -#endif - -/* Added at libpng version 1.4.0 */ -#ifndef PNG_NO_FLOATING_POINT_SUPPORTED -# ifndef PNG_FLOATING_POINT_SUPPORTED -# define PNG_FLOATING_POINT_SUPPORTED -# endif -#endif - -/* Added at libpng-1.4.0beta49 for testing (this test is no longer used - in libpng and png_calloc() is always present) - */ -#define PNG_CALLOC_SUPPORTED - -/* If you are running on a machine where you cannot allocate more - * than 64K of memory at once, uncomment this. While libpng will not - * normally need that much memory in a chunk (unless you load up a very - * large file), zlib needs to know how big of a chunk it can use, and - * libpng thus makes sure to check any memory allocation to verify it - * will fit into memory. -#define PNG_MAX_MALLOC_64K - */ -#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) -# define PNG_MAX_MALLOC_64K -#endif - -/* Special munging to support doing things the 'cygwin' way: - * 'Normal' png-on-win32 defines/defaults: - * PNG_BUILD_DLL -- building dll - * PNG_USE_DLL -- building an application, linking to dll - * (no define) -- building static library, or building an - * application and linking to the static lib - * 'Cygwin' defines/defaults: - * PNG_BUILD_DLL -- (ignored) building the dll - * (no define) -- (ignored) building an application, linking to the dll - * PNG_STATIC -- (ignored) building the static lib, or building an - * application that links to the static lib. - * ALL_STATIC -- (ignored) building various static libs, or building an - * application that links to the static libs. - * Thus, - * a cygwin user should define either PNG_BUILD_DLL or PNG_STATIC, and - * this bit of #ifdefs will define the 'correct' config variables based on - * that. If a cygwin user *wants* to define 'PNG_USE_DLL' that's okay, but - * unnecessary. - * - * Also, the precedence order is: - * ALL_STATIC (since we can't #undef something outside our namespace) - * PNG_BUILD_DLL - * PNG_STATIC - * (nothing) == PNG_USE_DLL - * - * CYGWIN (2002-01-20): The preceding is now obsolete. With the advent - * of auto-import in binutils, we no longer need to worry about - * __declspec(dllexport) / __declspec(dllimport) and friends. Therefore, - * we don't need to worry about PNG_STATIC or ALL_STATIC when it comes - * to __declspec() stuff. However, we DO need to worry about - * PNG_BUILD_DLL and PNG_STATIC because those change some defaults - * such as CONSOLE_IO. - */ -#ifdef __CYGWIN__ -# ifdef ALL_STATIC -# ifdef PNG_BUILD_DLL -# undef PNG_BUILD_DLL -# endif -# ifdef PNG_USE_DLL -# undef PNG_USE_DLL -# endif -# ifdef PNG_DLL -# undef PNG_DLL -# endif -# ifndef PNG_STATIC -# define PNG_STATIC -# endif -# else -# ifdef PNG_BUILD_DLL -# ifdef PNG_STATIC -# undef PNG_STATIC -# endif -# ifdef PNG_USE_DLL -# undef PNG_USE_DLL -# endif -# ifndef PNG_DLL -# define PNG_DLL -# endif -# else -# ifdef PNG_STATIC -# ifdef PNG_USE_DLL -# undef PNG_USE_DLL -# endif -# ifdef PNG_DLL -# undef PNG_DLL -# endif -# else -# ifndef PNG_USE_DLL -# define PNG_USE_DLL -# endif -# ifndef PNG_DLL -# define PNG_DLL -# endif -# endif -# endif -# endif -#endif - -/* This protects us against compilers that run on a windowing system - * and thus don't have or would rather us not use the stdio types: - * stdin, stdout, and stderr. The only one currently used is stderr - * in png_error() and png_warning(). #defining PNG_NO_CONSOLE_IO will - * prevent these from being compiled and used. #defining PNG_NO_STDIO - * will also prevent these, plus will prevent the entire set of stdio - * macros and functions (FILE *, printf, etc.) from being compiled and used, - * unless (PNG_DEBUG > 0) has been #defined. - * - * #define PNG_NO_CONSOLE_IO - * #define PNG_NO_STDIO - */ - -#ifdef _WIN32_WCE -# define PNG_NO_CONSOLE_IO -# define PNG_NO_STDIO -# define PNG_NO_TIME_RFC1123 -# ifdef PNG_DEBUG -# undef PNG_DEBUG -# endif -#endif - -#if !defined(PNG_NO_STDIO) && !defined(PNG_STDIO_SUPPORTED) -# define PNG_STDIO_SUPPORTED -#endif - -#ifdef PNG_BUILD_DLL -# if !defined(PNG_CONSOLE_IO_SUPPORTED) && !defined(PNG_NO_CONSOLE_IO) -# define PNG_NO_CONSOLE_IO -# endif -#endif - -# ifdef PNG_NO_STDIO -# ifndef PNG_NO_CONSOLE_IO -# define PNG_NO_CONSOLE_IO -# endif -# ifdef PNG_DEBUG -# if (PNG_DEBUG > 0) -# include -# endif -# endif -# else -# include -# endif - -#if !(defined PNG_NO_CONSOLE_IO) && !defined(PNG_CONSOLE_IO_SUPPORTED) -# define PNG_CONSOLE_IO_SUPPORTED -#endif - -/* This macro protects us against machines that don't have function - * prototypes (ie K&R style headers). If your compiler does not handle - * function prototypes, define this macro and use the included ansi2knr. - * I've always been able to use _NO_PROTO as the indicator, but you may - * need to drag the empty declaration out in front of here, or change the - * ifdef to suit your own needs. - */ -#ifndef PNGARG - -#ifdef OF /* zlib prototype munger */ -# define PNGARG(arglist) OF(arglist) -#else - -#ifdef _NO_PROTO -# define PNGARG(arglist) () -#else -# define PNGARG(arglist) arglist -#endif /* _NO_PROTO */ - -#endif /* OF */ - -#endif /* PNGARG */ - -/* Try to determine if we are compiling on a Mac. Note that testing for - * just __MWERKS__ is not good enough, because the Codewarrior is now used - * on non-Mac platforms. - */ -#ifndef MACOS -# if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \ - defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC) -# define MACOS -# endif -#endif - -/* Enough people need this for various reasons to include it here */ -#if !defined(MACOS) && !defined(RISCOS) -# include -#endif - -/* PNG_SETJMP_NOT_SUPPORTED and PNG_NO_SETJMP_SUPPORTED are deprecated. */ -#if !defined(PNG_NO_SETJMP) && \ - !defined(PNG_SETJMP_NOT_SUPPORTED) && !defined(PNG_NO_SETJMP_SUPPORTED) -# define PNG_SETJMP_SUPPORTED -#endif - -#ifdef PNG_SETJMP_SUPPORTED -/* This is an attempt to force a single setjmp behaviour on Linux. If - * the X config stuff didn't define _BSD_SOURCE we wouldn't need this. - * - * You can bypass this test if you know that your application uses exactly - * the same setjmp.h that was included when libpng was built. Only define - * PNG_SKIP_SETJMP_CHECK while building your application, prior to the - * application's '#include "png.h"'. Don't define PNG_SKIP_SETJMP_CHECK - * while building a separate libpng library for general use. - */ - -# ifndef PNG_SKIP_SETJMP_CHECK -# ifdef __linux__ -# ifdef _BSD_SOURCE -# define PNG_SAVE_BSD_SOURCE -# undef _BSD_SOURCE -# endif -# ifdef _SETJMP_H - /* If you encounter a compiler error here, see the explanation - * near the end of INSTALL. - */ - __pngconf.h__ in libpng already includes setjmp.h; - __dont__ include it again.; -# endif -# endif /* __linux__ */ -# endif /* PNG_SKIP_SETJMP_CHECK */ - - /* Include setjmp.h for error handling */ -# include - -# ifdef __linux__ -# ifdef PNG_SAVE_BSD_SOURCE -# ifdef _BSD_SOURCE -# undef _BSD_SOURCE -# endif -# define _BSD_SOURCE -# undef PNG_SAVE_BSD_SOURCE -# endif -# endif /* __linux__ */ -#endif /* PNG_SETJMP_SUPPORTED */ - -#ifdef BSD -# include -#else -# include -#endif - -/* Other defines for things like memory and the like can go here. */ - -/* This controls how fine the quantizing gets. As this allocates - * a largish chunk of memory (32K), those who are not as concerned - * with quantizing quality can decrease some or all of these. - */ - -/* Prior to libpng-1.4.2, these were PNG_DITHER_*_BITS - * These migration aids will be removed from libpng-1.5.0. - */ -#ifdef PNG_DITHER_RED_BITS -# define PNG_QUANTIZE_RED_BITS PNG_DITHER_RED_BITS -#endif -#ifdef PNG_DITHER_GREEN_BITS -# define PNG_QUANTIZE_GREEN_BITS PNG_DITHER_GREEN_BITS -#endif -#ifdef PNG_DITHER_BLUE_BITS -# define PNG_QUANTIZE_BLUE_BITS PNG_DITHER_BLUE_BITS -#endif - -#ifndef PNG_QUANTIZE_RED_BITS -# define PNG_QUANTIZE_RED_BITS 5 -#endif -#ifndef PNG_QUANTIZE_GREEN_BITS -# define PNG_QUANTIZE_GREEN_BITS 5 -#endif -#ifndef PNG_QUANTIZE_BLUE_BITS -# define PNG_QUANTIZE_BLUE_BITS 5 -#endif - -/* This controls how fine the gamma correction becomes when you - * are only interested in 8 bits anyway. Increasing this value - * results in more memory being used, and more pow() functions - * being called to fill in the gamma tables. Don't set this value - * less then 8, and even that may not work (I haven't tested it). - */ - -#ifndef PNG_MAX_GAMMA_8 -# define PNG_MAX_GAMMA_8 11 -#endif - -/* This controls how much a difference in gamma we can tolerate before - * we actually start doing gamma conversion. - */ -#ifndef PNG_GAMMA_THRESHOLD -# define PNG_GAMMA_THRESHOLD 0.05 -#endif - -/* The following uses const char * instead of char * for error - * and warning message functions, so some compilers won't complain. - * If you do not want to use const, define PNG_NO_CONST. - */ - -#ifndef PNG_CONST -# ifndef PNG_NO_CONST -# define PNG_CONST const -# else -# define PNG_CONST -# endif -#endif - -/* The following defines give you the ability to remove code from the - * library that you will not be using. I wish I could figure out how to - * automate this, but I can't do that without making it seriously hard - * on the users. So if you are not using an ability, change the #define - * to an #undef, or pass in PNG_NO_feature and that part of the library - * will not be compiled. - - * If your linker can't find a function, you may want to make sure the - * ability is defined here. Some of these depend upon some others being - * defined. I haven't figured out all the interactions here, so you may - * have to experiment awhile to get everything to compile. If you are - * creating or using a shared library, you probably shouldn't touch this, - * as it will affect the size of the structures, and this will cause bad - * things to happen if the library and/or application ever change. - */ - -/* Any features you will not be using can be undef'ed here */ - -/* GR-P, 0.96a: Set "*TRANSFORMS_SUPPORTED as default but allow user - * to turn it off with PNG_NO_READ|WRITE_TRANSFORMS on the compile line, - * then pick and choose which ones to define without having to edit this - * file. It is safe to use the PNG_NO_READ|WRITE_TRANSFORMS - * if you only want to have a png-compliant reader/writer but don't need - * any of the extra transformations. This saves about 80 kbytes in a - * typical installation of the library. (PNG_NO_* form added in version - * 1.0.1c, for consistency; PNG_*_TRANSFORMS_NOT_SUPPORTED deprecated in - * 1.4.0) - */ - -/* Ignore attempt to turn off both floating and fixed point support */ -#if !defined(PNG_FLOATING_POINT_SUPPORTED) || \ - !defined(PNG_NO_FIXED_POINT_SUPPORTED) -# define PNG_FIXED_POINT_SUPPORTED -#endif - -#ifdef PNG_READ_SUPPORTED - -/* PNG_READ_TRANSFORMS_NOT_SUPPORTED is deprecated. */ -#if !defined(PNG_READ_TRANSFORMS_NOT_SUPPORTED) && \ - !defined(PNG_NO_READ_TRANSFORMS) -# define PNG_READ_TRANSFORMS_SUPPORTED -#endif - -#ifdef PNG_READ_TRANSFORMS_SUPPORTED -# ifndef PNG_NO_READ_EXPAND -# define PNG_READ_EXPAND_SUPPORTED -# endif -# ifndef PNG_NO_READ_SHIFT -# define PNG_READ_SHIFT_SUPPORTED -# endif -# ifndef PNG_NO_READ_PACK -# define PNG_READ_PACK_SUPPORTED -# endif -# ifndef PNG_NO_READ_BGR -# define PNG_READ_BGR_SUPPORTED -# endif -# ifndef PNG_NO_READ_SWAP -# define PNG_READ_SWAP_SUPPORTED -# endif -# ifndef PNG_NO_READ_PACKSWAP -# define PNG_READ_PACKSWAP_SUPPORTED -# endif -# ifndef PNG_NO_READ_INVERT -# define PNG_READ_INVERT_SUPPORTED -# endif -# ifndef PNG_NO_READ_QUANTIZE - /* Prior to libpng-1.4.0 this was PNG_READ_DITHER_SUPPORTED */ -# ifndef PNG_NO_READ_DITHER /* This migration aid will be removed */ -# define PNG_READ_QUANTIZE_SUPPORTED -# endif -# endif -# ifndef PNG_NO_READ_BACKGROUND -# define PNG_READ_BACKGROUND_SUPPORTED -# endif -# ifndef PNG_NO_READ_16_TO_8 -# define PNG_READ_16_TO_8_SUPPORTED -# endif -# ifndef PNG_NO_READ_FILLER -# define PNG_READ_FILLER_SUPPORTED -# endif -# ifndef PNG_NO_READ_GAMMA -# define PNG_READ_GAMMA_SUPPORTED -# endif -# ifndef PNG_NO_READ_GRAY_TO_RGB -# define PNG_READ_GRAY_TO_RGB_SUPPORTED -# endif -# ifndef PNG_NO_READ_SWAP_ALPHA -# define PNG_READ_SWAP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_INVERT_ALPHA -# define PNG_READ_INVERT_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_STRIP_ALPHA -# define PNG_READ_STRIP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_READ_USER_TRANSFORM -# define PNG_READ_USER_TRANSFORM_SUPPORTED -# endif -# ifndef PNG_NO_READ_RGB_TO_GRAY -# define PNG_READ_RGB_TO_GRAY_SUPPORTED -# endif -#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ - -/* PNG_PROGRESSIVE_READ_NOT_SUPPORTED is deprecated. */ -#if !defined(PNG_NO_PROGRESSIVE_READ) && \ - !defined(PNG_PROGRESSIVE_READ_NOT_SUPPORTED) /* if you don't do progressive */ -# define PNG_PROGRESSIVE_READ_SUPPORTED /* reading. This is not talking */ -#endif /* about interlacing capability! You'll */ - /* still have interlacing unless you change the following define: */ - -#define PNG_READ_INTERLACING_SUPPORTED /* required for PNG-compliant decoders */ - -/* PNG_NO_SEQUENTIAL_READ_SUPPORTED is deprecated. */ -#if !defined(PNG_NO_SEQUENTIAL_READ) && \ - !defined(PNG_SEQUENTIAL_READ_SUPPORTED) && \ - !defined(PNG_NO_SEQUENTIAL_READ_SUPPORTED) -# define PNG_SEQUENTIAL_READ_SUPPORTED -#endif - -#ifndef PNG_NO_READ_COMPOSITE_NODIV -# ifndef PNG_NO_READ_COMPOSITED_NODIV /* libpng-1.0.x misspelling */ -# define PNG_READ_COMPOSITE_NODIV_SUPPORTED /* well tested on Intel, SGI */ -# endif -#endif - -#if !defined(PNG_NO_GET_INT_32) || defined(PNG_READ_oFFS_SUPPORTED) || \ - defined(PNG_READ_pCAL_SUPPORTED) -# ifndef PNG_GET_INT_32_SUPPORTED -# define PNG_GET_INT_32_SUPPORTED -# endif -#endif - -#endif /* PNG_READ_SUPPORTED */ - -#ifdef PNG_WRITE_SUPPORTED - -/* PNG_WRITE_TRANSFORMS_NOT_SUPPORTED is deprecated. */ -#if !defined(PNG_WRITE_TRANSFORMS_NOT_SUPPORTED) && \ - !defined(PNG_NO_WRITE_TRANSFORMS) -# define PNG_WRITE_TRANSFORMS_SUPPORTED -#endif - -#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED -# ifndef PNG_NO_WRITE_SHIFT -# define PNG_WRITE_SHIFT_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_PACK -# define PNG_WRITE_PACK_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_BGR -# define PNG_WRITE_BGR_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_SWAP -# define PNG_WRITE_SWAP_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_PACKSWAP -# define PNG_WRITE_PACKSWAP_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_INVERT -# define PNG_WRITE_INVERT_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_FILLER -# define PNG_WRITE_FILLER_SUPPORTED /* same as WRITE_STRIP_ALPHA */ -# endif -# ifndef PNG_NO_WRITE_SWAP_ALPHA -# define PNG_WRITE_SWAP_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_INVERT_ALPHA -# define PNG_WRITE_INVERT_ALPHA_SUPPORTED -# endif -# ifndef PNG_NO_WRITE_USER_TRANSFORM -# define PNG_WRITE_USER_TRANSFORM_SUPPORTED -# endif -#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */ - -#if !defined(PNG_NO_WRITE_INTERLACING_SUPPORTED) && \ - !defined(PNG_WRITE_INTERLACING_SUPPORTED) - /* This is not required for PNG-compliant encoders, but can cause - * trouble if left undefined - */ -# define PNG_WRITE_INTERLACING_SUPPORTED -#endif - -#if !defined(PNG_NO_WRITE_WEIGHTED_FILTER) && \ - !defined(PNG_WRITE_WEIGHTED_FILTER) && \ - defined(PNG_FLOATING_POINT_SUPPORTED) -# define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED -#endif - -#ifndef PNG_NO_WRITE_FLUSH -# define PNG_WRITE_FLUSH_SUPPORTED -#endif - -#if !defined(PNG_NO_SAVE_INT_32) || defined(PNG_WRITE_oFFS_SUPPORTED) || \ - defined(PNG_WRITE_pCAL_SUPPORTED) -# ifndef PNG_SAVE_INT_32_SUPPORTED -# define PNG_SAVE_INT_32_SUPPORTED -# endif -#endif - -#endif /* PNG_WRITE_SUPPORTED */ - -#define PNG_NO_ERROR_NUMBERS - -#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ - defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -# ifndef PNG_NO_USER_TRANSFORM_PTR -# define PNG_USER_TRANSFORM_PTR_SUPPORTED -# endif -#endif - -#if defined(PNG_STDIO_SUPPORTED) && !defined(PNG_TIME_RFC1123_SUPPORTED) -# define PNG_TIME_RFC1123_SUPPORTED -#endif - -/* This adds extra functions in pngget.c for accessing data from the - * info pointer (added in version 0.99) - * png_get_image_width() - * png_get_image_height() - * png_get_bit_depth() - * png_get_color_type() - * png_get_compression_type() - * png_get_filter_type() - * png_get_interlace_type() - * png_get_pixel_aspect_ratio() - * png_get_pixels_per_meter() - * png_get_x_offset_pixels() - * png_get_y_offset_pixels() - * png_get_x_offset_microns() - * png_get_y_offset_microns() - */ -#if !defined(PNG_NO_EASY_ACCESS) && !defined(PNG_EASY_ACCESS_SUPPORTED) -# define PNG_EASY_ACCESS_SUPPORTED -#endif - -/* Added at libpng-1.2.0 */ -#if !defined(PNG_NO_USER_MEM) && !defined(PNG_USER_MEM_SUPPORTED) -# define PNG_USER_MEM_SUPPORTED -#endif - -/* Added at libpng-1.2.6 */ -#ifndef PNG_NO_SET_USER_LIMITS -# ifndef PNG_SET_USER_LIMITS_SUPPORTED -# define PNG_SET_USER_LIMITS_SUPPORTED -# endif - /* Feature added at libpng-1.4.0, this flag added at 1.4.1 */ -# ifndef PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED -# define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED -# endif - /* Feature added at libpng-1.4.1, this flag added at 1.4.1 */ -# ifndef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED -# define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED -# endif -#endif - -/* Added at libpng-1.2.43 */ -#ifndef PNG_USER_LIMITS_SUPPORTED -# ifndef PNG_NO_USER_LIMITS -# define PNG_USER_LIMITS_SUPPORTED -# endif -#endif - -/* Added at libpng-1.0.16 and 1.2.6. To accept all valid PNGs no matter - * how large, set these two limits to 0x7fffffffL - */ -#ifndef PNG_USER_WIDTH_MAX -# define PNG_USER_WIDTH_MAX 1000000L -#endif -#ifndef PNG_USER_HEIGHT_MAX -# define PNG_USER_HEIGHT_MAX 1000000L -#endif - -/* Added at libpng-1.2.43. To accept all valid PNGs no matter - * how large, set these two limits to 0. - */ -#ifndef PNG_USER_CHUNK_CACHE_MAX -# define PNG_USER_CHUNK_CACHE_MAX 0 -#endif - -/* Added at libpng-1.2.43 */ -#ifndef PNG_USER_CHUNK_MALLOC_MAX -# define PNG_USER_CHUNK_MALLOC_MAX 0 -#endif - -/* Added at libpng-1.4.0 */ -#if !defined(PNG_NO_IO_STATE) && !defined(PNG_IO_STATE_SUPPORTED) -# define PNG_IO_STATE_SUPPORTED -#endif - -#ifndef PNG_LITERAL_SHARP -# define PNG_LITERAL_SHARP 0x23 -#endif -#ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET -# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b -#endif -#ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET -# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d -#endif -#ifndef PNG_STRING_NEWLINE -#define PNG_STRING_NEWLINE "\n" -#endif - -/* These are currently experimental features, define them if you want */ - -/* Very little testing */ -/* -#ifdef PNG_READ_SUPPORTED -# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED -# define PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED -# endif -#endif -*/ - -/* This is only for PowerPC big-endian and 680x0 systems */ -/* some testing */ -/* -#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED -# define PNG_READ_BIG_ENDIAN_SUPPORTED -#endif -*/ - -#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS) -# define PNG_USE_READ_MACROS -#endif - -/* Buggy compilers (e.g., gcc 2.7.2.2) need PNG_NO_POINTER_INDEXING */ - -#if !defined(PNG_NO_POINTER_INDEXING) && \ - !defined(PNG_POINTER_INDEXING_SUPPORTED) -# define PNG_POINTER_INDEXING_SUPPORTED -#endif - - -/* Any chunks you are not interested in, you can undef here. The - * ones that allocate memory may be expecially important (hIST, - * tEXt, zTXt, tRNS, pCAL). Others will just save time and make png_info - * a bit smaller. - */ - -/* The size of the png_text structure changed in libpng-1.0.6 when - * iTXt support was added. iTXt support was turned off by default through - * libpng-1.2.x, to support old apps that malloc the png_text structure - * instead of calling png_set_text() and letting libpng malloc it. It - * was turned on by default in libpng-1.4.0. - */ - -/* PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED is deprecated. */ -#if defined(PNG_READ_SUPPORTED) && \ - !defined(PNG_READ_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ - !defined(PNG_NO_READ_ANCILLARY_CHUNKS) -# define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED -#endif - -/* PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED is deprecated. */ -#if defined(PNG_WRITE_SUPPORTED) && \ - !defined(PNG_WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED) && \ - !defined(PNG_NO_WRITE_ANCILLARY_CHUNKS) -# define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED -#endif - -#ifdef PNG_READ_ANCILLARY_CHUNKS_SUPPORTED - -#ifdef PNG_NO_READ_TEXT -# define PNG_NO_READ_iTXt -# define PNG_NO_READ_tEXt -# define PNG_NO_READ_zTXt -#endif - -#ifndef PNG_NO_READ_bKGD -# define PNG_READ_bKGD_SUPPORTED -# define PNG_bKGD_SUPPORTED -#endif -#ifndef PNG_NO_READ_cHRM -# define PNG_READ_cHRM_SUPPORTED -# define PNG_cHRM_SUPPORTED -#endif -#ifndef PNG_NO_READ_gAMA -# define PNG_READ_gAMA_SUPPORTED -# define PNG_gAMA_SUPPORTED -#endif -#ifndef PNG_NO_READ_hIST -# define PNG_READ_hIST_SUPPORTED -# define PNG_hIST_SUPPORTED -#endif -#ifndef PNG_NO_READ_iCCP -# define PNG_READ_iCCP_SUPPORTED -# define PNG_iCCP_SUPPORTED -#endif -#ifndef PNG_NO_READ_iTXt -# ifndef PNG_READ_iTXt_SUPPORTED -# define PNG_READ_iTXt_SUPPORTED -# endif -# ifndef PNG_iTXt_SUPPORTED -# define PNG_iTXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_READ_oFFs -# define PNG_READ_oFFs_SUPPORTED -# define PNG_oFFs_SUPPORTED -#endif -#ifndef PNG_NO_READ_pCAL -# define PNG_READ_pCAL_SUPPORTED -# define PNG_pCAL_SUPPORTED -#endif -#ifndef PNG_NO_READ_sCAL -# define PNG_READ_sCAL_SUPPORTED -# define PNG_sCAL_SUPPORTED -#endif -#ifndef PNG_NO_READ_pHYs -# define PNG_READ_pHYs_SUPPORTED -# define PNG_pHYs_SUPPORTED -#endif -#ifndef PNG_NO_READ_sBIT -# define PNG_READ_sBIT_SUPPORTED -# define PNG_sBIT_SUPPORTED -#endif -#ifndef PNG_NO_READ_sPLT -# define PNG_READ_sPLT_SUPPORTED -# define PNG_sPLT_SUPPORTED -#endif -#ifndef PNG_NO_READ_sRGB -# define PNG_READ_sRGB_SUPPORTED -# define PNG_sRGB_SUPPORTED -#endif -#ifndef PNG_NO_READ_tEXt -# define PNG_READ_tEXt_SUPPORTED -# define PNG_tEXt_SUPPORTED -#endif -#ifndef PNG_NO_READ_tIME -# define PNG_READ_tIME_SUPPORTED -# define PNG_tIME_SUPPORTED -#endif -#ifndef PNG_NO_READ_tRNS -# define PNG_READ_tRNS_SUPPORTED -# define PNG_tRNS_SUPPORTED -#endif -#ifndef PNG_NO_READ_zTXt -# define PNG_READ_zTXt_SUPPORTED -# define PNG_zTXt_SUPPORTED -#endif -#ifndef PNG_NO_READ_OPT_PLTE -# define PNG_READ_OPT_PLTE_SUPPORTED /* only affects support of the */ -#endif /* optional PLTE chunk in RGB and RGBA images */ -#if defined(PNG_READ_iTXt_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) || \ - defined(PNG_READ_zTXt_SUPPORTED) -# define PNG_READ_TEXT_SUPPORTED -# define PNG_TEXT_SUPPORTED -#endif - -#endif /* PNG_READ_ANCILLARY_CHUNKS_SUPPORTED */ - -#ifndef PNG_NO_READ_UNKNOWN_CHUNKS -# ifndef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED -# endif -# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_UNKNOWN_CHUNKS_SUPPORTED -# endif -# ifndef PNG_READ_USER_CHUNKS_SUPPORTED -# define PNG_READ_USER_CHUNKS_SUPPORTED -# endif -#endif -#ifndef PNG_NO_READ_USER_CHUNKS -# ifndef PNG_READ_USER_CHUNKS_SUPPORTED -# define PNG_READ_USER_CHUNKS_SUPPORTED -# endif -# ifndef PNG_USER_CHUNKS_SUPPORTED -# define PNG_USER_CHUNKS_SUPPORTED -# endif -#endif -#ifndef PNG_NO_HANDLE_AS_UNKNOWN -# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# endif -#endif - -#ifdef PNG_WRITE_SUPPORTED -#ifdef PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED - -#ifdef PNG_NO_WRITE_TEXT -# define PNG_NO_WRITE_iTXt -# define PNG_NO_WRITE_tEXt -# define PNG_NO_WRITE_zTXt -#endif -#ifndef PNG_NO_WRITE_bKGD -# define PNG_WRITE_bKGD_SUPPORTED -# ifndef PNG_bKGD_SUPPORTED -# define PNG_bKGD_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_cHRM -# define PNG_WRITE_cHRM_SUPPORTED -# ifndef PNG_cHRM_SUPPORTED -# define PNG_cHRM_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_gAMA -# define PNG_WRITE_gAMA_SUPPORTED -# ifndef PNG_gAMA_SUPPORTED -# define PNG_gAMA_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_hIST -# define PNG_WRITE_hIST_SUPPORTED -# ifndef PNG_hIST_SUPPORTED -# define PNG_hIST_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_iCCP -# define PNG_WRITE_iCCP_SUPPORTED -# ifndef PNG_iCCP_SUPPORTED -# define PNG_iCCP_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_iTXt -# ifndef PNG_WRITE_iTXt_SUPPORTED -# define PNG_WRITE_iTXt_SUPPORTED -# endif -# ifndef PNG_iTXt_SUPPORTED -# define PNG_iTXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_oFFs -# define PNG_WRITE_oFFs_SUPPORTED -# ifndef PNG_oFFs_SUPPORTED -# define PNG_oFFs_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_pCAL -# define PNG_WRITE_pCAL_SUPPORTED -# ifndef PNG_pCAL_SUPPORTED -# define PNG_pCAL_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sCAL -# define PNG_WRITE_sCAL_SUPPORTED -# ifndef PNG_sCAL_SUPPORTED -# define PNG_sCAL_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_pHYs -# define PNG_WRITE_pHYs_SUPPORTED -# ifndef PNG_pHYs_SUPPORTED -# define PNG_pHYs_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sBIT -# define PNG_WRITE_sBIT_SUPPORTED -# ifndef PNG_sBIT_SUPPORTED -# define PNG_sBIT_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sPLT -# define PNG_WRITE_sPLT_SUPPORTED -# ifndef PNG_sPLT_SUPPORTED -# define PNG_sPLT_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_sRGB -# define PNG_WRITE_sRGB_SUPPORTED -# ifndef PNG_sRGB_SUPPORTED -# define PNG_sRGB_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tEXt -# define PNG_WRITE_tEXt_SUPPORTED -# ifndef PNG_tEXt_SUPPORTED -# define PNG_tEXt_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tIME -# define PNG_WRITE_tIME_SUPPORTED -# ifndef PNG_tIME_SUPPORTED -# define PNG_tIME_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_tRNS -# define PNG_WRITE_tRNS_SUPPORTED -# ifndef PNG_tRNS_SUPPORTED -# define PNG_tRNS_SUPPORTED -# endif -#endif -#ifndef PNG_NO_WRITE_zTXt -# define PNG_WRITE_zTXt_SUPPORTED -# ifndef PNG_zTXt_SUPPORTED -# define PNG_zTXt_SUPPORTED -# endif -#endif -#if defined(PNG_WRITE_iTXt_SUPPORTED) || defined(PNG_WRITE_tEXt_SUPPORTED) || \ - defined(PNG_WRITE_zTXt_SUPPORTED) -# define PNG_WRITE_TEXT_SUPPORTED -# ifndef PNG_TEXT_SUPPORTED -# define PNG_TEXT_SUPPORTED -# endif -#endif - -#ifdef PNG_WRITE_tIME_SUPPORTED -# ifndef PNG_NO_CONVERT_tIME -# ifndef _WIN32_WCE -/* The "tm" structure is not supported on WindowsCE */ -# ifndef PNG_CONVERT_tIME_SUPPORTED -# define PNG_CONVERT_tIME_SUPPORTED -# endif -# endif -# endif -#endif - -#endif /* PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED */ - -#ifndef PNG_NO_WRITE_FILTER -# ifndef PNG_WRITE_FILTER_SUPPORTED -# define PNG_WRITE_FILTER_SUPPORTED -# endif -#endif - -#ifndef PNG_NO_WRITE_UNKNOWN_CHUNKS -# define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED -# ifndef PNG_UNKNOWN_CHUNKS_SUPPORTED -# define PNG_UNKNOWN_CHUNKS_SUPPORTED -# endif -#endif -#ifndef PNG_NO_HANDLE_AS_UNKNOWN -# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# define PNG_HANDLE_AS_UNKNOWN_SUPPORTED -# endif -#endif -#endif /* PNG_WRITE_SUPPORTED */ - -/* Turn this off to disable png_read_png() and - * png_write_png() and leave the row_pointers member - * out of the info structure. - */ -#ifndef PNG_NO_INFO_IMAGE -# define PNG_INFO_IMAGE_SUPPORTED -#endif - -/* Need the time information for converting tIME chunks */ -#ifdef PNG_CONVERT_tIME_SUPPORTED - /* "time.h" functions are not supported on WindowsCE */ -# include -#endif - -/* Some typedefs to get us started. These should be safe on most of the - * common platforms. The typedefs should be at least as large as the - * numbers suggest (a png_uint_32 must be at least 32 bits long), but they - * don't have to be exactly that size. Some compilers dislike passing - * unsigned shorts as function parameters, so you may be better off using - * unsigned int for png_uint_16. - */ - -#if defined(INT_MAX) && (INT_MAX > 0x7ffffffeL) -typedef unsigned int png_uint_32; -typedef int png_int_32; -#else -typedef unsigned long png_uint_32; -typedef long png_int_32; -#endif -typedef unsigned short png_uint_16; -typedef short png_int_16; -typedef unsigned char png_byte; - -#ifdef PNG_NO_SIZE_T - typedef unsigned int png_size_t; -#else - typedef size_t png_size_t; -#endif -#define png_sizeof(x) (sizeof (x)) - -/* The following is needed for medium model support. It cannot be in the - * pngpriv.h header. Needs modification for other compilers besides - * MSC. Model independent support declares all arrays and pointers to be - * large using the far keyword. The zlib version used must also support - * model independent data. As of version zlib 1.0.4, the necessary changes - * have been made in zlib. The USE_FAR_KEYWORD define triggers other - * changes that are needed. (Tim Wegner) - */ - -/* Separate compiler dependencies (problem here is that zlib.h always - * defines FAR. (SJT) - */ -#ifdef __BORLANDC__ -# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__) -# define LDATA 1 -# else -# define LDATA 0 -# endif - /* GRR: why is Cygwin in here? Cygwin is not Borland C... */ -# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__) -# define PNG_MAX_MALLOC_64K -# if (LDATA != 1) -# ifndef FAR -# define FAR __far -# endif -# define USE_FAR_KEYWORD -# endif /* LDATA != 1 */ - /* Possibly useful for moving data out of default segment. - * Uncomment it if you want. Could also define FARDATA as - * const if your compiler supports it. (SJT) -# define FARDATA FAR - */ -# endif /* __WIN32__, __FLAT__, __CYGWIN__ */ -#endif /* __BORLANDC__ */ - - -/* Suggest testing for specific compiler first before testing for - * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM, - * making reliance oncertain keywords suspect. (SJT) - */ - -/* MSC Medium model */ -#ifdef FAR -# ifdef M_I86MM -# define USE_FAR_KEYWORD -# define FARDATA FAR -# include -# endif -#endif - -/* SJT: default case */ -#ifndef FAR -# define FAR -#endif - -/* At this point FAR is always defined */ -#ifndef FARDATA -# define FARDATA -#endif - -/* Typedef for floating-point numbers that are converted - to fixed-point with a multiple of 100,000, e.g., int_gamma */ -typedef png_int_32 png_fixed_point; - -/* Add typedefs for pointers */ -typedef void FAR * png_voidp; -typedef png_byte FAR * png_bytep; -typedef png_uint_32 FAR * png_uint_32p; -typedef png_int_32 FAR * png_int_32p; -typedef png_uint_16 FAR * png_uint_16p; -typedef png_int_16 FAR * png_int_16p; -typedef PNG_CONST char FAR * png_const_charp; -typedef char FAR * png_charp; -typedef png_fixed_point FAR * png_fixed_point_p; - -#ifndef PNG_NO_STDIO -typedef FILE * png_FILE_p; -#endif - -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * png_doublep; -#endif - -/* Pointers to pointers; i.e. arrays */ -typedef png_byte FAR * FAR * png_bytepp; -typedef png_uint_32 FAR * FAR * png_uint_32pp; -typedef png_int_32 FAR * FAR * png_int_32pp; -typedef png_uint_16 FAR * FAR * png_uint_16pp; -typedef png_int_16 FAR * FAR * png_int_16pp; -typedef PNG_CONST char FAR * FAR * png_const_charpp; -typedef char FAR * FAR * png_charpp; -typedef png_fixed_point FAR * FAR * png_fixed_point_pp; -#ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double FAR * FAR * png_doublepp; -#endif - -/* Pointers to pointers to pointers; i.e., pointer to array */ -typedef char FAR * FAR * FAR * png_charppp; - -/* Define PNG_BUILD_DLL if the module being built is a Windows - * LIBPNG DLL. - * - * Define PNG_USE_DLL if you want to *link* to the Windows LIBPNG DLL. - * It is equivalent to Microsoft predefined macro _DLL that is - * automatically defined when you compile using the share - * version of the CRT (C Run-Time library) - * - * The cygwin mods make this behavior a little different: - * Define PNG_BUILD_DLL if you are building a dll for use with cygwin - * Define PNG_STATIC if you are building a static library for use with cygwin, - * -or- if you are building an application that you want to link to the - * static library. - * PNG_USE_DLL is defined by default (no user action needed) unless one of - * the other flags is defined. - */ - -#if !defined(PNG_DLL) && (defined(PNG_BUILD_DLL) || defined(PNG_USE_DLL)) -# define PNG_DLL -#endif - -/* If you define PNGAPI, e.g., with compiler option "-DPNGAPI=__stdcall", - * you may get warnings regarding the linkage of png_zalloc and png_zfree. - * Don't ignore those warnings; you must also reset the default calling - * convention in your compiler to match your PNGAPI, and you must build - * zlib and your applications the same way you build libpng. - */ - -#ifdef __CYGWIN__ -# undef PNGAPI -# define PNGAPI __cdecl -# undef PNG_IMPEXP -# define PNG_IMPEXP -#endif - -#ifdef __WATCOMC__ -# ifndef PNGAPI -# define PNGAPI -# endif -#endif - -#if defined(__MINGW32__) && !defined(PNG_MODULEDEF) -# ifndef PNG_NO_MODULEDEF -# define PNG_NO_MODULEDEF -# endif -#endif - -#if !defined(PNG_IMPEXP) && defined(PNG_BUILD_DLL) && !defined(PNG_NO_MODULEDEF) -# define PNG_IMPEXP -#endif - -#if defined(PNG_DLL) || defined(_DLL) || defined(__DLL__ ) || \ - (( defined(_Windows) || defined(_WINDOWS) || \ - defined(WIN32) || defined(_WIN32) || defined(__WIN32__) )) - -# ifndef PNGAPI -# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800)) -# define PNGAPI __cdecl -# else -# define PNGAPI _cdecl -# endif -# endif - -# if !defined(PNG_IMPEXP) && (!defined(PNG_DLL) || \ - 0 /* WINCOMPILER_WITH_NO_SUPPORT_FOR_DECLIMPEXP */) -# define PNG_IMPEXP -# endif - -# ifndef PNG_IMPEXP - -# define PNG_EXPORT_TYPE1(type,symbol) PNG_IMPEXP type PNGAPI symbol -# define PNG_EXPORT_TYPE2(type,symbol) type PNG_IMPEXP PNGAPI symbol - - /* Borland/Microsoft */ -# if defined(_MSC_VER) || defined(__BORLANDC__) -# if (_MSC_VER >= 800) || (__BORLANDC__ >= 0x500) -# define PNG_EXPORT PNG_EXPORT_TYPE1 -# else -# define PNG_EXPORT PNG_EXPORT_TYPE2 -# ifdef PNG_BUILD_DLL -# define PNG_IMPEXP __export -# else -# define PNG_IMPEXP /*__import */ /* doesn't exist AFAIK in VC++ */ -# endif /* Exists in Borland C++ for - C++ classes (== huge) */ -# endif -# endif - -# ifndef PNG_IMPEXP -# ifdef PNG_BUILD_DLL -# define PNG_IMPEXP __declspec(dllexport) -# else -# define PNG_IMPEXP __declspec(dllimport) -# endif -# endif -# endif /* PNG_IMPEXP */ -#else /* !(DLL || non-cygwin WINDOWS) */ -# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) -# ifndef PNGAPI -# define PNGAPI _System -# endif -# else -# if 0 /* ... other platforms, with other meanings */ -# endif -# endif -#endif - -#ifndef PNGAPI -# define PNGAPI -#endif -#ifndef PNG_IMPEXP -# define PNG_IMPEXP -#endif - -#ifdef PNG_BUILDSYMS -# ifndef PNG_EXPORT -# define PNG_EXPORT(type,symbol) PNG_FUNCTION_EXPORT symbol END -# endif -#endif - -#ifndef PNG_EXPORT -# define PNG_EXPORT(type,symbol) PNG_IMPEXP type PNGAPI symbol -#endif - -#define PNG_USE_LOCAL_ARRAYS /* Not used in libpng, defined for legacy apps */ - -/* Support for compiler specific function attributes. These are used - * so that where compiler support is available incorrect use of API - * functions in png.h will generate compiler warnings. - * - * Added at libpng-1.2.41. - */ - -#ifndef PNG_NO_PEDANTIC_WARNINGS -# ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED -# define PNG_PEDANTIC_WARNINGS_SUPPORTED -# endif -#endif - -#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED -/* Support for compiler specific function attributes. These are used - * so that where compiler support is available incorrect use of API - * functions in png.h will generate compiler warnings. Added at libpng - * version 1.2.41. - */ -# ifdef __GNUC__ -# ifndef PNG_USE_RESULT -# define PNG_USE_RESULT __attribute__((__warn_unused_result__)) -# endif -# ifndef PNG_NORETURN -# define PNG_NORETURN __attribute__((__noreturn__)) -# endif -# ifndef PNG_ALLOCATED -# define PNG_ALLOCATED __attribute__((__malloc__)) -# endif - - /* This specifically protects structure members that should only be - * accessed from within the library, therefore should be empty during - * a library build. - */ -# ifndef PNG_DEPRECATED -# define PNG_DEPRECATED __attribute__((__deprecated__)) -# endif -# ifndef PNG_DEPSTRUCT -# define PNG_DEPSTRUCT __attribute__((__deprecated__)) -# endif -# ifndef PNG_PRIVATE -# if 0 /* Doesn't work so we use deprecated instead*/ -# define PNG_PRIVATE \ - __attribute__((warning("This function is not exported by libpng."))) -# else -# define PNG_PRIVATE \ - __attribute__((__deprecated__)) -# endif -# endif /* PNG_PRIVATE */ -# endif /* __GNUC__ */ -#endif /* PNG_PEDANTIC_WARNINGS */ - -#ifndef PNG_DEPRECATED -# define PNG_DEPRECATED /* Use of this function is deprecated */ -#endif -#ifndef PNG_USE_RESULT -# define PNG_USE_RESULT /* The result of this function must be checked */ -#endif -#ifndef PNG_NORETURN -# define PNG_NORETURN /* This function does not return */ -#endif -#ifndef PNG_ALLOCATED -# define PNG_ALLOCATED /* The result of the function is new memory */ -#endif -#ifndef PNG_DEPSTRUCT -# define PNG_DEPSTRUCT /* Access to this struct member is deprecated */ -#endif -#ifndef PNG_PRIVATE -# define PNG_PRIVATE /* This is a private libpng function */ -#endif - -/* Users may want to use these so they are not private. Any library - * functions that are passed far data must be model-independent. - */ - -/* memory model/platform independent fns */ -#ifndef PNG_ABORT -# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_)) -# define PNG_ABORT() ExitProcess(0) -# else -# define PNG_ABORT() abort() -# endif -#endif - -#ifdef USE_FAR_KEYWORD -/* Use this to make far-to-near assignments */ -# define CHECK 1 -# define NOCHECK 0 -# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK)) -# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK)) -# define png_strcpy _fstrcpy -# define png_strncpy _fstrncpy /* Added to v 1.2.6 */ -# define png_strlen _fstrlen -# define png_memcmp _fmemcmp /* SJT: added */ -# define png_memcpy _fmemcpy -# define png_memset _fmemset -# define png_sprintf sprintf -#else -# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_)) -# /* Favor Windows over C runtime fns */ -# define CVT_PTR(ptr) (ptr) -# define CVT_PTR_NOCHECK(ptr) (ptr) -# define png_strcpy lstrcpyA -# define png_strncpy lstrcpynA -# define png_strlen lstrlenA -# define png_memcmp memcmp -# define png_memcpy CopyMemory -# define png_memset memset -# define png_sprintf wsprintfA -# else -# define CVT_PTR(ptr) (ptr) -# define CVT_PTR_NOCHECK(ptr) (ptr) -# define png_strcpy strcpy -# define png_strncpy strncpy /* Added to v 1.2.6 */ -# define png_strlen strlen -# define png_memcmp memcmp /* SJT: added */ -# define png_memcpy memcpy -# define png_memset memset -# define png_sprintf sprintf -# endif -#endif - -#ifndef PNG_NO_SNPRINTF -# ifdef _MSC_VER -# define png_snprintf _snprintf /* Added to v 1.2.19 */ -# define png_snprintf2 _snprintf -# define png_snprintf6 _snprintf -# else -# define png_snprintf snprintf /* Added to v 1.2.19 */ -# define png_snprintf2 snprintf -# define png_snprintf6 snprintf -# endif -#else - /* You don't have or don't want to use snprintf(). Caution: Using - * sprintf instead of snprintf exposes your application to accidental - * or malevolent buffer overflows. If you don't have snprintf() - * as a general rule you should provide one (you can get one from - * Portable OpenSSH). - */ -# define png_snprintf(s1,n,fmt,x1) png_sprintf(s1,fmt,x1) -# define png_snprintf2(s1,n,fmt,x1,x2) png_sprintf(s1,fmt,x1,x2) -# define png_snprintf6(s1,n,fmt,x1,x2,x3,x4,x5,x6) \ - png_sprintf(s1,fmt,x1,x2,x3,x4,x5,x6) -#endif - -/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, - * and no smaller than png_uint_32. Casts from png_size_t or png_uint_32 - * to png_alloc_size_t are not necessary; in fact, it is recommended - * not to use them at all so that the compiler can complain when something - * turns out to be problematic. - * Casts in the other direction (from png_alloc_size_t to png_size_t or - * png_uint_32) should be explicitly applied; however, we do not expect - * to encounter practical situations that require such conversions. - */ -#if defined(__TURBOC__) && !defined(__FLAT__) - typedef unsigned long png_alloc_size_t; -#else -# if defined(_MSC_VER) && defined(MAXSEG_64K) - typedef unsigned long png_alloc_size_t; -# else - /* This is an attempt to detect an old Windows system where (int) is - * actually 16 bits, in that case png_malloc must have an argument with a - * bigger size to accomodate the requirements of the library. - */ -# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_)) && \ - (!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL) - typedef DWORD png_alloc_size_t; -# else - typedef png_size_t png_alloc_size_t; -# endif -# endif -#endif -/* End of memory model/platform independent support */ - -/* Just a little check that someone hasn't tried to define something - * contradictory. - */ -#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K) -# undef PNG_ZBUF_SIZE -# define PNG_ZBUF_SIZE 65536L -#endif - - -/* Added at libpng-1.2.8 */ -#endif /* PNG_VERSION_INFO_ONLY */ - -#endif /* PNGCONF_H */ diff --git a/inc/zconf.h b/inc/zconf.h deleted file mode 100644 index b234387..0000000 --- a/inc/zconf.h +++ /dev/null @@ -1,428 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2010 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#ifndef ZCONF_H -#define ZCONF_H - -/* - * If you *really* need a unique prefix for all types and library functions, - * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. - * Even better than compiling with -DZ_PREFIX would be to use configure to set - * this permanently in zconf.h using "./configure --zprefix". - */ -#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ - -/* all linked symbols */ -# define _dist_code z__dist_code -# define _length_code z__length_code -# define _tr_align z__tr_align -# define _tr_flush_block z__tr_flush_block -# define _tr_init z__tr_init -# define _tr_stored_block z__tr_stored_block -# define _tr_tally z__tr_tally -# define adler32 z_adler32 -# define adler32_combine z_adler32_combine -# define adler32_combine64 z_adler32_combine64 -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# define crc32 z_crc32 -# define crc32_combine z_crc32_combine -# define crc32_combine64 z_crc32_combine64 -# define deflate z_deflate -# define deflateBound z_deflateBound -# define deflateCopy z_deflateCopy -# define deflateEnd z_deflateEnd -# define deflateInit2_ z_deflateInit2_ -# define deflateInit_ z_deflateInit_ -# define deflateParams z_deflateParams -# define deflatePrime z_deflatePrime -# define deflateReset z_deflateReset -# define deflateSetDictionary z_deflateSetDictionary -# define deflateSetHeader z_deflateSetHeader -# define deflateTune z_deflateTune -# define deflate_copyright z_deflate_copyright -# define get_crc_table z_get_crc_table -# define gz_error z_gz_error -# define gz_intmax z_gz_intmax -# define gz_strwinerror z_gz_strwinerror -# define gzbuffer z_gzbuffer -# define gzclearerr z_gzclearerr -# define gzclose z_gzclose -# define gzclose_r z_gzclose_r -# define gzclose_w z_gzclose_w -# define gzdirect z_gzdirect -# define gzdopen z_gzdopen -# define gzeof z_gzeof -# define gzerror z_gzerror -# define gzflush z_gzflush -# define gzgetc z_gzgetc -# define gzgets z_gzgets -# define gzoffset z_gzoffset -# define gzoffset64 z_gzoffset64 -# define gzopen z_gzopen -# define gzopen64 z_gzopen64 -# define gzprintf z_gzprintf -# define gzputc z_gzputc -# define gzputs z_gzputs -# define gzread z_gzread -# define gzrewind z_gzrewind -# define gzseek z_gzseek -# define gzseek64 z_gzseek64 -# define gzsetparams z_gzsetparams -# define gztell z_gztell -# define gztell64 z_gztell64 -# define gzungetc z_gzungetc -# define gzwrite z_gzwrite -# define inflate z_inflate -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define inflateBackInit_ z_inflateBackInit_ -# define inflateCopy z_inflateCopy -# define inflateEnd z_inflateEnd -# define inflateGetHeader z_inflateGetHeader -# define inflateInit2_ z_inflateInit2_ -# define inflateInit_ z_inflateInit_ -# define inflateMark z_inflateMark -# define inflatePrime z_inflatePrime -# define inflateReset z_inflateReset -# define inflateReset2 z_inflateReset2 -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateUndermine z_inflateUndermine -# define inflate_copyright z_inflate_copyright -# define inflate_fast z_inflate_fast -# define inflate_table z_inflate_table -# define uncompress z_uncompress -# define zError z_zError -# define zcalloc z_zcalloc -# define zcfree z_zcfree -# define zlibCompileFlags z_zlibCompileFlags -# define zlibVersion z_zlibVersion - -/* all zlib typedefs in zlib.h and zconf.h */ -# define Byte z_Byte -# define Bytef z_Bytef -# define alloc_func z_alloc_func -# define charf z_charf -# define free_func z_free_func -# define gzFile z_gzFile -# define gz_header z_gz_header -# define gz_headerp z_gz_headerp -# define in_func z_in_func -# define intf z_intf -# define out_func z_out_func -# define uInt z_uInt -# define uIntf z_uIntf -# define uLong z_uLong -# define uLongf z_uLongf -# define voidp z_voidp -# define voidpc z_voidpc -# define voidpf z_voidpf - -/* all zlib structs in zlib.h and zconf.h */ -# define gz_header_s z_gz_header_s -# define internal_state z_internal_state - -#endif - -#if defined(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif -#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) -# define OS2 -#endif -#if defined(_WINDOWS) && !defined(WINDOWS) -# define WINDOWS -#endif -#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) -# ifndef WIN32 -# define WIN32 -# endif -#endif -#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) -# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif -# endif -#endif - -/* - * Compile with -DMAXSEG_64K if the alloc function cannot allocate more - * than 64k bytes at a time (needed on systems with 16-bit int). - */ -#ifdef SYS16BIT -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#ifdef __STDC_VERSION__ -# ifndef STDC -# define STDC -# endif -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif -#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) -# define STDC -#endif -#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) -# define STDC -#endif -#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) -# define STDC -#endif -#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) -# define STDC -#endif - -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ -# endif -#endif - -/* Some Mac compilers merge all .h files incorrectly: */ -#if defined(__MWERKS__)||defined(applec)||defined(THINK_C)||defined(__SC__) -# define NO_DUMMY_DECL -#endif - -/* Maximum value for memLevel in deflateInit2 */ -#ifndef MAX_MEM_LEVEL -# ifdef MAXSEG_64K -# define MAX_MEM_LEVEL 8 -# else -# define MAX_MEM_LEVEL 9 -# endif -#endif - -/* Maximum value for windowBits in deflateInit2 and inflateInit2. - * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files - * created by gzip. (Files created by minigzip can still be extracted by - * gzip.) - */ -#ifndef MAX_WBITS -# define MAX_WBITS 15 /* 32K LZ77 window */ -#endif - -/* The memory requirements for deflate are (in bytes): - (1 << (windowBits+2)) + (1 << (memLevel+9)) - that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) - plus a few kilobytes for small objects. For example, if you want to reduce - the default memory requirements from 256K to 128K, compile with - make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" - Of course this will generally degrade compression (there's no free lunch). - - The memory requirements for inflate are (in bytes) 1 << windowBits - that is, 32K for windowBits=15 (default value) plus a few kilobytes - for small objects. -*/ - - /* Type declarations */ - -#ifndef OF /* function prototypes */ -# ifdef STDC -# define OF(args) args -# else -# define OF(args) () -# endif -#endif - -/* The following definitions for FAR are needed only for MSDOS mixed - * model programming (small or medium model with some far allocations). - * This was tested only with MSC; for other MSDOS compilers you may have - * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, - * just define FAR to be empty. - */ -#ifdef SYS16BIT -# if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -# endif -# if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif -# endif -#endif - -#if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -# ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif -# endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -# ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif -# endif -#endif - -#if defined (__BEOS__) -# ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif -# endif -#endif - -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(__MACTYPES__) -typedef unsigned char Byte; /* 8 bits */ -#endif -typedef unsigned int uInt; /* 16 bits or more */ -typedef unsigned long uLong; /* 32 bits or more */ - -#ifdef SMALL_MEDIUM - /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ -# define Bytef Byte FAR -#else - typedef Byte FAR Bytef; -#endif -typedef char FAR charf; -typedef int FAR intf; -typedef uInt FAR uIntf; -typedef uLong FAR uLongf; - -#ifdef STDC - typedef void const *voidpc; - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte const *voidpc; - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#if 1 /* was set to #if 1 by ./configure */ -# define Z_HAVE_UNISTD_H -#endif - -#ifdef STDC -# include /* for off_t */ -#endif - -/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and - * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even - * though the former does not conform to the LFS document), but considering - * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as - * equivalently requesting no 64-bit operations - */ -#if -_LARGEFILE64_SOURCE - -1 == 1 -# undef _LARGEFILE64_SOURCE -#endif - -#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) -# include /* for SEEK_* and off_t */ -# ifdef VMS -# include /* for off_t */ -# endif -# ifndef z_off_t -# define z_off_t off_t -# endif -#endif - -#ifndef SEEK_SET -# define SEEK_SET 0 /* Seek from beginning of file. */ -# define SEEK_CUR 1 /* Seek from current position. */ -# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ -#endif - -#ifndef z_off_t -# define z_off_t long -#endif - -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 -# define z_off64_t off64_t -#else -# define z_off64_t z_off_t -#endif - -#if defined(__OS400__) -# define NO_vsnprintf -#endif - -#if defined(__MVS__) -# define NO_vsnprintf -#endif - -/* MVS linker does not support external names larger than 8 bytes */ -#if defined(__MVS__) - #pragma map(deflateInit_,"DEIN") - #pragma map(deflateInit2_,"DEIN2") - #pragma map(deflateEnd,"DEEND") - #pragma map(deflateBound,"DEBND") - #pragma map(inflateInit_,"ININ") - #pragma map(inflateInit2_,"ININ2") - #pragma map(inflateEnd,"INEND") - #pragma map(inflateSync,"INSY") - #pragma map(inflateSetDictionary,"INSEDI") - #pragma map(compressBound,"CMBND") - #pragma map(inflate_table,"INTABL") - #pragma map(inflate_fast,"INFA") - #pragma map(inflate_copyright,"INCOPY") -#endif - -#endif /* ZCONF_H */ diff --git a/inc/zlib.h b/inc/zlib.h deleted file mode 100644 index bfbba83..0000000 --- a/inc/zlib.h +++ /dev/null @@ -1,1613 +0,0 @@ -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.5, April 19th, 2010 - - Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - Jean-loup Gailly Mark Adler - jloup@gzip.org madler@alumni.caltech.edu - - - The data format used by the zlib library is described by RFCs (Request for - Comments) 1950 to 1952 in the files http://www.ietf.org/rfc/rfc1950.txt - (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). -*/ - -#ifndef ZLIB_H -#define ZLIB_H - -#include "zconf.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define ZLIB_VERSION "1.2.5" -#define ZLIB_VERNUM 0x1250 -#define ZLIB_VER_MAJOR 1 -#define ZLIB_VER_MINOR 2 -#define ZLIB_VER_REVISION 5 -#define ZLIB_VER_SUBREVISION 0 - -/* - The 'zlib' compression library provides in-memory compression and - decompression functions, including integrity checks of the uncompressed data. - This version of the library supports only one compression method (deflation) - but other algorithms will be added later and will have the same stream - interface. - - Compression can be done in a single step if the buffers are large enough, - or can be done by repeated calls of the compression function. In the latter - case, the application must provide more input and/or consume the output - (providing more output space) before each call. - - The compressed data format used by default by the in-memory functions is - the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped - around a deflate stream, which is itself documented in RFC 1951. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio using the functions that start - with "gz". The gzip format is different from the zlib format. gzip is a - gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - - This library can optionally read and write gzip streams in memory as well. - - The zlib format was designed to be compact and fast for use in memory - and on communications channels. The gzip format was designed for single- - file compression on file systems, has a larger header than zlib to maintain - directory information, and uses a different, slower check method than zlib. - - The library does not install any signal handler. The decoder checks - the consistency of the compressed data, so the library should never crash - even in case of corrupted input. -*/ - -typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); -typedef void (*free_func) OF((voidpf opaque, voidpf address)); - -struct internal_state; - -typedef struct z_stream_s { - Bytef *next_in; /* next input byte */ - uInt avail_in; /* number of bytes available at next_in */ - uLong total_in; /* total nb of input bytes read so far */ - - Bytef *next_out; /* next output byte should be put there */ - uInt avail_out; /* remaining free space at next_out */ - uLong total_out; /* total nb of bytes output so far */ - - char *msg; /* last error message, NULL if no error */ - struct internal_state FAR *state; /* not visible by applications */ - - alloc_func zalloc; /* used to allocate the internal state */ - free_func zfree; /* used to free the internal state */ - voidpf opaque; /* private data object passed to zalloc and zfree */ - - int data_type; /* best guess about the data type: binary or text */ - uLong adler; /* adler32 value of the uncompressed data */ - uLong reserved; /* reserved for future use */ -} z_stream; - -typedef z_stream FAR *z_streamp; - -/* - gzip header information passed to and from zlib routines. See RFC 1952 - for more details on the meanings of these fields. -*/ -typedef struct gz_header_s { - int text; /* true if compressed data believed to be text */ - uLong time; /* modification time */ - int xflags; /* extra flags (not used when writing a gzip file) */ - int os; /* operating system */ - Bytef *extra; /* pointer to extra field or Z_NULL if none */ - uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ - uInt extra_max; /* space at extra (only when reading header) */ - Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ - uInt name_max; /* space at name (only when reading header) */ - Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ - uInt comm_max; /* space at comment (only when reading header) */ - int hcrc; /* true if there was or will be a header crc */ - int done; /* true when done reading gzip header (not used - when writing a gzip file) */ -} gz_header; - -typedef gz_header FAR *gz_headerp; - -/* - The application must update next_in and avail_in when avail_in has dropped - to zero. It must update next_out and avail_out when avail_out has dropped - to zero. The application must initialize zalloc, zfree and opaque before - calling the init function. All other fields are set by the compression - library and must not be updated by the application. - - The opaque value provided by the application will be passed as the first - parameter for calls of zalloc and zfree. This can be useful for custom - memory management. The compression library attaches no meaning to the - opaque value. - - zalloc must return Z_NULL if there is not enough memory for the object. - If zlib is used in a multi-threaded application, zalloc and zfree must be - thread safe. - - On 16-bit systems, the functions zalloc and zfree must be able to allocate - exactly 65536 bytes, but will not be required to allocate more than this if - the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers - returned by zalloc for objects of exactly 65536 bytes *must* have their - offset normalized to zero. The default allocation function provided by this - library ensures this (see zutil.c). To reduce memory requirements and avoid - any allocation of 64K objects, at the expense of compression ratio, compile - the library with -DMAX_WBITS=14 (see zconf.h). - - The fields total_in and total_out can be used for statistics or progress - reports. After compression, total_in holds the total size of the - uncompressed data and may be saved for use in the decompressor (particularly - if the decompressor wants to decompress everything in a single step). -*/ - - /* constants */ - -#define Z_NO_FLUSH 0 -#define Z_PARTIAL_FLUSH 1 -#define Z_SYNC_FLUSH 2 -#define Z_FULL_FLUSH 3 -#define Z_FINISH 4 -#define Z_BLOCK 5 -#define Z_TREES 6 -/* Allowed flush values; see deflate() and inflate() below for details */ - -#define Z_OK 0 -#define Z_STREAM_END 1 -#define Z_NEED_DICT 2 -#define Z_ERRNO (-1) -#define Z_STREAM_ERROR (-2) -#define Z_DATA_ERROR (-3) -#define Z_MEM_ERROR (-4) -#define Z_BUF_ERROR (-5) -#define Z_VERSION_ERROR (-6) -/* Return codes for the compression/decompression functions. Negative values - * are errors, positive values are used for special but normal events. - */ - -#define Z_NO_COMPRESSION 0 -#define Z_BEST_SPEED 1 -#define Z_BEST_COMPRESSION 9 -#define Z_DEFAULT_COMPRESSION (-1) -/* compression levels */ - -#define Z_FILTERED 1 -#define Z_HUFFMAN_ONLY 2 -#define Z_RLE 3 -#define Z_FIXED 4 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ - -#define Z_BINARY 0 -#define Z_TEXT 1 -#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ -#define Z_UNKNOWN 2 -/* Possible values of the data_type field (though see inflate()) */ - -#define Z_DEFLATED 8 -/* The deflate compression method (the only one supported in this version) */ - -#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ - -#define zlib_version zlibVersion() -/* for compatibility with versions < 1.0.2 */ - - - /* basic functions */ - -ZEXTERN const char * ZEXPORT zlibVersion OF((void)); -/* The application can compare zlibVersion and ZLIB_VERSION for consistency. - If the first character differs, the library code actually used is not - compatible with the zlib.h header file used by the application. This check - is automatically made by deflateInit and inflateInit. - */ - -/* -ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); - - Initializes the internal stream state for compression. The fields - zalloc, zfree and opaque must be initialized before by the caller. If - zalloc and zfree are set to Z_NULL, deflateInit updates them to use default - allocation functions. - - The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: - 1 gives best speed, 9 gives best compression, 0 gives no compression at all - (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION - requests a default compromise between speed and compression (currently - equivalent to level 6). - - deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if level is not a valid compression level, or - Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible - with the version assumed by the caller (ZLIB_VERSION). msg is set to null - if there is no error message. deflateInit does not perform any compression: - this will be done by deflate(). -*/ - - -ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); -/* - deflate compresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. deflate performs one or both of the - following actions: - - - Compress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in and avail_in are updated and - processing will resume at this point for the next call of deflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. This action is forced if the parameter flush is non zero. - Forcing flush frequently degrades the compression ratio, so this parameter - should be set only when necessary (in interactive applications). Some - output may be provided even if flush is not set. - - Before the call of deflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming more - output, and updating avail_in or avail_out accordingly; avail_out should - never be zero before the call. The application can consume the compressed - output when it wants, for example when the output buffer is full (avail_out - == 0), or after each call of deflate(). If deflate returns Z_OK and with - zero avail_out, it must be called again after making room in the output - buffer because there might be more output pending. - - Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to - decide how much data to accumulate before producing output, in order to - maximize compression. - - If the parameter flush is set to Z_SYNC_FLUSH, all pending output is - flushed to the output buffer and the output is aligned on a byte boundary, so - that the decompressor can get all input data available so far. (In - particular avail_in is zero after the call if enough output space has been - provided before the call.) Flushing may degrade compression for some - compression algorithms and so it should be used only when necessary. This - completes the current deflate block and follows it with an empty stored block - that is three bits plus filler bits to the next byte, followed by four bytes - (00 00 ff ff). - - If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the - output buffer, but the output is not aligned to a byte boundary. All of the - input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. - This completes the current deflate block and follows it with an empty fixed - codes block that is 10 bits long. This assures that enough bytes are output - in order for the decompressor to finish the block before the empty fixed code - block. - - If flush is set to Z_BLOCK, a deflate block is completed and emitted, as - for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to - seven bits of the current block are held to be written as the next byte after - the next deflate block is completed. In this case, the decompressor may not - be provided enough bits at this point in order to complete decompression of - the data provided so far to the compressor. It may need to wait for the next - block to be emitted. This is for advanced applications that need to control - the emission of deflate blocks. - - If flush is set to Z_FULL_FLUSH, all output is flushed as with - Z_SYNC_FLUSH, and the compression state is reset so that decompression can - restart from this point if previous compressed data has been damaged or if - random access is desired. Using Z_FULL_FLUSH too often can seriously degrade - compression. - - If deflate returns with avail_out == 0, this function must be called again - with the same value of the flush parameter and more output space (updated - avail_out), until the flush is complete (deflate returns with non-zero - avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. - - If the parameter flush is set to Z_FINISH, pending input is processed, - pending output is flushed and deflate returns with Z_STREAM_END if there was - enough output space; if deflate returns with Z_OK, this function must be - called again with Z_FINISH and more output space (updated avail_out) but no - more input data, until it returns with Z_STREAM_END or an error. After - deflate has returned Z_STREAM_END, the only possible operations on the stream - are deflateReset or deflateEnd. - - Z_FINISH can be used immediately after deflateInit if all the compression - is to be done in a single step. In this case, avail_out must be at least the - value returned by deflateBound (see below). If deflate does not return - Z_STREAM_END, then it must be called again as described above. - - deflate() sets strm->adler to the adler32 checksum of all input read - so far (that is, total_in bytes). - - deflate() may update strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). In doubt, the data is considered - binary. This field is only for information purposes and does not affect the - compression algorithm in any manner. - - deflate() returns Z_OK if some progress has been made (more input - processed or more output produced), Z_STREAM_END if all input has been - consumed and all output has been produced (only when flush is set to - Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example - if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible - (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not - fatal, and deflate() can be called again with more input and more output - space to continue compressing. -*/ - - -ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the - stream state was inconsistent, Z_DATA_ERROR if the stream was freed - prematurely (some input or output was discarded). In the error case, msg - may be set but then points to a static string (which must not be - deallocated). -*/ - - -/* -ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); - - Initializes the internal stream state for decompression. The fields - next_in, avail_in, zalloc, zfree and opaque must be initialized before by - the caller. If next_in is not Z_NULL and avail_in is large enough (the - exact value depends on the compression method), inflateInit determines the - compression method from the zlib header and allocates all data structures - accordingly; otherwise the allocation will be deferred to the first call of - inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to - use default allocation functions. - - inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit() does not process any header information -- that is deferred - until inflate() is called. -*/ - - -ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); -/* - inflate decompresses as much data as possible, and stops when the input - buffer becomes empty or the output buffer becomes full. It may introduce - some output latency (reading input without producing any output) except when - forced to flush. - - The detailed semantics are as follows. inflate performs one or both of the - following actions: - - - Decompress more input starting at next_in and update next_in and avail_in - accordingly. If not all input can be processed (because there is not - enough room in the output buffer), next_in is updated and processing will - resume at this point for the next call of inflate(). - - - Provide more output starting at next_out and update next_out and avail_out - accordingly. inflate() provides as much output as possible, until there is - no more input data or no more space in the output buffer (see below about - the flush parameter). - - Before the call of inflate(), the application should ensure that at least - one of the actions is possible, by providing more input and/or consuming more - output, and updating the next_* and avail_* values accordingly. The - application can consume the uncompressed output when it wants, for example - when the output buffer is full (avail_out == 0), or after each call of - inflate(). If inflate returns Z_OK and with zero avail_out, it must be - called again after making room in the output buffer because there might be - more output pending. - - The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, - Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much - output as possible to the output buffer. Z_BLOCK requests that inflate() - stop if and when it gets to the next deflate block boundary. When decoding - the zlib or gzip format, this will cause inflate() to return immediately - after the header and before the first block. When doing a raw inflate, - inflate() will go ahead and process the first block, and will return when it - gets to the end of that block, or when it runs out of data. - - The Z_BLOCK option assists in appending to or combining deflate streams. - Also to assist in this, on return inflate() will set strm->data_type to the - number of unused bits in the last byte taken from strm->next_in, plus 64 if - inflate() is currently decoding the last block in the deflate stream, plus - 128 if inflate() returned immediately after decoding an end-of-block code or - decoding the complete header up to just before the first byte of the deflate - stream. The end-of-block will not be indicated until all of the uncompressed - data from that block has been written to strm->next_out. The number of - unused bits may in general be greater than seven, except when bit 7 of - data_type is set, in which case the number of unused bits will be less than - eight. data_type is set as noted here every time inflate() returns for all - flush options, and so can be used to determine the amount of currently - consumed input in bits. - - The Z_TREES option behaves as Z_BLOCK does, but it also returns when the - end of each deflate block header is reached, before any actual data in that - block is decoded. This allows the caller to determine the length of the - deflate block header for later use in random access within a deflate block. - 256 is added to the value of strm->data_type when inflate() returns - immediately after reaching the end of the deflate block header. - - inflate() should normally be called until it returns Z_STREAM_END or an - error. However if all decompression is to be performed in a single step (a - single call of inflate), the parameter flush should be set to Z_FINISH. In - this case all pending input is processed and all pending output is flushed; - avail_out must be large enough to hold all the uncompressed data. (The size - of the uncompressed data may have been saved by the compressor for this - purpose.) The next operation on this stream must be inflateEnd to deallocate - the decompression state. The use of Z_FINISH is never required, but can be - used to inform inflate that a faster approach may be used for the single - inflate() call. - - In this implementation, inflate() always flushes as much output as - possible to the output buffer, and always uses the faster approach on the - first call. So the only effect of the flush parameter in this implementation - is on the return value of inflate(), as noted below, or when it returns early - because Z_BLOCK or Z_TREES is used. - - If a preset dictionary is needed after this call (see inflateSetDictionary - below), inflate sets strm->adler to the adler32 checksum of the dictionary - chosen by the compressor and returns Z_NEED_DICT; otherwise it sets - strm->adler to the adler32 checksum of all output produced so far (that is, - total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described - below. At the end of the stream, inflate() checks that its computed adler32 - checksum is equal to that saved by the compressor and returns Z_STREAM_END - only if the checksum is correct. - - inflate() can decompress and check either zlib-wrapped or gzip-wrapped - deflate data. The header type is detected automatically, if requested when - initializing with inflateInit2(). Any information contained in the gzip - header is not retained, so applications that need that information should - instead use raw inflate, see inflateInit2() below, or inflateBack() and - perform their own processing of the gzip header and trailer. - - inflate() returns Z_OK if some progress has been made (more input processed - or more output produced), Z_STREAM_END if the end of the compressed data has - been reached and all uncompressed output has been produced, Z_NEED_DICT if a - preset dictionary is needed at this point, Z_DATA_ERROR if the input data was - corrupted (input stream not conforming to the zlib format or incorrect check - value), Z_STREAM_ERROR if the stream structure was inconsistent (for example - next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, - Z_BUF_ERROR if no progress is possible or if there was not enough room in the - output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and - inflate() can be called again with more input and more output space to - continue decompressing. If Z_DATA_ERROR is returned, the application may - then call inflateSync() to look for a good compression block if a partial - recovery of the data is desired. -*/ - - -ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); -/* - All dynamically allocated data structures for this stream are freed. - This function discards any unprocessed input and does not flush any pending - output. - - inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state - was inconsistent. In the error case, msg may be set but then points to a - static string (which must not be deallocated). -*/ - - - /* Advanced functions */ - -/* - The following functions are needed only in some special applications. -*/ - -/* -ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, - int level, - int method, - int windowBits, - int memLevel, - int strategy)); - - This is another version of deflateInit with more compression options. The - fields next_in, zalloc, zfree and opaque must be initialized before by the - caller. - - The method parameter is the compression method. It must be Z_DEFLATED in - this version of the library. - - The windowBits parameter is the base two logarithm of the window size - (the size of the history buffer). It should be in the range 8..15 for this - version of the library. Larger values of this parameter result in better - compression at the expense of memory usage. The default value is 15 if - deflateInit is used instead. - - windowBits can also be -8..-15 for raw deflate. In this case, -windowBits - determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute an adler32 check value. - - windowBits can also be greater than 15 for optional gzip encoding. Add - 16 to windowBits to write a simple gzip header and trailer around the - compressed data instead of a zlib wrapper. The gzip header will have no - file name, no extra data, no comment, no modification time (set to zero), no - header crc, and the operating system will be set to 255 (unknown). If a - gzip stream is being written, strm->adler is a crc32 instead of an adler32. - - The memLevel parameter specifies how much memory should be allocated - for the internal compression state. memLevel=1 uses minimum memory but is - slow and reduces compression ratio; memLevel=9 uses maximum memory for - optimal speed. The default value is 8. See zconf.h for total memory usage - as a function of windowBits and memLevel. - - The strategy parameter is used to tune the compression algorithm. Use the - value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a - filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). Filtered data consists mostly of small values with a somewhat - random distribution. In this case, the compression algorithm is tuned to - compress them better. The effect of Z_FILTERED is to force more Huffman - coding and less string matching; it is somewhat intermediate between - Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as - fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The - strategy parameter only affects the compression ratio but not the - correctness of the compressed output even if it is not set appropriately. - Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler - decoder for special applications. - - deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid - method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is - incompatible with the version assumed by the caller (ZLIB_VERSION). msg is - set to null if there is no error message. deflateInit2 does not perform any - compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the compression dictionary from the given byte sequence - without producing any compressed output. This function must be called - immediately after deflateInit, deflateInit2 or deflateReset, before any call - of deflate. The compressor and decompressor must use exactly the same - dictionary (see inflateSetDictionary). - - The dictionary should consist of strings (byte sequences) that are likely - to be encountered later in the data to be compressed, with the most commonly - used strings preferably put towards the end of the dictionary. Using a - dictionary is most useful when the data to be compressed is short and can be - predicted with good accuracy; the data can then be compressed better than - with the default empty dictionary. - - Depending on the size of the compression data structures selected by - deflateInit or deflateInit2, a part of the dictionary may in effect be - discarded, for example if the dictionary is larger than the window size - provided in deflateInit or deflateInit2. Thus the strings most likely to be - useful should be put at the end of the dictionary, not at the front. In - addition, the current implementation of deflate will use at most the window - size minus 262 bytes of the provided dictionary. - - Upon return of this function, strm->adler is set to the adler32 value - of the dictionary; the decompressor may later use this value to determine - which dictionary has been used by the compressor. (The adler32 value - applies to the whole dictionary even if only a subset of the dictionary is - actually used by the compressor.) If a raw deflate was requested, then the - adler32 value is not computed and strm->adler is not set. - - deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is - inconsistent (for example if deflate has already been called for this stream - or if the compression method is bsort). deflateSetDictionary does not - perform any compression: this will be done by deflate(). -*/ - -ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when several compression strategies will be - tried, for example when there are several ways of pre-processing the input - data with a filter. The streams that will be discarded should then be freed - by calling deflateEnd. Note that deflateCopy duplicates the internal - compression state which can be quite large, so this strategy is slow and can - consume lots of memory. - - deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being Z_NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); -/* - This function is equivalent to deflateEnd followed by deflateInit, - but does not free and reallocate all the internal compression state. The - stream will keep the same compression level and any other attributes that - may have been set by deflateInit2. - - deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL). -*/ - -ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, - int level, - int strategy)); -/* - Dynamically update the compression level and compression strategy. The - interpretation of level and strategy is as in deflateInit2. This can be - used to switch between compression and straight copy of the input data, or - to switch to a different kind of input data requiring a different strategy. - If the compression level is changed, the input available so far is - compressed with the old level (and may be flushed); the new level will take - effect only at the next call of deflate(). - - Before the call of deflateParams, the stream state must be set as for - a call of deflate(), since the currently available input may have to be - compressed and flushed. In particular, strm->avail_out must be non-zero. - - deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source - stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR if - strm->avail_out was zero. -*/ - -ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain)); -/* - Fine tune deflate's internal compression parameters. This should only be - used by someone who understands the algorithm used by zlib's deflate for - searching for the best matching string, and even then only by the most - fanatic optimizer trying to squeeze out the last compressed bit for their - specific input data. Read the deflate.c source code for the meaning of the - max_lazy, good_length, nice_length, and max_chain parameters. - - deflateTune() can be called after deflateInit() or deflateInit2(), and - returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. - */ - -ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, - uLong sourceLen)); -/* - deflateBound() returns an upper bound on the compressed size after - deflation of sourceLen bytes. It must be called after deflateInit() or - deflateInit2(), and after deflateSetHeader(), if used. This would be used - to allocate an output buffer for deflation in a single pass, and so would be - called before deflate(). -*/ - -ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - deflatePrime() inserts bits in the deflate output stream. The intent - is that this function is used to start off the deflate output with the bits - leftover from a previous deflate stream when appending to it. As such, this - function can only be used for raw deflate, and must be used before the first - deflate() call after a deflateInit2() or deflateReset(). bits must be less - than or equal to 16, and that many of the least significant bits of value - will be inserted in the output. - - deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, - gz_headerp head)); -/* - deflateSetHeader() provides gzip header information for when a gzip - stream is requested by deflateInit2(). deflateSetHeader() may be called - after deflateInit2() or deflateReset() and before the first call of - deflate(). The text, time, os, extra field, name, and comment information - in the provided gz_header structure are written to the gzip header (xflag is - ignored -- the extra flags are set according to the compression level). The - caller must assure that, if not Z_NULL, name and comment are terminated with - a zero byte, and that if extra is not Z_NULL, that extra_len bytes are - available there. If hcrc is true, a gzip header crc is included. Note that - the current versions of the command-line version of gzip (up through version - 1.3.x) do not support header crc's, and will report that it is a "multi-part - gzip file" and give up. - - If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). - - deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, - int windowBits)); - - This is another version of inflateInit with an extra parameter. The - fields next_in, avail_in, zalloc, zfree and opaque must be initialized - before by the caller. - - The windowBits parameter is the base two logarithm of the maximum window - size (the size of the history buffer). It should be in the range 8..15 for - this version of the library. The default value is 15 if inflateInit is used - instead. windowBits must be greater than or equal to the windowBits value - provided to deflateInit2() while compressing, or it must be equal to 15 if - deflateInit2() was not used. If a compressed stream with a larger window - size is given as input, inflate() will return with the error code - Z_DATA_ERROR instead of trying to allocate a larger window. - - windowBits can also be zero to request that inflate use the window size in - the zlib header of the compressed stream. - - windowBits can also be -8..-15 for raw inflate. In this case, -windowBits - determines the window size. inflate() will then process raw deflate data, - not looking for a zlib or gzip header, not generating a check value, and not - looking for any check values for comparison at the end of the stream. This - is for use with other formats that use the deflate compressed data format - such as zip. Those formats provide their own check values. If a custom - format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an adler32 or a crc32 be applied to - the uncompressed data as is done in the zlib, gzip, and zip formats. For - most applications, the zlib format should be used as is. Note that comments - above on the use in deflateInit2() applies to the magnitude of windowBits. - - windowBits can also be greater than 15 for optional gzip decoding. Add - 32 to windowBits to enable zlib and gzip decoding with automatic header - detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a - crc32 instead of an adler32. - - inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_VERSION_ERROR if the zlib library version is incompatible with the - version assumed by the caller, or Z_STREAM_ERROR if the parameters are - invalid, such as a null pointer to the structure. msg is set to null if - there is no error message. inflateInit2 does not perform any decompression - apart from possibly reading the zlib header if present: actual decompression - will be done by inflate(). (So next_in and avail_in may be modified, but - next_out and avail_out are unused and unchanged.) The current implementation - of inflateInit2() does not process any header information -- that is - deferred until inflate() is called. -*/ - -ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, - const Bytef *dictionary, - uInt dictLength)); -/* - Initializes the decompression dictionary from the given uncompressed byte - sequence. This function must be called immediately after a call of inflate, - if that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by that call of inflate. - The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called - immediately after inflateInit2() or inflateReset() and before any call of - inflate() to set the dictionary. The application must insure that the - dictionary that was used for compression is provided. - - inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a - parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is - inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the - expected one (incorrect adler32 value). inflateSetDictionary does not - perform any decompression: this will be done by subsequent calls of - inflate(). -*/ - -ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); -/* - Skips invalid compressed data until a full flush point (see above the - description of deflate with Z_FULL_FLUSH) can be found, or until all - available input is skipped. No output is provided. - - inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR - if no more input was provided, Z_DATA_ERROR if no flush point has been - found, or Z_STREAM_ERROR if the stream structure was inconsistent. In the - success case, the application may save the current current value of total_in - which indicates where valid compressed data was found. In the error case, - the application may repeatedly call inflateSync, providing more input each - time, until success or end of the input data. -*/ - -ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, - z_streamp source)); -/* - Sets the destination stream as a complete copy of the source stream. - - This function can be useful when randomly accessing a large stream. The - first pass through the stream can periodically record the inflate state, - allowing restarting inflate at those points when randomly accessing the - stream. - - inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_STREAM_ERROR if the source stream state was inconsistent - (such as zalloc being Z_NULL). msg is left unchanged in both source and - destination. -*/ - -ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); -/* - This function is equivalent to inflateEnd followed by inflateInit, - but does not free and reallocate all the internal decompression state. The - stream will keep attributes that may have been set by inflateInit2. - - inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL). -*/ - -ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, - int windowBits)); -/* - This function is the same as inflateReset, but it also permits changing - the wrap and window size requests. The windowBits parameter is interpreted - the same as it is for inflateInit2. - - inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent (such as zalloc or state being Z_NULL), or if - the windowBits parameter is invalid. -*/ - -ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - This function inserts bits in the inflate input stream. The intent is - that this function is used to start inflating at a bit position in the - middle of a byte. The provided bits will be used before any bytes are used - from next_in. This function should only be used with raw inflate, and - should be used before the first inflate() call after inflateInit2() or - inflateReset(). bits must be less than or equal to 16, and that many of the - least significant bits of value will be inserted in the input. - - If bits is negative, then the input stream bit buffer is emptied. Then - inflatePrime() can be called again to put bits in the buffer. This is used - to clear out bits leftover after feeding inflate a block description prior - to feeding inflate codes. - - inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); -/* - This function returns two values, one in the lower 16 bits of the return - value, and the other in the remaining upper bits, obtained by shifting the - return value down 16 bits. If the upper value is -1 and the lower value is - zero, then inflate() is currently decoding information outside of a block. - If the upper value is -1 and the lower value is non-zero, then inflate is in - the middle of a stored block, with the lower value equaling the number of - bytes from the input remaining to copy. If the upper value is not -1, then - it is the number of bits back from the current bit position in the input of - the code (literal or length/distance pair) currently being processed. In - that case the lower value is the number of bytes already emitted for that - code. - - A code is being processed if inflate is waiting for more input to complete - decoding of the code, or if it has completed decoding but is waiting for - more output space to write the literal or match data. - - inflateMark() is used to mark locations in the input data for random - access, which may be at bit positions, and to note those cases where the - output of a code may span boundaries of random access blocks. The current - location in the input stream can be determined from avail_in and data_type - as noted in the description for the Z_BLOCK flush parameter for inflate. - - inflateMark returns the value noted above or -1 << 16 if the provided - source stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, - gz_headerp head)); -/* - inflateGetHeader() requests that gzip header information be stored in the - provided gz_header structure. inflateGetHeader() may be called after - inflateInit2() or inflateReset(), and before the first call of inflate(). - As inflate() processes the gzip stream, head->done is zero until the header - is completed, at which time head->done is set to one. If a zlib stream is - being decoded, then head->done is set to -1 to indicate that there will be - no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be - used to force inflate() to return immediately after header processing is - complete and before any actual data is decompressed. - - The text, time, xflags, and os fields are filled in with the gzip header - contents. hcrc is set to true if there is a header CRC. (The header CRC - was valid if done is set to one.) If extra is not Z_NULL, then extra_max - contains the maximum number of bytes to write to extra. Once done is true, - extra_len contains the actual extra field length, and extra contains the - extra field, or that field truncated if extra_max is less than extra_len. - If name is not Z_NULL, then up to name_max characters are written there, - terminated with a zero unless the length is greater than name_max. If - comment is not Z_NULL, then up to comm_max characters are written there, - terminated with a zero unless the length is greater than comm_max. When any - of extra, name, or comment are not Z_NULL and the respective field is not - present in the header, then that field is set to Z_NULL to signal its - absence. This allows the use of deflateSetHeader() with the returned - structure to duplicate the header. However if those fields are set to - allocated memory, then the application will need to save those pointers - elsewhere so that they can be eventually freed. - - If inflateGetHeader is not used, then the header information is simply - discarded. The header is always checked for validity, including the header - CRC if present. inflateReset() will reset the process to discard the header - information. The application would need to call inflateGetHeader() again to - retrieve the header from the next gzip stream. - - inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, - unsigned char FAR *window)); - - Initialize the internal stream state for decompression using inflateBack() - calls. The fields zalloc, zfree and opaque in strm must be initialized - before the call. If zalloc and zfree are Z_NULL, then the default library- - derived memory allocation routines are used. windowBits is the base two - logarithm of the window size, in the range 8..15. window is a caller - supplied buffer of that size. Except for special applications where it is - assured that deflate was used with small window sizes, windowBits must be 15 - and a 32K byte window must be supplied to be able to decompress general - deflate streams. - - See inflateBack() for the usage of these routines. - - inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the paramaters are invalid, Z_MEM_ERROR if the internal state could not be - allocated, or Z_VERSION_ERROR if the version of the library does not match - the version of the header file. -*/ - -typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); -typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); - -ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); -/* - inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is more efficient than inflate() for - file i/o applications in that it avoids copying between the output and the - sliding window by simply making the window itself the output buffer. This - function trusts the application to not change the output buffer passed by - the output function, at least until inflateBack() returns. - - inflateBackInit() must be called first to allocate the internal state - and to initialize the state with the user-provided window buffer. - inflateBack() may then be used multiple times to inflate a complete, raw - deflate stream with each call. inflateBackEnd() is then called to free the - allocated state. - - A raw deflate stream is one with no zlib or gzip header or trailer. - This routine would normally be used in a utility that reads zip or gzip - files and writes out uncompressed files. The utility would decode the - header and process the trailer on its own, hence this routine expects only - the raw deflate stream to decompress. This is different from the normal - behavior of inflate(), which expects either a zlib or gzip header and - trailer around the deflate stream. - - inflateBack() uses two subroutines supplied by the caller that are then - called by inflateBack() for input and output. inflateBack() calls those - routines until it reads a complete deflate stream and writes out all of the - uncompressed data, or until it encounters an error. The function's - parameters and return types are defined above in the in_func and out_func - typedefs. inflateBack() will call in(in_desc, &buf) which should return the - number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero--buf is ignored in that - case--and inflateBack() will return a buffer error. inflateBack() will call - out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() - should return zero on success, or non-zero on failure. If out() returns - non-zero, inflateBack() will return with an error. Neither in() nor out() - are permitted to change the contents of the window provided to - inflateBackInit(), which is also the buffer that out() uses to write from. - The length written by out() will be at most the window size. Any non-zero - amount of input may be provided by in(). - - For convenience, inflateBack() can be provided input on the first call by - setting strm->next_in and strm->avail_in. If that input is exhausted, then - in() will be called. Therefore strm->next_in must be initialized before - calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called - immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in - must also be initialized, and then if strm->avail_in is not zero, input will - initially be taken from strm->next_in[0 .. strm->avail_in - 1]. - - The in_desc and out_desc parameters of inflateBack() is passed as the - first parameter of in() and out() respectively when they are called. These - descriptors can be optionally used to pass any information that the caller- - supplied in() and out() functions need to do their job. - - On return, inflateBack() will set strm->next_in and strm->avail_in to - pass back any unused input that was provided by the last in() call. The - return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR - if in() or out() returned an error, Z_DATA_ERROR if there was a format error - in the deflate stream (in which case strm->msg is set to indicate the nature - of the error), or Z_STREAM_ERROR if the stream was not properly initialized. - In the case of Z_BUF_ERROR, an input or output error can be distinguished - using strm->next_in which will be Z_NULL only if in() returned an error. If - strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning - non-zero. (in() will always be called before out(), so strm->next_in is - assured to be defined if out() returns non-zero.) Note that inflateBack() - cannot return Z_OK. -*/ - -ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); -/* - All memory allocated by inflateBackInit() is freed. - - inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream - state was inconsistent. -*/ - -ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); -/* Return flags indicating compile-time options. - - Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: - 1.0: size of uInt - 3.2: size of uLong - 5.4: size of voidpf (pointer) - 7.6: size of z_off_t - - Compiler, assembler, and debug options: - 8: DEBUG - 9: ASMV or ASMINF -- use ASM code - 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention - 11: 0 (reserved) - - One-time table building (smaller code, but not thread-safe if true): - 12: BUILDFIXED -- build static block decoding tables when needed - 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed - 14,15: 0 (reserved) - - Library content (indicates missing functionality): - 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking - deflate code when not needed) - 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect - and decode gzip streams (to avoid linking crc code) - 18-19: 0 (reserved) - - Operation variations (changes in library functionality): - 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate - 21: FASTEST -- deflate algorithm with only one, lowest compression level - 22,23: 0 (reserved) - - The sprintf variant used by gzprintf (zero is best): - 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format - 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! - 26: 0 = returns value, 1 = void -- 1 means inferred string length returned - - Remainder: - 27-31: 0 (reserved) - */ - - - /* utility functions */ - -/* - The following utility functions are implemented on top of the basic - stream-oriented functions. To simplify the interface, some default options - are assumed (compression level and memory usage, standard memory allocation - functions). The source code of these utility functions can be modified if - you need special options. -*/ - -ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Compresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - - compress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer. -*/ - -ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen, - int level)); -/* - Compresses the source buffer into the destination buffer. The level - parameter has the same meaning as in deflateInit. sourceLen is the byte - length of the source buffer. Upon entry, destLen is the total size of the - destination buffer, which must be at least the value returned by - compressBound(sourceLen). Upon exit, destLen is the actual size of the - compressed buffer. - - compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough - memory, Z_BUF_ERROR if there was not enough room in the output buffer, - Z_STREAM_ERROR if the level parameter is invalid. -*/ - -ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); -/* - compressBound() returns an upper bound on the compressed size after - compress() or compress2() on sourceLen bytes. It would be used before a - compress() or compress2() call to allocate the destination buffer. -*/ - -ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, - const Bytef *source, uLong sourceLen)); -/* - Decompresses the source buffer into the destination buffer. sourceLen is - the byte length of the source buffer. Upon entry, destLen is the total size - of the destination buffer, which must be large enough to hold the entire - uncompressed data. (The size of the uncompressed data must have been saved - previously by the compressor and transmitted to the decompressor by some - mechanism outside the scope of this compression library.) Upon exit, destLen - is the actual size of the uncompressed buffer. - - uncompress returns Z_OK if success, Z_MEM_ERROR if there was not - enough memory, Z_BUF_ERROR if there was not enough room in the output - buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. -*/ - - - /* gzip file access functions */ - -/* - This library supports reading and writing files in gzip (.gz) format with - an interface similar to that of stdio, using the functions that start with - "gz". The gzip format is different from the zlib format. gzip is a gzip - wrapper, documented in RFC 1952, wrapped around a deflate stream. -*/ - -typedef voidp gzFile; /* opaque gzip file descriptor */ - -/* -ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); - - Opens a gzip (.gz) file for reading or writing. The mode parameter is as - in fopen ("rb" or "wb") but can also include a compression level ("wb9") or - a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only - compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' - for fixed code compression as in "wb9F". (See the description of - deflateInit2 for more information about the strategy parameter.) Also "a" - can be used instead of "w" to request that the gzip stream that will be - written be appended to the file. "+" will result in an error, since reading - and writing to the same gzip file is not supported. - - gzopen can be used to read a file which is not in gzip format; in this - case gzread will directly read from the file without decompression. - - gzopen returns NULL if the file could not be opened, if there was - insufficient memory to allocate the gzFile state, or if an invalid mode was - specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). - errno can be checked to determine if the reason gzopen failed was that the - file could not be opened. -*/ - -ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); -/* - gzdopen associates a gzFile with the file descriptor fd. File descriptors - are obtained from calls like open, dup, creat, pipe or fileno (if the file - has been previously opened with fopen). The mode parameter is as in gzopen. - - The next call of gzclose on the returned gzFile will also close the file - descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor - fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, - mode);. The duplicated descriptor should be saved to avoid a leak, since - gzdopen does not close fd if it fails. - - gzdopen returns NULL if there was insufficient memory to allocate the - gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not - provided, or '+' was provided), or if fd is -1. The file descriptor is not - used until the next gz* read, write, seek, or close operation, so gzdopen - will not detect if fd is invalid (unless fd is -1). -*/ - -ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); -/* - Set the internal buffer size used by this library's functions. The - default buffer size is 8192 bytes. This function must be called after - gzopen() or gzdopen(), and before any other calls that read or write the - file. The buffer memory allocation is always deferred to the first read or - write. Two buffers are allocated, either both of the specified size when - writing, or one of the specified size and the other twice that size when - reading. A larger buffer size of, for example, 64K or 128K bytes will - noticeably increase the speed of decompression (reading). - - The new buffer size also affects the maximum length for gzprintf(). - - gzbuffer() returns 0 on success, or -1 on failure, such as being called - too late. -*/ - -ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); -/* - Dynamically update the compression level or strategy. See the description - of deflateInit2 for the meaning of these parameters. - - gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not - opened for writing. -*/ - -ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); -/* - Reads the given number of uncompressed bytes from the compressed file. If - the input file was not in gzip format, gzread copies the given number of - bytes into the buffer. - - After reaching the end of a gzip stream in the input, gzread will continue - to read, looking for another gzip stream, or failing that, reading the rest - of the input file directly without decompression. The entire input file - will be read if gzread is called until it returns less than the requested - len. - - gzread returns the number of uncompressed bytes actually read, less than - len for end of file, or -1 for error. -*/ - -ZEXTERN int ZEXPORT gzwrite OF((gzFile file, - voidpc buf, unsigned len)); -/* - Writes the given number of uncompressed bytes into the compressed file. - gzwrite returns the number of uncompressed bytes written or 0 in case of - error. -*/ - -ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); -/* - Converts, formats, and writes the arguments to the compressed file under - control of the format string, as in fprintf. gzprintf returns the number of - uncompressed bytes actually written, or 0 in case of error. The number of - uncompressed bytes written is limited to 8191, or one less than the buffer - size given to gzbuffer(). The caller should assure that this limit is not - exceeded. If it is exceeded, then gzprintf() will return an error (0) with - nothing written. In this case, there may also be a buffer overflow with - unpredictable consequences, which is possible only if zlib was compiled with - the insecure functions sprintf() or vsprintf() because the secure snprintf() - or vsnprintf() functions were not available. This can be determined using - zlibCompileFlags(). -*/ - -ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); -/* - Writes the given null-terminated string to the compressed file, excluding - the terminating null character. - - gzputs returns the number of characters written, or -1 in case of error. -*/ - -ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); -/* - Reads bytes from the compressed file until len-1 characters are read, or a - newline character is read and transferred to buf, or an end-of-file - condition is encountered. If any characters are read or if len == 1, the - string is terminated with a null character. If no characters are read due - to an end-of-file or len < 1, then the buffer is left untouched. - - gzgets returns buf which is a null-terminated string, or it returns NULL - for end-of-file or in case of error. If there was an error, the contents at - buf are indeterminate. -*/ - -ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); -/* - Writes c, converted to an unsigned char, into the compressed file. gzputc - returns the value that was written, or -1 in case of error. -*/ - -ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); -/* - Reads one byte from the compressed file. gzgetc returns this byte or -1 - in case of end of file or error. -*/ - -ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); -/* - Push one character back onto the stream to be read as the first character - on the next read. At least one character of push-back is allowed. - gzungetc() returns the character pushed, or -1 on failure. gzungetc() will - fail if c is -1, and may fail if a character has been pushed but not read - yet. If gzungetc is used immediately after gzopen or gzdopen, at least the - output buffer size of pushed characters is allowed. (See gzbuffer above.) - The pushed character will be discarded if the stream is repositioned with - gzseek() or gzrewind(). -*/ - -ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); -/* - Flushes all pending output into the compressed file. The parameter flush - is as in the deflate() function. The return value is the zlib error number - (see function gzerror below). gzflush is only permitted when writing. - - If the flush parameter is Z_FINISH, the remaining data is written and the - gzip stream is completed in the output. If gzwrite() is called again, a new - gzip stream will be started in the output. gzread() is able to read such - concatented gzip streams. - - gzflush should be called only when strictly necessary because it will - degrade compression if called too often. -*/ - -/* -ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, - z_off_t offset, int whence)); - - Sets the starting position for the next gzread or gzwrite on the given - compressed file. The offset represents a number of bytes in the - uncompressed data stream. The whence parameter is defined as in lseek(2); - the value SEEK_END is not supported. - - If the file is opened for reading, this function is emulated but can be - extremely slow. If the file is opened for writing, only forward seeks are - supported; gzseek then compresses a sequence of zeroes up to the new - starting position. - - gzseek returns the resulting offset location as measured in bytes from - the beginning of the uncompressed stream, or -1 in case of error, in - particular if the file is opened for writing and the new starting position - would be before the current position. -*/ - -ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); -/* - Rewinds the given file. This function is supported only for reading. - - gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) -*/ - -/* -ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); - - Returns the starting position for the next gzread or gzwrite on the given - compressed file. This position represents a number of bytes in the - uncompressed data stream, and is zero when starting, even if appending or - reading a gzip stream from the middle of a file using gzdopen(). - - gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) -*/ - -/* -ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); - - Returns the current offset in the file being read or written. This offset - includes the count of bytes that precede the gzip stream, for example when - appending or when using gzdopen() for reading. When reading, the offset - does not include as yet unused buffered input. This information can be used - for a progress indicator. On error, gzoffset() returns -1. -*/ - -ZEXTERN int ZEXPORT gzeof OF((gzFile file)); -/* - Returns true (1) if the end-of-file indicator has been set while reading, - false (0) otherwise. Note that the end-of-file indicator is set only if the - read tried to go past the end of the input, but came up short. Therefore, - just like feof(), gzeof() may return false even if there is no more data to - read, in the event that the last read request was for the exact number of - bytes remaining in the input file. This will happen if the input file size - is an exact multiple of the buffer size. - - If gzeof() returns true, then the read functions will return no more data, - unless the end-of-file indicator is reset by gzclearerr() and the input file - has grown since the previous end of file was detected. -*/ - -ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); -/* - Returns true (1) if file is being copied directly while reading, or false - (0) if file is a gzip stream being decompressed. This state can change from - false to true while reading the input file if the end of a gzip stream is - reached, but is followed by data that is not another gzip stream. - - If the input file is empty, gzdirect() will return true, since the input - does not contain a gzip stream. - - If gzdirect() is used immediately after gzopen() or gzdopen() it will - cause buffers to be allocated to allow reading the file to determine if it - is a gzip file. Therefore if gzbuffer() is used, it should be called before - gzdirect(). -*/ - -ZEXTERN int ZEXPORT gzclose OF((gzFile file)); -/* - Flushes all pending output if necessary, closes the compressed file and - deallocates the (de)compression state. Note that once file is closed, you - cannot call gzerror with file, since its structures have been deallocated. - gzclose must not be called more than once on the same file, just as free - must not be called more than once on the same allocation. - - gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a - file operation error, or Z_OK on success. -*/ - -ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); -ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); -/* - Same as gzclose(), but gzclose_r() is only for use when reading, and - gzclose_w() is only for use when writing or appending. The advantage to - using these instead of gzclose() is that they avoid linking in zlib - compression or decompression code that is not used when only reading or only - writing respectively. If gzclose() is used, then both compression and - decompression code will be included the application when linking to a static - zlib library. -*/ - -ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); -/* - Returns the error message for the last error which occurred on the given - compressed file. errnum is set to zlib error number. If an error occurred - in the file system and not in the compression library, errnum is set to - Z_ERRNO and the application may consult errno to get the exact error code. - - The application must not modify the returned string. Future calls to - this function may invalidate the previously returned string. If file is - closed, then the string previously returned by gzerror will no longer be - available. - - gzerror() should be used to distinguish errors from end-of-file for those - functions above that do not distinguish those cases in their return values. -*/ - -ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); -/* - Clears the error and end-of-file flags for file. This is analogous to the - clearerr() function in stdio. This is useful for continuing to read a gzip - file that is being written concurrently. -*/ - - - /* checksum functions */ - -/* - These functions are not related to compression but are exported - anyway because they might be useful in applications using the compression - library. -*/ - -ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); -/* - Update a running Adler-32 checksum with the bytes buf[0..len-1] and - return the updated checksum. If buf is Z_NULL, this function returns the - required initial value for the checksum. - - An Adler-32 checksum is almost as reliable as a CRC32 but can be computed - much faster. - - Usage example: - - uLong adler = adler32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - adler = adler32(adler, buffer, length); - } - if (adler != original_adler) error(); -*/ - -/* -ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, - z_off_t len2)); - - Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 - and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for - each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. -*/ - -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -/* - Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. If buf is Z_NULL, this function returns the required - initial value for the for the crc. Pre- and post-conditioning (one's - complement) is performed within this function so it shouldn't be done by the - application. - - Usage example: - - uLong crc = crc32(0L, Z_NULL, 0); - - while (read_buffer(buffer, length) != EOF) { - crc = crc32(crc, buffer, length); - } - if (crc != original_crc) error(); -*/ - -/* -ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); - - Combine two CRC-32 check values into one. For two sequences of bytes, - seq1 and seq2 with lengths len1 and len2, CRC-32 check values were - calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 - check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. -*/ - - - /* various hacks, don't look :) */ - -/* deflateInit and inflateInit are macros to allow checking the zlib version - * and the compiler's view of z_stream: - */ -ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, - int windowBits, int memLevel, - int strategy, const char *version, - int stream_size)); -ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, - const char *version, int stream_size)); -ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, - unsigned char FAR *window, - const char *version, - int stream_size)); -#define deflateInit(strm, level) \ - deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit(strm) \ - inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) -#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ - deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ - (strategy), ZLIB_VERSION, sizeof(z_stream)) -#define inflateInit2(strm, windowBits) \ - inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) -#define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, sizeof(z_stream)) - -/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or - * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if - * both are true, the application gets the *64 functions, and the regular - * functions are changed to 64 bits) -- in case these are set on systems - * without large file support, _LFS64_LARGEFILE must also be true - */ -#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); - ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); -#endif - -#if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS-0 == 64 && _LFS64_LARGEFILE-0 -# define gzopen gzopen64 -# define gzseek gzseek64 -# define gztell gztell64 -# define gzoffset gzoffset64 -# define adler32_combine adler32_combine64 -# define crc32_combine crc32_combine64 -# ifdef _LARGEFILE64_SOURCE - ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); -# endif -#else - ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); - ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); - ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); - ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); - ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); - ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); -#endif - -/* hack for buggy compilers */ -#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; -#endif - -/* undocumented functions */ -ZEXTERN const char * ZEXPORT zError OF((int)); -ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); -ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); -ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); - -#ifdef __cplusplus -} -#endif - -#endif /* ZLIB_H */ diff --git a/lib/libpng14.a b/lib/libpng14.a deleted file mode 100644 index 3ce34d79355fb530c009d6ca38a151a33ec9cbce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 210758 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

guac`Div~-je#o^L(To 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 h0zHO?IPp_KcciXv0#p4)^6$?_<>ELkH; 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 diff --git a/src/lodepng.c b/src/lodepng.c new file mode 100644 index 0000000..05287bb --- /dev/null +++ b/src/lodepng.c @@ -0,0 +1,6853 @@ +/* +LodePNG version 20180910 + +Copyright (c) 2005-2018 Lode Vandevenne + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any damages +arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + + 3. This notice may not be removed or altered from any source + distribution. +*/ + +/* +The manual and changelog are in the header file "lodepng.h" +Rename this file to lodepng.cpp to use it for C++, or to lodepng.c to use it for C. +*/ + +#include "lodepng.h" + +#include +#include +#include + +#if defined(_MSC_VER) && (_MSC_VER >= 1310) /*Visual Studio: A few warning types are not desired here.*/ +#pragma warning( disable : 4244 ) /*implicit conversions: not warned by gcc -Wall -Wextra and requires too much casts*/ +#pragma warning( disable : 4996 ) /*VS does not like fopen, but fopen_s is not standard C so unusable here*/ +#endif /*_MSC_VER */ + +const char* LODEPNG_VERSION_STRING = "20180910"; + +/* +This source file is built up in the following large parts. The code sections +with the "LODEPNG_COMPILE_" #defines divide this up further in an intermixed way. +-Tools for C and common code for PNG and Zlib +-C Code for Zlib (huffman, deflate, ...) +-C Code for PNG (file format chunks, adam7, PNG filters, color conversions, ...) +-The C++ wrapper around all of the above +*/ + +/*The malloc, realloc and free functions defined here with "lodepng_" in front +of the name, so that you can easily change them to others related to your +platform if needed. Everything else in the code calls these. Pass +-DLODEPNG_NO_COMPILE_ALLOCATORS to the compiler, or comment out +#define LODEPNG_COMPILE_ALLOCATORS in the header, to disable the ones here and +define them in your own project's source files without needing to change +lodepng source code. Don't forget to remove "static" if you copypaste them +from here.*/ + +#ifdef LODEPNG_COMPILE_ALLOCATORS +static void* lodepng_malloc(size_t size) +{ +#ifdef LODEPNG_MAX_ALLOC + if(size > LODEPNG_MAX_ALLOC) return 0; +#endif + return malloc(size); +} + +static void* lodepng_realloc(void* ptr, size_t new_size) +{ +#ifdef LODEPNG_MAX_ALLOC + if(new_size > LODEPNG_MAX_ALLOC) return 0; +#endif + return realloc(ptr, new_size); +} + +static void lodepng_free(void* ptr) +{ + free(ptr); +} +#else /*LODEPNG_COMPILE_ALLOCATORS*/ +void* lodepng_malloc(size_t size); +void* lodepng_realloc(void* ptr, size_t new_size); +void lodepng_free(void* ptr); +#endif /*LODEPNG_COMPILE_ALLOCATORS*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // Tools for C, and common code for PNG and Zlib. // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#define LODEPNG_MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define LODEPNG_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +/* +Often in case of an error a value is assigned to a variable and then it breaks +out of a loop (to go to the cleanup phase of a function). This macro does that. +It makes the error handling code shorter and more readable. + +Example: if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83); +*/ +#define CERROR_BREAK(errorvar, code)\ +{\ + errorvar = code;\ + break;\ +} + +/*version of CERROR_BREAK that assumes the common case where the error variable is named "error"*/ +#define ERROR_BREAK(code) CERROR_BREAK(error, code) + +/*Set error var to the error code, and return it.*/ +#define CERROR_RETURN_ERROR(errorvar, code)\ +{\ + errorvar = code;\ + return code;\ +} + +/*Try the code, if it returns error, also return the error.*/ +#define CERROR_TRY_RETURN(call)\ +{\ + unsigned error = call;\ + if(error) return error;\ +} + +/*Set error var to the error code, and return from the void function.*/ +#define CERROR_RETURN(errorvar, code)\ +{\ + errorvar = code;\ + return;\ +} + +/* +About uivector, ucvector and string: +-All of them wrap dynamic arrays or text strings in a similar way. +-LodePNG was originally written in C++. The vectors replace the std::vectors that were used in the C++ version. +-The string tools are made to avoid problems with compilers that declare things like strncat as deprecated. +-They're not used in the interface, only internally in this file as static functions. +-As with many other structs in this file, the init and cleanup functions serve as ctor and dtor. +*/ + +#ifdef LODEPNG_COMPILE_ZLIB +/*dynamic vector of unsigned ints*/ +typedef struct uivector +{ + unsigned* data; + size_t size; /*size in number of unsigned longs*/ + size_t allocsize; /*allocated size in bytes*/ +} uivector; + +static void uivector_cleanup(void* p) +{ + ((uivector*)p)->size = ((uivector*)p)->allocsize = 0; + lodepng_free(((uivector*)p)->data); + ((uivector*)p)->data = NULL; +} + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned uivector_reserve(uivector* p, size_t allocsize) +{ + if(allocsize > p->allocsize) + { + size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2); + void* data = lodepng_realloc(p->data, newsize); + if(data) + { + p->allocsize = newsize; + p->data = (unsigned*)data; + } + else return 0; /*error: not enough memory*/ + } + return 1; +} + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned uivector_resize(uivector* p, size_t size) +{ + if(!uivector_reserve(p, size * sizeof(unsigned))) return 0; + p->size = size; + return 1; /*success*/ +} + +/*resize and give all new elements the value*/ +static unsigned uivector_resizev(uivector* p, size_t size, unsigned value) +{ + size_t oldsize = p->size, i; + if(!uivector_resize(p, size)) return 0; + for(i = oldsize; i < size; ++i) p->data[i] = value; + return 1; +} + +static void uivector_init(uivector* p) +{ + p->data = NULL; + p->size = p->allocsize = 0; +} + +#ifdef LODEPNG_COMPILE_ENCODER +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned uivector_push_back(uivector* p, unsigned c) +{ + if(!uivector_resize(p, p->size + 1)) return 0; + p->data[p->size - 1] = c; + return 1; +} +#endif /*LODEPNG_COMPILE_ENCODER*/ +#endif /*LODEPNG_COMPILE_ZLIB*/ + +/* /////////////////////////////////////////////////////////////////////////// */ + +/*dynamic vector of unsigned chars*/ +typedef struct ucvector +{ + unsigned char* data; + size_t size; /*used size*/ + size_t allocsize; /*allocated size*/ +} ucvector; + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned ucvector_reserve(ucvector* p, size_t allocsize) +{ + if(allocsize > p->allocsize) + { + size_t newsize = (allocsize > p->allocsize * 2) ? allocsize : (allocsize * 3 / 2); + void* data = lodepng_realloc(p->data, newsize); + if(data) + { + p->allocsize = newsize; + p->data = (unsigned char*)data; + } + else return 0; /*error: not enough memory*/ + } + return 1; +} + +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned ucvector_resize(ucvector* p, size_t size) +{ + if(!ucvector_reserve(p, size * sizeof(unsigned char))) return 0; + p->size = size; + return 1; /*success*/ +} + +#ifdef LODEPNG_COMPILE_PNG + +static void ucvector_cleanup(void* p) +{ + ((ucvector*)p)->size = ((ucvector*)p)->allocsize = 0; + lodepng_free(((ucvector*)p)->data); + ((ucvector*)p)->data = NULL; +} + +static void ucvector_init(ucvector* p) +{ + p->data = NULL; + p->size = p->allocsize = 0; +} +#endif /*LODEPNG_COMPILE_PNG*/ + +#ifdef LODEPNG_COMPILE_ZLIB +/*you can both convert from vector to buffer&size and vica versa. If you use +init_buffer to take over a buffer and size, it is not needed to use cleanup*/ +static void ucvector_init_buffer(ucvector* p, unsigned char* buffer, size_t size) +{ + p->data = buffer; + p->allocsize = p->size = size; +} +#endif /*LODEPNG_COMPILE_ZLIB*/ + +#if (defined(LODEPNG_COMPILE_PNG) && defined(LODEPNG_COMPILE_ANCILLARY_CHUNKS)) || defined(LODEPNG_COMPILE_ENCODER) +/*returns 1 if success, 0 if failure ==> nothing done*/ +static unsigned ucvector_push_back(ucvector* p, unsigned char c) +{ + if(!ucvector_resize(p, p->size + 1)) return 0; + p->data[p->size - 1] = c; + return 1; +} +#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/ + + +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_PNG +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + +/*free string pointer and set it to NULL*/ +static void string_cleanup(char** out) +{ + lodepng_free(*out); + *out = NULL; +} + +/* dynamically allocates a new string with a copy of the null terminated input text */ +static char* alloc_string(const char* in) +{ + size_t insize = strlen(in); + char* out = (char*)lodepng_malloc(insize + 1); + if(out) + { + size_t i; + for(i = 0; i != insize; ++i) + { + out[i] = in[i]; + } + out[i] = 0; + } + return out; +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +/* ////////////////////////////////////////////////////////////////////////// */ + +unsigned lodepng_read32bitInt(const unsigned char* buffer) +{ + return (unsigned)((buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]); +} + +#if defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER) +/*buffer must have at least 4 allocated bytes available*/ +static void lodepng_set32bitInt(unsigned char* buffer, unsigned value) +{ + buffer[0] = (unsigned char)((value >> 24) & 0xff); + buffer[1] = (unsigned char)((value >> 16) & 0xff); + buffer[2] = (unsigned char)((value >> 8) & 0xff); + buffer[3] = (unsigned char)((value ) & 0xff); +} +#endif /*defined(LODEPNG_COMPILE_PNG) || defined(LODEPNG_COMPILE_ENCODER)*/ + +#ifdef LODEPNG_COMPILE_ENCODER +static void lodepng_add32bitInt(ucvector* buffer, unsigned value) +{ + ucvector_resize(buffer, buffer->size + 4); /*todo: give error if resize failed*/ + lodepng_set32bitInt(&buffer->data[buffer->size - 4], value); +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / File IO / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_DISK + +/* returns negative value on error. This should be pure C compatible, so no fstat. */ +static long lodepng_filesize(const char* filename) +{ + FILE* file; + long size; + file = fopen(filename, "rb"); + if(!file) return -1; + + if(fseek(file, 0, SEEK_END) != 0) + { + fclose(file); + return -1; + } + + size = ftell(file); + /* It may give LONG_MAX as directory size, this is invalid for us. */ + if(size == LONG_MAX) size = -1; + + fclose(file); + return size; +} + +/* load file into buffer that already has the correct allocated size. Returns error code.*/ +static unsigned lodepng_buffer_file(unsigned char* out, size_t size, const char* filename) +{ + FILE* file; + size_t readsize; + file = fopen(filename, "rb"); + if(!file) return 78; + + readsize = fread(out, 1, size, file); + fclose(file); + + if (readsize != size) return 78; + return 0; +} + +unsigned lodepng_load_file(unsigned char** out, size_t* outsize, const char* filename) +{ + long size = lodepng_filesize(filename); + if (size < 0) return 78; + *outsize = (size_t)size; + + *out = (unsigned char*)lodepng_malloc((size_t)size); + if(!(*out) && size > 0) return 83; /*the above malloc failed*/ + + return lodepng_buffer_file(*out, (size_t)size, filename); +} + +/*write given buffer to the file, overwriting the file, it doesn't append to it.*/ +unsigned lodepng_save_file(const unsigned char* buffer, size_t buffersize, const char* filename) +{ + FILE* file; + file = fopen(filename, "wb" ); + if(!file) return 79; + fwrite(buffer, 1, buffersize, file); + fclose(file); + return 0; +} + +#endif /*LODEPNG_COMPILE_DISK*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // End of common code and tools. Begin of Zlib related code. // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_ENCODER +/*TODO: this ignores potential out of memory errors*/ +#define addBitToStream(/*size_t**/ bitpointer, /*ucvector**/ bitstream, /*unsigned char*/ bit)\ +{\ + /*add a new byte at the end*/\ + if(((*bitpointer) & 7) == 0) ucvector_push_back(bitstream, (unsigned char)0);\ + /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/\ + (bitstream->data[bitstream->size - 1]) |= (bit << ((*bitpointer) & 0x7));\ + ++(*bitpointer);\ +} + +static void addBitsToStream(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) +{ + size_t i; + for(i = 0; i != nbits; ++i) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> i) & 1)); +} + +static void addBitsToStreamReversed(size_t* bitpointer, ucvector* bitstream, unsigned value, size_t nbits) +{ + size_t i; + for(i = 0; i != nbits; ++i) addBitToStream(bitpointer, bitstream, (unsigned char)((value >> (nbits - 1 - i)) & 1)); +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_DECODER + +#define READBIT(bitpointer, bitstream) ((bitstream[bitpointer >> 3] >> (bitpointer & 0x7)) & (unsigned char)1) + +static unsigned char readBitFromStream(size_t* bitpointer, const unsigned char* bitstream) +{ + unsigned char result = (unsigned char)(READBIT(*bitpointer, bitstream)); + ++(*bitpointer); + return result; +} + +static unsigned readBitsFromStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) +{ + unsigned result = 0, i; + for(i = 0; i != nbits; ++i) + { + result += ((unsigned)READBIT(*bitpointer, bitstream)) << i; + ++(*bitpointer); + } + return result; +} +#endif /*LODEPNG_COMPILE_DECODER*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Deflate - Huffman / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#define FIRST_LENGTH_CODE_INDEX 257 +#define LAST_LENGTH_CODE_INDEX 285 +/*256 literals, the end code, some length codes, and 2 unused codes*/ +#define NUM_DEFLATE_CODE_SYMBOLS 288 +/*the distance codes have their own symbols, 30 used, 2 unused*/ +#define NUM_DISTANCE_SYMBOLS 32 +/*the code length codes. 0-15: code lengths, 16: copy previous 3-6 times, 17: 3-10 zeros, 18: 11-138 zeros*/ +#define NUM_CODE_LENGTH_CODES 19 + +/*the base lengths represented by codes 257-285*/ +static const unsigned LENGTHBASE[29] + = {3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, + 67, 83, 99, 115, 131, 163, 195, 227, 258}; + +/*the extra bits used by codes 257-285 (added to base length)*/ +static const unsigned LENGTHEXTRA[29] + = {0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, + 4, 4, 4, 4, 5, 5, 5, 5, 0}; + +/*the base backwards distances (the bits of distance codes appear after length codes and use their own huffman tree)*/ +static const unsigned DISTANCEBASE[30] + = {1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, + 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577}; + +/*the extra bits of backwards distances (added to base)*/ +static const unsigned DISTANCEEXTRA[30] + = {0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, + 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13}; + +/*the order in which "code length alphabet code lengths" are stored, out of this +the huffman tree of the dynamic huffman tree lengths is generated*/ +static const unsigned CLCL_ORDER[NUM_CODE_LENGTH_CODES] + = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + +/* ////////////////////////////////////////////////////////////////////////// */ + +/* +Huffman tree struct, containing multiple representations of the tree +*/ +typedef struct HuffmanTree +{ + unsigned* tree2d; + unsigned* tree1d; + unsigned* lengths; /*the lengths of the codes of the 1d-tree*/ + unsigned maxbitlen; /*maximum number of bits a single code can get*/ + unsigned numcodes; /*number of symbols in the alphabet = number of codes*/ +} HuffmanTree; + +/*function used for debug purposes to draw the tree in ascii art with C++*/ +/* +static void HuffmanTree_draw(HuffmanTree* tree) +{ + std::cout << "tree. length: " << tree->numcodes << " maxbitlen: " << tree->maxbitlen << std::endl; + for(size_t i = 0; i != tree->tree1d.size; ++i) + { + if(tree->lengths.data[i]) + std::cout << i << " " << tree->tree1d.data[i] << " " << tree->lengths.data[i] << std::endl; + } + std::cout << std::endl; +}*/ + +static void HuffmanTree_init(HuffmanTree* tree) +{ + tree->tree2d = 0; + tree->tree1d = 0; + tree->lengths = 0; +} + +static void HuffmanTree_cleanup(HuffmanTree* tree) +{ + lodepng_free(tree->tree2d); + lodepng_free(tree->tree1d); + lodepng_free(tree->lengths); +} + +/*the tree representation used by the decoder. return value is error*/ +static unsigned HuffmanTree_make2DTree(HuffmanTree* tree) +{ + unsigned nodefilled = 0; /*up to which node it is filled*/ + unsigned treepos = 0; /*position in the tree (1 of the numcodes columns)*/ + unsigned n, i; + + tree->tree2d = (unsigned*)lodepng_malloc(tree->numcodes * 2 * sizeof(unsigned)); + if(!tree->tree2d) return 83; /*alloc fail*/ + + /* + convert tree1d[] to tree2d[][]. In the 2D array, a value of 32767 means + uninited, a value >= numcodes is an address to another bit, a value < numcodes + is a code. The 2 rows are the 2 possible bit values (0 or 1), there are as + many columns as codes - 1. + A good huffman tree has N * 2 - 1 nodes, of which N - 1 are internal nodes. + Here, the internal nodes are stored (what their 0 and 1 option point to). + There is only memory for such good tree currently, if there are more nodes + (due to too long length codes), error 55 will happen + */ + for(n = 0; n < tree->numcodes * 2; ++n) + { + tree->tree2d[n] = 32767; /*32767 here means the tree2d isn't filled there yet*/ + } + + for(n = 0; n < tree->numcodes; ++n) /*the codes*/ + { + for(i = 0; i != tree->lengths[n]; ++i) /*the bits for this code*/ + { + unsigned char bit = (unsigned char)((tree->tree1d[n] >> (tree->lengths[n] - i - 1)) & 1); + /*oversubscribed, see comment in lodepng_error_text*/ + if(treepos > 2147483647 || treepos + 2 > tree->numcodes) return 55; + if(tree->tree2d[2 * treepos + bit] == 32767) /*not yet filled in*/ + { + if(i + 1 == tree->lengths[n]) /*last bit*/ + { + tree->tree2d[2 * treepos + bit] = n; /*put the current code in it*/ + treepos = 0; + } + else + { + /*put address of the next step in here, first that address has to be found of course + (it's just nodefilled + 1)...*/ + ++nodefilled; + /*addresses encoded with numcodes added to it*/ + tree->tree2d[2 * treepos + bit] = nodefilled + tree->numcodes; + treepos = nodefilled; + } + } + else treepos = tree->tree2d[2 * treepos + bit] - tree->numcodes; + } + } + + for(n = 0; n < tree->numcodes * 2; ++n) + { + if(tree->tree2d[n] == 32767) tree->tree2d[n] = 0; /*remove possible remaining 32767's*/ + } + + return 0; +} + +/* +Second step for the ...makeFromLengths and ...makeFromFrequencies functions. +numcodes, lengths and maxbitlen must already be filled in correctly. return +value is error. +*/ +static unsigned HuffmanTree_makeFromLengths2(HuffmanTree* tree) +{ + uivector blcount; + uivector nextcode; + unsigned error = 0; + unsigned bits, n; + + uivector_init(&blcount); + uivector_init(&nextcode); + + tree->tree1d = (unsigned*)lodepng_malloc(tree->numcodes * sizeof(unsigned)); + if(!tree->tree1d) error = 83; /*alloc fail*/ + + if(!uivector_resizev(&blcount, tree->maxbitlen + 1, 0) + || !uivector_resizev(&nextcode, tree->maxbitlen + 1, 0)) + error = 83; /*alloc fail*/ + + if(!error) + { + /*step 1: count number of instances of each code length*/ + for(bits = 0; bits != tree->numcodes; ++bits) ++blcount.data[tree->lengths[bits]]; + /*step 2: generate the nextcode values*/ + for(bits = 1; bits <= tree->maxbitlen; ++bits) + { + nextcode.data[bits] = (nextcode.data[bits - 1] + blcount.data[bits - 1]) << 1; + } + /*step 3: generate all the codes*/ + for(n = 0; n != tree->numcodes; ++n) + { + if(tree->lengths[n] != 0) tree->tree1d[n] = nextcode.data[tree->lengths[n]]++; + } + } + + uivector_cleanup(&blcount); + uivector_cleanup(&nextcode); + + if(!error) return HuffmanTree_make2DTree(tree); + else return error; +} + +/* +given the code lengths (as stored in the PNG file), generate the tree as defined +by Deflate. maxbitlen is the maximum bits that a code in the tree can have. +return value is error. +*/ +static unsigned HuffmanTree_makeFromLengths(HuffmanTree* tree, const unsigned* bitlen, + size_t numcodes, unsigned maxbitlen) +{ + unsigned i; + tree->lengths = (unsigned*)lodepng_malloc(numcodes * sizeof(unsigned)); + if(!tree->lengths) return 83; /*alloc fail*/ + for(i = 0; i != numcodes; ++i) tree->lengths[i] = bitlen[i]; + tree->numcodes = (unsigned)numcodes; /*number of symbols*/ + tree->maxbitlen = maxbitlen; + return HuffmanTree_makeFromLengths2(tree); +} + +#ifdef LODEPNG_COMPILE_ENCODER + +/*BPM: Boundary Package Merge, see "A Fast and Space-Economical Algorithm for Length-Limited Coding", +Jyrki Katajainen, Alistair Moffat, Andrew Turpin, 1995.*/ + +/*chain node for boundary package merge*/ +typedef struct BPMNode +{ + int weight; /*the sum of all weights in this chain*/ + unsigned index; /*index of this leaf node (called "count" in the paper)*/ + struct BPMNode* tail; /*the next nodes in this chain (null if last)*/ + int in_use; +} BPMNode; + +/*lists of chains*/ +typedef struct BPMLists +{ + /*memory pool*/ + unsigned memsize; + BPMNode* memory; + unsigned numfree; + unsigned nextfree; + BPMNode** freelist; + /*two heads of lookahead chains per list*/ + unsigned listsize; + BPMNode** chains0; + BPMNode** chains1; +} BPMLists; + +/*creates a new chain node with the given parameters, from the memory in the lists */ +static BPMNode* bpmnode_create(BPMLists* lists, int weight, unsigned index, BPMNode* tail) +{ + unsigned i; + BPMNode* result; + + /*memory full, so garbage collect*/ + if(lists->nextfree >= lists->numfree) + { + /*mark only those that are in use*/ + for(i = 0; i != lists->memsize; ++i) lists->memory[i].in_use = 0; + for(i = 0; i != lists->listsize; ++i) + { + BPMNode* node; + for(node = lists->chains0[i]; node != 0; node = node->tail) node->in_use = 1; + for(node = lists->chains1[i]; node != 0; node = node->tail) node->in_use = 1; + } + /*collect those that are free*/ + lists->numfree = 0; + for(i = 0; i != lists->memsize; ++i) + { + if(!lists->memory[i].in_use) lists->freelist[lists->numfree++] = &lists->memory[i]; + } + lists->nextfree = 0; + } + + result = lists->freelist[lists->nextfree++]; + result->weight = weight; + result->index = index; + result->tail = tail; + return result; +} + +/*sort the leaves with stable mergesort*/ +static void bpmnode_sort(BPMNode* leaves, size_t num) +{ + BPMNode* mem = (BPMNode*)lodepng_malloc(sizeof(*leaves) * num); + size_t width, counter = 0; + for(width = 1; width < num; width *= 2) + { + BPMNode* a = (counter & 1) ? mem : leaves; + BPMNode* b = (counter & 1) ? leaves : mem; + size_t p; + for(p = 0; p < num; p += 2 * width) + { + size_t q = (p + width > num) ? num : (p + width); + size_t r = (p + 2 * width > num) ? num : (p + 2 * width); + size_t i = p, j = q, k; + for(k = p; k < r; k++) + { + if(i < q && (j >= r || a[i].weight <= a[j].weight)) b[k] = a[i++]; + else b[k] = a[j++]; + } + } + counter++; + } + if(counter & 1) memcpy(leaves, mem, sizeof(*leaves) * num); + lodepng_free(mem); +} + +/*Boundary Package Merge step, numpresent is the amount of leaves, and c is the current chain.*/ +static void boundaryPM(BPMLists* lists, BPMNode* leaves, size_t numpresent, int c, int num) +{ + unsigned lastindex = lists->chains1[c]->index; + + if(c == 0) + { + if(lastindex >= numpresent) return; + lists->chains0[c] = lists->chains1[c]; + lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, 0); + } + else + { + /*sum of the weights of the head nodes of the previous lookahead chains.*/ + int sum = lists->chains0[c - 1]->weight + lists->chains1[c - 1]->weight; + lists->chains0[c] = lists->chains1[c]; + if(lastindex < numpresent && sum > leaves[lastindex].weight) + { + lists->chains1[c] = bpmnode_create(lists, leaves[lastindex].weight, lastindex + 1, lists->chains1[c]->tail); + return; + } + lists->chains1[c] = bpmnode_create(lists, sum, lastindex, lists->chains1[c - 1]); + /*in the end we are only interested in the chain of the last list, so no + need to recurse if we're at the last one (this gives measurable speedup)*/ + if(num + 1 < (int)(2 * numpresent - 2)) + { + boundaryPM(lists, leaves, numpresent, c - 1, num); + boundaryPM(lists, leaves, numpresent, c - 1, num); + } + } +} + +unsigned lodepng_huffman_code_lengths(unsigned* lengths, const unsigned* frequencies, + size_t numcodes, unsigned maxbitlen) +{ + unsigned error = 0; + unsigned i; + size_t numpresent = 0; /*number of symbols with non-zero frequency*/ + BPMNode* leaves; /*the symbols, only those with > 0 frequency*/ + + if(numcodes == 0) return 80; /*error: a tree of 0 symbols is not supposed to be made*/ + if((1u << maxbitlen) < (unsigned)numcodes) return 80; /*error: represent all symbols*/ + + leaves = (BPMNode*)lodepng_malloc(numcodes * sizeof(*leaves)); + if(!leaves) return 83; /*alloc fail*/ + + for(i = 0; i != numcodes; ++i) + { + if(frequencies[i] > 0) + { + leaves[numpresent].weight = (int)frequencies[i]; + leaves[numpresent].index = i; + ++numpresent; + } + } + + for(i = 0; i != numcodes; ++i) lengths[i] = 0; + + /*ensure at least two present symbols. There should be at least one symbol + according to RFC 1951 section 3.2.7. Some decoders incorrectly require two. To + make these work as well ensure there are at least two symbols. The + Package-Merge code below also doesn't work correctly if there's only one + symbol, it'd give it the theoritical 0 bits but in practice zlib wants 1 bit*/ + if(numpresent == 0) + { + lengths[0] = lengths[1] = 1; /*note that for RFC 1951 section 3.2.7, only lengths[0] = 1 is needed*/ + } + else if(numpresent == 1) + { + lengths[leaves[0].index] = 1; + lengths[leaves[0].index == 0 ? 1 : 0] = 1; + } + else + { + BPMLists lists; + BPMNode* node; + + bpmnode_sort(leaves, numpresent); + + lists.listsize = maxbitlen; + lists.memsize = 2 * maxbitlen * (maxbitlen + 1); + lists.nextfree = 0; + lists.numfree = lists.memsize; + lists.memory = (BPMNode*)lodepng_malloc(lists.memsize * sizeof(*lists.memory)); + lists.freelist = (BPMNode**)lodepng_malloc(lists.memsize * sizeof(BPMNode*)); + lists.chains0 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*)); + lists.chains1 = (BPMNode**)lodepng_malloc(lists.listsize * sizeof(BPMNode*)); + if(!lists.memory || !lists.freelist || !lists.chains0 || !lists.chains1) error = 83; /*alloc fail*/ + + if(!error) + { + for(i = 0; i != lists.memsize; ++i) lists.freelist[i] = &lists.memory[i]; + + bpmnode_create(&lists, leaves[0].weight, 1, 0); + bpmnode_create(&lists, leaves[1].weight, 2, 0); + + for(i = 0; i != lists.listsize; ++i) + { + lists.chains0[i] = &lists.memory[0]; + lists.chains1[i] = &lists.memory[1]; + } + + /*each boundaryPM call adds one chain to the last list, and we need 2 * numpresent - 2 chains.*/ + for(i = 2; i != 2 * numpresent - 2; ++i) boundaryPM(&lists, leaves, numpresent, (int)maxbitlen - 1, (int)i); + + for(node = lists.chains1[maxbitlen - 1]; node; node = node->tail) + { + for(i = 0; i != node->index; ++i) ++lengths[leaves[i].index]; + } + } + + lodepng_free(lists.memory); + lodepng_free(lists.freelist); + lodepng_free(lists.chains0); + lodepng_free(lists.chains1); + } + + lodepng_free(leaves); + return error; +} + +/*Create the Huffman tree given the symbol frequencies*/ +static unsigned HuffmanTree_makeFromFrequencies(HuffmanTree* tree, const unsigned* frequencies, + size_t mincodes, size_t numcodes, unsigned maxbitlen) +{ + unsigned error = 0; + while(!frequencies[numcodes - 1] && numcodes > mincodes) --numcodes; /*trim zeroes*/ + tree->maxbitlen = maxbitlen; + tree->numcodes = (unsigned)numcodes; /*number of symbols*/ + tree->lengths = (unsigned*)lodepng_realloc(tree->lengths, numcodes * sizeof(unsigned)); + if(!tree->lengths) return 83; /*alloc fail*/ + /*initialize all lengths to 0*/ + memset(tree->lengths, 0, numcodes * sizeof(unsigned)); + + error = lodepng_huffman_code_lengths(tree->lengths, frequencies, numcodes, maxbitlen); + if(!error) error = HuffmanTree_makeFromLengths2(tree); + return error; +} + +static unsigned HuffmanTree_getCode(const HuffmanTree* tree, unsigned index) +{ + return tree->tree1d[index]; +} + +static unsigned HuffmanTree_getLength(const HuffmanTree* tree, unsigned index) +{ + return tree->lengths[index]; +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +/*get the literal and length code tree of a deflated block with fixed tree, as per the deflate specification*/ +static unsigned generateFixedLitLenTree(HuffmanTree* tree) +{ + unsigned i, error = 0; + unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned)); + if(!bitlen) return 83; /*alloc fail*/ + + /*288 possible codes: 0-255=literals, 256=endcode, 257-285=lengthcodes, 286-287=unused*/ + for(i = 0; i <= 143; ++i) bitlen[i] = 8; + for(i = 144; i <= 255; ++i) bitlen[i] = 9; + for(i = 256; i <= 279; ++i) bitlen[i] = 7; + for(i = 280; i <= 287; ++i) bitlen[i] = 8; + + error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DEFLATE_CODE_SYMBOLS, 15); + + lodepng_free(bitlen); + return error; +} + +/*get the distance code tree of a deflated block with fixed tree, as specified in the deflate specification*/ +static unsigned generateFixedDistanceTree(HuffmanTree* tree) +{ + unsigned i, error = 0; + unsigned* bitlen = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned)); + if(!bitlen) return 83; /*alloc fail*/ + + /*there are 32 distance codes, but 30-31 are unused*/ + for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen[i] = 5; + error = HuffmanTree_makeFromLengths(tree, bitlen, NUM_DISTANCE_SYMBOLS, 15); + + lodepng_free(bitlen); + return error; +} + +#ifdef LODEPNG_COMPILE_DECODER + +/* +returns the code, or (unsigned)(-1) if error happened +inbitlength is the length of the complete buffer, in bits (so its byte length times 8) +*/ +static unsigned huffmanDecodeSymbol(const unsigned char* in, size_t* bp, + const HuffmanTree* codetree, size_t inbitlength) +{ + unsigned treepos = 0, ct; + for(;;) + { + if(*bp >= inbitlength) return (unsigned)(-1); /*error: end of input memory reached without endcode*/ + /* + decode the symbol from the tree. The "readBitFromStream" code is inlined in + the expression below because this is the biggest bottleneck while decoding + */ + ct = codetree->tree2d[(treepos << 1) + READBIT(*bp, in)]; + ++(*bp); + if(ct < codetree->numcodes) return ct; /*the symbol is decoded, return it*/ + else treepos = ct - codetree->numcodes; /*symbol not yet decoded, instead move tree position*/ + + if(treepos >= codetree->numcodes) return (unsigned)(-1); /*error: it appeared outside the codetree*/ + } +} +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_DECODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Inflator (Decompressor) / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*get the tree of a deflated block with fixed tree, as specified in the deflate specification*/ +static void getTreeInflateFixed(HuffmanTree* tree_ll, HuffmanTree* tree_d) +{ + /*TODO: check for out of memory errors*/ + generateFixedLitLenTree(tree_ll); + generateFixedDistanceTree(tree_d); +} + +/*get the tree of a deflated block with dynamic tree, the tree itself is also Huffman compressed with a known tree*/ +static unsigned getTreeInflateDynamic(HuffmanTree* tree_ll, HuffmanTree* tree_d, + const unsigned char* in, size_t* bp, size_t inlength) +{ + /*make sure that length values that aren't filled in will be 0, or a wrong tree will be generated*/ + unsigned error = 0; + unsigned n, HLIT, HDIST, HCLEN, i; + size_t inbitlength = inlength * 8; + + /*see comments in deflateDynamic for explanation of the context and these variables, it is analogous*/ + unsigned* bitlen_ll = 0; /*lit,len code lengths*/ + unsigned* bitlen_d = 0; /*dist code lengths*/ + /*code length code lengths ("clcl"), the bit lengths of the huffman tree used to compress bitlen_ll and bitlen_d*/ + unsigned* bitlen_cl = 0; + HuffmanTree tree_cl; /*the code tree for code length codes (the huffman tree for compressed huffman trees)*/ + + if((*bp) + 14 > (inlength << 3)) return 49; /*error: the bit pointer is or will go past the memory*/ + + /*number of literal/length codes + 257. Unlike the spec, the value 257 is added to it here already*/ + HLIT = readBitsFromStream(bp, in, 5) + 257; + /*number of distance codes. Unlike the spec, the value 1 is added to it here already*/ + HDIST = readBitsFromStream(bp, in, 5) + 1; + /*number of code length codes. Unlike the spec, the value 4 is added to it here already*/ + HCLEN = readBitsFromStream(bp, in, 4) + 4; + + if((*bp) + HCLEN * 3 > (inlength << 3)) return 50; /*error: the bit pointer is or will go past the memory*/ + + HuffmanTree_init(&tree_cl); + + while(!error) + { + /*read the code length codes out of 3 * (amount of code length codes) bits*/ + + bitlen_cl = (unsigned*)lodepng_malloc(NUM_CODE_LENGTH_CODES * sizeof(unsigned)); + if(!bitlen_cl) ERROR_BREAK(83 /*alloc fail*/); + + for(i = 0; i != NUM_CODE_LENGTH_CODES; ++i) + { + if(i < HCLEN) bitlen_cl[CLCL_ORDER[i]] = readBitsFromStream(bp, in, 3); + else bitlen_cl[CLCL_ORDER[i]] = 0; /*if not, it must stay 0*/ + } + + error = HuffmanTree_makeFromLengths(&tree_cl, bitlen_cl, NUM_CODE_LENGTH_CODES, 7); + if(error) break; + + /*now we can use this tree to read the lengths for the tree that this function will return*/ + bitlen_ll = (unsigned*)lodepng_malloc(NUM_DEFLATE_CODE_SYMBOLS * sizeof(unsigned)); + bitlen_d = (unsigned*)lodepng_malloc(NUM_DISTANCE_SYMBOLS * sizeof(unsigned)); + if(!bitlen_ll || !bitlen_d) ERROR_BREAK(83 /*alloc fail*/); + for(i = 0; i != NUM_DEFLATE_CODE_SYMBOLS; ++i) bitlen_ll[i] = 0; + for(i = 0; i != NUM_DISTANCE_SYMBOLS; ++i) bitlen_d[i] = 0; + + /*i is the current symbol we're reading in the part that contains the code lengths of lit/len and dist codes*/ + i = 0; + while(i < HLIT + HDIST) + { + unsigned code = huffmanDecodeSymbol(in, bp, &tree_cl, inbitlength); + if(code <= 15) /*a length code*/ + { + if(i < HLIT) bitlen_ll[i] = code; + else bitlen_d[i - HLIT] = code; + ++i; + } + else if(code == 16) /*repeat previous*/ + { + unsigned replength = 3; /*read in the 2 bits that indicate repeat length (3-6)*/ + unsigned value; /*set value to the previous code*/ + + if(i == 0) ERROR_BREAK(54); /*can't repeat previous if i is 0*/ + + if((*bp + 2) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/ + replength += readBitsFromStream(bp, in, 2); + + if(i < HLIT + 1) value = bitlen_ll[i - 1]; + else value = bitlen_d[i - HLIT - 1]; + /*repeat this value in the next lengths*/ + for(n = 0; n < replength; ++n) + { + if(i >= HLIT + HDIST) ERROR_BREAK(13); /*error: i is larger than the amount of codes*/ + if(i < HLIT) bitlen_ll[i] = value; + else bitlen_d[i - HLIT] = value; + ++i; + } + } + else if(code == 17) /*repeat "0" 3-10 times*/ + { + unsigned replength = 3; /*read in the bits that indicate repeat length*/ + if((*bp + 3) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/ + replength += readBitsFromStream(bp, in, 3); + + /*repeat this value in the next lengths*/ + for(n = 0; n < replength; ++n) + { + if(i >= HLIT + HDIST) ERROR_BREAK(14); /*error: i is larger than the amount of codes*/ + + if(i < HLIT) bitlen_ll[i] = 0; + else bitlen_d[i - HLIT] = 0; + ++i; + } + } + else if(code == 18) /*repeat "0" 11-138 times*/ + { + unsigned replength = 11; /*read in the bits that indicate repeat length*/ + if((*bp + 7) > inbitlength) ERROR_BREAK(50); /*error, bit pointer jumps past memory*/ + replength += readBitsFromStream(bp, in, 7); + + /*repeat this value in the next lengths*/ + for(n = 0; n < replength; ++n) + { + if(i >= HLIT + HDIST) ERROR_BREAK(15); /*error: i is larger than the amount of codes*/ + + if(i < HLIT) bitlen_ll[i] = 0; + else bitlen_d[i - HLIT] = 0; + ++i; + } + } + else /*if(code == (unsigned)(-1))*/ /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/ + { + if(code == (unsigned)(-1)) + { + /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol + (10=no endcode, 11=wrong jump outside of tree)*/ + error = (*bp) > inbitlength ? 10 : 11; + } + else error = 16; /*unexisting code, this can never happen*/ + break; + } + } + if(error) break; + + if(bitlen_ll[256] == 0) ERROR_BREAK(64); /*the length of the end code 256 must be larger than 0*/ + + /*now we've finally got HLIT and HDIST, so generate the code trees, and the function is done*/ + error = HuffmanTree_makeFromLengths(tree_ll, bitlen_ll, NUM_DEFLATE_CODE_SYMBOLS, 15); + if(error) break; + error = HuffmanTree_makeFromLengths(tree_d, bitlen_d, NUM_DISTANCE_SYMBOLS, 15); + + break; /*end of error-while*/ + } + + lodepng_free(bitlen_cl); + lodepng_free(bitlen_ll); + lodepng_free(bitlen_d); + HuffmanTree_cleanup(&tree_cl); + + return error; +} + +/*inflate a block with dynamic of fixed Huffman tree*/ +static unsigned inflateHuffmanBlock(ucvector* out, const unsigned char* in, size_t* bp, + size_t* pos, size_t inlength, unsigned btype) +{ + unsigned error = 0; + HuffmanTree tree_ll; /*the huffman tree for literal and length codes*/ + HuffmanTree tree_d; /*the huffman tree for distance codes*/ + size_t inbitlength = inlength * 8; + + HuffmanTree_init(&tree_ll); + HuffmanTree_init(&tree_d); + + if(btype == 1) getTreeInflateFixed(&tree_ll, &tree_d); + else if(btype == 2) error = getTreeInflateDynamic(&tree_ll, &tree_d, in, bp, inlength); + + while(!error) /*decode all symbols until end reached, breaks at end code*/ + { + /*code_ll is literal, length or end code*/ + unsigned code_ll = huffmanDecodeSymbol(in, bp, &tree_ll, inbitlength); + if(code_ll <= 255) /*literal symbol*/ + { + /*ucvector_push_back would do the same, but for some reason the two lines below run 10% faster*/ + if(!ucvector_resize(out, (*pos) + 1)) ERROR_BREAK(83 /*alloc fail*/); + out->data[*pos] = (unsigned char)code_ll; + ++(*pos); + } + else if(code_ll >= FIRST_LENGTH_CODE_INDEX && code_ll <= LAST_LENGTH_CODE_INDEX) /*length code*/ + { + unsigned code_d, distance; + unsigned numextrabits_l, numextrabits_d; /*extra bits for length and distance*/ + size_t start, forward, backward, length; + + /*part 1: get length base*/ + length = LENGTHBASE[code_ll - FIRST_LENGTH_CODE_INDEX]; + + /*part 2: get extra bits and add the value of that to length*/ + numextrabits_l = LENGTHEXTRA[code_ll - FIRST_LENGTH_CODE_INDEX]; + if((*bp + numextrabits_l) > inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/ + length += readBitsFromStream(bp, in, numextrabits_l); + + /*part 3: get distance code*/ + code_d = huffmanDecodeSymbol(in, bp, &tree_d, inbitlength); + if(code_d > 29) + { + if(code_d == (unsigned)(-1)) /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/ + { + /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol + (10=no endcode, 11=wrong jump outside of tree)*/ + error = (*bp) > inlength * 8 ? 10 : 11; + } + else error = 18; /*error: invalid distance code (30-31 are never used)*/ + break; + } + distance = DISTANCEBASE[code_d]; + + /*part 4: get extra bits from distance*/ + numextrabits_d = DISTANCEEXTRA[code_d]; + if((*bp + numextrabits_d) > inbitlength) ERROR_BREAK(51); /*error, bit pointer will jump past memory*/ + distance += readBitsFromStream(bp, in, numextrabits_d); + + /*part 5: fill in all the out[n] values based on the length and dist*/ + start = (*pos); + if(distance > start) ERROR_BREAK(52); /*too long backward distance*/ + backward = start - distance; + + if(!ucvector_resize(out, (*pos) + length)) ERROR_BREAK(83 /*alloc fail*/); + if (distance < length) { + for(forward = 0; forward < length; ++forward) + { + out->data[(*pos)++] = out->data[backward++]; + } + } else { + memcpy(out->data + *pos, out->data + backward, length); + *pos += length; + } + } + else if(code_ll == 256) + { + break; /*end code, break the loop*/ + } + else /*if(code == (unsigned)(-1))*/ /*huffmanDecodeSymbol returns (unsigned)(-1) in case of error*/ + { + /*return error code 10 or 11 depending on the situation that happened in huffmanDecodeSymbol + (10=no endcode, 11=wrong jump outside of tree)*/ + error = ((*bp) > inlength * 8) ? 10 : 11; + break; + } + } + + HuffmanTree_cleanup(&tree_ll); + HuffmanTree_cleanup(&tree_d); + + return error; +} + +static unsigned inflateNoCompression(ucvector* out, const unsigned char* in, size_t* bp, size_t* pos, size_t inlength) +{ + size_t p; + unsigned LEN, NLEN, n, error = 0; + + /*go to first boundary of byte*/ + while(((*bp) & 0x7) != 0) ++(*bp); + p = (*bp) / 8; /*byte position*/ + + /*read LEN (2 bytes) and NLEN (2 bytes)*/ + if(p + 4 >= inlength) return 52; /*error, bit pointer will jump past memory*/ + LEN = in[p] + 256u * in[p + 1]; p += 2; + NLEN = in[p] + 256u * in[p + 1]; p += 2; + + /*check if 16-bit NLEN is really the one's complement of LEN*/ + if(LEN + NLEN != 65535) return 21; /*error: NLEN is not one's complement of LEN*/ + + if(!ucvector_resize(out, (*pos) + LEN)) return 83; /*alloc fail*/ + + /*read the literal data: LEN bytes are now stored in the out buffer*/ + if(p + LEN > inlength) return 23; /*error: reading outside of in buffer*/ + for(n = 0; n < LEN; ++n) out->data[(*pos)++] = in[p++]; + + (*bp) = p * 8; + + return error; +} + +static unsigned lodepng_inflatev(ucvector* out, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings) +{ + /*bit pointer in the "in" data, current byte is bp >> 3, current bit is bp & 0x7 (from lsb to msb of the byte)*/ + size_t bp = 0; + unsigned BFINAL = 0; + size_t pos = 0; /*byte position in the out buffer*/ + unsigned error = 0; + + (void)settings; + + while(!BFINAL) + { + unsigned BTYPE; + if(bp + 2 >= insize * 8) return 52; /*error, bit pointer will jump past memory*/ + BFINAL = readBitFromStream(&bp, in); + BTYPE = 1u * readBitFromStream(&bp, in); + BTYPE += 2u * readBitFromStream(&bp, in); + + if(BTYPE == 3) return 20; /*error: invalid BTYPE*/ + else if(BTYPE == 0) error = inflateNoCompression(out, in, &bp, &pos, insize); /*no compression*/ + else error = inflateHuffmanBlock(out, in, &bp, &pos, insize, BTYPE); /*compression, BTYPE 01 or 10*/ + + if(error) return error; + } + + return error; +} + +unsigned lodepng_inflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings) +{ + unsigned error; + ucvector v; + ucvector_init_buffer(&v, *out, *outsize); + error = lodepng_inflatev(&v, in, insize, settings); + *out = v.data; + *outsize = v.size; + return error; +} + +static unsigned inflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGDecompressSettings* settings) +{ + if(settings->custom_inflate) + { + return settings->custom_inflate(out, outsize, in, insize, settings); + } + else + { + return lodepng_inflate(out, outsize, in, insize, settings); + } +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Deflator (Compressor) / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +static const size_t MAX_SUPPORTED_DEFLATE_LENGTH = 258; + +/*bitlen is the size in bits of the code*/ +static void addHuffmanSymbol(size_t* bp, ucvector* compressed, unsigned code, unsigned bitlen) +{ + addBitsToStreamReversed(bp, compressed, code, bitlen); +} + +/*search the index in the array, that has the largest value smaller than or equal to the given value, +given array must be sorted (if no value is smaller, it returns the size of the given array)*/ +static size_t searchCodeIndex(const unsigned* array, size_t array_size, size_t value) +{ + /*binary search (only small gain over linear). TODO: use CPU log2 instruction for getting symbols instead*/ + size_t left = 1; + size_t right = array_size - 1; + + while(left <= right) { + size_t mid = (left + right) >> 1; + if (array[mid] >= value) right = mid - 1; + else left = mid + 1; + } + if(left >= array_size || array[left] > value) left--; + return left; +} + +static void addLengthDistance(uivector* values, size_t length, size_t distance) +{ + /*values in encoded vector are those used by deflate: + 0-255: literal bytes + 256: end + 257-285: length/distance pair (length code, followed by extra length bits, distance code, extra distance bits) + 286-287: invalid*/ + + unsigned length_code = (unsigned)searchCodeIndex(LENGTHBASE, 29, length); + unsigned extra_length = (unsigned)(length - LENGTHBASE[length_code]); + unsigned dist_code = (unsigned)searchCodeIndex(DISTANCEBASE, 30, distance); + unsigned extra_distance = (unsigned)(distance - DISTANCEBASE[dist_code]); + + uivector_push_back(values, length_code + FIRST_LENGTH_CODE_INDEX); + uivector_push_back(values, extra_length); + uivector_push_back(values, dist_code); + uivector_push_back(values, extra_distance); +} + +/*3 bytes of data get encoded into two bytes. The hash cannot use more than 3 +bytes as input because 3 is the minimum match length for deflate*/ +static const unsigned HASH_NUM_VALUES = 65536; +static const unsigned HASH_BIT_MASK = 65535; /*HASH_NUM_VALUES - 1, but C90 does not like that as initializer*/ + +typedef struct Hash +{ + int* head; /*hash value to head circular pos - can be outdated if went around window*/ + /*circular pos to prev circular pos*/ + unsigned short* chain; + int* val; /*circular pos to hash value*/ + + /*TODO: do this not only for zeros but for any repeated byte. However for PNG + it's always going to be the zeros that dominate, so not important for PNG*/ + int* headz; /*similar to head, but for chainz*/ + unsigned short* chainz; /*those with same amount of zeros*/ + unsigned short* zeros; /*length of zeros streak, used as a second hash chain*/ +} Hash; + +static unsigned hash_init(Hash* hash, unsigned windowsize) +{ + unsigned i; + hash->head = (int*)lodepng_malloc(sizeof(int) * HASH_NUM_VALUES); + hash->val = (int*)lodepng_malloc(sizeof(int) * windowsize); + hash->chain = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); + + hash->zeros = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); + hash->headz = (int*)lodepng_malloc(sizeof(int) * (MAX_SUPPORTED_DEFLATE_LENGTH + 1)); + hash->chainz = (unsigned short*)lodepng_malloc(sizeof(unsigned short) * windowsize); + + if(!hash->head || !hash->chain || !hash->val || !hash->headz|| !hash->chainz || !hash->zeros) + { + return 83; /*alloc fail*/ + } + + /*initialize hash table*/ + for(i = 0; i != HASH_NUM_VALUES; ++i) hash->head[i] = -1; + for(i = 0; i != windowsize; ++i) hash->val[i] = -1; + for(i = 0; i != windowsize; ++i) hash->chain[i] = i; /*same value as index indicates uninitialized*/ + + for(i = 0; i <= MAX_SUPPORTED_DEFLATE_LENGTH; ++i) hash->headz[i] = -1; + for(i = 0; i != windowsize; ++i) hash->chainz[i] = i; /*same value as index indicates uninitialized*/ + + return 0; +} + +static void hash_cleanup(Hash* hash) +{ + lodepng_free(hash->head); + lodepng_free(hash->val); + lodepng_free(hash->chain); + + lodepng_free(hash->zeros); + lodepng_free(hash->headz); + lodepng_free(hash->chainz); +} + + + +static unsigned getHash(const unsigned char* data, size_t size, size_t pos) +{ + unsigned result = 0; + if(pos + 2 < size) + { + /*A simple shift and xor hash is used. Since the data of PNGs is dominated + by zeroes due to the filters, a better hash does not have a significant + effect on speed in traversing the chain, and causes more time spend on + calculating the hash.*/ + result ^= (unsigned)(data[pos + 0] << 0u); + result ^= (unsigned)(data[pos + 1] << 4u); + result ^= (unsigned)(data[pos + 2] << 8u); + } else { + size_t amount, i; + if(pos >= size) return 0; + amount = size - pos; + for(i = 0; i != amount; ++i) result ^= (unsigned)(data[pos + i] << (i * 8u)); + } + return result & HASH_BIT_MASK; +} + +static unsigned countZeros(const unsigned char* data, size_t size, size_t pos) +{ + const unsigned char* start = data + pos; + const unsigned char* end = start + MAX_SUPPORTED_DEFLATE_LENGTH; + if(end > data + size) end = data + size; + data = start; + while(data != end && *data == 0) ++data; + /*subtracting two addresses returned as 32-bit number (max value is MAX_SUPPORTED_DEFLATE_LENGTH)*/ + return (unsigned)(data - start); +} + +/*wpos = pos & (windowsize - 1)*/ +static void updateHashChain(Hash* hash, size_t wpos, unsigned hashval, unsigned short numzeros) +{ + hash->val[wpos] = (int)hashval; + if(hash->head[hashval] != -1) hash->chain[wpos] = hash->head[hashval]; + hash->head[hashval] = (int)wpos; + + hash->zeros[wpos] = numzeros; + if(hash->headz[numzeros] != -1) hash->chainz[wpos] = hash->headz[numzeros]; + hash->headz[numzeros] = (int)wpos; +} + +/* +LZ77-encode the data. Return value is error code. The input are raw bytes, the output +is in the form of unsigned integers with codes representing for example literal bytes, or +length/distance pairs. +It uses a hash table technique to let it encode faster. When doing LZ77 encoding, a +sliding window (of windowsize) is used, and all past bytes in that window can be used as +the "dictionary". A brute force search through all possible distances would be slow, and +this hash technique is one out of several ways to speed this up. +*/ +static unsigned encodeLZ77(uivector* out, Hash* hash, + const unsigned char* in, size_t inpos, size_t insize, unsigned windowsize, + unsigned minmatch, unsigned nicematch, unsigned lazymatching) +{ + size_t pos; + unsigned i, error = 0; + /*for large window lengths, assume the user wants no compression loss. Otherwise, max hash chain length speedup.*/ + unsigned maxchainlength = windowsize >= 8192 ? windowsize : windowsize / 8; + unsigned maxlazymatch = windowsize >= 8192 ? MAX_SUPPORTED_DEFLATE_LENGTH : 64; + + unsigned usezeros = 1; /*not sure if setting it to false for windowsize < 8192 is better or worse*/ + unsigned numzeros = 0; + + unsigned offset; /*the offset represents the distance in LZ77 terminology*/ + unsigned length; + unsigned lazy = 0; + unsigned lazylength = 0, lazyoffset = 0; + unsigned hashval; + unsigned current_offset, current_length; + unsigned prev_offset; + const unsigned char *lastptr, *foreptr, *backptr; + unsigned hashpos; + + if(windowsize == 0 || windowsize > 32768) return 60; /*error: windowsize smaller/larger than allowed*/ + if((windowsize & (windowsize - 1)) != 0) return 90; /*error: must be power of two*/ + + if(nicematch > MAX_SUPPORTED_DEFLATE_LENGTH) nicematch = MAX_SUPPORTED_DEFLATE_LENGTH; + + for(pos = inpos; pos < insize; ++pos) + { + size_t wpos = pos & (windowsize - 1); /*position for in 'circular' hash buffers*/ + unsigned chainlength = 0; + + hashval = getHash(in, insize, pos); + + if(usezeros && hashval == 0) + { + if(numzeros == 0) numzeros = countZeros(in, insize, pos); + else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros; + } + else + { + numzeros = 0; + } + + updateHashChain(hash, wpos, hashval, numzeros); + + /*the length and offset found for the current position*/ + length = 0; + offset = 0; + + hashpos = hash->chain[wpos]; + + lastptr = &in[insize < pos + MAX_SUPPORTED_DEFLATE_LENGTH ? insize : pos + MAX_SUPPORTED_DEFLATE_LENGTH]; + + /*search for the longest string*/ + prev_offset = 0; + for(;;) + { + if(chainlength++ >= maxchainlength) break; + current_offset = (unsigned)(hashpos <= wpos ? wpos - hashpos : wpos - hashpos + windowsize); + + if(current_offset < prev_offset) break; /*stop when went completely around the circular buffer*/ + prev_offset = current_offset; + if(current_offset > 0) + { + /*test the next characters*/ + foreptr = &in[pos]; + backptr = &in[pos - current_offset]; + + /*common case in PNGs is lots of zeros. Quickly skip over them as a speedup*/ + if(numzeros >= 3) + { + unsigned skip = hash->zeros[hashpos]; + if(skip > numzeros) skip = numzeros; + backptr += skip; + foreptr += skip; + } + + while(foreptr != lastptr && *backptr == *foreptr) /*maximum supported length by deflate is max length*/ + { + ++backptr; + ++foreptr; + } + current_length = (unsigned)(foreptr - &in[pos]); + + if(current_length > length) + { + length = current_length; /*the longest length*/ + offset = current_offset; /*the offset that is related to this longest length*/ + /*jump out once a length of max length is found (speed gain). This also jumps + out if length is MAX_SUPPORTED_DEFLATE_LENGTH*/ + if(current_length >= nicematch) break; + } + } + + if(hashpos == hash->chain[hashpos]) break; + + if(numzeros >= 3 && length > numzeros) + { + hashpos = hash->chainz[hashpos]; + if(hash->zeros[hashpos] != numzeros) break; + } + else + { + hashpos = hash->chain[hashpos]; + /*outdated hash value, happens if particular value was not encountered in whole last window*/ + if(hash->val[hashpos] != (int)hashval) break; + } + } + + if(lazymatching) + { + if(!lazy && length >= 3 && length <= maxlazymatch && length < MAX_SUPPORTED_DEFLATE_LENGTH) + { + lazy = 1; + lazylength = length; + lazyoffset = offset; + continue; /*try the next byte*/ + } + if(lazy) + { + lazy = 0; + if(pos == 0) ERROR_BREAK(81); + if(length > lazylength + 1) + { + /*push the previous character as literal*/ + if(!uivector_push_back(out, in[pos - 1])) ERROR_BREAK(83 /*alloc fail*/); + } + else + { + length = lazylength; + offset = lazyoffset; + hash->head[hashval] = -1; /*the same hashchain update will be done, this ensures no wrong alteration*/ + hash->headz[numzeros] = -1; /*idem*/ + --pos; + } + } + } + if(length >= 3 && offset > windowsize) ERROR_BREAK(86 /*too big (or overflown negative) offset*/); + + /*encode it as length/distance pair or literal value*/ + if(length < 3) /*only lengths of 3 or higher are supported as length/distance pair*/ + { + if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/); + } + else if(length < minmatch || (length == 3 && offset > 4096)) + { + /*compensate for the fact that longer offsets have more extra bits, a + length of only 3 may be not worth it then*/ + if(!uivector_push_back(out, in[pos])) ERROR_BREAK(83 /*alloc fail*/); + } + else + { + addLengthDistance(out, length, offset); + for(i = 1; i < length; ++i) + { + ++pos; + wpos = pos & (windowsize - 1); + hashval = getHash(in, insize, pos); + if(usezeros && hashval == 0) + { + if(numzeros == 0) numzeros = countZeros(in, insize, pos); + else if(pos + numzeros > insize || in[pos + numzeros - 1] != 0) --numzeros; + } + else + { + numzeros = 0; + } + updateHashChain(hash, wpos, hashval, numzeros); + } + } + } /*end of the loop through each character of input*/ + + return error; +} + +/* /////////////////////////////////////////////////////////////////////////// */ + +static unsigned deflateNoCompression(ucvector* out, const unsigned char* data, size_t datasize) +{ + /*non compressed deflate block data: 1 bit BFINAL,2 bits BTYPE,(5 bits): it jumps to start of next byte, + 2 bytes LEN, 2 bytes NLEN, LEN bytes literal DATA*/ + + size_t i, j, numdeflateblocks = (datasize + 65534) / 65535; + unsigned datapos = 0; + for(i = 0; i != numdeflateblocks; ++i) + { + unsigned BFINAL, BTYPE, LEN, NLEN; + unsigned char firstbyte; + + BFINAL = (i == numdeflateblocks - 1); + BTYPE = 0; + + firstbyte = (unsigned char)(BFINAL + ((BTYPE & 1) << 1) + ((BTYPE & 2) << 1)); + ucvector_push_back(out, firstbyte); + + LEN = 65535; + if(datasize - datapos < 65535) LEN = (unsigned)datasize - datapos; + NLEN = 65535 - LEN; + + ucvector_push_back(out, (unsigned char)(LEN & 255)); + ucvector_push_back(out, (unsigned char)(LEN >> 8)); + ucvector_push_back(out, (unsigned char)(NLEN & 255)); + ucvector_push_back(out, (unsigned char)(NLEN >> 8)); + + /*Decompressed data*/ + for(j = 0; j < 65535 && datapos < datasize; ++j) + { + ucvector_push_back(out, data[datapos++]); + } + } + + return 0; +} + +/* +write the lz77-encoded data, which has lit, len and dist codes, to compressed stream using huffman trees. +tree_ll: the tree for lit and len codes. +tree_d: the tree for distance codes. +*/ +static void writeLZ77data(size_t* bp, ucvector* out, const uivector* lz77_encoded, + const HuffmanTree* tree_ll, const HuffmanTree* tree_d) +{ + size_t i = 0; + for(i = 0; i != lz77_encoded->size; ++i) + { + unsigned val = lz77_encoded->data[i]; + addHuffmanSymbol(bp, out, HuffmanTree_getCode(tree_ll, val), HuffmanTree_getLength(tree_ll, val)); + if(val > 256) /*for a length code, 3 more things have to be added*/ + { + unsigned length_index = val - FIRST_LENGTH_CODE_INDEX; + unsigned n_length_extra_bits = LENGTHEXTRA[length_index]; + unsigned length_extra_bits = lz77_encoded->data[++i]; + + unsigned distance_code = lz77_encoded->data[++i]; + + unsigned distance_index = distance_code; + unsigned n_distance_extra_bits = DISTANCEEXTRA[distance_index]; + unsigned distance_extra_bits = lz77_encoded->data[++i]; + + addBitsToStream(bp, out, length_extra_bits, n_length_extra_bits); + addHuffmanSymbol(bp, out, HuffmanTree_getCode(tree_d, distance_code), + HuffmanTree_getLength(tree_d, distance_code)); + addBitsToStream(bp, out, distance_extra_bits, n_distance_extra_bits); + } + } +} + +/*Deflate for a block of type "dynamic", that is, with freely, optimally, created huffman trees*/ +static unsigned deflateDynamic(ucvector* out, size_t* bp, Hash* hash, + const unsigned char* data, size_t datapos, size_t dataend, + const LodePNGCompressSettings* settings, unsigned final) +{ + unsigned error = 0; + + /* + A block is compressed as follows: The PNG data is lz77 encoded, resulting in + literal bytes and length/distance pairs. This is then huffman compressed with + two huffman trees. One huffman tree is used for the lit and len values ("ll"), + another huffman tree is used for the dist values ("d"). These two trees are + stored using their code lengths, and to compress even more these code lengths + are also run-length encoded and huffman compressed. This gives a huffman tree + of code lengths "cl". The code lenghts used to describe this third tree are + the code length code lengths ("clcl"). + */ + + /*The lz77 encoded data, represented with integers since there will also be length and distance codes in it*/ + uivector lz77_encoded; + HuffmanTree tree_ll; /*tree for lit,len values*/ + HuffmanTree tree_d; /*tree for distance codes*/ + HuffmanTree tree_cl; /*tree for encoding the code lengths representing tree_ll and tree_d*/ + uivector frequencies_ll; /*frequency of lit,len codes*/ + uivector frequencies_d; /*frequency of dist codes*/ + uivector frequencies_cl; /*frequency of code length codes*/ + uivector bitlen_lld; /*lit,len,dist code lenghts (int bits), literally (without repeat codes).*/ + uivector bitlen_lld_e; /*bitlen_lld encoded with repeat codes (this is a rudemtary run length compression)*/ + /*bitlen_cl is the code length code lengths ("clcl"). The bit lengths of codes to represent tree_cl + (these are written as is in the file, it would be crazy to compress these using yet another huffman + tree that needs to be represented by yet another set of code lengths)*/ + uivector bitlen_cl; + size_t datasize = dataend - datapos; + + /* + Due to the huffman compression of huffman tree representations ("two levels"), there are some anologies: + bitlen_lld is to tree_cl what data is to tree_ll and tree_d. + bitlen_lld_e is to bitlen_lld what lz77_encoded is to data. + bitlen_cl is to bitlen_lld_e what bitlen_lld is to lz77_encoded. + */ + + unsigned BFINAL = final; + size_t numcodes_ll, numcodes_d, i; + unsigned HLIT, HDIST, HCLEN; + + uivector_init(&lz77_encoded); + HuffmanTree_init(&tree_ll); + HuffmanTree_init(&tree_d); + HuffmanTree_init(&tree_cl); + uivector_init(&frequencies_ll); + uivector_init(&frequencies_d); + uivector_init(&frequencies_cl); + uivector_init(&bitlen_lld); + uivector_init(&bitlen_lld_e); + uivector_init(&bitlen_cl); + + /*This while loop never loops due to a break at the end, it is here to + allow breaking out of it to the cleanup phase on error conditions.*/ + while(!error) + { + if(settings->use_lz77) + { + error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize, + settings->minmatch, settings->nicematch, settings->lazymatching); + if(error) break; + } + else + { + if(!uivector_resize(&lz77_encoded, datasize)) ERROR_BREAK(83 /*alloc fail*/); + for(i = datapos; i < dataend; ++i) lz77_encoded.data[i - datapos] = data[i]; /*no LZ77, but still will be Huffman compressed*/ + } + + if(!uivector_resizev(&frequencies_ll, 286, 0)) ERROR_BREAK(83 /*alloc fail*/); + if(!uivector_resizev(&frequencies_d, 30, 0)) ERROR_BREAK(83 /*alloc fail*/); + + /*Count the frequencies of lit, len and dist codes*/ + for(i = 0; i != lz77_encoded.size; ++i) + { + unsigned symbol = lz77_encoded.data[i]; + ++frequencies_ll.data[symbol]; + if(symbol > 256) + { + unsigned dist = lz77_encoded.data[i + 2]; + ++frequencies_d.data[dist]; + i += 3; + } + } + frequencies_ll.data[256] = 1; /*there will be exactly 1 end code, at the end of the block*/ + + /*Make both huffman trees, one for the lit and len codes, one for the dist codes*/ + error = HuffmanTree_makeFromFrequencies(&tree_ll, frequencies_ll.data, 257, frequencies_ll.size, 15); + if(error) break; + /*2, not 1, is chosen for mincodes: some buggy PNG decoders require at least 2 symbols in the dist tree*/ + error = HuffmanTree_makeFromFrequencies(&tree_d, frequencies_d.data, 2, frequencies_d.size, 15); + if(error) break; + + numcodes_ll = tree_ll.numcodes; if(numcodes_ll > 286) numcodes_ll = 286; + numcodes_d = tree_d.numcodes; if(numcodes_d > 30) numcodes_d = 30; + /*store the code lengths of both generated trees in bitlen_lld*/ + for(i = 0; i != numcodes_ll; ++i) uivector_push_back(&bitlen_lld, HuffmanTree_getLength(&tree_ll, (unsigned)i)); + for(i = 0; i != numcodes_d; ++i) uivector_push_back(&bitlen_lld, HuffmanTree_getLength(&tree_d, (unsigned)i)); + + /*run-length compress bitlen_ldd into bitlen_lld_e by using repeat codes 16 (copy length 3-6 times), + 17 (3-10 zeroes), 18 (11-138 zeroes)*/ + for(i = 0; i != (unsigned)bitlen_lld.size; ++i) + { + unsigned j = 0; /*amount of repititions*/ + while(i + j + 1 < (unsigned)bitlen_lld.size && bitlen_lld.data[i + j + 1] == bitlen_lld.data[i]) ++j; + + if(bitlen_lld.data[i] == 0 && j >= 2) /*repeat code for zeroes*/ + { + ++j; /*include the first zero*/ + if(j <= 10) /*repeat code 17 supports max 10 zeroes*/ + { + uivector_push_back(&bitlen_lld_e, 17); + uivector_push_back(&bitlen_lld_e, j - 3); + } + else /*repeat code 18 supports max 138 zeroes*/ + { + if(j > 138) j = 138; + uivector_push_back(&bitlen_lld_e, 18); + uivector_push_back(&bitlen_lld_e, j - 11); + } + i += (j - 1); + } + else if(j >= 3) /*repeat code for value other than zero*/ + { + size_t k; + unsigned num = j / 6, rest = j % 6; + uivector_push_back(&bitlen_lld_e, bitlen_lld.data[i]); + for(k = 0; k < num; ++k) + { + uivector_push_back(&bitlen_lld_e, 16); + uivector_push_back(&bitlen_lld_e, 6 - 3); + } + if(rest >= 3) + { + uivector_push_back(&bitlen_lld_e, 16); + uivector_push_back(&bitlen_lld_e, rest - 3); + } + else j -= rest; + i += j; + } + else /*too short to benefit from repeat code*/ + { + uivector_push_back(&bitlen_lld_e, bitlen_lld.data[i]); + } + } + + /*generate tree_cl, the huffmantree of huffmantrees*/ + + if(!uivector_resizev(&frequencies_cl, NUM_CODE_LENGTH_CODES, 0)) ERROR_BREAK(83 /*alloc fail*/); + for(i = 0; i != bitlen_lld_e.size; ++i) + { + ++frequencies_cl.data[bitlen_lld_e.data[i]]; + /*after a repeat code come the bits that specify the number of repetitions, + those don't need to be in the frequencies_cl calculation*/ + if(bitlen_lld_e.data[i] >= 16) ++i; + } + + error = HuffmanTree_makeFromFrequencies(&tree_cl, frequencies_cl.data, + frequencies_cl.size, frequencies_cl.size, 7); + if(error) break; + + if(!uivector_resize(&bitlen_cl, tree_cl.numcodes)) ERROR_BREAK(83 /*alloc fail*/); + for(i = 0; i != tree_cl.numcodes; ++i) + { + /*lenghts of code length tree is in the order as specified by deflate*/ + bitlen_cl.data[i] = HuffmanTree_getLength(&tree_cl, CLCL_ORDER[i]); + } + while(bitlen_cl.data[bitlen_cl.size - 1] == 0 && bitlen_cl.size > 4) + { + /*remove zeros at the end, but minimum size must be 4*/ + if(!uivector_resize(&bitlen_cl, bitlen_cl.size - 1)) ERROR_BREAK(83 /*alloc fail*/); + } + if(error) break; + + /* + Write everything into the output + + After the BFINAL and BTYPE, the dynamic block consists out of the following: + - 5 bits HLIT, 5 bits HDIST, 4 bits HCLEN + - (HCLEN+4)*3 bits code lengths of code length alphabet + - HLIT + 257 code lenghts of lit/length alphabet (encoded using the code length + alphabet, + possible repetition codes 16, 17, 18) + - HDIST + 1 code lengths of distance alphabet (encoded using the code length + alphabet, + possible repetition codes 16, 17, 18) + - compressed data + - 256 (end code) + */ + + /*Write block type*/ + addBitToStream(bp, out, BFINAL); + addBitToStream(bp, out, 0); /*first bit of BTYPE "dynamic"*/ + addBitToStream(bp, out, 1); /*second bit of BTYPE "dynamic"*/ + + /*write the HLIT, HDIST and HCLEN values*/ + HLIT = (unsigned)(numcodes_ll - 257); + HDIST = (unsigned)(numcodes_d - 1); + HCLEN = (unsigned)bitlen_cl.size - 4; + /*trim zeroes for HCLEN. HLIT and HDIST were already trimmed at tree creation*/ + while(!bitlen_cl.data[HCLEN + 4 - 1] && HCLEN > 0) --HCLEN; + addBitsToStream(bp, out, HLIT, 5); + addBitsToStream(bp, out, HDIST, 5); + addBitsToStream(bp, out, HCLEN, 4); + + /*write the code lenghts of the code length alphabet*/ + for(i = 0; i != HCLEN + 4; ++i) addBitsToStream(bp, out, bitlen_cl.data[i], 3); + + /*write the lenghts of the lit/len AND the dist alphabet*/ + for(i = 0; i != bitlen_lld_e.size; ++i) + { + addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_cl, bitlen_lld_e.data[i]), + HuffmanTree_getLength(&tree_cl, bitlen_lld_e.data[i])); + /*extra bits of repeat codes*/ + if(bitlen_lld_e.data[i] == 16) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 2); + else if(bitlen_lld_e.data[i] == 17) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 3); + else if(bitlen_lld_e.data[i] == 18) addBitsToStream(bp, out, bitlen_lld_e.data[++i], 7); + } + + /*write the compressed data symbols*/ + writeLZ77data(bp, out, &lz77_encoded, &tree_ll, &tree_d); + /*error: the length of the end code 256 must be larger than 0*/ + if(HuffmanTree_getLength(&tree_ll, 256) == 0) ERROR_BREAK(64); + + /*write the end code*/ + addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, 256), HuffmanTree_getLength(&tree_ll, 256)); + + break; /*end of error-while*/ + } + + /*cleanup*/ + uivector_cleanup(&lz77_encoded); + HuffmanTree_cleanup(&tree_ll); + HuffmanTree_cleanup(&tree_d); + HuffmanTree_cleanup(&tree_cl); + uivector_cleanup(&frequencies_ll); + uivector_cleanup(&frequencies_d); + uivector_cleanup(&frequencies_cl); + uivector_cleanup(&bitlen_lld_e); + uivector_cleanup(&bitlen_lld); + uivector_cleanup(&bitlen_cl); + + return error; +} + +static unsigned deflateFixed(ucvector* out, size_t* bp, Hash* hash, + const unsigned char* data, + size_t datapos, size_t dataend, + const LodePNGCompressSettings* settings, unsigned final) +{ + HuffmanTree tree_ll; /*tree for literal values and length codes*/ + HuffmanTree tree_d; /*tree for distance codes*/ + + unsigned BFINAL = final; + unsigned error = 0; + size_t i; + + HuffmanTree_init(&tree_ll); + HuffmanTree_init(&tree_d); + + generateFixedLitLenTree(&tree_ll); + generateFixedDistanceTree(&tree_d); + + addBitToStream(bp, out, BFINAL); + addBitToStream(bp, out, 1); /*first bit of BTYPE*/ + addBitToStream(bp, out, 0); /*second bit of BTYPE*/ + + if(settings->use_lz77) /*LZ77 encoded*/ + { + uivector lz77_encoded; + uivector_init(&lz77_encoded); + error = encodeLZ77(&lz77_encoded, hash, data, datapos, dataend, settings->windowsize, + settings->minmatch, settings->nicematch, settings->lazymatching); + if(!error) writeLZ77data(bp, out, &lz77_encoded, &tree_ll, &tree_d); + uivector_cleanup(&lz77_encoded); + } + else /*no LZ77, but still will be Huffman compressed*/ + { + for(i = datapos; i < dataend; ++i) + { + addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, data[i]), HuffmanTree_getLength(&tree_ll, data[i])); + } + } + /*add END code*/ + if(!error) addHuffmanSymbol(bp, out, HuffmanTree_getCode(&tree_ll, 256), HuffmanTree_getLength(&tree_ll, 256)); + + /*cleanup*/ + HuffmanTree_cleanup(&tree_ll); + HuffmanTree_cleanup(&tree_d); + + return error; +} + +static unsigned lodepng_deflatev(ucvector* out, const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings) +{ + unsigned error = 0; + size_t i, blocksize, numdeflateblocks; + size_t bp = 0; /*the bit pointer*/ + Hash hash; + + if(settings->btype > 2) return 61; + else if(settings->btype == 0) return deflateNoCompression(out, in, insize); + else if(settings->btype == 1) blocksize = insize; + else /*if(settings->btype == 2)*/ + { + /*on PNGs, deflate blocks of 65-262k seem to give most dense encoding*/ + blocksize = insize / 8 + 8; + if(blocksize < 65536) blocksize = 65536; + if(blocksize > 262144) blocksize = 262144; + } + + numdeflateblocks = (insize + blocksize - 1) / blocksize; + if(numdeflateblocks == 0) numdeflateblocks = 1; + + error = hash_init(&hash, settings->windowsize); + if(error) return error; + + for(i = 0; i != numdeflateblocks && !error; ++i) + { + unsigned final = (i == numdeflateblocks - 1); + size_t start = i * blocksize; + size_t end = start + blocksize; + if(end > insize) end = insize; + + if(settings->btype == 1) error = deflateFixed(out, &bp, &hash, in, start, end, settings, final); + else if(settings->btype == 2) error = deflateDynamic(out, &bp, &hash, in, start, end, settings, final); + } + + hash_cleanup(&hash); + + return error; +} + +unsigned lodepng_deflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings) +{ + unsigned error; + ucvector v; + ucvector_init_buffer(&v, *out, *outsize); + error = lodepng_deflatev(&v, in, insize, settings); + *out = v.data; + *outsize = v.size; + return error; +} + +static unsigned deflate(unsigned char** out, size_t* outsize, + const unsigned char* in, size_t insize, + const LodePNGCompressSettings* settings) +{ + if(settings->custom_deflate) + { + return settings->custom_deflate(out, outsize, in, insize, settings); + } + else + { + return lodepng_deflate(out, outsize, in, insize, settings); + } +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Adler32 */ +/* ////////////////////////////////////////////////////////////////////////// */ + +static unsigned update_adler32(unsigned adler, const unsigned char* data, unsigned len) +{ + unsigned s1 = adler & 0xffff; + unsigned s2 = (adler >> 16) & 0xffff; + + while(len > 0) + { + /*at least 5552 sums can be done before the sums overflow, saving a lot of module divisions*/ + unsigned amount = len > 5552 ? 5552 : len; + len -= amount; + while(amount > 0) + { + s1 += (*data++); + s2 += s1; + --amount; + } + s1 %= 65521; + s2 %= 65521; + } + + return (s2 << 16) | s1; +} + +/*Return the adler32 of the bytes data[0..len-1]*/ +static unsigned adler32(const unsigned char* data, unsigned len) +{ + return update_adler32(1L, data, len); +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Zlib / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_DECODER + +unsigned lodepng_zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGDecompressSettings* settings) +{ + unsigned error = 0; + unsigned CM, CINFO, FDICT; + + if(insize < 2) return 53; /*error, size of zlib data too small*/ + /*read information from zlib header*/ + if((in[0] * 256 + in[1]) % 31 != 0) + { + /*error: 256 * in[0] + in[1] must be a multiple of 31, the FCHECK value is supposed to be made that way*/ + return 24; + } + + CM = in[0] & 15; + CINFO = (in[0] >> 4) & 15; + /*FCHECK = in[1] & 31;*/ /*FCHECK is already tested above*/ + FDICT = (in[1] >> 5) & 1; + /*FLEVEL = (in[1] >> 6) & 3;*/ /*FLEVEL is not used here*/ + + if(CM != 8 || CINFO > 7) + { + /*error: only compression method 8: inflate with sliding window of 32k is supported by the PNG spec*/ + return 25; + } + if(FDICT != 0) + { + /*error: the specification of PNG says about the zlib stream: + "The additional flags shall not specify a preset dictionary."*/ + return 26; + } + + error = inflate(out, outsize, in + 2, insize - 2, settings); + if(error) return error; + + if(!settings->ignore_adler32) + { + unsigned ADLER32 = lodepng_read32bitInt(&in[insize - 4]); + unsigned checksum = adler32(*out, (unsigned)(*outsize)); + if(checksum != ADLER32) return 58; /*error, adler checksum not correct, data must be corrupted*/ + } + + return 0; /*no error*/ +} + +static unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGDecompressSettings* settings) +{ + if(settings->custom_zlib) + { + return settings->custom_zlib(out, outsize, in, insize, settings); + } + else + { + return lodepng_zlib_decompress(out, outsize, in, insize, settings); + } +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +#ifdef LODEPNG_COMPILE_ENCODER + +unsigned lodepng_zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGCompressSettings* settings) +{ + /*initially, *out must be NULL and outsize 0, if you just give some random *out + that's pointing to a non allocated buffer, this'll crash*/ + ucvector outv; + size_t i; + unsigned error; + unsigned char* deflatedata = 0; + size_t deflatesize = 0; + + /*zlib data: 1 byte CMF (CM+CINFO), 1 byte FLG, deflate data, 4 byte ADLER32 checksum of the Decompressed data*/ + unsigned CMF = 120; /*0b01111000: CM 8, CINFO 7. With CINFO 7, any window size up to 32768 can be used.*/ + unsigned FLEVEL = 0; + unsigned FDICT = 0; + unsigned CMFFLG = 256 * CMF + FDICT * 32 + FLEVEL * 64; + unsigned FCHECK = 31 - CMFFLG % 31; + CMFFLG += FCHECK; + + /*ucvector-controlled version of the output buffer, for dynamic array*/ + ucvector_init_buffer(&outv, *out, *outsize); + + ucvector_push_back(&outv, (unsigned char)(CMFFLG >> 8)); + ucvector_push_back(&outv, (unsigned char)(CMFFLG & 255)); + + error = deflate(&deflatedata, &deflatesize, in, insize, settings); + + if(!error) + { + unsigned ADLER32 = adler32(in, (unsigned)insize); + for(i = 0; i != deflatesize; ++i) ucvector_push_back(&outv, deflatedata[i]); + lodepng_free(deflatedata); + lodepng_add32bitInt(&outv, ADLER32); + } + + *out = outv.data; + *outsize = outv.size; + + return error; +} + +/* compress using the default or custom zlib function */ +static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGCompressSettings* settings) +{ + if(settings->custom_zlib) + { + return settings->custom_zlib(out, outsize, in, insize, settings); + } + else + { + return lodepng_zlib_compress(out, outsize, in, insize, settings); + } +} + +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#else /*no LODEPNG_COMPILE_ZLIB*/ + +#ifdef LODEPNG_COMPILE_DECODER +static unsigned zlib_decompress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGDecompressSettings* settings) +{ + if(!settings->custom_zlib) return 87; /*no custom zlib function provided */ + return settings->custom_zlib(out, outsize, in, insize, settings); +} +#endif /*LODEPNG_COMPILE_DECODER*/ +#ifdef LODEPNG_COMPILE_ENCODER +static unsigned zlib_compress(unsigned char** out, size_t* outsize, const unsigned char* in, + size_t insize, const LodePNGCompressSettings* settings) +{ + if(!settings->custom_zlib) return 87; /*no custom zlib function provided */ + return settings->custom_zlib(out, outsize, in, insize, settings); +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#endif /*LODEPNG_COMPILE_ZLIB*/ + +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_ENCODER + +/*this is a good tradeoff between speed and compression ratio*/ +#define DEFAULT_WINDOWSIZE 2048 + +void lodepng_compress_settings_init(LodePNGCompressSettings* settings) +{ + /*compress with dynamic huffman tree (not in the mathematical sense, just not the predefined one)*/ + settings->btype = 2; + settings->use_lz77 = 1; + settings->windowsize = DEFAULT_WINDOWSIZE; + settings->minmatch = 3; + settings->nicematch = 128; + settings->lazymatching = 1; + + settings->custom_zlib = 0; + settings->custom_deflate = 0; + settings->custom_context = 0; +} + +const LodePNGCompressSettings lodepng_default_compress_settings = {2, 1, DEFAULT_WINDOWSIZE, 3, 128, 1, 0, 0, 0}; + + +#endif /*LODEPNG_COMPILE_ENCODER*/ + +#ifdef LODEPNG_COMPILE_DECODER + +void lodepng_decompress_settings_init(LodePNGDecompressSettings* settings) +{ + settings->ignore_adler32 = 0; + + settings->custom_zlib = 0; + settings->custom_inflate = 0; + settings->custom_context = 0; +} + +const LodePNGDecompressSettings lodepng_default_decompress_settings = {0, 0, 0, 0}; + +#endif /*LODEPNG_COMPILE_DECODER*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // End of Zlib related code. Begin of PNG related code. // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_PNG + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / CRC32 / */ +/* ////////////////////////////////////////////////////////////////////////// */ + + +#ifndef LODEPNG_NO_COMPILE_CRC +/* CRC polynomial: 0xedb88320 */ +static unsigned lodepng_crc32_table[256] = { + 0u, 1996959894u, 3993919788u, 2567524794u, 124634137u, 1886057615u, 3915621685u, 2657392035u, + 249268274u, 2044508324u, 3772115230u, 2547177864u, 162941995u, 2125561021u, 3887607047u, 2428444049u, + 498536548u, 1789927666u, 4089016648u, 2227061214u, 450548861u, 1843258603u, 4107580753u, 2211677639u, + 325883990u, 1684777152u, 4251122042u, 2321926636u, 335633487u, 1661365465u, 4195302755u, 2366115317u, + 997073096u, 1281953886u, 3579855332u, 2724688242u, 1006888145u, 1258607687u, 3524101629u, 2768942443u, + 901097722u, 1119000684u, 3686517206u, 2898065728u, 853044451u, 1172266101u, 3705015759u, 2882616665u, + 651767980u, 1373503546u, 3369554304u, 3218104598u, 565507253u, 1454621731u, 3485111705u, 3099436303u, + 671266974u, 1594198024u, 3322730930u, 2970347812u, 795835527u, 1483230225u, 3244367275u, 3060149565u, + 1994146192u, 31158534u, 2563907772u, 4023717930u, 1907459465u, 112637215u, 2680153253u, 3904427059u, + 2013776290u, 251722036u, 2517215374u, 3775830040u, 2137656763u, 141376813u, 2439277719u, 3865271297u, + 1802195444u, 476864866u, 2238001368u, 4066508878u, 1812370925u, 453092731u, 2181625025u, 4111451223u, + 1706088902u, 314042704u, 2344532202u, 4240017532u, 1658658271u, 366619977u, 2362670323u, 4224994405u, + 1303535960u, 984961486u, 2747007092u, 3569037538u, 1256170817u, 1037604311u, 2765210733u, 3554079995u, + 1131014506u, 879679996u, 2909243462u, 3663771856u, 1141124467u, 855842277u, 2852801631u, 3708648649u, + 1342533948u, 654459306u, 3188396048u, 3373015174u, 1466479909u, 544179635u, 3110523913u, 3462522015u, + 1591671054u, 702138776u, 2966460450u, 3352799412u, 1504918807u, 783551873u, 3082640443u, 3233442989u, + 3988292384u, 2596254646u, 62317068u, 1957810842u, 3939845945u, 2647816111u, 81470997u, 1943803523u, + 3814918930u, 2489596804u, 225274430u, 2053790376u, 3826175755u, 2466906013u, 167816743u, 2097651377u, + 4027552580u, 2265490386u, 503444072u, 1762050814u, 4150417245u, 2154129355u, 426522225u, 1852507879u, + 4275313526u, 2312317920u, 282753626u, 1742555852u, 4189708143u, 2394877945u, 397917763u, 1622183637u, + 3604390888u, 2714866558u, 953729732u, 1340076626u, 3518719985u, 2797360999u, 1068828381u, 1219638859u, + 3624741850u, 2936675148u, 906185462u, 1090812512u, 3747672003u, 2825379669u, 829329135u, 1181335161u, + 3412177804u, 3160834842u, 628085408u, 1382605366u, 3423369109u, 3138078467u, 570562233u, 1426400815u, + 3317316542u, 2998733608u, 733239954u, 1555261956u, 3268935591u, 3050360625u, 752459403u, 1541320221u, + 2607071920u, 3965973030u, 1969922972u, 40735498u, 2617837225u, 3943577151u, 1913087877u, 83908371u, + 2512341634u, 3803740692u, 2075208622u, 213261112u, 2463272603u, 3855990285u, 2094854071u, 198958881u, + 2262029012u, 4057260610u, 1759359992u, 534414190u, 2176718541u, 4139329115u, 1873836001u, 414664567u, + 2282248934u, 4279200368u, 1711684554u, 285281116u, 2405801727u, 4167216745u, 1634467795u, 376229701u, + 2685067896u, 3608007406u, 1308918612u, 956543938u, 2808555105u, 3495958263u, 1231636301u, 1047427035u, + 2932959818u, 3654703836u, 1088359270u, 936918000u, 2847714899u, 3736837829u, 1202900863u, 817233897u, + 3183342108u, 3401237130u, 1404277552u, 615818150u, 3134207493u, 3453421203u, 1423857449u, 601450431u, + 3009837614u, 3294710456u, 1567103746u, 711928724u, 3020668471u, 3272380065u, 1510334235u, 755167117u +}; + +/*Return the CRC of the bytes buf[0..len-1].*/ +unsigned lodepng_crc32(const unsigned char* data, size_t length) +{ + unsigned r = 0xffffffffu; + size_t i; + for(i = 0; i < length; ++i) + { + r = lodepng_crc32_table[(r ^ data[i]) & 0xff] ^ (r >> 8); + } + return r ^ 0xffffffffu; +} +#else /* !LODEPNG_NO_COMPILE_CRC */ +unsigned lodepng_crc32(const unsigned char* data, size_t length); +#endif /* !LODEPNG_NO_COMPILE_CRC */ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Reading and writing single bits and bytes from/to stream for LodePNG / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +static unsigned char readBitFromReversedStream(size_t* bitpointer, const unsigned char* bitstream) +{ + unsigned char result = (unsigned char)((bitstream[(*bitpointer) >> 3] >> (7 - ((*bitpointer) & 0x7))) & 1); + ++(*bitpointer); + return result; +} + +static unsigned readBitsFromReversedStream(size_t* bitpointer, const unsigned char* bitstream, size_t nbits) +{ + unsigned result = 0; + size_t i; + for(i = 0 ; i < nbits; ++i) + { + result <<= 1; + result |= (unsigned)readBitFromReversedStream(bitpointer, bitstream); + } + return result; +} + +#ifdef LODEPNG_COMPILE_DECODER +static void setBitOfReversedStream0(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) +{ + /*the current bit in bitstream must be 0 for this to work*/ + if(bit) + { + /*earlier bit of huffman code is in a lesser significant bit of an earlier byte*/ + bitstream[(*bitpointer) >> 3] |= (bit << (7 - ((*bitpointer) & 0x7))); + } + ++(*bitpointer); +} +#endif /*LODEPNG_COMPILE_DECODER*/ + +static void setBitOfReversedStream(size_t* bitpointer, unsigned char* bitstream, unsigned char bit) +{ + /*the current bit in bitstream may be 0 or 1 for this to work*/ + if(bit == 0) bitstream[(*bitpointer) >> 3] &= (unsigned char)(~(1 << (7 - ((*bitpointer) & 0x7)))); + else bitstream[(*bitpointer) >> 3] |= (1 << (7 - ((*bitpointer) & 0x7))); + ++(*bitpointer); +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / PNG chunks / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +unsigned lodepng_chunk_length(const unsigned char* chunk) +{ + return lodepng_read32bitInt(&chunk[0]); +} + +void lodepng_chunk_type(char type[5], const unsigned char* chunk) +{ + unsigned i; + for(i = 0; i != 4; ++i) type[i] = (char)chunk[4 + i]; + type[4] = 0; /*null termination char*/ +} + +unsigned char lodepng_chunk_type_equals(const unsigned char* chunk, const char* type) +{ + if(strlen(type) != 4) return 0; + return (chunk[4] == type[0] && chunk[5] == type[1] && chunk[6] == type[2] && chunk[7] == type[3]); +} + +unsigned char lodepng_chunk_ancillary(const unsigned char* chunk) +{ + return((chunk[4] & 32) != 0); +} + +unsigned char lodepng_chunk_private(const unsigned char* chunk) +{ + return((chunk[6] & 32) != 0); +} + +unsigned char lodepng_chunk_safetocopy(const unsigned char* chunk) +{ + return((chunk[7] & 32) != 0); +} + +unsigned char* lodepng_chunk_data(unsigned char* chunk) +{ + return &chunk[8]; +} + +const unsigned char* lodepng_chunk_data_const(const unsigned char* chunk) +{ + return &chunk[8]; +} + +unsigned lodepng_chunk_check_crc(const unsigned char* chunk) +{ + unsigned length = lodepng_chunk_length(chunk); + unsigned CRC = lodepng_read32bitInt(&chunk[length + 8]); + /*the CRC is taken of the data and the 4 chunk type letters, not the length*/ + unsigned checksum = lodepng_crc32(&chunk[4], length + 4); + if(CRC != checksum) return 1; + else return 0; +} + +void lodepng_chunk_generate_crc(unsigned char* chunk) +{ + unsigned length = lodepng_chunk_length(chunk); + unsigned CRC = lodepng_crc32(&chunk[4], length + 4); + lodepng_set32bitInt(chunk + 8 + length, CRC); +} + +unsigned char* lodepng_chunk_next(unsigned char* chunk) +{ + if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47 + && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) { + /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */ + return chunk + 8; + } else { + unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12; + return chunk + total_chunk_length; + } +} + +const unsigned char* lodepng_chunk_next_const(const unsigned char* chunk) +{ + if(chunk[0] == 0x89 && chunk[1] == 0x50 && chunk[2] == 0x4e && chunk[3] == 0x47 + && chunk[4] == 0x0d && chunk[5] == 0x0a && chunk[6] == 0x1a && chunk[7] == 0x0a) { + /* Is PNG magic header at start of PNG file. Jump to first actual chunk. */ + return chunk + 8; + } else { + unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12; + return chunk + total_chunk_length; + } +} + +unsigned char* lodepng_chunk_find(unsigned char* chunk, const unsigned char* end, const char type[5]) +{ + for(;;) + { + if(chunk + 12 >= end) return 0; + if(lodepng_chunk_type_equals(chunk, type)) return chunk; + chunk = lodepng_chunk_next(chunk); + } +} + +const unsigned char* lodepng_chunk_find_const(const unsigned char* chunk, const unsigned char* end, const char type[5]) +{ + for(;;) + { + if(chunk + 12 >= end) return 0; + if(lodepng_chunk_type_equals(chunk, type)) return chunk; + chunk = lodepng_chunk_next_const(chunk); + } +} + +unsigned lodepng_chunk_append(unsigned char** out, size_t* outlength, const unsigned char* chunk) +{ + unsigned i; + unsigned total_chunk_length = lodepng_chunk_length(chunk) + 12; + unsigned char *chunk_start, *new_buffer; + size_t new_length = (*outlength) + total_chunk_length; + if(new_length < total_chunk_length || new_length < (*outlength)) return 77; /*integer overflow happened*/ + + new_buffer = (unsigned char*)lodepng_realloc(*out, new_length); + if(!new_buffer) return 83; /*alloc fail*/ + (*out) = new_buffer; + (*outlength) = new_length; + chunk_start = &(*out)[new_length - total_chunk_length]; + + for(i = 0; i != total_chunk_length; ++i) chunk_start[i] = chunk[i]; + + return 0; +} + +unsigned lodepng_chunk_create(unsigned char** out, size_t* outlength, unsigned length, + const char* type, const unsigned char* data) +{ + unsigned i; + unsigned char *chunk, *new_buffer; + size_t new_length = (*outlength) + length + 12; + if(new_length < length + 12 || new_length < (*outlength)) return 77; /*integer overflow happened*/ + new_buffer = (unsigned char*)lodepng_realloc(*out, new_length); + if(!new_buffer) return 83; /*alloc fail*/ + (*out) = new_buffer; + (*outlength) = new_length; + chunk = &(*out)[(*outlength) - length - 12]; + + /*1: length*/ + lodepng_set32bitInt(chunk, (unsigned)length); + + /*2: chunk name (4 letters)*/ + chunk[4] = (unsigned char)type[0]; + chunk[5] = (unsigned char)type[1]; + chunk[6] = (unsigned char)type[2]; + chunk[7] = (unsigned char)type[3]; + + /*3: the data*/ + for(i = 0; i != length; ++i) chunk[8 + i] = data[i]; + + /*4: CRC (of the chunkname characters and the data)*/ + lodepng_chunk_generate_crc(chunk); + + return 0; +} + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / Color types and such / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*return type is a LodePNG error code*/ +static unsigned checkColorValidity(LodePNGColorType colortype, unsigned bd) /*bd = bitdepth*/ +{ + switch(colortype) + { + case 0: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 || bd == 16)) return 37; break; /*grey*/ + case 2: if(!( bd == 8 || bd == 16)) return 37; break; /*RGB*/ + case 3: if(!(bd == 1 || bd == 2 || bd == 4 || bd == 8 )) return 37; break; /*palette*/ + case 4: if(!( bd == 8 || bd == 16)) return 37; break; /*grey + alpha*/ + case 6: if(!( bd == 8 || bd == 16)) return 37; break; /*RGBA*/ + default: return 31; + } + return 0; /*allowed color type / bits combination*/ +} + +static unsigned getNumColorChannels(LodePNGColorType colortype) +{ + switch(colortype) + { + case 0: return 1; /*grey*/ + case 2: return 3; /*RGB*/ + case 3: return 1; /*palette*/ + case 4: return 2; /*grey + alpha*/ + case 6: return 4; /*RGBA*/ + } + return 0; /*unexisting color type*/ +} + +static unsigned lodepng_get_bpp_lct(LodePNGColorType colortype, unsigned bitdepth) +{ + /*bits per pixel is amount of channels * bits per channel*/ + return getNumColorChannels(colortype) * bitdepth; +} + +/* ////////////////////////////////////////////////////////////////////////// */ + +void lodepng_color_mode_init(LodePNGColorMode* info) +{ + info->key_defined = 0; + info->key_r = info->key_g = info->key_b = 0; + info->colortype = LCT_RGBA; + info->bitdepth = 8; + info->palette = 0; + info->palettesize = 0; +} + +void lodepng_color_mode_cleanup(LodePNGColorMode* info) +{ + lodepng_palette_clear(info); +} + +unsigned lodepng_color_mode_copy(LodePNGColorMode* dest, const LodePNGColorMode* source) +{ + size_t i; + lodepng_color_mode_cleanup(dest); + *dest = *source; + if(source->palette) + { + dest->palette = (unsigned char*)lodepng_malloc(1024); + if(!dest->palette && source->palettesize) return 83; /*alloc fail*/ + for(i = 0; i != source->palettesize * 4; ++i) dest->palette[i] = source->palette[i]; + } + return 0; +} + +LodePNGColorMode lodepng_color_mode_make(LodePNGColorType colortype, unsigned bitdepth) +{ + LodePNGColorMode result; + lodepng_color_mode_init(&result); + result.colortype = colortype; + result.bitdepth = bitdepth; + return result; +} + +static int lodepng_color_mode_equal(const LodePNGColorMode* a, const LodePNGColorMode* b) +{ + size_t i; + if(a->colortype != b->colortype) return 0; + if(a->bitdepth != b->bitdepth) return 0; + if(a->key_defined != b->key_defined) return 0; + if(a->key_defined) + { + if(a->key_r != b->key_r) return 0; + if(a->key_g != b->key_g) return 0; + if(a->key_b != b->key_b) return 0; + } + if(a->palettesize != b->palettesize) return 0; + for(i = 0; i != a->palettesize * 4; ++i) + { + if(a->palette[i] != b->palette[i]) return 0; + } + return 1; +} + +void lodepng_palette_clear(LodePNGColorMode* info) +{ + if(info->palette) lodepng_free(info->palette); + info->palette = 0; + info->palettesize = 0; +} + +unsigned lodepng_palette_add(LodePNGColorMode* info, + unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + unsigned char* data; + /*the same resize technique as C++ std::vectors is used, and here it's made so that for a palette with + the max of 256 colors, it'll have the exact alloc size*/ + if(!info->palette) /*allocate palette if empty*/ + { + /*room for 256 colors with 4 bytes each*/ + data = (unsigned char*)lodepng_realloc(info->palette, 1024); + if(!data) return 83; /*alloc fail*/ + else info->palette = data; + } + info->palette[4 * info->palettesize + 0] = r; + info->palette[4 * info->palettesize + 1] = g; + info->palette[4 * info->palettesize + 2] = b; + info->palette[4 * info->palettesize + 3] = a; + ++info->palettesize; + return 0; +} + +/*calculate bits per pixel out of colortype and bitdepth*/ +unsigned lodepng_get_bpp(const LodePNGColorMode* info) +{ + return lodepng_get_bpp_lct(info->colortype, info->bitdepth); +} + +unsigned lodepng_get_channels(const LodePNGColorMode* info) +{ + return getNumColorChannels(info->colortype); +} + +unsigned lodepng_is_greyscale_type(const LodePNGColorMode* info) +{ + return info->colortype == LCT_GREY || info->colortype == LCT_GREY_ALPHA; +} + +unsigned lodepng_is_alpha_type(const LodePNGColorMode* info) +{ + return (info->colortype & 4) != 0; /*4 or 6*/ +} + +unsigned lodepng_is_palette_type(const LodePNGColorMode* info) +{ + return info->colortype == LCT_PALETTE; +} + +unsigned lodepng_has_palette_alpha(const LodePNGColorMode* info) +{ + size_t i; + for(i = 0; i != info->palettesize; ++i) + { + if(info->palette[i * 4 + 3] < 255) return 1; + } + return 0; +} + +unsigned lodepng_can_have_alpha(const LodePNGColorMode* info) +{ + return info->key_defined + || lodepng_is_alpha_type(info) + || lodepng_has_palette_alpha(info); +} + +size_t lodepng_get_raw_size_lct(unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) +{ + size_t bpp = lodepng_get_bpp_lct(colortype, bitdepth); + size_t n = (size_t)w * (size_t)h; + return ((n / 8) * bpp) + ((n & 7) * bpp + 7) / 8; +} + +size_t lodepng_get_raw_size(unsigned w, unsigned h, const LodePNGColorMode* color) +{ + return lodepng_get_raw_size_lct(w, h, color->colortype, color->bitdepth); +} + + +#ifdef LODEPNG_COMPILE_PNG +#ifdef LODEPNG_COMPILE_DECODER + +/*in an idat chunk, each scanline is a multiple of 8 bits, unlike the lodepng output buffer, +and in addition has one extra byte per line: the filter byte. So this gives a larger +result than lodepng_get_raw_size. */ +static size_t lodepng_get_raw_size_idat(unsigned w, unsigned h, const LodePNGColorMode* color) +{ + size_t bpp = lodepng_get_bpp(color); + /* + 1 for the filter byte, and possibly plus padding bits per line */ + size_t line = ((size_t)(w / 8) * bpp) + 1 + ((w & 7) * bpp + 7) / 8; + return (size_t)h * line; +} + +/* Safely check if multiplying two integers will overflow (no undefined +behavior, compiler removing the code, etc...) and output result. */ +static int lodepng_mulofl(size_t a, size_t b, size_t* result) +{ + *result = a * b; /* Unsigned multiplication is well defined and safe in C90 */ + return (a != 0 && *result / a != b); +} + +/* Safely check if adding two integers will overflow (no undefined +behavior, compiler removing the code, etc...) and output result. */ +static int lodepng_addofl(size_t a, size_t b, size_t* result) +{ + *result = a + b; /* Unsigned addition is well defined and safe in C90 */ + return *result < a; +} + +/*Safely checks whether size_t overflow can be caused due to amount of pixels. +This check is overcautious rather than precise. If this check indicates no overflow, +you can safely compute in a size_t (but not an unsigned): +-(size_t)w * (size_t)h * 8 +-amount of bytes in IDAT (including filter, padding and Adam7 bytes) +-amount of bytes in raw color model +Returns 1 if overflow possible, 0 if not. +*/ +static int lodepng_pixel_overflow(unsigned w, unsigned h, + const LodePNGColorMode* pngcolor, const LodePNGColorMode* rawcolor) +{ + size_t bpp = LODEPNG_MAX(lodepng_get_bpp(pngcolor), lodepng_get_bpp(rawcolor)); + size_t numpixels, total; + size_t line; /* bytes per line in worst case */ + + if(lodepng_mulofl((size_t)w, (size_t)h, &numpixels)) return 1; + if(lodepng_mulofl(numpixels, 8, &total)) return 1; /* bit pointer with 8-bit color, or 8 bytes per channel color */ + + /* Bytes per scanline with the expression "(w / 8) * bpp) + ((w & 7) * bpp + 7) / 8" */ + if(lodepng_mulofl((size_t)(w / 8), bpp, &line)) return 1; + if(lodepng_addofl(line, ((w & 7) * bpp + 7) / 8, &line)) return 1; + + if(lodepng_addofl(line, 5, &line)) return 1; /* 5 bytes overhead per line: 1 filterbyte, 4 for Adam7 worst case */ + if(lodepng_mulofl(line, h, &total)) return 1; /* Total bytes in worst case */ + + return 0; /* no overflow */ +} +#endif /*LODEPNG_COMPILE_DECODER*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + +static void LodePNGUnknownChunks_init(LodePNGInfo* info) +{ + unsigned i; + for(i = 0; i != 3; ++i) info->unknown_chunks_data[i] = 0; + for(i = 0; i != 3; ++i) info->unknown_chunks_size[i] = 0; +} + +static void LodePNGUnknownChunks_cleanup(LodePNGInfo* info) +{ + unsigned i; + for(i = 0; i != 3; ++i) lodepng_free(info->unknown_chunks_data[i]); +} + +static unsigned LodePNGUnknownChunks_copy(LodePNGInfo* dest, const LodePNGInfo* src) +{ + unsigned i; + + LodePNGUnknownChunks_cleanup(dest); + + for(i = 0; i != 3; ++i) + { + size_t j; + dest->unknown_chunks_size[i] = src->unknown_chunks_size[i]; + dest->unknown_chunks_data[i] = (unsigned char*)lodepng_malloc(src->unknown_chunks_size[i]); + if(!dest->unknown_chunks_data[i] && dest->unknown_chunks_size[i]) return 83; /*alloc fail*/ + for(j = 0; j < src->unknown_chunks_size[i]; ++j) + { + dest->unknown_chunks_data[i][j] = src->unknown_chunks_data[i][j]; + } + } + + return 0; +} + +/******************************************************************************/ + +static void LodePNGText_init(LodePNGInfo* info) +{ + info->text_num = 0; + info->text_keys = NULL; + info->text_strings = NULL; +} + +static void LodePNGText_cleanup(LodePNGInfo* info) +{ + size_t i; + for(i = 0; i != info->text_num; ++i) + { + string_cleanup(&info->text_keys[i]); + string_cleanup(&info->text_strings[i]); + } + lodepng_free(info->text_keys); + lodepng_free(info->text_strings); +} + +static unsigned LodePNGText_copy(LodePNGInfo* dest, const LodePNGInfo* source) +{ + size_t i = 0; + dest->text_keys = 0; + dest->text_strings = 0; + dest->text_num = 0; + for(i = 0; i != source->text_num; ++i) + { + CERROR_TRY_RETURN(lodepng_add_text(dest, source->text_keys[i], source->text_strings[i])); + } + return 0; +} + +void lodepng_clear_text(LodePNGInfo* info) +{ + LodePNGText_cleanup(info); +} + +unsigned lodepng_add_text(LodePNGInfo* info, const char* key, const char* str) +{ + char** new_keys = (char**)(lodepng_realloc(info->text_keys, sizeof(char*) * (info->text_num + 1))); + char** new_strings = (char**)(lodepng_realloc(info->text_strings, sizeof(char*) * (info->text_num + 1))); + if(!new_keys || !new_strings) + { + lodepng_free(new_keys); + lodepng_free(new_strings); + return 83; /*alloc fail*/ + } + + ++info->text_num; + info->text_keys = new_keys; + info->text_strings = new_strings; + + info->text_keys[info->text_num - 1] = alloc_string(key); + info->text_strings[info->text_num - 1] = alloc_string(str); + + return 0; +} + +/******************************************************************************/ + +static void LodePNGIText_init(LodePNGInfo* info) +{ + info->itext_num = 0; + info->itext_keys = NULL; + info->itext_langtags = NULL; + info->itext_transkeys = NULL; + info->itext_strings = NULL; +} + +static void LodePNGIText_cleanup(LodePNGInfo* info) +{ + size_t i; + for(i = 0; i != info->itext_num; ++i) + { + string_cleanup(&info->itext_keys[i]); + string_cleanup(&info->itext_langtags[i]); + string_cleanup(&info->itext_transkeys[i]); + string_cleanup(&info->itext_strings[i]); + } + lodepng_free(info->itext_keys); + lodepng_free(info->itext_langtags); + lodepng_free(info->itext_transkeys); + lodepng_free(info->itext_strings); +} + +static unsigned LodePNGIText_copy(LodePNGInfo* dest, const LodePNGInfo* source) +{ + size_t i = 0; + dest->itext_keys = 0; + dest->itext_langtags = 0; + dest->itext_transkeys = 0; + dest->itext_strings = 0; + dest->itext_num = 0; + for(i = 0; i != source->itext_num; ++i) + { + CERROR_TRY_RETURN(lodepng_add_itext(dest, source->itext_keys[i], source->itext_langtags[i], + source->itext_transkeys[i], source->itext_strings[i])); + } + return 0; +} + +void lodepng_clear_itext(LodePNGInfo* info) +{ + LodePNGIText_cleanup(info); +} + +unsigned lodepng_add_itext(LodePNGInfo* info, const char* key, const char* langtag, + const char* transkey, const char* str) +{ + char** new_keys = (char**)(lodepng_realloc(info->itext_keys, sizeof(char*) * (info->itext_num + 1))); + char** new_langtags = (char**)(lodepng_realloc(info->itext_langtags, sizeof(char*) * (info->itext_num + 1))); + char** new_transkeys = (char**)(lodepng_realloc(info->itext_transkeys, sizeof(char*) * (info->itext_num + 1))); + char** new_strings = (char**)(lodepng_realloc(info->itext_strings, sizeof(char*) * (info->itext_num + 1))); + if(!new_keys || !new_langtags || !new_transkeys || !new_strings) + { + lodepng_free(new_keys); + lodepng_free(new_langtags); + lodepng_free(new_transkeys); + lodepng_free(new_strings); + return 83; /*alloc fail*/ + } + + ++info->itext_num; + info->itext_keys = new_keys; + info->itext_langtags = new_langtags; + info->itext_transkeys = new_transkeys; + info->itext_strings = new_strings; + + info->itext_keys[info->itext_num - 1] = alloc_string(key); + info->itext_langtags[info->itext_num - 1] = alloc_string(langtag); + info->itext_transkeys[info->itext_num - 1] = alloc_string(transkey); + info->itext_strings[info->itext_num - 1] = alloc_string(str); + + return 0; +} + +/* same as set but does not delete */ +static unsigned lodepng_assign_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) +{ + info->iccp_name = alloc_string(name); + info->iccp_profile = (unsigned char*)lodepng_malloc(profile_size); + + if(!info->iccp_name || !info->iccp_profile) return 83; /*alloc fail*/ + + memcpy(info->iccp_profile, profile, profile_size); + info->iccp_profile_size = profile_size; + + return 0; /*ok*/ +} + +unsigned lodepng_set_icc(LodePNGInfo* info, const char* name, const unsigned char* profile, unsigned profile_size) +{ + if(info->iccp_name) lodepng_clear_icc(info); + + return lodepng_assign_icc(info, name, profile, profile_size); +} + +void lodepng_clear_icc(LodePNGInfo* info) +{ + string_cleanup(&info->iccp_name); + lodepng_free(info->iccp_profile); + info->iccp_profile = NULL; + info->iccp_profile_size = 0; +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +void lodepng_info_init(LodePNGInfo* info) +{ + lodepng_color_mode_init(&info->color); + info->interlace_method = 0; + info->compression_method = 0; + info->filter_method = 0; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + info->background_defined = 0; + info->background_r = info->background_g = info->background_b = 0; + + LodePNGText_init(info); + LodePNGIText_init(info); + + info->time_defined = 0; + info->phys_defined = 0; + + info->gama_defined = 0; + info->chrm_defined = 0; + info->srgb_defined = 0; + info->iccp_defined = 0; + info->iccp_name = NULL; + info->iccp_profile = NULL; + + LodePNGUnknownChunks_init(info); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} + +void lodepng_info_cleanup(LodePNGInfo* info) +{ + lodepng_color_mode_cleanup(&info->color); +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + LodePNGText_cleanup(info); + LodePNGIText_cleanup(info); + + lodepng_clear_icc(info); + + LodePNGUnknownChunks_cleanup(info); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} + +unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source) +{ + lodepng_info_cleanup(dest); + *dest = *source; + lodepng_color_mode_init(&dest->color); + CERROR_TRY_RETURN(lodepng_color_mode_copy(&dest->color, &source->color)); + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + CERROR_TRY_RETURN(LodePNGText_copy(dest, source)); + CERROR_TRY_RETURN(LodePNGIText_copy(dest, source)); + if(source->iccp_defined) + { + CERROR_TRY_RETURN(lodepng_assign_icc(dest, source->iccp_name, source->iccp_profile, source->iccp_profile_size)); + } + + LodePNGUnknownChunks_init(dest); + CERROR_TRY_RETURN(LodePNGUnknownChunks_copy(dest, source)); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + return 0; +} + +/* ////////////////////////////////////////////////////////////////////////// */ + +/*index: bitgroup index, bits: bitgroup size(1, 2 or 4), in: bitgroup value, out: octet array to add bits to*/ +static void addColorBits(unsigned char* out, size_t index, unsigned bits, unsigned in) +{ + unsigned m = bits == 1 ? 7 : bits == 2 ? 3 : 1; /*8 / bits - 1*/ + /*p = the partial index in the byte, e.g. with 4 palettebits it is 0 for first half or 1 for second half*/ + unsigned p = index & m; + in &= (1u << bits) - 1u; /*filter out any other bits of the input value*/ + in = in << (bits * (m - p)); + if(p == 0) out[index * bits / 8] = in; + else out[index * bits / 8] |= in; +} + +typedef struct ColorTree ColorTree; + +/* +One node of a color tree +This is the data structure used to count the number of unique colors and to get a palette +index for a color. It's like an octree, but because the alpha channel is used too, each +node has 16 instead of 8 children. +*/ +struct ColorTree +{ + ColorTree* children[16]; /*up to 16 pointers to ColorTree of next level*/ + int index; /*the payload. Only has a meaningful value if this is in the last level*/ +}; + +static void color_tree_init(ColorTree* tree) +{ + int i; + for(i = 0; i != 16; ++i) tree->children[i] = 0; + tree->index = -1; +} + +static void color_tree_cleanup(ColorTree* tree) +{ + int i; + for(i = 0; i != 16; ++i) + { + if(tree->children[i]) + { + color_tree_cleanup(tree->children[i]); + lodepng_free(tree->children[i]); + } + } +} + +/*returns -1 if color not present, its index otherwise*/ +static int color_tree_get(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + int bit = 0; + for(bit = 0; bit < 8; ++bit) + { + int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1); + if(!tree->children[i]) return -1; + else tree = tree->children[i]; + } + return tree ? tree->index : -1; +} + +#ifdef LODEPNG_COMPILE_ENCODER +static int color_tree_has(ColorTree* tree, unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + return color_tree_get(tree, r, g, b, a) >= 0; +} +#endif /*LODEPNG_COMPILE_ENCODER*/ + +/*color is not allowed to already exist. +Index should be >= 0 (it's signed to be compatible with using -1 for "doesn't exist")*/ +static void color_tree_add(ColorTree* tree, + unsigned char r, unsigned char g, unsigned char b, unsigned char a, unsigned index) +{ + int bit; + for(bit = 0; bit < 8; ++bit) + { + int i = 8 * ((r >> bit) & 1) + 4 * ((g >> bit) & 1) + 2 * ((b >> bit) & 1) + 1 * ((a >> bit) & 1); + if(!tree->children[i]) + { + tree->children[i] = (ColorTree*)lodepng_malloc(sizeof(ColorTree)); + color_tree_init(tree->children[i]); + } + tree = tree->children[i]; + } + tree->index = (int)index; +} + +/*put a pixel, given its RGBA color, into image of any color type*/ +static unsigned rgba8ToPixel(unsigned char* out, size_t i, + const LodePNGColorMode* mode, ColorTree* tree /*for palette*/, + unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ + if(mode->colortype == LCT_GREY) + { + unsigned char grey = r; /*((unsigned short)r + g + b) / 3*/; + if(mode->bitdepth == 8) out[i] = grey; + else if(mode->bitdepth == 16) out[i * 2 + 0] = out[i * 2 + 1] = grey; + else + { + /*take the most significant bits of grey*/ + grey = (grey >> (8 - mode->bitdepth)) & ((1 << mode->bitdepth) - 1); + addColorBits(out, i, mode->bitdepth, grey); + } + } + else if(mode->colortype == LCT_RGB) + { + if(mode->bitdepth == 8) + { + out[i * 3 + 0] = r; + out[i * 3 + 1] = g; + out[i * 3 + 2] = b; + } + else + { + out[i * 6 + 0] = out[i * 6 + 1] = r; + out[i * 6 + 2] = out[i * 6 + 3] = g; + out[i * 6 + 4] = out[i * 6 + 5] = b; + } + } + else if(mode->colortype == LCT_PALETTE) + { + int index = color_tree_get(tree, r, g, b, a); + if(index < 0) return 82; /*color not in palette*/ + if(mode->bitdepth == 8) out[i] = index; + else addColorBits(out, i, mode->bitdepth, (unsigned)index); + } + else if(mode->colortype == LCT_GREY_ALPHA) + { + unsigned char grey = r; /*((unsigned short)r + g + b) / 3*/; + if(mode->bitdepth == 8) + { + out[i * 2 + 0] = grey; + out[i * 2 + 1] = a; + } + else if(mode->bitdepth == 16) + { + out[i * 4 + 0] = out[i * 4 + 1] = grey; + out[i * 4 + 2] = out[i * 4 + 3] = a; + } + } + else if(mode->colortype == LCT_RGBA) + { + if(mode->bitdepth == 8) + { + out[i * 4 + 0] = r; + out[i * 4 + 1] = g; + out[i * 4 + 2] = b; + out[i * 4 + 3] = a; + } + else + { + out[i * 8 + 0] = out[i * 8 + 1] = r; + out[i * 8 + 2] = out[i * 8 + 3] = g; + out[i * 8 + 4] = out[i * 8 + 5] = b; + out[i * 8 + 6] = out[i * 8 + 7] = a; + } + } + + return 0; /*no error*/ +} + +/*put a pixel, given its RGBA16 color, into image of any color 16-bitdepth type*/ +static void rgba16ToPixel(unsigned char* out, size_t i, + const LodePNGColorMode* mode, + unsigned short r, unsigned short g, unsigned short b, unsigned short a) +{ + if(mode->colortype == LCT_GREY) + { + unsigned short grey = r; /*((unsigned)r + g + b) / 3*/; + out[i * 2 + 0] = (grey >> 8) & 255; + out[i * 2 + 1] = grey & 255; + } + else if(mode->colortype == LCT_RGB) + { + out[i * 6 + 0] = (r >> 8) & 255; + out[i * 6 + 1] = r & 255; + out[i * 6 + 2] = (g >> 8) & 255; + out[i * 6 + 3] = g & 255; + out[i * 6 + 4] = (b >> 8) & 255; + out[i * 6 + 5] = b & 255; + } + else if(mode->colortype == LCT_GREY_ALPHA) + { + unsigned short grey = r; /*((unsigned)r + g + b) / 3*/; + out[i * 4 + 0] = (grey >> 8) & 255; + out[i * 4 + 1] = grey & 255; + out[i * 4 + 2] = (a >> 8) & 255; + out[i * 4 + 3] = a & 255; + } + else if(mode->colortype == LCT_RGBA) + { + out[i * 8 + 0] = (r >> 8) & 255; + out[i * 8 + 1] = r & 255; + out[i * 8 + 2] = (g >> 8) & 255; + out[i * 8 + 3] = g & 255; + out[i * 8 + 4] = (b >> 8) & 255; + out[i * 8 + 5] = b & 255; + out[i * 8 + 6] = (a >> 8) & 255; + out[i * 8 + 7] = a & 255; + } +} + +/*Get RGBA8 color of pixel with index i (y * width + x) from the raw image with given color type.*/ +static void getPixelColorRGBA8(unsigned char* r, unsigned char* g, + unsigned char* b, unsigned char* a, + const unsigned char* in, size_t i, + const LodePNGColorMode* mode) +{ + if(mode->colortype == LCT_GREY) + { + if(mode->bitdepth == 8) + { + *r = *g = *b = in[i]; + if(mode->key_defined && *r == mode->key_r) *a = 0; + else *a = 255; + } + else if(mode->bitdepth == 16) + { + *r = *g = *b = in[i * 2 + 0]; + if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0; + else *a = 255; + } + else + { + unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ + size_t j = i * mode->bitdepth; + unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); + *r = *g = *b = (value * 255) / highest; + if(mode->key_defined && value == mode->key_r) *a = 0; + else *a = 255; + } + } + else if(mode->colortype == LCT_RGB) + { + if(mode->bitdepth == 8) + { + *r = in[i * 3 + 0]; *g = in[i * 3 + 1]; *b = in[i * 3 + 2]; + if(mode->key_defined && *r == mode->key_r && *g == mode->key_g && *b == mode->key_b) *a = 0; + else *a = 255; + } + else + { + *r = in[i * 6 + 0]; + *g = in[i * 6 + 2]; + *b = in[i * 6 + 4]; + if(mode->key_defined && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r + && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g + && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; + else *a = 255; + } + } + else if(mode->colortype == LCT_PALETTE) + { + unsigned index; + if(mode->bitdepth == 8) index = in[i]; + else + { + size_t j = i * mode->bitdepth; + index = readBitsFromReversedStream(&j, in, mode->bitdepth); + } + + if(index >= mode->palettesize) + { + /*This is an error according to the PNG spec, but common PNG decoders make it black instead. + Done here too, slightly faster due to no error handling needed.*/ + *r = *g = *b = 0; + *a = 255; + } + else + { + *r = mode->palette[index * 4 + 0]; + *g = mode->palette[index * 4 + 1]; + *b = mode->palette[index * 4 + 2]; + *a = mode->palette[index * 4 + 3]; + } + } + else if(mode->colortype == LCT_GREY_ALPHA) + { + if(mode->bitdepth == 8) + { + *r = *g = *b = in[i * 2 + 0]; + *a = in[i * 2 + 1]; + } + else + { + *r = *g = *b = in[i * 4 + 0]; + *a = in[i * 4 + 2]; + } + } + else if(mode->colortype == LCT_RGBA) + { + if(mode->bitdepth == 8) + { + *r = in[i * 4 + 0]; + *g = in[i * 4 + 1]; + *b = in[i * 4 + 2]; + *a = in[i * 4 + 3]; + } + else + { + *r = in[i * 8 + 0]; + *g = in[i * 8 + 2]; + *b = in[i * 8 + 4]; + *a = in[i * 8 + 6]; + } + } +} + +/*Similar to getPixelColorRGBA8, but with all the for loops inside of the color +mode test cases, optimized to convert the colors much faster, when converting +to RGBA or RGB with 8 bit per cannel. buffer must be RGBA or RGB output with +enough memory, if has_alpha is true the output is RGBA. mode has the color mode +of the input buffer.*/ +static void getPixelColorsRGBA8(unsigned char* buffer, size_t numpixels, + unsigned has_alpha, const unsigned char* in, + const LodePNGColorMode* mode) +{ + unsigned num_channels = has_alpha ? 4 : 3; + size_t i; + if(mode->colortype == LCT_GREY) + { + if(mode->bitdepth == 8) + { + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + buffer[0] = buffer[1] = buffer[2] = in[i]; + if(has_alpha) buffer[3] = mode->key_defined && in[i] == mode->key_r ? 0 : 255; + } + } + else if(mode->bitdepth == 16) + { + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + buffer[0] = buffer[1] = buffer[2] = in[i * 2]; + if(has_alpha) buffer[3] = mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r ? 0 : 255; + } + } + else + { + unsigned highest = ((1U << mode->bitdepth) - 1U); /*highest possible value for this bit depth*/ + size_t j = 0; + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + unsigned value = readBitsFromReversedStream(&j, in, mode->bitdepth); + buffer[0] = buffer[1] = buffer[2] = (value * 255) / highest; + if(has_alpha) buffer[3] = mode->key_defined && value == mode->key_r ? 0 : 255; + } + } + } + else if(mode->colortype == LCT_RGB) + { + if(mode->bitdepth == 8) + { + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + buffer[0] = in[i * 3 + 0]; + buffer[1] = in[i * 3 + 1]; + buffer[2] = in[i * 3 + 2]; + if(has_alpha) buffer[3] = mode->key_defined && buffer[0] == mode->key_r + && buffer[1]== mode->key_g && buffer[2] == mode->key_b ? 0 : 255; + } + } + else + { + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + buffer[0] = in[i * 6 + 0]; + buffer[1] = in[i * 6 + 2]; + buffer[2] = in[i * 6 + 4]; + if(has_alpha) buffer[3] = mode->key_defined + && 256U * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r + && 256U * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g + && 256U * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b ? 0 : 255; + } + } + } + else if(mode->colortype == LCT_PALETTE) + { + unsigned index; + size_t j = 0; + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + if(mode->bitdepth == 8) index = in[i]; + else index = readBitsFromReversedStream(&j, in, mode->bitdepth); + + if(index >= mode->palettesize) + { + /*This is an error according to the PNG spec, but most PNG decoders make it black instead. + Done here too, slightly faster due to no error handling needed.*/ + buffer[0] = buffer[1] = buffer[2] = 0; + if(has_alpha) buffer[3] = 255; + } + else + { + buffer[0] = mode->palette[index * 4 + 0]; + buffer[1] = mode->palette[index * 4 + 1]; + buffer[2] = mode->palette[index * 4 + 2]; + if(has_alpha) buffer[3] = mode->palette[index * 4 + 3]; + } + } + } + else if(mode->colortype == LCT_GREY_ALPHA) + { + if(mode->bitdepth == 8) + { + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + buffer[0] = buffer[1] = buffer[2] = in[i * 2 + 0]; + if(has_alpha) buffer[3] = in[i * 2 + 1]; + } + } + else + { + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + buffer[0] = buffer[1] = buffer[2] = in[i * 4 + 0]; + if(has_alpha) buffer[3] = in[i * 4 + 2]; + } + } + } + else if(mode->colortype == LCT_RGBA) + { + if(mode->bitdepth == 8) + { + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + buffer[0] = in[i * 4 + 0]; + buffer[1] = in[i * 4 + 1]; + buffer[2] = in[i * 4 + 2]; + if(has_alpha) buffer[3] = in[i * 4 + 3]; + } + } + else + { + for(i = 0; i != numpixels; ++i, buffer += num_channels) + { + buffer[0] = in[i * 8 + 0]; + buffer[1] = in[i * 8 + 2]; + buffer[2] = in[i * 8 + 4]; + if(has_alpha) buffer[3] = in[i * 8 + 6]; + } + } + } +} + +/*Get RGBA16 color of pixel with index i (y * width + x) from the raw image with +given color type, but the given color type must be 16-bit itself.*/ +static void getPixelColorRGBA16(unsigned short* r, unsigned short* g, unsigned short* b, unsigned short* a, + const unsigned char* in, size_t i, const LodePNGColorMode* mode) +{ + if(mode->colortype == LCT_GREY) + { + *r = *g = *b = 256 * in[i * 2 + 0] + in[i * 2 + 1]; + if(mode->key_defined && 256U * in[i * 2 + 0] + in[i * 2 + 1] == mode->key_r) *a = 0; + else *a = 65535; + } + else if(mode->colortype == LCT_RGB) + { + *r = 256u * in[i * 6 + 0] + in[i * 6 + 1]; + *g = 256u * in[i * 6 + 2] + in[i * 6 + 3]; + *b = 256u * in[i * 6 + 4] + in[i * 6 + 5]; + if(mode->key_defined + && 256u * in[i * 6 + 0] + in[i * 6 + 1] == mode->key_r + && 256u * in[i * 6 + 2] + in[i * 6 + 3] == mode->key_g + && 256u * in[i * 6 + 4] + in[i * 6 + 5] == mode->key_b) *a = 0; + else *a = 65535; + } + else if(mode->colortype == LCT_GREY_ALPHA) + { + *r = *g = *b = 256u * in[i * 4 + 0] + in[i * 4 + 1]; + *a = 256u * in[i * 4 + 2] + in[i * 4 + 3]; + } + else if(mode->colortype == LCT_RGBA) + { + *r = 256u * in[i * 8 + 0] + in[i * 8 + 1]; + *g = 256u * in[i * 8 + 2] + in[i * 8 + 3]; + *b = 256u * in[i * 8 + 4] + in[i * 8 + 5]; + *a = 256u * in[i * 8 + 6] + in[i * 8 + 7]; + } +} + +unsigned lodepng_convert(unsigned char* out, const unsigned char* in, + const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in, + unsigned w, unsigned h) +{ + size_t i; + ColorTree tree; + size_t numpixels = (size_t)w * (size_t)h; + unsigned error = 0; + + if(lodepng_color_mode_equal(mode_out, mode_in)) + { + size_t numbytes = lodepng_get_raw_size(w, h, mode_in); + for(i = 0; i != numbytes; ++i) out[i] = in[i]; + return 0; + } + + if(mode_out->colortype == LCT_PALETTE) + { + size_t palettesize = mode_out->palettesize; + const unsigned char* palette = mode_out->palette; + size_t palsize = (size_t)1u << mode_out->bitdepth; + /*if the user specified output palette but did not give the values, assume + they want the values of the input color type (assuming that one is palette). + Note that we never create a new palette ourselves.*/ + if(palettesize == 0) + { + palettesize = mode_in->palettesize; + palette = mode_in->palette; + /*if the input was also palette with same bitdepth, then the color types are also + equal, so copy literally. This to preserve the exact indices that were in the PNG + even in case there are duplicate colors in the palette.*/ + if (mode_in->colortype == LCT_PALETTE && mode_in->bitdepth == mode_out->bitdepth) + { + size_t numbytes = lodepng_get_raw_size(w, h, mode_in); + for(i = 0; i != numbytes; ++i) out[i] = in[i]; + return 0; + } + } + if(palettesize < palsize) palsize = palettesize; + color_tree_init(&tree); + for(i = 0; i != palsize; ++i) + { + const unsigned char* p = &palette[i * 4]; + color_tree_add(&tree, p[0], p[1], p[2], p[3], (unsigned)i); + } + } + + if(mode_in->bitdepth == 16 && mode_out->bitdepth == 16) + { + for(i = 0; i != numpixels; ++i) + { + unsigned short r = 0, g = 0, b = 0, a = 0; + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); + rgba16ToPixel(out, i, mode_out, r, g, b, a); + } + } + else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGBA) + { + getPixelColorsRGBA8(out, numpixels, 1, in, mode_in); + } + else if(mode_out->bitdepth == 8 && mode_out->colortype == LCT_RGB) + { + getPixelColorsRGBA8(out, numpixels, 0, in, mode_in); + } + else + { + unsigned char r = 0, g = 0, b = 0, a = 0; + for(i = 0; i != numpixels; ++i) + { + getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); + error = rgba8ToPixel(out, i, mode_out, &tree, r, g, b, a); + if (error) break; + } + } + + if(mode_out->colortype == LCT_PALETTE) + { + color_tree_cleanup(&tree); + } + + return error; +} + + +/* Converts a single rgb color without alpha from one type to another, color bits truncated to +their bitdepth. In case of single channel (grey or palette), only the r channel is used. Slow +function, do not use to process all pixels of an image. Alpha channel not supported on purpose: +this is for bKGD, supporting alpha may prevent it from finding a color in the palette, from the +specification it looks like bKGD should ignore the alpha values of the palette since it can use +any palette index but doesn't have an alpha channel. Idem with ignoring color key. */ +unsigned lodepng_convert_rgb( + unsigned* r_out, unsigned* g_out, unsigned* b_out, + unsigned r_in, unsigned g_in, unsigned b_in, + const LodePNGColorMode* mode_out, const LodePNGColorMode* mode_in) +{ + unsigned r = 0, g = 0, b = 0; + unsigned mul = 65535 / ((1u << mode_in->bitdepth) - 1u); /*65535, 21845, 4369, 257, 1*/ + unsigned shift = 16 - mode_out->bitdepth; + + if(mode_in->colortype == LCT_GREY || mode_in->colortype == LCT_GREY_ALPHA) + { + r = g = b = r_in * mul; + } + else if(mode_in->colortype == LCT_RGB || mode_in->colortype == LCT_RGBA) + { + r = r_in * mul; + g = g_in * mul; + b = b_in * mul; + } + else if(mode_in->colortype == LCT_PALETTE) + { + if(r_in >= mode_in->palettesize) return 82; + r = mode_in->palette[r_in * 4 + 0] * 257u; + g = mode_in->palette[r_in * 4 + 1] * 257u; + b = mode_in->palette[r_in * 4 + 2] * 257u; + } + else + { + return 31; + } + + /* now convert to output format */ + if(mode_out->colortype == LCT_GREY || mode_out->colortype == LCT_GREY_ALPHA) + { + *r_out = r >> shift ; + } + else if(mode_out->colortype == LCT_RGB || mode_out->colortype == LCT_RGBA) + { + *r_out = r >> shift ; + *g_out = g >> shift ; + *b_out = b >> shift ; + } + else if(mode_out->colortype == LCT_PALETTE) + { + unsigned i; + /* a 16-bit color cannot be in the palette */ + if((r >> 8) != (r & 255) || (g >> 8) != (g & 255) || (b >> 8) != (b & 255)) return 82; + for(i = 0; i < mode_out->palettesize; i++) { + unsigned j = i * 4; + if((r >> 8) == mode_out->palette[j + 0] && (g >> 8) == mode_out->palette[j + 1] && + (b >> 8) == mode_out->palette[j + 2]) + { + *r_out = i; + return 0; + } + } + return 82; + } + else + { + return 31; + } + + return 0; +} + +#ifdef LODEPNG_COMPILE_ENCODER + +void lodepng_color_profile_init(LodePNGColorProfile* profile) +{ + profile->colored = 0; + profile->key = 0; + profile->key_r = profile->key_g = profile->key_b = 0; + profile->alpha = 0; + profile->numcolors = 0; + profile->bits = 1; + profile->numpixels = 0; +} + +/*function used for debug purposes with C++*/ +/*void printColorProfile(LodePNGColorProfile* p) +{ + std::cout << "colored: " << (int)p->colored << ", "; + std::cout << "key: " << (int)p->key << ", "; + std::cout << "key_r: " << (int)p->key_r << ", "; + std::cout << "key_g: " << (int)p->key_g << ", "; + std::cout << "key_b: " << (int)p->key_b << ", "; + std::cout << "alpha: " << (int)p->alpha << ", "; + std::cout << "numcolors: " << (int)p->numcolors << ", "; + std::cout << "bits: " << (int)p->bits << std::endl; +}*/ + +/*Returns how many bits needed to represent given value (max 8 bit)*/ +static unsigned getValueRequiredBits(unsigned char value) +{ + if(value == 0 || value == 255) return 1; + /*The scaling of 2-bit and 4-bit values uses multiples of 85 and 17*/ + if(value % 17 == 0) return value % 85 == 0 ? 2 : 4; + return 8; +} + +/*profile must already have been inited. +It's ok to set some parameters of profile to done already.*/ +unsigned lodepng_get_color_profile(LodePNGColorProfile* profile, + const unsigned char* in, unsigned w, unsigned h, + const LodePNGColorMode* mode_in) +{ + unsigned error = 0; + size_t i; + ColorTree tree; + size_t numpixels = (size_t)w * (size_t)h; + + /* mark things as done already if it would be impossible to have a more expensive case */ + unsigned colored_done = lodepng_is_greyscale_type(mode_in) ? 1 : 0; + unsigned alpha_done = lodepng_can_have_alpha(mode_in) ? 0 : 1; + unsigned numcolors_done = 0; + unsigned bpp = lodepng_get_bpp(mode_in); + unsigned bits_done = (profile->bits == 1 && bpp == 1) ? 1 : 0; + unsigned sixteen = 0; /* whether the input image is 16 bit */ + unsigned maxnumcolors = 257; + if(bpp <= 8) maxnumcolors = LODEPNG_MIN(257, profile->numcolors + (1u << bpp)); + + profile->numpixels += numpixels; + + color_tree_init(&tree); + + /*If the profile was already filled in from previous data, fill its palette in tree + and mark things as done already if we know they are the most expensive case already*/ + if(profile->alpha) alpha_done = 1; + if(profile->colored) colored_done = 1; + if(profile->bits == 16) numcolors_done = 1; + if(profile->bits >= bpp) bits_done = 1; + if(profile->numcolors >= maxnumcolors) numcolors_done = 1; + + if(!numcolors_done) + { + for(i = 0; i < profile->numcolors; i++) + { + const unsigned char* color = &profile->palette[i * 4]; + color_tree_add(&tree, color[0], color[1], color[2], color[3], i); + } + } + + /*Check if the 16-bit input is truly 16-bit*/ + if(mode_in->bitdepth == 16 && !sixteen) + { + unsigned short r, g, b, a; + for(i = 0; i != numpixels; ++i) + { + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); + if((r & 255) != ((r >> 8) & 255) || (g & 255) != ((g >> 8) & 255) || + (b & 255) != ((b >> 8) & 255) || (a & 255) != ((a >> 8) & 255)) /*first and second byte differ*/ + { + profile->bits = 16; + sixteen = 1; + bits_done = 1; + numcolors_done = 1; /*counting colors no longer useful, palette doesn't support 16-bit*/ + break; + } + } + } + + if(sixteen) + { + unsigned short r = 0, g = 0, b = 0, a = 0; + + for(i = 0; i != numpixels; ++i) + { + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); + + if(!colored_done && (r != g || r != b)) + { + profile->colored = 1; + colored_done = 1; + } + + if(!alpha_done) + { + unsigned matchkey = (r == profile->key_r && g == profile->key_g && b == profile->key_b); + if(a != 65535 && (a != 0 || (profile->key && !matchkey))) + { + profile->alpha = 1; + profile->key = 0; + alpha_done = 1; + } + else if(a == 0 && !profile->alpha && !profile->key) + { + profile->key = 1; + profile->key_r = r; + profile->key_g = g; + profile->key_b = b; + } + else if(a == 65535 && profile->key && matchkey) + { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + profile->alpha = 1; + profile->key = 0; + alpha_done = 1; + } + } + if(alpha_done && numcolors_done && colored_done && bits_done) break; + } + + if(profile->key && !profile->alpha) + { + for(i = 0; i != numpixels; ++i) + { + getPixelColorRGBA16(&r, &g, &b, &a, in, i, mode_in); + if(a != 0 && r == profile->key_r && g == profile->key_g && b == profile->key_b) + { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + profile->alpha = 1; + profile->key = 0; + alpha_done = 1; + } + } + } + } + else /* < 16-bit */ + { + unsigned char r = 0, g = 0, b = 0, a = 0; + for(i = 0; i != numpixels; ++i) + { + getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); + + if(!bits_done && profile->bits < 8) + { + /*only r is checked, < 8 bits is only relevant for greyscale*/ + unsigned bits = getValueRequiredBits(r); + if(bits > profile->bits) profile->bits = bits; + } + bits_done = (profile->bits >= bpp); + + if(!colored_done && (r != g || r != b)) + { + profile->colored = 1; + colored_done = 1; + if(profile->bits < 8) profile->bits = 8; /*PNG has no colored modes with less than 8-bit per channel*/ + } + + if(!alpha_done) + { + unsigned matchkey = (r == profile->key_r && g == profile->key_g && b == profile->key_b); + if(a != 255 && (a != 0 || (profile->key && !matchkey))) + { + profile->alpha = 1; + profile->key = 0; + alpha_done = 1; + if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + else if(a == 0 && !profile->alpha && !profile->key) + { + profile->key = 1; + profile->key_r = r; + profile->key_g = g; + profile->key_b = b; + } + else if(a == 255 && profile->key && matchkey) + { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + profile->alpha = 1; + profile->key = 0; + alpha_done = 1; + if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + } + + if(!numcolors_done) + { + if(!color_tree_has(&tree, r, g, b, a)) + { + color_tree_add(&tree, r, g, b, a, profile->numcolors); + if(profile->numcolors < 256) + { + unsigned char* p = profile->palette; + unsigned n = profile->numcolors; + p[n * 4 + 0] = r; + p[n * 4 + 1] = g; + p[n * 4 + 2] = b; + p[n * 4 + 3] = a; + } + ++profile->numcolors; + numcolors_done = profile->numcolors >= maxnumcolors; + } + } + + if(alpha_done && numcolors_done && colored_done && bits_done) break; + } + + if(profile->key && !profile->alpha) + { + for(i = 0; i != numpixels; ++i) + { + getPixelColorRGBA8(&r, &g, &b, &a, in, i, mode_in); + if(a != 0 && r == profile->key_r && g == profile->key_g && b == profile->key_b) + { + /* Color key cannot be used if an opaque pixel also has that RGB color. */ + profile->alpha = 1; + profile->key = 0; + alpha_done = 1; + if(profile->bits < 8) profile->bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + } + } + + /*make the profile's key always 16-bit for consistency - repeat each byte twice*/ + profile->key_r += (profile->key_r << 8); + profile->key_g += (profile->key_g << 8); + profile->key_b += (profile->key_b << 8); + } + + color_tree_cleanup(&tree); + return error; +} + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +/*Adds a single color to the color profile. The profile must already have been inited. The color must be given as 16-bit +(with 2 bytes repeating for 8-bit and 65535 for opaque alpha channel). This function is expensive, do not call it for +all pixels of an image but only for a few additional values. */ +static unsigned lodepng_color_profile_add(LodePNGColorProfile* profile, + unsigned r, unsigned g, unsigned b, unsigned a) +{ + unsigned error = 0; + unsigned char image[8]; + LodePNGColorMode mode; + lodepng_color_mode_init(&mode); + image[0] = r >> 8; image[1] = r; image[2] = g >> 8; image[3] = g; + image[4] = b >> 8; image[5] = b; image[6] = a >> 8; image[7] = a; + mode.bitdepth = 16; + mode.colortype = LCT_RGBA; + error = lodepng_get_color_profile(profile, image, 1, 1, &mode); + lodepng_color_mode_cleanup(&mode); + return error; +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +/*Autochoose color model given the computed profile. mode_in is to copy palette order from +when relevant.*/ +static unsigned auto_choose_color_from_profile(LodePNGColorMode* mode_out, + const LodePNGColorMode* mode_in, + const LodePNGColorProfile* prof) +{ + unsigned error = 0; + unsigned palettebits, palette_ok; + size_t i, n; + size_t numpixels = prof->numpixels; + + unsigned alpha = prof->alpha; + unsigned key = prof->key; + unsigned bits = prof->bits; + + mode_out->key_defined = 0; + + if(key && numpixels <= 16) + { + alpha = 1; /*too few pixels to justify tRNS chunk overhead*/ + key = 0; + if(bits < 8) bits = 8; /*PNG has no alphachannel modes with less than 8-bit per channel*/ + } + n = prof->numcolors; + palettebits = n <= 2 ? 1 : (n <= 4 ? 2 : (n <= 16 ? 4 : 8)); + palette_ok = n <= 256 && bits <= 8; + if(numpixels < n * 2) palette_ok = 0; /*don't add palette overhead if image has only a few pixels*/ + if(!prof->colored && bits <= palettebits) palette_ok = 0; /*grey is less overhead*/ + + if(palette_ok) + { + const unsigned char* p = prof->palette; + lodepng_palette_clear(mode_out); /*remove potential earlier palette*/ + for(i = 0; i != prof->numcolors; ++i) + { + error = lodepng_palette_add(mode_out, p[i * 4 + 0], p[i * 4 + 1], p[i * 4 + 2], p[i * 4 + 3]); + if(error) break; + } + + mode_out->colortype = LCT_PALETTE; + mode_out->bitdepth = palettebits; + + if(mode_in->colortype == LCT_PALETTE && mode_in->palettesize >= mode_out->palettesize + && mode_in->bitdepth == mode_out->bitdepth) + { + /*If input should have same palette colors, keep original to preserve its order and prevent conversion*/ + lodepng_color_mode_cleanup(mode_out); + lodepng_color_mode_copy(mode_out, mode_in); + } + } + else /*8-bit or 16-bit per channel*/ + { + mode_out->bitdepth = bits; + mode_out->colortype = alpha ? (prof->colored ? LCT_RGBA : LCT_GREY_ALPHA) + : (prof->colored ? LCT_RGB : LCT_GREY); + + if(key) + { + unsigned mask = (1u << mode_out->bitdepth) - 1u; /*profile always uses 16-bit, mask converts it*/ + mode_out->key_r = prof->key_r & mask; + mode_out->key_g = prof->key_g & mask; + mode_out->key_b = prof->key_b & mask; + mode_out->key_defined = 1; + } + } + + return error; +} + +/*Automatically chooses color type that gives smallest amount of bits in the +output image, e.g. grey if there are only greyscale pixels, palette if there +are less than 256 colors, color key if only single transparent color, ... +Updates values of mode with a potentially smaller color model. mode_out should +contain the user chosen color model, but will be overwritten with the new chosen one.*/ +unsigned lodepng_auto_choose_color(LodePNGColorMode* mode_out, + const unsigned char* image, unsigned w, unsigned h, + const LodePNGColorMode* mode_in) +{ + unsigned error = 0; + LodePNGColorProfile prof; + lodepng_color_profile_init(&prof); + error = lodepng_get_color_profile(&prof, image, w, h, mode_in); + if(error) return error; + return auto_choose_color_from_profile(mode_out, mode_in, &prof); +} + +#endif /* #ifdef LODEPNG_COMPILE_ENCODER */ + +/* +Paeth predicter, used by PNG filter type 4 +The parameters are of type short, but should come from unsigned chars, the shorts +are only needed to make the paeth calculation correct. +*/ +static unsigned char paethPredictor(short a, short b, short c) +{ + short pa = abs(b - c); + short pb = abs(a - c); + short pc = abs(a + b - c - c); + + if(pc < pa && pc < pb) return (unsigned char)c; + else if(pb < pa) return (unsigned char)b; + else return (unsigned char)a; +} + +/*shared values used by multiple Adam7 related functions*/ + +static const unsigned ADAM7_IX[7] = { 0, 4, 0, 2, 0, 1, 0 }; /*x start values*/ +static const unsigned ADAM7_IY[7] = { 0, 0, 4, 0, 2, 0, 1 }; /*y start values*/ +static const unsigned ADAM7_DX[7] = { 8, 8, 4, 4, 2, 2, 1 }; /*x delta values*/ +static const unsigned ADAM7_DY[7] = { 8, 8, 8, 4, 4, 2, 2 }; /*y delta values*/ + +/* +Outputs various dimensions and positions in the image related to the Adam7 reduced images. +passw: output containing the width of the 7 passes +passh: output containing the height of the 7 passes +filter_passstart: output containing the index of the start and end of each + reduced image with filter bytes +padded_passstart output containing the index of the start and end of each + reduced image when without filter bytes but with padded scanlines +passstart: output containing the index of the start and end of each reduced + image without padding between scanlines, but still padding between the images +w, h: width and height of non-interlaced image +bpp: bits per pixel +"padded" is only relevant if bpp is less than 8 and a scanline or image does not + end at a full byte +*/ +static void Adam7_getpassvalues(unsigned passw[7], unsigned passh[7], size_t filter_passstart[8], + size_t padded_passstart[8], size_t passstart[8], unsigned w, unsigned h, unsigned bpp) +{ + /*the passstart values have 8 values: the 8th one indicates the byte after the end of the 7th (= last) pass*/ + unsigned i; + + /*calculate width and height in pixels of each pass*/ + for(i = 0; i != 7; ++i) + { + passw[i] = (w + ADAM7_DX[i] - ADAM7_IX[i] - 1) / ADAM7_DX[i]; + passh[i] = (h + ADAM7_DY[i] - ADAM7_IY[i] - 1) / ADAM7_DY[i]; + if(passw[i] == 0) passh[i] = 0; + if(passh[i] == 0) passw[i] = 0; + } + + filter_passstart[0] = padded_passstart[0] = passstart[0] = 0; + for(i = 0; i != 7; ++i) + { + /*if passw[i] is 0, it's 0 bytes, not 1 (no filtertype-byte)*/ + filter_passstart[i + 1] = filter_passstart[i] + + ((passw[i] && passh[i]) ? passh[i] * (1 + (passw[i] * bpp + 7) / 8) : 0); + /*bits padded if needed to fill full byte at end of each scanline*/ + padded_passstart[i + 1] = padded_passstart[i] + passh[i] * ((passw[i] * bpp + 7) / 8); + /*only padded at end of reduced image*/ + passstart[i + 1] = passstart[i] + (passh[i] * passw[i] * bpp + 7) / 8; + } +} + +#ifdef LODEPNG_COMPILE_DECODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / PNG Decoder / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*read the information from the header and store it in the LodePNGInfo. return value is error*/ +unsigned lodepng_inspect(unsigned* w, unsigned* h, LodePNGState* state, + const unsigned char* in, size_t insize) +{ + unsigned width, height; + LodePNGInfo* info = &state->info_png; + if(insize == 0 || in == 0) + { + CERROR_RETURN_ERROR(state->error, 48); /*error: the given data is empty*/ + } + if(insize < 33) + { + CERROR_RETURN_ERROR(state->error, 27); /*error: the data length is smaller than the length of a PNG header*/ + } + + /*when decoding a new PNG image, make sure all parameters created after previous decoding are reset*/ + /* TODO: remove this. One should use a new LodePNGState for new sessions */ + lodepng_info_cleanup(info); + lodepng_info_init(info); + + if(in[0] != 137 || in[1] != 80 || in[2] != 78 || in[3] != 71 + || in[4] != 13 || in[5] != 10 || in[6] != 26 || in[7] != 10) + { + CERROR_RETURN_ERROR(state->error, 28); /*error: the first 8 bytes are not the correct PNG signature*/ + } + if(lodepng_chunk_length(in + 8) != 13) + { + CERROR_RETURN_ERROR(state->error, 94); /*error: header size must be 13 bytes*/ + } + if(!lodepng_chunk_type_equals(in + 8, "IHDR")) + { + CERROR_RETURN_ERROR(state->error, 29); /*error: it doesn't start with a IHDR chunk!*/ + } + + /*read the values given in the header*/ + width = lodepng_read32bitInt(&in[16]); + height = lodepng_read32bitInt(&in[20]); + info->color.bitdepth = in[24]; + info->color.colortype = (LodePNGColorType)in[25]; + info->compression_method = in[26]; + info->filter_method = in[27]; + info->interlace_method = in[28]; + + if(width == 0 || height == 0) + { + CERROR_RETURN_ERROR(state->error, 93); + } + + if(w) *w = width; + if(h) *h = height; + + if(!state->decoder.ignore_crc) + { + unsigned CRC = lodepng_read32bitInt(&in[29]); + unsigned checksum = lodepng_crc32(&in[12], 17); + if(CRC != checksum) + { + CERROR_RETURN_ERROR(state->error, 57); /*invalid CRC*/ + } + } + + /*error: only compression method 0 is allowed in the specification*/ + if(info->compression_method != 0) CERROR_RETURN_ERROR(state->error, 32); + /*error: only filter method 0 is allowed in the specification*/ + if(info->filter_method != 0) CERROR_RETURN_ERROR(state->error, 33); + /*error: only interlace methods 0 and 1 exist in the specification*/ + if(info->interlace_method > 1) CERROR_RETURN_ERROR(state->error, 34); + + state->error = checkColorValidity(info->color.colortype, info->color.bitdepth); + return state->error; +} + +static unsigned unfilterScanline(unsigned char* recon, const unsigned char* scanline, const unsigned char* precon, + size_t bytewidth, unsigned char filterType, size_t length) +{ + /* + For PNG filter method 0 + unfilter a PNG image scanline by scanline. when the pixels are smaller than 1 byte, + the filter works byte per byte (bytewidth = 1) + precon is the previous unfiltered scanline, recon the result, scanline the current one + the incoming scanlines do NOT include the filtertype byte, that one is given in the parameter filterType instead + recon and scanline MAY be the same memory address! precon must be disjoint. + */ + + size_t i; + switch(filterType) + { + case 0: + for(i = 0; i != length; ++i) recon[i] = scanline[i]; + break; + case 1: + for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; + for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + recon[i - bytewidth]; + break; + case 2: + if(precon) + { + for(i = 0; i != length; ++i) recon[i] = scanline[i] + precon[i]; + } + else + { + for(i = 0; i != length; ++i) recon[i] = scanline[i]; + } + break; + case 3: + if(precon) + { + for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i] + (precon[i] >> 1); + for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + ((recon[i - bytewidth] + precon[i]) >> 1); + } + else + { + for(i = 0; i != bytewidth; ++i) recon[i] = scanline[i]; + for(i = bytewidth; i < length; ++i) recon[i] = scanline[i] + (recon[i - bytewidth] >> 1); + } + break; + case 4: + if(precon) + { + for(i = 0; i != bytewidth; ++i) + { + recon[i] = (scanline[i] + precon[i]); /*paethPredictor(0, precon[i], 0) is always precon[i]*/ + } + for(i = bytewidth; i < length; ++i) + { + recon[i] = (scanline[i] + paethPredictor(recon[i - bytewidth], precon[i], precon[i - bytewidth])); + } + } + else + { + for(i = 0; i != bytewidth; ++i) + { + recon[i] = scanline[i]; + } + for(i = bytewidth; i < length; ++i) + { + /*paethPredictor(recon[i - bytewidth], 0, 0) is always recon[i - bytewidth]*/ + recon[i] = (scanline[i] + recon[i - bytewidth]); + } + } + break; + default: return 36; /*error: unexisting filter type given*/ + } + return 0; +} + +static unsigned unfilter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) +{ + /* + For PNG filter method 0 + this function unfilters a single image (e.g. without interlacing this is called once, with Adam7 seven times) + out must have enough bytes allocated already, in must have the scanlines + 1 filtertype byte per scanline + w and h are image dimensions or dimensions of reduced image, bpp is bits per pixel + in and out are allowed to be the same memory address (but aren't the same size since in has the extra filter bytes) + */ + + unsigned y; + unsigned char* prevline = 0; + + /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ + size_t bytewidth = (bpp + 7) / 8; + size_t linebytes = (w * bpp + 7) / 8; + + for(y = 0; y < h; ++y) + { + size_t outindex = linebytes * y; + size_t inindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ + unsigned char filterType = in[inindex]; + + CERROR_TRY_RETURN(unfilterScanline(&out[outindex], &in[inindex + 1], prevline, bytewidth, filterType, linebytes)); + + prevline = &out[outindex]; + } + + return 0; +} + +/* +in: Adam7 interlaced image, with no padding bits between scanlines, but between + reduced images so that each reduced image starts at a byte. +out: the same pixels, but re-ordered so that they're now a non-interlaced image with size w*h +bpp: bits per pixel +out has the following size in bits: w * h * bpp. +in is possibly bigger due to padding bits between reduced images. +out must be big enough AND must be 0 everywhere if bpp < 8 in the current implementation +(because that's likely a little bit faster) +NOTE: comments about padding bits are only relevant if bpp < 8 +*/ +static void Adam7_deinterlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) +{ + unsigned passw[7], passh[7]; + size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned i; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + if(bpp >= 8) + { + for(i = 0; i != 7; ++i) + { + unsigned x, y, b; + size_t bytewidth = bpp / 8; + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) + { + size_t pixelinstart = passstart[i] + (y * passw[i] + x) * bytewidth; + size_t pixeloutstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth; + for(b = 0; b < bytewidth; ++b) + { + out[pixeloutstart + b] = in[pixelinstart + b]; + } + } + } + } + else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ + { + for(i = 0; i != 7; ++i) + { + unsigned x, y, b; + unsigned ilinebits = bpp * passw[i]; + unsigned olinebits = bpp * w; + size_t obp, ibp; /*bit pointers (for out and in buffer)*/ + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) + { + ibp = (8 * passstart[i]) + (y * ilinebits + x * bpp); + obp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp; + for(b = 0; b < bpp; ++b) + { + unsigned char bit = readBitFromReversedStream(&ibp, in); + /*note that this function assumes the out buffer is completely 0, use setBitOfReversedStream otherwise*/ + setBitOfReversedStream0(&obp, out, bit); + } + } + } + } +} + +static void removePaddingBits(unsigned char* out, const unsigned char* in, + size_t olinebits, size_t ilinebits, unsigned h) +{ + /* + After filtering there are still padding bits if scanlines have non multiple of 8 bit amounts. They need + to be removed (except at last scanline of (Adam7-reduced) image) before working with pure image buffers + for the Adam7 code, the color convert code and the output to the user. + in and out are allowed to be the same buffer, in may also be higher but still overlapping; in must + have >= ilinebits*h bits, out must have >= olinebits*h bits, olinebits must be <= ilinebits + also used to move bits after earlier such operations happened, e.g. in a sequence of reduced images from Adam7 + only useful if (ilinebits - olinebits) is a value in the range 1..7 + */ + unsigned y; + size_t diff = ilinebits - olinebits; + size_t ibp = 0, obp = 0; /*input and output bit pointers*/ + for(y = 0; y < h; ++y) + { + size_t x; + for(x = 0; x < olinebits; ++x) + { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + ibp += diff; + } +} + +/*out must be buffer big enough to contain full image, and in must contain the full decompressed data from +the IDAT chunks (with filter index bytes and possible padding bits) +return value is error*/ +static unsigned postProcessScanlines(unsigned char* out, unsigned char* in, + unsigned w, unsigned h, const LodePNGInfo* info_png) +{ + /* + This function converts the filtered-padded-interlaced data into pure 2D image buffer with the PNG's colortype. + Steps: + *) if no Adam7: 1) unfilter 2) remove padding bits (= posible extra bits per scanline if bpp < 8) + *) if adam7: 1) 7x unfilter 2) 7x remove padding bits 3) Adam7_deinterlace + NOTE: the in buffer will be overwritten with intermediate data! + */ + unsigned bpp = lodepng_get_bpp(&info_png->color); + if(bpp == 0) return 31; /*error: invalid colortype*/ + + if(info_png->interlace_method == 0) + { + if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8) + { + CERROR_TRY_RETURN(unfilter(in, in, w, h, bpp)); + removePaddingBits(out, in, w * bpp, ((w * bpp + 7) / 8) * 8, h); + } + /*we can immediately filter into the out buffer, no other steps needed*/ + else CERROR_TRY_RETURN(unfilter(out, in, w, h, bpp)); + } + else /*interlace_method is 1 (Adam7)*/ + { + unsigned passw[7], passh[7]; size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned i; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + for(i = 0; i != 7; ++i) + { + CERROR_TRY_RETURN(unfilter(&in[padded_passstart[i]], &in[filter_passstart[i]], passw[i], passh[i], bpp)); + /*TODO: possible efficiency improvement: if in this reduced image the bits fit nicely in 1 scanline, + move bytes instead of bits or move not at all*/ + if(bpp < 8) + { + /*remove padding bits in scanlines; after this there still may be padding + bits between the different reduced images: each reduced image still starts nicely at a byte*/ + removePaddingBits(&in[passstart[i]], &in[padded_passstart[i]], passw[i] * bpp, + ((passw[i] * bpp + 7) / 8) * 8, passh[i]); + } + } + + Adam7_deinterlace(out, in, w, h, bpp); + } + + return 0; +} + +static unsigned readChunk_PLTE(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) +{ + unsigned pos = 0, i; + if(color->palette) lodepng_free(color->palette); + color->palettesize = chunkLength / 3; + color->palette = (unsigned char*)lodepng_malloc(4 * color->palettesize); + if(!color->palette && color->palettesize) + { + color->palettesize = 0; + return 83; /*alloc fail*/ + } + if(color->palettesize > 256) return 38; /*error: palette too big*/ + + for(i = 0; i != color->palettesize; ++i) + { + color->palette[4 * i + 0] = data[pos++]; /*R*/ + color->palette[4 * i + 1] = data[pos++]; /*G*/ + color->palette[4 * i + 2] = data[pos++]; /*B*/ + color->palette[4 * i + 3] = 255; /*alpha*/ + } + + return 0; /* OK */ +} + +static unsigned readChunk_tRNS(LodePNGColorMode* color, const unsigned char* data, size_t chunkLength) +{ + unsigned i; + if(color->colortype == LCT_PALETTE) + { + /*error: more alpha values given than there are palette entries*/ + if(chunkLength > color->palettesize) return 39; + + for(i = 0; i != chunkLength; ++i) color->palette[4 * i + 3] = data[i]; + } + else if(color->colortype == LCT_GREY) + { + /*error: this chunk must be 2 bytes for greyscale image*/ + if(chunkLength != 2) return 30; + + color->key_defined = 1; + color->key_r = color->key_g = color->key_b = 256u * data[0] + data[1]; + } + else if(color->colortype == LCT_RGB) + { + /*error: this chunk must be 6 bytes for RGB image*/ + if(chunkLength != 6) return 41; + + color->key_defined = 1; + color->key_r = 256u * data[0] + data[1]; + color->key_g = 256u * data[2] + data[3]; + color->key_b = 256u * data[4] + data[5]; + } + else return 42; /*error: tRNS chunk not allowed for other color models*/ + + return 0; /* OK */ +} + + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +/*background color chunk (bKGD)*/ +static unsigned readChunk_bKGD(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) +{ + if(info->color.colortype == LCT_PALETTE) + { + /*error: this chunk must be 1 byte for indexed color image*/ + if(chunkLength != 1) return 43; + + /*error: invalid palette index, or maybe this chunk appeared before PLTE*/ + if(data[0] >= info->color.palettesize) return 103; + + info->background_defined = 1; + info->background_r = info->background_g = info->background_b = data[0]; + } + else if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) + { + /*error: this chunk must be 2 bytes for greyscale image*/ + if(chunkLength != 2) return 44; + + /*the values are truncated to bitdepth in the PNG file*/ + info->background_defined = 1; + info->background_r = info->background_g = info->background_b = 256u * data[0] + data[1]; + } + else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) + { + /*error: this chunk must be 6 bytes for greyscale image*/ + if(chunkLength != 6) return 45; + + /*the values are truncated to bitdepth in the PNG file*/ + info->background_defined = 1; + info->background_r = 256u * data[0] + data[1]; + info->background_g = 256u * data[2] + data[3]; + info->background_b = 256u * data[4] + data[5]; + } + + return 0; /* OK */ +} + +/*text chunk (tEXt)*/ +static unsigned readChunk_tEXt(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) +{ + unsigned error = 0; + char *key = 0, *str = 0; + unsigned i; + + while(!error) /*not really a while loop, only used to break on error*/ + { + unsigned length, string2_begin; + + length = 0; + while(length < chunkLength && data[length] != 0) ++length; + /*even though it's not allowed by the standard, no error is thrown if + there's no null termination char, if the text is empty*/ + if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ + + key = (char*)lodepng_malloc(length + 1); + if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ + + key[length] = 0; + for(i = 0; i != length; ++i) key[i] = (char)data[i]; + + string2_begin = length + 1; /*skip keyword null terminator*/ + + length = (unsigned)(chunkLength < string2_begin ? 0 : chunkLength - string2_begin); + str = (char*)lodepng_malloc(length + 1); + if(!str) CERROR_BREAK(error, 83); /*alloc fail*/ + + str[length] = 0; + for(i = 0; i != length; ++i) str[i] = (char)data[string2_begin + i]; + + error = lodepng_add_text(info, key, str); + + break; + } + + lodepng_free(key); + lodepng_free(str); + + return error; +} + +/*compressed text chunk (zTXt)*/ +static unsigned readChunk_zTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings, + const unsigned char* data, size_t chunkLength) +{ + unsigned error = 0; + unsigned i; + + unsigned length, string2_begin; + char *key = 0; + ucvector decoded; + + ucvector_init(&decoded); + + while(!error) /*not really a while loop, only used to break on error*/ + { + for(length = 0; length < chunkLength && data[length] != 0; ++length) ; + if(length + 2 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/ + if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ + + key = (char*)lodepng_malloc(length + 1); + if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ + + key[length] = 0; + for(i = 0; i != length; ++i) key[i] = (char)data[i]; + + if(data[length + 1] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/ + + string2_begin = length + 2; + if(string2_begin > chunkLength) CERROR_BREAK(error, 75); /*no null termination, corrupt?*/ + + length = (unsigned)chunkLength - string2_begin; + /*will fail if zlib error, e.g. if length is too small*/ + error = zlib_decompress(&decoded.data, &decoded.size, + (unsigned char*)(&data[string2_begin]), + length, zlibsettings); + if(error) break; + ucvector_push_back(&decoded, 0); + + error = lodepng_add_text(info, key, (char*)decoded.data); + + break; + } + + lodepng_free(key); + ucvector_cleanup(&decoded); + + return error; +} + +/*international text chunk (iTXt)*/ +static unsigned readChunk_iTXt(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings, + const unsigned char* data, size_t chunkLength) +{ + unsigned error = 0; + unsigned i; + + unsigned length, begin, compressed; + char *key = 0, *langtag = 0, *transkey = 0; + ucvector decoded; + ucvector_init(&decoded); /* TODO: only use in case of compressed text */ + + while(!error) /*not really a while loop, only used to break on error*/ + { + /*Quick check if the chunk length isn't too small. Even without check + it'd still fail with other error checks below if it's too short. This just gives a different error code.*/ + if(chunkLength < 5) CERROR_BREAK(error, 30); /*iTXt chunk too short*/ + + /*read the key*/ + for(length = 0; length < chunkLength && data[length] != 0; ++length) ; + if(length + 3 >= chunkLength) CERROR_BREAK(error, 75); /*no null termination char, corrupt?*/ + if(length < 1 || length > 79) CERROR_BREAK(error, 89); /*keyword too short or long*/ + + key = (char*)lodepng_malloc(length + 1); + if(!key) CERROR_BREAK(error, 83); /*alloc fail*/ + + key[length] = 0; + for(i = 0; i != length; ++i) key[i] = (char)data[i]; + + /*read the compression method*/ + compressed = data[length + 1]; + if(data[length + 2] != 0) CERROR_BREAK(error, 72); /*the 0 byte indicating compression must be 0*/ + + /*even though it's not allowed by the standard, no error is thrown if + there's no null termination char, if the text is empty for the next 3 texts*/ + + /*read the langtag*/ + begin = length + 3; + length = 0; + for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length; + + langtag = (char*)lodepng_malloc(length + 1); + if(!langtag) CERROR_BREAK(error, 83); /*alloc fail*/ + + langtag[length] = 0; + for(i = 0; i != length; ++i) langtag[i] = (char)data[begin + i]; + + /*read the transkey*/ + begin += length + 1; + length = 0; + for(i = begin; i < chunkLength && data[i] != 0; ++i) ++length; + + transkey = (char*)lodepng_malloc(length + 1); + if(!transkey) CERROR_BREAK(error, 83); /*alloc fail*/ + + transkey[length] = 0; + for(i = 0; i != length; ++i) transkey[i] = (char)data[begin + i]; + + /*read the actual text*/ + begin += length + 1; + + length = (unsigned)chunkLength < begin ? 0 : (unsigned)chunkLength - begin; + + if(compressed) + { + /*will fail if zlib error, e.g. if length is too small*/ + error = zlib_decompress(&decoded.data, &decoded.size, + (unsigned char*)(&data[begin]), + length, zlibsettings); + if(error) break; + if(decoded.allocsize < decoded.size) decoded.allocsize = decoded.size; + ucvector_push_back(&decoded, 0); + } + else + { + if(!ucvector_resize(&decoded, length + 1)) CERROR_BREAK(error, 83 /*alloc fail*/); + + decoded.data[length] = 0; + for(i = 0; i != length; ++i) decoded.data[i] = data[begin + i]; + } + + error = lodepng_add_itext(info, key, langtag, transkey, (char*)decoded.data); + + break; + } + + lodepng_free(key); + lodepng_free(langtag); + lodepng_free(transkey); + ucvector_cleanup(&decoded); + + return error; +} + +static unsigned readChunk_tIME(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) +{ + if(chunkLength != 7) return 73; /*invalid tIME chunk size*/ + + info->time_defined = 1; + info->time.year = 256u * data[0] + data[1]; + info->time.month = data[2]; + info->time.day = data[3]; + info->time.hour = data[4]; + info->time.minute = data[5]; + info->time.second = data[6]; + + return 0; /* OK */ +} + +static unsigned readChunk_pHYs(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) +{ + if(chunkLength != 9) return 74; /*invalid pHYs chunk size*/ + + info->phys_defined = 1; + info->phys_x = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3]; + info->phys_y = 16777216u * data[4] + 65536u * data[5] + 256u * data[6] + data[7]; + info->phys_unit = data[8]; + + return 0; /* OK */ +} + +static unsigned readChunk_gAMA(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) +{ + if(chunkLength != 4) return 96; /*invalid gAMA chunk size*/ + + info->gama_defined = 1; + info->gama_gamma = 16777216u * data[0] + 65536u * data[1] + 256u * data[2] + data[3]; + + return 0; /* OK */ +} + +static unsigned readChunk_cHRM(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) +{ + if(chunkLength != 32) return 97; /*invalid cHRM chunk size*/ + + info->chrm_defined = 1; + info->chrm_white_x = 16777216u * data[ 0] + 65536u * data[ 1] + 256u * data[ 2] + data[ 3]; + info->chrm_white_y = 16777216u * data[ 4] + 65536u * data[ 5] + 256u * data[ 6] + data[ 7]; + info->chrm_red_x = 16777216u * data[ 8] + 65536u * data[ 9] + 256u * data[10] + data[11]; + info->chrm_red_y = 16777216u * data[12] + 65536u * data[13] + 256u * data[14] + data[15]; + info->chrm_green_x = 16777216u * data[16] + 65536u * data[17] + 256u * data[18] + data[19]; + info->chrm_green_y = 16777216u * data[20] + 65536u * data[21] + 256u * data[22] + data[23]; + info->chrm_blue_x = 16777216u * data[24] + 65536u * data[25] + 256u * data[26] + data[27]; + info->chrm_blue_y = 16777216u * data[28] + 65536u * data[29] + 256u * data[30] + data[31]; + + return 0; /* OK */ +} + +static unsigned readChunk_sRGB(LodePNGInfo* info, const unsigned char* data, size_t chunkLength) +{ + if(chunkLength != 1) return 98; /*invalid sRGB chunk size (this one is never ignored)*/ + + info->srgb_defined = 1; + info->srgb_intent = data[0]; + + return 0; /* OK */ +} + +static unsigned readChunk_iCCP(LodePNGInfo* info, const LodePNGDecompressSettings* zlibsettings, + const unsigned char* data, size_t chunkLength) +{ + unsigned error = 0; + unsigned i; + + unsigned length, string2_begin; + ucvector decoded; + + info->iccp_defined = 1; + if(info->iccp_name) lodepng_clear_icc(info); + + for(length = 0; length < chunkLength && data[length] != 0; ++length) ; + if(length + 2 >= chunkLength) return 75; /*no null termination, corrupt?*/ + if(length < 1 || length > 79) return 89; /*keyword too short or long*/ + + info->iccp_name = (char*)lodepng_malloc(length + 1); + if(!info->iccp_name) return 83; /*alloc fail*/ + + info->iccp_name[length] = 0; + for(i = 0; i != length; ++i) info->iccp_name[i] = (char)data[i]; + + if(data[length + 1] != 0) return 72; /*the 0 byte indicating compression must be 0*/ + + string2_begin = length + 2; + if(string2_begin > chunkLength) return 75; /*no null termination, corrupt?*/ + + length = (unsigned)chunkLength - string2_begin; + ucvector_init(&decoded); + error = zlib_decompress(&decoded.data, &decoded.size, + (unsigned char*)(&data[string2_begin]), + length, zlibsettings); + if(!error) { + info->iccp_profile_size = decoded.size; + info->iccp_profile = (unsigned char*)lodepng_malloc(decoded.size); + if(info->iccp_profile) { + memcpy(info->iccp_profile, decoded.data, decoded.size); + } else { + error = 83; /* alloc fail */ + } + } + ucvector_cleanup(&decoded); + return error; +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +unsigned lodepng_inspect_chunk(LodePNGState* state, size_t pos, + const unsigned char* in, size_t insize) +{ + const unsigned char* chunk = in + pos; + unsigned chunkLength; + const unsigned char* data; + unsigned unhandled = 0; + unsigned error = 0; + + if (pos + 4 > insize) return 30; + chunkLength = lodepng_chunk_length(chunk); + if(chunkLength > 2147483647) return 63; + data = lodepng_chunk_data_const(chunk); + if(data + chunkLength + 4 > in + insize) return 30; + + if(lodepng_chunk_type_equals(chunk, "PLTE")) + { + error = readChunk_PLTE(&state->info_png.color, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "tRNS")) + { + error = readChunk_tRNS(&state->info_png.color, data, chunkLength); + } +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + else if(lodepng_chunk_type_equals(chunk, "bKGD")) + { + error = readChunk_bKGD(&state->info_png, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "tEXt")) + { + error = readChunk_tEXt(&state->info_png, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "zTXt")) + { + error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "iTXt")) + { + error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "tIME")) + { + error = readChunk_tIME(&state->info_png, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "pHYs")) + { + error = readChunk_pHYs(&state->info_png, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "gAMA")) + { + error = readChunk_gAMA(&state->info_png, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "cHRM")) + { + error = readChunk_cHRM(&state->info_png, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "sRGB")) + { + error = readChunk_sRGB(&state->info_png, data, chunkLength); + } + else if(lodepng_chunk_type_equals(chunk, "iCCP")) + { + error = readChunk_iCCP(&state->info_png, &state->decoder.zlibsettings, data, chunkLength); + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + else + { + /* unhandled chunk is ok (is not an error) */ + unhandled = 1; + } + + if(!error && !unhandled && !state->decoder.ignore_crc) + { + if(lodepng_chunk_check_crc(chunk)) return 57; /*invalid CRC*/ + } + + return error; +} + +/*read a PNG, the result will be in the same color type as the PNG (hence "generic")*/ +static void decodeGeneric(unsigned char** out, unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize) +{ + unsigned char IEND = 0; + const unsigned char* chunk; + size_t i; + ucvector idat; /*the data from idat chunks*/ + ucvector scanlines; + size_t predict; + size_t outsize = 0; + + /*for unknown chunk order*/ + unsigned unknown = 0; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + unsigned critical_pos = 1; /*1 = after IHDR, 2 = after PLTE, 3 = after IDAT*/ +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + + /*provide some proper output values if error will happen*/ + *out = 0; + + state->error = lodepng_inspect(w, h, state, in, insize); /*reads header and resets other parameters in state->info_png*/ + if(state->error) return; + + if(lodepng_pixel_overflow(*w, *h, &state->info_png.color, &state->info_raw)) + { + CERROR_RETURN(state->error, 92); /*overflow possible due to amount of pixels*/ + } + + ucvector_init(&idat); + chunk = &in[33]; /*first byte of the first chunk after the header*/ + + /*loop through the chunks, ignoring unknown chunks and stopping at IEND chunk. + IDAT data is put at the start of the in buffer*/ + while(!IEND && !state->error) + { + unsigned chunkLength; + const unsigned char* data; /*the data in the chunk*/ + + /*error: size of the in buffer too small to contain next chunk*/ + if((size_t)((chunk - in) + 12) > insize || chunk < in) + { + if(state->decoder.ignore_end) break; /*other errors may still happen though*/ + CERROR_BREAK(state->error, 30); + } + + /*length of the data of the chunk, excluding the length bytes, chunk type and CRC bytes*/ + chunkLength = lodepng_chunk_length(chunk); + /*error: chunk length larger than the max PNG chunk size*/ + if(chunkLength > 2147483647) + { + if(state->decoder.ignore_end) break; /*other errors may still happen though*/ + CERROR_BREAK(state->error, 63); + } + + if((size_t)((chunk - in) + chunkLength + 12) > insize || (chunk + chunkLength + 12) < in) + { + CERROR_BREAK(state->error, 64); /*error: size of the in buffer too small to contain next chunk*/ + } + + data = lodepng_chunk_data_const(chunk); + + unknown = 0; + + /*IDAT chunk, containing compressed image data*/ + if(lodepng_chunk_type_equals(chunk, "IDAT")) + { + size_t oldsize = idat.size; + size_t newsize; + if(lodepng_addofl(oldsize, chunkLength, &newsize)) CERROR_BREAK(state->error, 95); + if(!ucvector_resize(&idat, newsize)) CERROR_BREAK(state->error, 83 /*alloc fail*/); + for(i = 0; i != chunkLength; ++i) idat.data[oldsize + i] = data[i]; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + critical_pos = 3; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } + /*IEND chunk*/ + else if(lodepng_chunk_type_equals(chunk, "IEND")) + { + IEND = 1; + } + /*palette chunk (PLTE)*/ + else if(lodepng_chunk_type_equals(chunk, "PLTE")) + { + state->error = readChunk_PLTE(&state->info_png.color, data, chunkLength); + if(state->error) break; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + critical_pos = 2; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } + /*palette transparency chunk (tRNS). Even though this one is an ancillary chunk , it is still compiled + in without 'LODEPNG_COMPILE_ANCILLARY_CHUNKS' because it contains essential color information that + affects the alpha channel of pixels. */ + else if(lodepng_chunk_type_equals(chunk, "tRNS")) + { + state->error = readChunk_tRNS(&state->info_png.color, data, chunkLength); + if(state->error) break; + } +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*background color chunk (bKGD)*/ + else if(lodepng_chunk_type_equals(chunk, "bKGD")) + { + state->error = readChunk_bKGD(&state->info_png, data, chunkLength); + if(state->error) break; + } + /*text chunk (tEXt)*/ + else if(lodepng_chunk_type_equals(chunk, "tEXt")) + { + if(state->decoder.read_text_chunks) + { + state->error = readChunk_tEXt(&state->info_png, data, chunkLength); + if(state->error) break; + } + } + /*compressed text chunk (zTXt)*/ + else if(lodepng_chunk_type_equals(chunk, "zTXt")) + { + if(state->decoder.read_text_chunks) + { + state->error = readChunk_zTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength); + if(state->error) break; + } + } + /*international text chunk (iTXt)*/ + else if(lodepng_chunk_type_equals(chunk, "iTXt")) + { + if(state->decoder.read_text_chunks) + { + state->error = readChunk_iTXt(&state->info_png, &state->decoder.zlibsettings, data, chunkLength); + if(state->error) break; + } + } + else if(lodepng_chunk_type_equals(chunk, "tIME")) + { + state->error = readChunk_tIME(&state->info_png, data, chunkLength); + if(state->error) break; + } + else if(lodepng_chunk_type_equals(chunk, "pHYs")) + { + state->error = readChunk_pHYs(&state->info_png, data, chunkLength); + if(state->error) break; + } + else if(lodepng_chunk_type_equals(chunk, "gAMA")) + { + state->error = readChunk_gAMA(&state->info_png, data, chunkLength); + if(state->error) break; + } + else if(lodepng_chunk_type_equals(chunk, "cHRM")) + { + state->error = readChunk_cHRM(&state->info_png, data, chunkLength); + if(state->error) break; + } + else if(lodepng_chunk_type_equals(chunk, "sRGB")) + { + state->error = readChunk_sRGB(&state->info_png, data, chunkLength); + if(state->error) break; + } + else if(lodepng_chunk_type_equals(chunk, "iCCP")) + { + state->error = readChunk_iCCP(&state->info_png, &state->decoder.zlibsettings, data, chunkLength); + if(state->error) break; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + else /*it's not an implemented chunk type, so ignore it: skip over the data*/ + { + /*error: unknown critical chunk (5th bit of first byte of chunk type is 0)*/ + if(!state->decoder.ignore_critical && !lodepng_chunk_ancillary(chunk)) + { + CERROR_BREAK(state->error, 69); + } + + unknown = 1; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(state->decoder.remember_unknown_chunks) + { + state->error = lodepng_chunk_append(&state->info_png.unknown_chunks_data[critical_pos - 1], + &state->info_png.unknown_chunks_size[critical_pos - 1], chunk); + if(state->error) break; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + } + + if(!state->decoder.ignore_crc && !unknown) /*check CRC if wanted, only on known chunk types*/ + { + if(lodepng_chunk_check_crc(chunk)) CERROR_BREAK(state->error, 57); /*invalid CRC*/ + } + + if(!IEND) chunk = lodepng_chunk_next_const(chunk); + } + + ucvector_init(&scanlines); + /*predict output size, to allocate exact size for output buffer to avoid more dynamic allocation. + If the decompressed size does not match the prediction, the image must be corrupt.*/ + if(state->info_png.interlace_method == 0) + { + predict = lodepng_get_raw_size_idat(*w, *h, &state->info_png.color); + } + else + { + /*Adam-7 interlaced: predicted size is the sum of the 7 sub-images sizes*/ + const LodePNGColorMode* color = &state->info_png.color; + predict = 0; + predict += lodepng_get_raw_size_idat((*w + 7) >> 3, (*h + 7) >> 3, color); + if(*w > 4) predict += lodepng_get_raw_size_idat((*w + 3) >> 3, (*h + 7) >> 3, color); + predict += lodepng_get_raw_size_idat((*w + 3) >> 2, (*h + 3) >> 3, color); + if(*w > 2) predict += lodepng_get_raw_size_idat((*w + 1) >> 2, (*h + 3) >> 2, color); + predict += lodepng_get_raw_size_idat((*w + 1) >> 1, (*h + 1) >> 2, color); + if(*w > 1) predict += lodepng_get_raw_size_idat((*w + 0) >> 1, (*h + 1) >> 1, color); + predict += lodepng_get_raw_size_idat((*w + 0), (*h + 0) >> 1, color); + } + if(!state->error && !ucvector_reserve(&scanlines, predict)) state->error = 83; /*alloc fail*/ + if(!state->error) + { + state->error = zlib_decompress(&scanlines.data, &scanlines.size, idat.data, + idat.size, &state->decoder.zlibsettings); + if(!state->error && scanlines.size != predict) state->error = 91; /*decompressed size doesn't match prediction*/ + } + ucvector_cleanup(&idat); + + if(!state->error) + { + outsize = lodepng_get_raw_size(*w, *h, &state->info_png.color); + *out = (unsigned char*)lodepng_malloc(outsize); + if(!*out) state->error = 83; /*alloc fail*/ + } + if(!state->error) + { + for(i = 0; i < outsize; i++) (*out)[i] = 0; + state->error = postProcessScanlines(*out, scanlines.data, *w, *h, &state->info_png); + } + ucvector_cleanup(&scanlines); +} + +unsigned lodepng_decode(unsigned char** out, unsigned* w, unsigned* h, + LodePNGState* state, + const unsigned char* in, size_t insize) +{ + *out = 0; + decodeGeneric(out, w, h, state, in, insize); + if(state->error) return state->error; + if(!state->decoder.color_convert || lodepng_color_mode_equal(&state->info_raw, &state->info_png.color)) + { + /*same color type, no copying or converting of data needed*/ + /*store the info_png color settings on the info_raw so that the info_raw still reflects what colortype + the raw image has to the end user*/ + if(!state->decoder.color_convert) + { + state->error = lodepng_color_mode_copy(&state->info_raw, &state->info_png.color); + if(state->error) return state->error; + } + } + else + { + /*color conversion needed; sort of copy of the data*/ + unsigned char* data = *out; + size_t outsize; + + /*TODO: check if this works according to the statement in the documentation: "The converter can convert + from greyscale input color type, to 8-bit greyscale or greyscale with alpha"*/ + if(!(state->info_raw.colortype == LCT_RGB || state->info_raw.colortype == LCT_RGBA) + && !(state->info_raw.bitdepth == 8)) + { + return 56; /*unsupported color mode conversion*/ + } + + outsize = lodepng_get_raw_size(*w, *h, &state->info_raw); + *out = (unsigned char*)lodepng_malloc(outsize); + if(!(*out)) + { + state->error = 83; /*alloc fail*/ + } + else state->error = lodepng_convert(*out, data, &state->info_raw, + &state->info_png.color, *w, *h); + lodepng_free(data); + } + return state->error; +} + +unsigned lodepng_decode_memory(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, + size_t insize, LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned error; + LodePNGState state; + lodepng_state_init(&state); + state.info_raw.colortype = colortype; + state.info_raw.bitdepth = bitdepth; + error = lodepng_decode(out, w, h, &state, in, insize); + lodepng_state_cleanup(&state); + return error; +} + +unsigned lodepng_decode32(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) +{ + return lodepng_decode_memory(out, w, h, in, insize, LCT_RGBA, 8); +} + +unsigned lodepng_decode24(unsigned char** out, unsigned* w, unsigned* h, const unsigned char* in, size_t insize) +{ + return lodepng_decode_memory(out, w, h, in, insize, LCT_RGB, 8); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned lodepng_decode_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename, + LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned char* buffer = 0; + size_t buffersize; + unsigned error; + error = lodepng_load_file(&buffer, &buffersize, filename); + if(!error) error = lodepng_decode_memory(out, w, h, buffer, buffersize, colortype, bitdepth); + lodepng_free(buffer); + return error; +} + +unsigned lodepng_decode32_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) +{ + return lodepng_decode_file(out, w, h, filename, LCT_RGBA, 8); +} + +unsigned lodepng_decode24_file(unsigned char** out, unsigned* w, unsigned* h, const char* filename) +{ + return lodepng_decode_file(out, w, h, filename, LCT_RGB, 8); +} +#endif /*LODEPNG_COMPILE_DISK*/ + +void lodepng_decoder_settings_init(LodePNGDecoderSettings* settings) +{ + settings->color_convert = 1; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + settings->read_text_chunks = 1; + settings->remember_unknown_chunks = 0; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + settings->ignore_crc = 0; + settings->ignore_critical = 0; + settings->ignore_end = 0; + lodepng_decompress_settings_init(&settings->zlibsettings); +} + +#endif /*LODEPNG_COMPILE_DECODER*/ + +#if defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) + +void lodepng_state_init(LodePNGState* state) +{ +#ifdef LODEPNG_COMPILE_DECODER + lodepng_decoder_settings_init(&state->decoder); +#endif /*LODEPNG_COMPILE_DECODER*/ +#ifdef LODEPNG_COMPILE_ENCODER + lodepng_encoder_settings_init(&state->encoder); +#endif /*LODEPNG_COMPILE_ENCODER*/ + lodepng_color_mode_init(&state->info_raw); + lodepng_info_init(&state->info_png); + state->error = 1; +} + +void lodepng_state_cleanup(LodePNGState* state) +{ + lodepng_color_mode_cleanup(&state->info_raw); + lodepng_info_cleanup(&state->info_png); +} + +void lodepng_state_copy(LodePNGState* dest, const LodePNGState* source) +{ + lodepng_state_cleanup(dest); + *dest = *source; + lodepng_color_mode_init(&dest->info_raw); + lodepng_info_init(&dest->info_png); + dest->error = lodepng_color_mode_copy(&dest->info_raw, &source->info_raw); if(dest->error) return; + dest->error = lodepng_info_copy(&dest->info_png, &source->info_png); if(dest->error) return; +} + +#endif /* defined(LODEPNG_COMPILE_DECODER) || defined(LODEPNG_COMPILE_ENCODER) */ + +#ifdef LODEPNG_COMPILE_ENCODER + +/* ////////////////////////////////////////////////////////////////////////// */ +/* / PNG Encoder / */ +/* ////////////////////////////////////////////////////////////////////////// */ + +/*chunkName must be string of 4 characters*/ +static unsigned addChunk(ucvector* out, const char* chunkName, const unsigned char* data, size_t length) +{ + CERROR_TRY_RETURN(lodepng_chunk_create(&out->data, &out->size, (unsigned)length, chunkName, data)); + out->allocsize = out->size; /*fix the allocsize again*/ + return 0; +} + +static void writeSignature(ucvector* out) +{ + /*8 bytes PNG signature, aka the magic bytes*/ + ucvector_push_back(out, 137); + ucvector_push_back(out, 80); + ucvector_push_back(out, 78); + ucvector_push_back(out, 71); + ucvector_push_back(out, 13); + ucvector_push_back(out, 10); + ucvector_push_back(out, 26); + ucvector_push_back(out, 10); +} + +static unsigned addChunk_IHDR(ucvector* out, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth, unsigned interlace_method) +{ + unsigned error = 0; + ucvector header; + ucvector_init(&header); + + lodepng_add32bitInt(&header, w); /*width*/ + lodepng_add32bitInt(&header, h); /*height*/ + ucvector_push_back(&header, (unsigned char)bitdepth); /*bit depth*/ + ucvector_push_back(&header, (unsigned char)colortype); /*color type*/ + ucvector_push_back(&header, 0); /*compression method*/ + ucvector_push_back(&header, 0); /*filter method*/ + ucvector_push_back(&header, interlace_method); /*interlace method*/ + + error = addChunk(out, "IHDR", header.data, header.size); + ucvector_cleanup(&header); + + return error; +} + +static unsigned addChunk_PLTE(ucvector* out, const LodePNGColorMode* info) +{ + unsigned error = 0; + size_t i; + ucvector PLTE; + ucvector_init(&PLTE); + for(i = 0; i != info->palettesize * 4; ++i) + { + /*add all channels except alpha channel*/ + if(i % 4 != 3) ucvector_push_back(&PLTE, info->palette[i]); + } + error = addChunk(out, "PLTE", PLTE.data, PLTE.size); + ucvector_cleanup(&PLTE); + + return error; +} + +static unsigned addChunk_tRNS(ucvector* out, const LodePNGColorMode* info) +{ + unsigned error = 0; + size_t i; + ucvector tRNS; + ucvector_init(&tRNS); + if(info->colortype == LCT_PALETTE) + { + size_t amount = info->palettesize; + /*the tail of palette values that all have 255 as alpha, does not have to be encoded*/ + for(i = info->palettesize; i != 0; --i) + { + if(info->palette[4 * (i - 1) + 3] == 255) --amount; + else break; + } + /*add only alpha channel*/ + for(i = 0; i != amount; ++i) ucvector_push_back(&tRNS, info->palette[4 * i + 3]); + } + else if(info->colortype == LCT_GREY) + { + if(info->key_defined) + { + ucvector_push_back(&tRNS, (unsigned char)(info->key_r >> 8)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_r & 255)); + } + } + else if(info->colortype == LCT_RGB) + { + if(info->key_defined) + { + ucvector_push_back(&tRNS, (unsigned char)(info->key_r >> 8)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_r & 255)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_g >> 8)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_g & 255)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_b >> 8)); + ucvector_push_back(&tRNS, (unsigned char)(info->key_b & 255)); + } + } + + error = addChunk(out, "tRNS", tRNS.data, tRNS.size); + ucvector_cleanup(&tRNS); + + return error; +} + +static unsigned addChunk_IDAT(ucvector* out, const unsigned char* data, size_t datasize, + LodePNGCompressSettings* zlibsettings) +{ + ucvector zlibdata; + unsigned error = 0; + + /*compress with the Zlib compressor*/ + ucvector_init(&zlibdata); + error = zlib_compress(&zlibdata.data, &zlibdata.size, data, datasize, zlibsettings); + if(!error) error = addChunk(out, "IDAT", zlibdata.data, zlibdata.size); + ucvector_cleanup(&zlibdata); + + return error; +} + +static unsigned addChunk_IEND(ucvector* out) +{ + unsigned error = 0; + error = addChunk(out, "IEND", 0, 0); + return error; +} + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + +static unsigned addChunk_tEXt(ucvector* out, const char* keyword, const char* textstring) +{ + unsigned error = 0; + size_t i; + ucvector text; + ucvector_init(&text); + for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&text, (unsigned char)keyword[i]); + if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/ + ucvector_push_back(&text, 0); /*0 termination char*/ + for(i = 0; textstring[i] != 0; ++i) ucvector_push_back(&text, (unsigned char)textstring[i]); + error = addChunk(out, "tEXt", text.data, text.size); + ucvector_cleanup(&text); + + return error; +} + +static unsigned addChunk_zTXt(ucvector* out, const char* keyword, const char* textstring, + LodePNGCompressSettings* zlibsettings) +{ + unsigned error = 0; + ucvector data, compressed; + size_t i, textsize = strlen(textstring); + + ucvector_init(&data); + ucvector_init(&compressed); + for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)keyword[i]); + if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/ + ucvector_push_back(&data, 0); /*0 termination char*/ + ucvector_push_back(&data, 0); /*compression method: 0*/ + + error = zlib_compress(&compressed.data, &compressed.size, + (unsigned char*)textstring, textsize, zlibsettings); + if(!error) + { + for(i = 0; i != compressed.size; ++i) ucvector_push_back(&data, compressed.data[i]); + error = addChunk(out, "zTXt", data.data, data.size); + } + + ucvector_cleanup(&compressed); + ucvector_cleanup(&data); + return error; +} + +static unsigned addChunk_iTXt(ucvector* out, unsigned compressed, const char* keyword, const char* langtag, + const char* transkey, const char* textstring, LodePNGCompressSettings* zlibsettings) +{ + unsigned error = 0; + ucvector data; + size_t i, textsize = strlen(textstring); + + ucvector_init(&data); + + for(i = 0; keyword[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)keyword[i]); + if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/ + ucvector_push_back(&data, 0); /*null termination char*/ + ucvector_push_back(&data, compressed ? 1 : 0); /*compression flag*/ + ucvector_push_back(&data, 0); /*compression method*/ + for(i = 0; langtag[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)langtag[i]); + ucvector_push_back(&data, 0); /*null termination char*/ + for(i = 0; transkey[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)transkey[i]); + ucvector_push_back(&data, 0); /*null termination char*/ + + if(compressed) + { + ucvector compressed_data; + ucvector_init(&compressed_data); + error = zlib_compress(&compressed_data.data, &compressed_data.size, + (unsigned char*)textstring, textsize, zlibsettings); + if(!error) + { + for(i = 0; i != compressed_data.size; ++i) ucvector_push_back(&data, compressed_data.data[i]); + } + ucvector_cleanup(&compressed_data); + } + else /*not compressed*/ + { + for(i = 0; textstring[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)textstring[i]); + } + + if(!error) error = addChunk(out, "iTXt", data.data, data.size); + ucvector_cleanup(&data); + return error; +} + +static unsigned addChunk_bKGD(ucvector* out, const LodePNGInfo* info) +{ + unsigned error = 0; + ucvector bKGD; + ucvector_init(&bKGD); + if(info->color.colortype == LCT_GREY || info->color.colortype == LCT_GREY_ALPHA) + { + ucvector_push_back(&bKGD, (unsigned char)(info->background_r >> 8)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255)); + } + else if(info->color.colortype == LCT_RGB || info->color.colortype == LCT_RGBA) + { + ucvector_push_back(&bKGD, (unsigned char)(info->background_r >> 8)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_g >> 8)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_g & 255)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_b >> 8)); + ucvector_push_back(&bKGD, (unsigned char)(info->background_b & 255)); + } + else if(info->color.colortype == LCT_PALETTE) + { + ucvector_push_back(&bKGD, (unsigned char)(info->background_r & 255)); /*palette index*/ + } + + error = addChunk(out, "bKGD", bKGD.data, bKGD.size); + ucvector_cleanup(&bKGD); + + return error; +} + +static unsigned addChunk_tIME(ucvector* out, const LodePNGTime* time) +{ + unsigned error = 0; + unsigned char* data = (unsigned char*)lodepng_malloc(7); + if(!data) return 83; /*alloc fail*/ + data[0] = (unsigned char)(time->year >> 8); + data[1] = (unsigned char)(time->year & 255); + data[2] = (unsigned char)time->month; + data[3] = (unsigned char)time->day; + data[4] = (unsigned char)time->hour; + data[5] = (unsigned char)time->minute; + data[6] = (unsigned char)time->second; + error = addChunk(out, "tIME", data, 7); + lodepng_free(data); + return error; +} + +static unsigned addChunk_pHYs(ucvector* out, const LodePNGInfo* info) +{ + unsigned error = 0; + ucvector data; + ucvector_init(&data); + + lodepng_add32bitInt(&data, info->phys_x); + lodepng_add32bitInt(&data, info->phys_y); + ucvector_push_back(&data, info->phys_unit); + + error = addChunk(out, "pHYs", data.data, data.size); + ucvector_cleanup(&data); + + return error; +} + +static unsigned addChunk_gAMA(ucvector* out, const LodePNGInfo* info) +{ + unsigned error = 0; + ucvector data; + ucvector_init(&data); + + lodepng_add32bitInt(&data, info->gama_gamma); + + error = addChunk(out, "gAMA", data.data, data.size); + ucvector_cleanup(&data); + + return error; +} + +static unsigned addChunk_cHRM(ucvector* out, const LodePNGInfo* info) +{ + unsigned error = 0; + ucvector data; + ucvector_init(&data); + + lodepng_add32bitInt(&data, info->chrm_white_x); + lodepng_add32bitInt(&data, info->chrm_white_y); + lodepng_add32bitInt(&data, info->chrm_red_x); + lodepng_add32bitInt(&data, info->chrm_red_y); + lodepng_add32bitInt(&data, info->chrm_green_x); + lodepng_add32bitInt(&data, info->chrm_green_y); + lodepng_add32bitInt(&data, info->chrm_blue_x); + lodepng_add32bitInt(&data, info->chrm_blue_y); + + error = addChunk(out, "cHRM", data.data, data.size); + ucvector_cleanup(&data); + + return error; +} + +static unsigned addChunk_sRGB(ucvector* out, const LodePNGInfo* info) +{ + unsigned char data = info->srgb_intent; + return addChunk(out, "sRGB", &data, 1); +} + +static unsigned addChunk_iCCP(ucvector* out, const LodePNGInfo* info, LodePNGCompressSettings* zlibsettings) +{ + unsigned error = 0; + ucvector data, compressed; + size_t i; + + ucvector_init(&data); + ucvector_init(&compressed); + for(i = 0; info->iccp_name[i] != 0; ++i) ucvector_push_back(&data, (unsigned char)info->iccp_name[i]); + if(i < 1 || i > 79) return 89; /*error: invalid keyword size*/ + ucvector_push_back(&data, 0); /*0 termination char*/ + ucvector_push_back(&data, 0); /*compression method: 0*/ + + error = zlib_compress(&compressed.data, &compressed.size, + info->iccp_profile, info->iccp_profile_size, zlibsettings); + if(!error) + { + for(i = 0; i != compressed.size; ++i) ucvector_push_back(&data, compressed.data[i]); + error = addChunk(out, "iCCP", data.data, data.size); + } + + ucvector_cleanup(&compressed); + ucvector_cleanup(&data); + return error; +} + +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +static void filterScanline(unsigned char* out, const unsigned char* scanline, const unsigned char* prevline, + size_t length, size_t bytewidth, unsigned char filterType) +{ + size_t i; + switch(filterType) + { + case 0: /*None*/ + for(i = 0; i != length; ++i) out[i] = scanline[i]; + break; + case 1: /*Sub*/ + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; + for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - scanline[i - bytewidth]; + break; + case 2: /*Up*/ + if(prevline) + { + for(i = 0; i != length; ++i) out[i] = scanline[i] - prevline[i]; + } + else + { + for(i = 0; i != length; ++i) out[i] = scanline[i]; + } + break; + case 3: /*Average*/ + if(prevline) + { + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i] - (prevline[i] >> 1); + for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - ((scanline[i - bytewidth] + prevline[i]) >> 1); + } + else + { + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; + for(i = bytewidth; i < length; ++i) out[i] = scanline[i] - (scanline[i - bytewidth] >> 1); + } + break; + case 4: /*Paeth*/ + if(prevline) + { + /*paethPredictor(0, prevline[i], 0) is always prevline[i]*/ + for(i = 0; i != bytewidth; ++i) out[i] = (scanline[i] - prevline[i]); + for(i = bytewidth; i < length; ++i) + { + out[i] = (scanline[i] - paethPredictor(scanline[i - bytewidth], prevline[i], prevline[i - bytewidth])); + } + } + else + { + for(i = 0; i != bytewidth; ++i) out[i] = scanline[i]; + /*paethPredictor(scanline[i - bytewidth], 0, 0) is always scanline[i - bytewidth]*/ + for(i = bytewidth; i < length; ++i) out[i] = (scanline[i] - scanline[i - bytewidth]); + } + break; + default: return; /*unexisting filter type given*/ + } +} + +/* log2 approximation. A slight bit faster than std::log. */ +static float flog2(float f) +{ + float result = 0; + while(f > 32) { result += 4; f /= 16; } + while(f > 2) { ++result; f /= 2; } + return result + 1.442695f * (f * f * f / 3 - 3 * f * f / 2 + 3 * f - 1.83333f); +} + +static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, + const LodePNGColorMode* info, const LodePNGEncoderSettings* settings) +{ + /* + For PNG filter method 0 + out must be a buffer with as size: h + (w * h * bpp + 7) / 8, because there are + the scanlines with 1 extra byte per scanline + */ + + unsigned bpp = lodepng_get_bpp(info); + /*the width of a scanline in bytes, not including the filter type*/ + size_t linebytes = (w * bpp + 7) / 8; + /*bytewidth is used for filtering, is 1 when bpp < 8, number of bytes per pixel otherwise*/ + size_t bytewidth = (bpp + 7) / 8; + const unsigned char* prevline = 0; + unsigned x, y; + unsigned error = 0; + LodePNGFilterStrategy strategy = settings->filter_strategy; + + /* + There is a heuristic called the minimum sum of absolute differences heuristic, suggested by the PNG standard: + * If the image type is Palette, or the bit depth is smaller than 8, then do not filter the image (i.e. + use fixed filtering, with the filter None). + * (The other case) If the image type is Grayscale or RGB (with or without Alpha), and the bit depth is + not smaller than 8, then use adaptive filtering heuristic as follows: independently for each row, apply + all five filters and select the filter that produces the smallest sum of absolute values per row. + This heuristic is used if filter strategy is LFS_MINSUM and filter_palette_zero is true. + + If filter_palette_zero is true and filter_strategy is not LFS_MINSUM, the above heuristic is followed, + but for "the other case", whatever strategy filter_strategy is set to instead of the minimum sum + heuristic is used. + */ + if(settings->filter_palette_zero && + (info->colortype == LCT_PALETTE || info->bitdepth < 8)) strategy = LFS_ZERO; + + if(bpp == 0) return 31; /*error: invalid color type*/ + + if(strategy == LFS_ZERO) + { + for(y = 0; y != h; ++y) + { + size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ + size_t inindex = linebytes * y; + out[outindex] = 0; /*filter type byte*/ + filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, 0); + prevline = &in[inindex]; + } + } + else if(strategy == LFS_MINSUM) + { + /*adaptive filtering*/ + size_t sum[5]; + unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ + size_t smallest = 0; + unsigned char type, bestType = 0; + + for(type = 0; type != 5; ++type) + { + attempt[type] = (unsigned char*)lodepng_malloc(linebytes); + if(!attempt[type]) return 83; /*alloc fail*/ + } + + if(!error) + { + for(y = 0; y != h; ++y) + { + /*try the 5 filter types*/ + for(type = 0; type != 5; ++type) + { + filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); + + /*calculate the sum of the result*/ + sum[type] = 0; + if(type == 0) + { + for(x = 0; x != linebytes; ++x) sum[type] += (unsigned char)(attempt[type][x]); + } + else + { + for(x = 0; x != linebytes; ++x) + { + /*For differences, each byte should be treated as signed, values above 127 are negative + (converted to signed char). Filtertype 0 isn't a difference though, so use unsigned there. + This means filtertype 0 is almost never chosen, but that is justified.*/ + unsigned char s = attempt[type][x]; + sum[type] += s < 128 ? s : (255U - s); + } + } + + /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ + if(type == 0 || sum[type] < smallest) + { + bestType = type; + smallest = sum[type]; + } + } + + prevline = &in[y * linebytes]; + + /*now fill the out values*/ + out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; + } + } + + for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); + } + else if(strategy == LFS_ENTROPY) + { + float sum[5]; + unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ + float smallest = 0; + unsigned type, bestType = 0; + unsigned count[256]; + + for(type = 0; type != 5; ++type) + { + attempt[type] = (unsigned char*)lodepng_malloc(linebytes); + if(!attempt[type]) return 83; /*alloc fail*/ + } + + for(y = 0; y != h; ++y) + { + /*try the 5 filter types*/ + for(type = 0; type != 5; ++type) + { + filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); + for(x = 0; x != 256; ++x) count[x] = 0; + for(x = 0; x != linebytes; ++x) ++count[attempt[type][x]]; + ++count[type]; /*the filter type itself is part of the scanline*/ + sum[type] = 0; + for(x = 0; x != 256; ++x) + { + float p = count[x] / (float)(linebytes + 1); + sum[type] += count[x] == 0 ? 0 : flog2(1 / p) * p; + } + /*check if this is smallest sum (or if type == 0 it's the first case so always store the values)*/ + if(type == 0 || sum[type] < smallest) + { + bestType = type; + smallest = sum[type]; + } + } + + prevline = &in[y * linebytes]; + + /*now fill the out values*/ + out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; + } + + for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); + } + else if(strategy == LFS_PREDEFINED) + { + for(y = 0; y != h; ++y) + { + size_t outindex = (1 + linebytes) * y; /*the extra filterbyte added to each row*/ + size_t inindex = linebytes * y; + unsigned char type = settings->predefined_filters[y]; + out[outindex] = type; /*filter type byte*/ + filterScanline(&out[outindex + 1], &in[inindex], prevline, linebytes, bytewidth, type); + prevline = &in[inindex]; + } + } + else if(strategy == LFS_BRUTE_FORCE) + { + /*brute force filter chooser. + deflate the scanline after every filter attempt to see which one deflates best. + This is very slow and gives only slightly smaller, sometimes even larger, result*/ + size_t size[5]; + unsigned char* attempt[5]; /*five filtering attempts, one for each filter type*/ + size_t smallest = 0; + unsigned type = 0, bestType = 0; + unsigned char* dummy; + LodePNGCompressSettings zlibsettings = settings->zlibsettings; + /*use fixed tree on the attempts so that the tree is not adapted to the filtertype on purpose, + to simulate the true case where the tree is the same for the whole image. Sometimes it gives + better result with dynamic tree anyway. Using the fixed tree sometimes gives worse, but in rare + cases better compression. It does make this a bit less slow, so it's worth doing this.*/ + zlibsettings.btype = 1; + /*a custom encoder likely doesn't read the btype setting and is optimized for complete PNG + images only, so disable it*/ + zlibsettings.custom_zlib = 0; + zlibsettings.custom_deflate = 0; + for(type = 0; type != 5; ++type) + { + attempt[type] = (unsigned char*)lodepng_malloc(linebytes); + if(!attempt[type]) return 83; /*alloc fail*/ + } + for(y = 0; y != h; ++y) /*try the 5 filter types*/ + { + for(type = 0; type != 5; ++type) + { + unsigned testsize = (unsigned)linebytes; + /*if(testsize > 8) testsize /= 8;*/ /*it already works good enough by testing a part of the row*/ + + filterScanline(attempt[type], &in[y * linebytes], prevline, linebytes, bytewidth, type); + size[type] = 0; + dummy = 0; + zlib_compress(&dummy, &size[type], attempt[type], testsize, &zlibsettings); + lodepng_free(dummy); + /*check if this is smallest size (or if type == 0 it's the first case so always store the values)*/ + if(type == 0 || size[type] < smallest) + { + bestType = type; + smallest = size[type]; + } + } + prevline = &in[y * linebytes]; + out[y * (linebytes + 1)] = bestType; /*the first byte of a scanline will be the filter type*/ + for(x = 0; x != linebytes; ++x) out[y * (linebytes + 1) + 1 + x] = attempt[bestType][x]; + } + for(type = 0; type != 5; ++type) lodepng_free(attempt[type]); + } + else return 88; /* unknown filter strategy */ + + return error; +} + +static void addPaddingBits(unsigned char* out, const unsigned char* in, + size_t olinebits, size_t ilinebits, unsigned h) +{ + /*The opposite of the removePaddingBits function + olinebits must be >= ilinebits*/ + unsigned y; + size_t diff = olinebits - ilinebits; + size_t obp = 0, ibp = 0; /*bit pointers*/ + for(y = 0; y != h; ++y) + { + size_t x; + for(x = 0; x < ilinebits; ++x) + { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + /*obp += diff; --> no, fill in some value in the padding bits too, to avoid + "Use of uninitialised value of size ###" warning from valgrind*/ + for(x = 0; x != diff; ++x) setBitOfReversedStream(&obp, out, 0); + } +} + +/* +in: non-interlaced image with size w*h +out: the same pixels, but re-ordered according to PNG's Adam7 interlacing, with + no padding bits between scanlines, but between reduced images so that each + reduced image starts at a byte. +bpp: bits per pixel +there are no padding bits, not between scanlines, not between reduced images +in has the following size in bits: w * h * bpp. +out is possibly bigger due to padding bits between reduced images +NOTE: comments about padding bits are only relevant if bpp < 8 +*/ +static void Adam7_interlace(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, unsigned bpp) +{ + unsigned passw[7], passh[7]; + size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned i; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + if(bpp >= 8) + { + for(i = 0; i != 7; ++i) + { + unsigned x, y, b; + size_t bytewidth = bpp / 8; + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) + { + size_t pixelinstart = ((ADAM7_IY[i] + y * ADAM7_DY[i]) * w + ADAM7_IX[i] + x * ADAM7_DX[i]) * bytewidth; + size_t pixeloutstart = passstart[i] + (y * passw[i] + x) * bytewidth; + for(b = 0; b < bytewidth; ++b) + { + out[pixeloutstart + b] = in[pixelinstart + b]; + } + } + } + } + else /*bpp < 8: Adam7 with pixels < 8 bit is a bit trickier: with bit pointers*/ + { + for(i = 0; i != 7; ++i) + { + unsigned x, y, b; + unsigned ilinebits = bpp * passw[i]; + unsigned olinebits = bpp * w; + size_t obp, ibp; /*bit pointers (for out and in buffer)*/ + for(y = 0; y < passh[i]; ++y) + for(x = 0; x < passw[i]; ++x) + { + ibp = (ADAM7_IY[i] + y * ADAM7_DY[i]) * olinebits + (ADAM7_IX[i] + x * ADAM7_DX[i]) * bpp; + obp = (8 * passstart[i]) + (y * ilinebits + x * bpp); + for(b = 0; b < bpp; ++b) + { + unsigned char bit = readBitFromReversedStream(&ibp, in); + setBitOfReversedStream(&obp, out, bit); + } + } + } + } +} + +/*out must be buffer big enough to contain uncompressed IDAT chunk data, and in must contain the full image. +return value is error**/ +static unsigned preProcessScanlines(unsigned char** out, size_t* outsize, const unsigned char* in, + unsigned w, unsigned h, + const LodePNGInfo* info_png, const LodePNGEncoderSettings* settings) +{ + /* + This function converts the pure 2D image with the PNG's colortype, into filtered-padded-interlaced data. Steps: + *) if no Adam7: 1) add padding bits (= posible extra bits per scanline if bpp < 8) 2) filter + *) if adam7: 1) Adam7_interlace 2) 7x add padding bits 3) 7x filter + */ + unsigned bpp = lodepng_get_bpp(&info_png->color); + unsigned error = 0; + + if(info_png->interlace_method == 0) + { + *outsize = h + (h * ((w * bpp + 7) / 8)); /*image size plus an extra byte per scanline + possible padding bits*/ + *out = (unsigned char*)lodepng_malloc(*outsize); + if(!(*out) && (*outsize)) error = 83; /*alloc fail*/ + + if(!error) + { + /*non multiple of 8 bits per scanline, padding bits needed per scanline*/ + if(bpp < 8 && w * bpp != ((w * bpp + 7) / 8) * 8) + { + unsigned char* padded = (unsigned char*)lodepng_malloc(h * ((w * bpp + 7) / 8)); + if(!padded) error = 83; /*alloc fail*/ + if(!error) + { + addPaddingBits(padded, in, ((w * bpp + 7) / 8) * 8, w * bpp, h); + error = filter(*out, padded, w, h, &info_png->color, settings); + } + lodepng_free(padded); + } + else + { + /*we can immediately filter into the out buffer, no other steps needed*/ + error = filter(*out, in, w, h, &info_png->color, settings); + } + } + } + else /*interlace_method is 1 (Adam7)*/ + { + unsigned passw[7], passh[7]; + size_t filter_passstart[8], padded_passstart[8], passstart[8]; + unsigned char* adam7; + + Adam7_getpassvalues(passw, passh, filter_passstart, padded_passstart, passstart, w, h, bpp); + + *outsize = filter_passstart[7]; /*image size plus an extra byte per scanline + possible padding bits*/ + *out = (unsigned char*)lodepng_malloc(*outsize); + if(!(*out)) error = 83; /*alloc fail*/ + + adam7 = (unsigned char*)lodepng_malloc(passstart[7]); + if(!adam7 && passstart[7]) error = 83; /*alloc fail*/ + + if(!error) + { + unsigned i; + + Adam7_interlace(adam7, in, w, h, bpp); + for(i = 0; i != 7; ++i) + { + if(bpp < 8) + { + unsigned char* padded = (unsigned char*)lodepng_malloc(padded_passstart[i + 1] - padded_passstart[i]); + if(!padded) ERROR_BREAK(83); /*alloc fail*/ + addPaddingBits(padded, &adam7[passstart[i]], + ((passw[i] * bpp + 7) / 8) * 8, passw[i] * bpp, passh[i]); + error = filter(&(*out)[filter_passstart[i]], padded, + passw[i], passh[i], &info_png->color, settings); + lodepng_free(padded); + } + else + { + error = filter(&(*out)[filter_passstart[i]], &adam7[padded_passstart[i]], + passw[i], passh[i], &info_png->color, settings); + } + + if(error) break; + } + } + + lodepng_free(adam7); + } + + return error; +} + +/* +palette must have 4 * palettesize bytes allocated, and given in format RGBARGBARGBARGBA... +returns 0 if the palette is opaque, +returns 1 if the palette has a single color with alpha 0 ==> color key +returns 2 if the palette is semi-translucent. +*/ +static unsigned getPaletteTranslucency(const unsigned char* palette, size_t palettesize) +{ + size_t i; + unsigned key = 0; + unsigned r = 0, g = 0, b = 0; /*the value of the color with alpha 0, so long as color keying is possible*/ + for(i = 0; i != palettesize; ++i) + { + if(!key && palette[4 * i + 3] == 0) + { + r = palette[4 * i + 0]; g = palette[4 * i + 1]; b = palette[4 * i + 2]; + key = 1; + i = (size_t)(-1); /*restart from beginning, to detect earlier opaque colors with key's value*/ + } + else if(palette[4 * i + 3] != 255) return 2; + /*when key, no opaque RGB may have key's RGB*/ + else if(key && r == palette[i * 4 + 0] && g == palette[i * 4 + 1] && b == palette[i * 4 + 2]) return 2; + } + return key; +} + +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS +static unsigned addUnknownChunks(ucvector* out, unsigned char* data, size_t datasize) +{ + unsigned char* inchunk = data; + while((size_t)(inchunk - data) < datasize) + { + CERROR_TRY_RETURN(lodepng_chunk_append(&out->data, &out->size, inchunk)); + out->allocsize = out->size; /*fix the allocsize again*/ + inchunk = lodepng_chunk_next(inchunk); + } + return 0; +} + +static unsigned isGreyICCProfile(const unsigned char* profile, unsigned size) +{ + /* + It is a grey profile if bytes 16-19 are "GRAY", rgb profile if bytes 16-19 + are "RGB ". We do not perform any full parsing of the ICC profile here, other + than check those 4 bytes to grayscale profile. Other than that, validity of + the profile is not checked. This is needed only because the PNG specification + requires using a non-grey color model if there is an ICC profile with "RGB " + (sadly limiting compression opportunities if the input data is greyscale RGB + data), and requires using a grey color model if it is "GRAY". + */ + if(size < 20) return 0; + return profile[16] == 'G' && profile[17] == 'R' && profile[18] == 'A' && profile[19] == 'Y'; +} + +static unsigned isRGBICCProfile(const unsigned char* profile, unsigned size) +{ + /* See comment in isGreyICCProfile*/ + if(size < 20) return 0; + return profile[16] == 'R' && profile[17] == 'G' && profile[18] == 'B' && profile[19] == ' '; +} +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + +unsigned lodepng_encode(unsigned char** out, size_t* outsize, + const unsigned char* image, unsigned w, unsigned h, + LodePNGState* state) +{ + unsigned char* data = 0; /*uncompressed version of the IDAT chunk data*/ + size_t datasize = 0; + ucvector outv; + LodePNGInfo info; + + ucvector_init(&outv); + lodepng_info_init(&info); + + /*provide some proper output values if error will happen*/ + *out = 0; + *outsize = 0; + state->error = 0; + + /*check input values validity*/ + if((state->info_png.color.colortype == LCT_PALETTE || state->encoder.force_palette) + && (state->info_png.color.palettesize == 0 || state->info_png.color.palettesize > 256)) + { + state->error = 68; /*invalid palette size, it is only allowed to be 1-256*/ + goto cleanup; + } + if(state->encoder.zlibsettings.btype > 2) + { + state->error = 61; /*error: unexisting btype*/ + goto cleanup; + } + if(state->info_png.interlace_method > 1) + { + state->error = 71; /*error: unexisting interlace mode*/ + goto cleanup; + } + state->error = checkColorValidity(state->info_png.color.colortype, state->info_png.color.bitdepth); + if(state->error) goto cleanup; /*error: unexisting color type given*/ + state->error = checkColorValidity(state->info_raw.colortype, state->info_raw.bitdepth); + if(state->error) goto cleanup; /*error: unexisting color type given*/ + + /* color convert and compute scanline filter types */ + lodepng_info_copy(&info, &state->info_png); + if(state->encoder.auto_convert) + { +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(state->info_png.background_defined) + { + unsigned bg_r = state->info_png.background_r; + unsigned bg_g = state->info_png.background_g; + unsigned bg_b = state->info_png.background_b; + unsigned r = 0, g = 0, b = 0; + LodePNGColorProfile prof; + LodePNGColorMode mode16 = lodepng_color_mode_make(LCT_RGB, 16); + lodepng_convert_rgb(&r, &g, &b, bg_r, bg_g, bg_b, &mode16, &state->info_png.color); + lodepng_color_profile_init(&prof); + state->error = lodepng_get_color_profile(&prof, image, w, h, &state->info_raw); + if(state->error) goto cleanup; + lodepng_color_profile_add(&prof, r, g, b, 65535); + state->error = auto_choose_color_from_profile(&info.color, &state->info_raw, &prof); + if(state->error) goto cleanup; + if(lodepng_convert_rgb(&info.background_r, &info.background_g, &info.background_b, + bg_r, bg_g, bg_b, &info.color, &state->info_png.color)) + { + state->error = 104; + goto cleanup; + } + } + else +#endif /* LODEPNG_COMPILE_ANCILLARY_CHUNKS */ + { + state->error = lodepng_auto_choose_color(&info.color, image, w, h, &state->info_raw); + if(state->error) goto cleanup; + } + } +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + if(state->info_png.iccp_defined) + { + unsigned grey_icc = isGreyICCProfile(state->info_png.iccp_profile, state->info_png.iccp_profile_size); + unsigned grey_png = info.color.colortype == LCT_GREY || info.color.colortype == LCT_GREY_ALPHA; + /* TODO: perhaps instead of giving errors or less optimal compression, we can automatically modify + the ICC profile here to say "GRAY" or "RGB " to match the PNG color type, unless this will require + non trivial changes to the rest of the ICC profile */ + if(!grey_icc && !isRGBICCProfile(state->info_png.iccp_profile, state->info_png.iccp_profile_size)) + { + state->error = 100; /* Disallowed profile color type for PNG */ + goto cleanup; + } + if(!state->encoder.auto_convert && grey_icc != grey_png) + { + /* Non recoverable: encoder not allowed to convert color type, and requested color type not + compatible with ICC color type */ + state->error = 101; + goto cleanup; + } + if(grey_icc && !grey_png) + { + /* Non recoverable: trying to set greyscale ICC profile while colored pixels were given */ + state->error = 102; + goto cleanup; + /* NOTE: this relies on the fact that lodepng_auto_choose_color never returns palette for greyscale pixels */ + } + if(!grey_icc && grey_png) + { + /* Recoverable but an unfortunate loss in compression density: We have greyscale pixels but + are forced to store them in more expensive RGB format that will repeat each value 3 times + because the PNG spec does not allow an RGB ICC profile with internal greyscale color data */ + if(info.color.colortype == LCT_GREY) info.color.colortype = LCT_RGB; + if(info.color.colortype == LCT_GREY_ALPHA) info.color.colortype = LCT_RGBA; + if(info.color.bitdepth < 8) info.color.bitdepth = 8; + } + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + if(!lodepng_color_mode_equal(&state->info_raw, &info.color)) + { + unsigned char* converted; + size_t size = ((size_t)w * (size_t)h * (size_t)lodepng_get_bpp(&info.color) + 7) / 8; + + converted = (unsigned char*)lodepng_malloc(size); + if(!converted && size) state->error = 83; /*alloc fail*/ + if(!state->error) + { + state->error = lodepng_convert(converted, image, &info.color, &state->info_raw, w, h); + } + if(!state->error) preProcessScanlines(&data, &datasize, converted, w, h, &info, &state->encoder); + lodepng_free(converted); + if(state->error) goto cleanup; + } + else preProcessScanlines(&data, &datasize, image, w, h, &info, &state->encoder); + + /* output all PNG chunks */ + { +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + size_t i; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + /*write signature and chunks*/ + writeSignature(&outv); + /*IHDR*/ + addChunk_IHDR(&outv, w, h, info.color.colortype, info.color.bitdepth, info.interlace_method); +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*unknown chunks between IHDR and PLTE*/ + if(info.unknown_chunks_data[0]) + { + state->error = addUnknownChunks(&outv, info.unknown_chunks_data[0], info.unknown_chunks_size[0]); + if(state->error) goto cleanup; + } + /*color profile chunks must come before PLTE */ + if(info.iccp_defined) addChunk_iCCP(&outv, &info, &state->encoder.zlibsettings); + if(info.srgb_defined) addChunk_sRGB(&outv, &info); + if(info.gama_defined) addChunk_gAMA(&outv, &info); + if(info.chrm_defined) addChunk_cHRM(&outv, &info); +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + /*PLTE*/ + if(info.color.colortype == LCT_PALETTE) + { + addChunk_PLTE(&outv, &info.color); + } + if(state->encoder.force_palette && (info.color.colortype == LCT_RGB || info.color.colortype == LCT_RGBA)) + { + addChunk_PLTE(&outv, &info.color); + } + /*tRNS*/ + if(info.color.colortype == LCT_PALETTE && getPaletteTranslucency(info.color.palette, info.color.palettesize) != 0) + { + addChunk_tRNS(&outv, &info.color); + } + if((info.color.colortype == LCT_GREY || info.color.colortype == LCT_RGB) && info.color.key_defined) + { + addChunk_tRNS(&outv, &info.color); + } +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*bKGD (must come between PLTE and the IDAt chunks*/ + if(info.background_defined) + { + state->error = addChunk_bKGD(&outv, &info); + if(state->error) goto cleanup; + } + /*pHYs (must come before the IDAT chunks)*/ + if(info.phys_defined) addChunk_pHYs(&outv, &info); + + /*unknown chunks between PLTE and IDAT*/ + if(info.unknown_chunks_data[1]) + { + state->error = addUnknownChunks(&outv, info.unknown_chunks_data[1], info.unknown_chunks_size[1]); + if(state->error) goto cleanup; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + /*IDAT (multiple IDAT chunks must be consecutive)*/ + state->error = addChunk_IDAT(&outv, data, datasize, &state->encoder.zlibsettings); + if(state->error) goto cleanup; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + /*tIME*/ + if(info.time_defined) addChunk_tIME(&outv, &info.time); + /*tEXt and/or zTXt*/ + for(i = 0; i != info.text_num; ++i) + { + if(strlen(info.text_keys[i]) > 79) + { + state->error = 66; /*text chunk too large*/ + goto cleanup; + } + if(strlen(info.text_keys[i]) < 1) + { + state->error = 67; /*text chunk too small*/ + goto cleanup; + } + if(state->encoder.text_compression) + { + addChunk_zTXt(&outv, info.text_keys[i], info.text_strings[i], &state->encoder.zlibsettings); + } + else + { + addChunk_tEXt(&outv, info.text_keys[i], info.text_strings[i]); + } + } + /*LodePNG version id in text chunk*/ + if(state->encoder.add_id) + { + unsigned already_added_id_text = 0; + for(i = 0; i != info.text_num; ++i) + { + if(!strcmp(info.text_keys[i], "LodePNG")) + { + already_added_id_text = 1; + break; + } + } + if(already_added_id_text == 0) + { + addChunk_tEXt(&outv, "LodePNG", LODEPNG_VERSION_STRING); /*it's shorter as tEXt than as zTXt chunk*/ + } + } + /*iTXt*/ + for(i = 0; i != info.itext_num; ++i) + { + if(strlen(info.itext_keys[i]) > 79) + { + state->error = 66; /*text chunk too large*/ + goto cleanup; + } + if(strlen(info.itext_keys[i]) < 1) + { + state->error = 67; /*text chunk too small*/ + goto cleanup; + } + addChunk_iTXt(&outv, state->encoder.text_compression, + info.itext_keys[i], info.itext_langtags[i], info.itext_transkeys[i], info.itext_strings[i], + &state->encoder.zlibsettings); + } + + /*unknown chunks between IDAT and IEND*/ + if(info.unknown_chunks_data[2]) + { + state->error = addUnknownChunks(&outv, info.unknown_chunks_data[2], info.unknown_chunks_size[2]); + if(state->error) goto cleanup; + } +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ + addChunk_IEND(&outv); + } + +cleanup: + lodepng_info_cleanup(&info); + lodepng_free(data); + + /*instead of cleaning the vector up, give it to the output*/ + *out = outv.data; + *outsize = outv.size; + + return state->error; +} + +unsigned lodepng_encode_memory(unsigned char** out, size_t* outsize, const unsigned char* image, + unsigned w, unsigned h, LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned error; + LodePNGState state; + lodepng_state_init(&state); + state.info_raw.colortype = colortype; + state.info_raw.bitdepth = bitdepth; + state.info_png.color.colortype = colortype; + state.info_png.color.bitdepth = bitdepth; + lodepng_encode(out, outsize, image, w, h, &state); + error = state.error; + lodepng_state_cleanup(&state); + return error; +} + +unsigned lodepng_encode32(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) +{ + return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGBA, 8); +} + +unsigned lodepng_encode24(unsigned char** out, size_t* outsize, const unsigned char* image, unsigned w, unsigned h) +{ + return lodepng_encode_memory(out, outsize, image, w, h, LCT_RGB, 8); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned lodepng_encode_file(const char* filename, const unsigned char* image, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned char* buffer; + size_t buffersize; + unsigned error = lodepng_encode_memory(&buffer, &buffersize, image, w, h, colortype, bitdepth); + if(!error) error = lodepng_save_file(buffer, buffersize, filename); + lodepng_free(buffer); + return error; +} + +unsigned lodepng_encode32_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) +{ + return lodepng_encode_file(filename, image, w, h, LCT_RGBA, 8); +} + +unsigned lodepng_encode24_file(const char* filename, const unsigned char* image, unsigned w, unsigned h) +{ + return lodepng_encode_file(filename, image, w, h, LCT_RGB, 8); +} +#endif /*LODEPNG_COMPILE_DISK*/ + +void lodepng_encoder_settings_init(LodePNGEncoderSettings* settings) +{ + lodepng_compress_settings_init(&settings->zlibsettings); + settings->filter_palette_zero = 1; + settings->filter_strategy = LFS_MINSUM; + settings->auto_convert = 1; + settings->force_palette = 0; + settings->predefined_filters = 0; +#ifdef LODEPNG_COMPILE_ANCILLARY_CHUNKS + settings->add_id = 0; + settings->text_compression = 1; +#endif /*LODEPNG_COMPILE_ANCILLARY_CHUNKS*/ +} + +#endif /*LODEPNG_COMPILE_ENCODER*/ +#endif /*LODEPNG_COMPILE_PNG*/ + +#ifdef LODEPNG_COMPILE_ERROR_TEXT +/* +This returns the description of a numerical error code in English. This is also +the documentation of all the error codes. +*/ +const char* lodepng_error_text(unsigned code) +{ + switch(code) + { + case 0: return "no error, everything went ok"; + case 1: return "nothing done yet"; /*the Encoder/Decoder has done nothing yet, error checking makes no sense yet*/ + case 10: return "end of input memory reached without huffman end code"; /*while huffman decoding*/ + case 11: return "error in code tree made it jump outside of huffman tree"; /*while huffman decoding*/ + case 13: return "problem while processing dynamic deflate block"; + case 14: return "problem while processing dynamic deflate block"; + case 15: return "problem while processing dynamic deflate block"; + case 16: return "unexisting code while processing dynamic deflate block"; + case 17: return "end of out buffer memory reached while inflating"; + case 18: return "invalid distance code while inflating"; + case 19: return "end of out buffer memory reached while inflating"; + case 20: return "invalid deflate block BTYPE encountered while decoding"; + case 21: return "NLEN is not ones complement of LEN in a deflate block"; + /*end of out buffer memory reached while inflating: + This can happen if the inflated deflate data is longer than the amount of bytes required to fill up + all the pixels of the image, given the color depth and image dimensions. Something that doesn't + happen in a normal, well encoded, PNG image.*/ + case 22: return "end of out buffer memory reached while inflating"; + case 23: return "end of in buffer memory reached while inflating"; + case 24: return "invalid FCHECK in zlib header"; + case 25: return "invalid compression method in zlib header"; + case 26: return "FDICT encountered in zlib header while it's not used for PNG"; + case 27: return "PNG file is smaller than a PNG header"; + /*Checks the magic file header, the first 8 bytes of the PNG file*/ + case 28: return "incorrect PNG signature, it's no PNG or corrupted"; + case 29: return "first chunk is not the header chunk"; + case 30: return "chunk length too large, chunk broken off at end of file"; + case 31: return "illegal PNG color type or bpp"; + case 32: return "illegal PNG compression method"; + case 33: return "illegal PNG filter method"; + case 34: return "illegal PNG interlace method"; + case 35: return "chunk length of a chunk is too large or the chunk too small"; + case 36: return "illegal PNG filter type encountered"; + case 37: return "illegal bit depth for this color type given"; + case 38: return "the palette is too big"; /*more than 256 colors*/ + case 39: return "tRNS chunk before PLTE or has more entries than palette size"; + case 40: return "tRNS chunk has wrong size for greyscale image"; + case 41: return "tRNS chunk has wrong size for RGB image"; + case 42: return "tRNS chunk appeared while it was not allowed for this color type"; + case 43: return "bKGD chunk has wrong size for palette image"; + case 44: return "bKGD chunk has wrong size for greyscale image"; + case 45: return "bKGD chunk has wrong size for RGB image"; + case 48: return "empty input buffer given to decoder. Maybe caused by non-existing file?"; + case 49: return "jumped past memory while generating dynamic huffman tree"; + case 50: return "jumped past memory while generating dynamic huffman tree"; + case 51: return "jumped past memory while inflating huffman block"; + case 52: return "jumped past memory while inflating"; + case 53: return "size of zlib data too small"; + case 54: return "repeat symbol in tree while there was no value symbol yet"; + /*jumped past tree while generating huffman tree, this could be when the + tree will have more leaves than symbols after generating it out of the + given lenghts. They call this an oversubscribed dynamic bit lengths tree in zlib.*/ + case 55: return "jumped past tree while generating huffman tree"; + case 56: return "given output image colortype or bitdepth not supported for color conversion"; + case 57: return "invalid CRC encountered (checking CRC can be disabled)"; + case 58: return "invalid ADLER32 encountered (checking ADLER32 can be disabled)"; + case 59: return "requested color conversion not supported"; + case 60: return "invalid window size given in the settings of the encoder (must be 0-32768)"; + case 61: return "invalid BTYPE given in the settings of the encoder (only 0, 1 and 2 are allowed)"; + /*LodePNG leaves the choice of RGB to greyscale conversion formula to the user.*/ + case 62: return "conversion from color to greyscale not supported"; + case 63: return "length of a chunk too long, max allowed for PNG is 2147483647 bytes per chunk"; /*(2^31-1)*/ + /*this would result in the inability of a deflated block to ever contain an end code. It must be at least 1.*/ + case 64: return "the length of the END symbol 256 in the Huffman tree is 0"; + case 66: return "the length of a text chunk keyword given to the encoder is longer than the maximum of 79 bytes"; + case 67: return "the length of a text chunk keyword given to the encoder is smaller than the minimum of 1 byte"; + case 68: return "tried to encode a PLTE chunk with a palette that has less than 1 or more than 256 colors"; + case 69: return "unknown chunk type with 'critical' flag encountered by the decoder"; + case 71: return "unexisting interlace mode given to encoder (must be 0 or 1)"; + case 72: return "while decoding, unexisting compression method encountering in zTXt or iTXt chunk (it must be 0)"; + case 73: return "invalid tIME chunk size"; + case 74: return "invalid pHYs chunk size"; + /*length could be wrong, or data chopped off*/ + case 75: return "no null termination char found while decoding text chunk"; + case 76: return "iTXt chunk too short to contain required bytes"; + case 77: return "integer overflow in buffer size"; + case 78: return "failed to open file for reading"; /*file doesn't exist or couldn't be opened for reading*/ + case 79: return "failed to open file for writing"; + case 80: return "tried creating a tree of 0 symbols"; + case 81: return "lazy matching at pos 0 is impossible"; + case 82: return "color conversion to palette requested while a color isn't in palette, or index out of bounds"; + case 83: return "memory allocation failed"; + case 84: return "given image too small to contain all pixels to be encoded"; + case 86: return "impossible offset in lz77 encoding (internal bug)"; + case 87: return "must provide custom zlib function pointer if LODEPNG_COMPILE_ZLIB is not defined"; + case 88: return "invalid filter strategy given for LodePNGEncoderSettings.filter_strategy"; + case 89: return "text chunk keyword too short or long: must have size 1-79"; + /*the windowsize in the LodePNGCompressSettings. Requiring POT(==> & instead of %) makes encoding 12% faster.*/ + case 90: return "windowsize must be a power of two"; + case 91: return "invalid decompressed idat size"; + case 92: return "integer overflow due to too many pixels"; + case 93: return "zero width or height is invalid"; + case 94: return "header chunk must have a size of 13 bytes"; + case 95: return "integer overflow with combined idat chunk size"; + case 96: return "invalid gAMA chunk size"; + case 97: return "invalid cHRM chunk size"; + case 98: return "invalid sRGB chunk size"; + case 99: return "invalid sRGB rendering intent"; + case 100: return "invalid ICC profile color type, the PNG specification only allows RGB or GRAY"; + case 101: return "PNG specification does not allow RGB ICC profile on grey color types and vice versa"; + case 102: return "not allowed to set greyscale ICC profile with colored pixels by PNG specification"; + case 103: return "Invalid palette index in bKGD chunk. Maybe it came before PLTE chunk?"; + case 104: return "Invalid bKGD color while encoding (e.g. palette index out of range)"; + } + return "unknown error code"; +} +#endif /*LODEPNG_COMPILE_ERROR_TEXT*/ + +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* // C++ Wrapper // */ +/* ////////////////////////////////////////////////////////////////////////// */ +/* ////////////////////////////////////////////////////////////////////////// */ + +#ifdef LODEPNG_COMPILE_CPP +namespace lodepng +{ + +#ifdef LODEPNG_COMPILE_DISK +unsigned load_file(std::vector& buffer, const std::string& filename) +{ + long size = lodepng_filesize(filename.c_str()); + if(size < 0) return 78; + buffer.resize((size_t)size); + return size == 0 ? 0 : lodepng_buffer_file(&buffer[0], (size_t)size, filename.c_str()); +} + +/*write given buffer to the file, overwriting the file, it doesn't append to it.*/ +unsigned save_file(const std::vector& buffer, const std::string& filename) +{ + return lodepng_save_file(buffer.empty() ? 0 : &buffer[0], buffer.size(), filename.c_str()); +} +#endif /* LODEPNG_COMPILE_DISK */ + +#ifdef LODEPNG_COMPILE_ZLIB +#ifdef LODEPNG_COMPILE_DECODER +unsigned decompress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGDecompressSettings& settings) +{ + unsigned char* buffer = 0; + size_t buffersize = 0; + unsigned error = zlib_decompress(&buffer, &buffersize, in, insize, &settings); + if(buffer) + { + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned decompress(std::vector& out, const std::vector& in, + const LodePNGDecompressSettings& settings) +{ + return decompress(out, in.empty() ? 0 : &in[0], in.size(), settings); +} +#endif /* LODEPNG_COMPILE_DECODER */ + +#ifdef LODEPNG_COMPILE_ENCODER +unsigned compress(std::vector& out, const unsigned char* in, size_t insize, + const LodePNGCompressSettings& settings) +{ + unsigned char* buffer = 0; + size_t buffersize = 0; + unsigned error = zlib_compress(&buffer, &buffersize, in, insize, &settings); + if(buffer) + { + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned compress(std::vector& out, const std::vector& in, + const LodePNGCompressSettings& settings) +{ + return compress(out, in.empty() ? 0 : &in[0], in.size(), settings); +} +#endif /* LODEPNG_COMPILE_ENCODER */ +#endif /* LODEPNG_COMPILE_ZLIB */ + + +#ifdef LODEPNG_COMPILE_PNG + +State::State() +{ + lodepng_state_init(this); +} + +State::State(const State& other) +{ + lodepng_state_init(this); + lodepng_state_copy(this, &other); +} + +State::~State() +{ + lodepng_state_cleanup(this); +} + +State& State::operator=(const State& other) +{ + lodepng_state_copy(this, &other); + return *this; +} + +#ifdef LODEPNG_COMPILE_DECODER + +unsigned decode(std::vector& out, unsigned& w, unsigned& h, const unsigned char* in, + size_t insize, LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned char* buffer; + unsigned error = lodepng_decode_memory(&buffer, &w, &h, in, insize, colortype, bitdepth); + if(buffer && !error) + { + State state; + state.info_raw.colortype = colortype; + state.info_raw.bitdepth = bitdepth; + size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw); + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + const std::vector& in, LodePNGColorType colortype, unsigned bitdepth) +{ + return decode(out, w, h, in.empty() ? 0 : &in[0], (unsigned)in.size(), colortype, bitdepth); +} + +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const unsigned char* in, size_t insize) +{ + unsigned char* buffer = NULL; + unsigned error = lodepng_decode(&buffer, &w, &h, &state, in, insize); + if(buffer && !error) + { + size_t buffersize = lodepng_get_raw_size(w, h, &state.info_raw); + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + } + lodepng_free(buffer); + return error; +} + +unsigned decode(std::vector& out, unsigned& w, unsigned& h, + State& state, + const std::vector& in) +{ + return decode(out, w, h, state, in.empty() ? 0 : &in[0], in.size()); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned decode(std::vector& out, unsigned& w, unsigned& h, const std::string& filename, + LodePNGColorType colortype, unsigned bitdepth) +{ + std::vector buffer; + unsigned error = load_file(buffer, filename); + if(error) return error; + return decode(out, w, h, buffer, colortype, bitdepth); +} +#endif /* LODEPNG_COMPILE_DECODER */ +#endif /* LODEPNG_COMPILE_DISK */ + +#ifdef LODEPNG_COMPILE_ENCODER +unsigned encode(std::vector& out, const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) +{ + unsigned char* buffer; + size_t buffersize; + unsigned error = lodepng_encode_memory(&buffer, &buffersize, in, w, h, colortype, bitdepth); + if(buffer) + { + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) +{ + if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84; + return encode(out, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth); +} + +unsigned encode(std::vector& out, + const unsigned char* in, unsigned w, unsigned h, + State& state) +{ + unsigned char* buffer; + size_t buffersize; + unsigned error = lodepng_encode(&buffer, &buffersize, in, w, h, &state); + if(buffer) + { + out.insert(out.end(), &buffer[0], &buffer[buffersize]); + lodepng_free(buffer); + } + return error; +} + +unsigned encode(std::vector& out, + const std::vector& in, unsigned w, unsigned h, + State& state) +{ + if(lodepng_get_raw_size(w, h, &state.info_raw) > in.size()) return 84; + return encode(out, in.empty() ? 0 : &in[0], w, h, state); +} + +#ifdef LODEPNG_COMPILE_DISK +unsigned encode(const std::string& filename, + const unsigned char* in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) +{ + std::vector buffer; + unsigned error = encode(buffer, in, w, h, colortype, bitdepth); + if(!error) error = save_file(buffer, filename); + return error; +} + +unsigned encode(const std::string& filename, + const std::vector& in, unsigned w, unsigned h, + LodePNGColorType colortype, unsigned bitdepth) +{ + if(lodepng_get_raw_size_lct(w, h, colortype, bitdepth) > in.size()) return 84; + return encode(filename, in.empty() ? 0 : &in[0], w, h, colortype, bitdepth); +} +#endif /* LODEPNG_COMPILE_DISK */ +#endif /* LODEPNG_COMPILE_ENCODER */ +#endif /* LODEPNG_COMPILE_PNG */ +} /* namespace lodepng */ +#endif /*LODEPNG_COMPILE_CPP*/ diff --git a/src/screenshot.c b/src/screenshot.c index 0b43ffa..afa77b9 100644 --- a/src/screenshot.c +++ b/src/screenshot.c @@ -16,31 +16,22 @@ #include #include #include +#include #include "ddraw.h" - #include "palette.h" #include "surface.h" - -#ifndef HAVE_LIBPNG - -//https://docs.microsoft.com/en-us/windows/desktop/gdi/storing-an-image +#include "lodepng.h" BOOL screenshot(struct IDirectDrawSurfaceImpl *src) { - HANDLE hf; // file handle - BITMAPFILEHEADER hdr; // bitmap file-header - PBITMAPINFOHEADER pbih; // bitmap info-header - LPBYTE lpBits; // memory pointer - DWORD dwTotal; // total count of bytes - DWORD cb; // incremental count of bytes - BYTE *hp; // byte pointer - DWORD dwTmp; + if (!src || !src->palette || !src->surface) + return FALSE; + int i; char title[128]; char filename[128]; char str_time[64]; time_t t = time(NULL); - BOOL result = TRUE; strncpy(title, ddraw->title, sizeof(ddraw->title)); @@ -55,145 +46,33 @@ BOOL screenshot(struct IDirectDrawSurfaceImpl *src) } } - strftime(str_time, 64, "%Y-%m-%d-%H_%M_%S", localtime(&t)); - _snprintf(filename, 128, "%s-%s.bmp", title, str_time); - - pbih = (PBITMAPINFOHEADER)src->bmi; - lpBits = (LPBYTE)src->surface; - - if (!lpBits) - return FALSE; - - // Create the .BMP file. - hf = CreateFile(filename, - GENERIC_READ | GENERIC_WRITE, - (DWORD)0, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - (HANDLE)NULL); - - if (hf == INVALID_HANDLE_VALUE) - return FALSE; - - hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M" - // Compute the size of the entire file. - hdr.bfSize = (DWORD)(sizeof(BITMAPFILEHEADER) + - pbih->biSize + pbih->biClrUsed - * sizeof(RGBQUAD) + pbih->biSizeImage); - hdr.bfReserved1 = 0; - hdr.bfReserved2 = 0; - - // Compute the offset to the array of color indices. - hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + - pbih->biSize + pbih->biClrUsed - * sizeof(RGBQUAD); - - // Copy the BITMAPFILEHEADER into the .BMP file. - if (!WriteFile(hf, (LPVOID)&hdr, sizeof(BITMAPFILEHEADER), - (LPDWORD)&dwTmp, NULL)) - { - result = FALSE; - } - - // Copy the BITMAPINFOHEADER and RGBQUAD array into the file. - if (!WriteFile(hf, (LPVOID)pbih, sizeof(BITMAPINFOHEADER) - + pbih->biClrUsed * sizeof(RGBQUAD), - (LPDWORD)&dwTmp, (NULL))) - result = FALSE; - - // Copy the array of color indices into the .BMP file. - dwTotal = cb = pbih->biSizeImage; - hp = lpBits; - if (!WriteFile(hf, (LPSTR)hp, (int)cb, (LPDWORD)&dwTmp, NULL)) - result = FALSE; - - // Close the .BMP file. - if (!CloseHandle(hf)) - result = FALSE; - - return result; -} - -#else - -#include - -BOOL screenshot(struct IDirectDrawSurfaceImpl *src) -{ - int i; - FILE *fh; - char title[128]; - char filename[128]; - - png_structp png_ptr; - png_infop info_ptr; - png_bytep *row_pointers; - png_color palette[256]; - - char str_time[64]; - time_t t = time(NULL); - - strncpy(title, ddraw->title, sizeof(ddraw->title)); - - for(i=0;ipalette) + unsigned char* png; + size_t pngsize; + LodePNGState state; + + lodepng_state_init(&state); + + for (i = 0; i < 256; i++) { - return FALSE; + RGBQUAD *c = &src->palette->data_rgb[i]; + lodepng_palette_add(&state.info_png.color, c->rgbRed, c->rgbGreen, c->rgbBlue, 255); + lodepng_palette_add(&state.info_raw, c->rgbRed, c->rgbGreen, c->rgbBlue, 255); } - if( !(fh = fopen(filename, "wb")) ) - { - return FALSE; - } + state.info_png.color.colortype = LCT_PALETTE; + state.info_png.color.bitdepth = 8; + state.info_raw.colortype = LCT_PALETTE; + state.info_raw.bitdepth = 8; + state.encoder.auto_convert = 0; - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); - if(!png_ptr) - { - return FALSE; - } + unsigned int error = lodepng_encode(&png, &pngsize, src->surface, src->width, src->height, &state); + if (!error) lodepng_save_file(png, pngsize, filename); - info_ptr = png_create_info_struct(png_ptr); + lodepng_state_cleanup(&state); + free(png); - for(i=0;i<256;i++) { - palette[i].red = src->palette->data_bgr[i]; - palette[i].green = src->palette->data_bgr[i] >> 8; - palette[i].blue = src->palette->data_bgr[i] >> 16; - } - - setjmp(png_jmpbuf(png_ptr)); - - png_init_io(png_ptr, fh); - - png_set_IHDR(png_ptr, info_ptr, src->width, src->height, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); - png_set_PLTE(png_ptr, info_ptr, (png_colorp)&palette, 256); - - row_pointers = (png_bytep *)png_malloc(png_ptr, sizeof(png_bytep) * src->height); - - for(i=0;iheight;i++) { - row_pointers[i] = src->surface + (src->width * i); - } - - png_set_rows(png_ptr, info_ptr, row_pointers); - - png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL); - - fclose(fh); - - return TRUE; + return !error; } - -#endif