aboutsummaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorToomas Soome <tsoome@FreeBSD.org>2021-01-02 19:27:29 +0000
committerToomas Soome <tsoome@FreeBSD.org>2021-01-02 19:27:29 +0000
commit72c59f1728c12fbdcd316c172708d8f3a60299be (patch)
tree58c01034147b5f7b252b420979d6f19ffb1f1f37 /contrib
parent5bcd0b860c7d4935db5b290cf932357fc22adf3a (diff)
parenta70c2a23d0d84dfc63a1d9413a7f4aaede7313aa (diff)
downloadsrc-72c59f1728c12fbdcd316c172708d8f3a60299be.tar.gz
src-72c59f1728c12fbdcd316c172708d8f3a60299be.zip
Add 'contrib/pnglite/' from commit 'a70c2a23d0d84dfc63a1d9413a7f4aaede7313aa'
git-subtree-dir: contrib/pnglite git-subtree-mainline: 5bcd0b860c7d4935db5b290cf932357fc22adf3a git-subtree-split: a70c2a23d0d84dfc63a1d9413a7f4aaede7313aa
Diffstat (limited to 'contrib')
-rw-r--r--contrib/pnglite/LICENSE25
-rw-r--r--contrib/pnglite/README.md5
-rw-r--r--contrib/pnglite/pnglite.c862
-rw-r--r--contrib/pnglite/pnglite.h232
4 files changed, 1124 insertions, 0 deletions
diff --git a/contrib/pnglite/LICENSE b/contrib/pnglite/LICENSE
new file mode 100644
index 000000000000..460af5e106f5
--- /dev/null
+++ b/contrib/pnglite/LICENSE
@@ -0,0 +1,25 @@
+pnglite.h - Interface for pnglite library
+
+Copyright (c) 2007 Daniel Karling
+
+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.
+
+Daniel Karling
+daniel.karling@gmail.com
diff --git a/contrib/pnglite/README.md b/contrib/pnglite/README.md
new file mode 100644
index 000000000000..4d2929600228
--- /dev/null
+++ b/contrib/pnglite/README.md
@@ -0,0 +1,5 @@
+pnglite
+====
+#### A pretty small png library
+
+Currently all documentation resides in pnglite.h.
diff --git a/contrib/pnglite/pnglite.c b/contrib/pnglite/pnglite.c
new file mode 100644
index 000000000000..4899f24b6a85
--- /dev/null
+++ b/contrib/pnglite/pnglite.c
@@ -0,0 +1,862 @@
+/* pnglite.c - pnglite library
+ For conditions of distribution and use, see copyright notice in pnglite.h
+*/
+#define DO_CRC_CHECKS 1
+#define USE_ZLIB 1
+
+#if USE_ZLIB
+#include <zlib.h>
+#else
+#include "zlite.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "pnglite.h"
+
+static png_alloc_t png_alloc;
+static png_free_t png_free;
+
+static size_t file_read(png_t* png, void* out, size_t size, size_t numel)
+{
+ size_t result;
+ if(png->read_fun)
+ {
+ result = png->read_fun(out, size, numel, png->user_pointer);
+ }
+ else
+ {
+ if(!out)
+ {
+ result = fseek(png->user_pointer, (long)(size*numel), SEEK_CUR);
+ }
+ else
+ {
+ result = fread(out, size, numel, png->user_pointer);
+ }
+ }
+
+ return result;
+}
+
+static size_t file_write(png_t* png, void* p, size_t size, size_t numel)
+{
+ size_t result;
+
+ if(png->write_fun)
+ {
+ result = png->write_fun(p, size, numel, png->user_pointer);
+ }
+ else
+ {
+ result = fwrite(p, size, numel, png->user_pointer);
+ }
+
+ return result;
+}
+
+static int file_read_ul(png_t* png, unsigned *out)
+{
+ unsigned char buf[4];
+
+ if(file_read(png, buf, 1, 4) != 4)
+ return PNG_FILE_ERROR;
+
+ *out = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];
+
+ return PNG_NO_ERROR;
+}
+
+static int file_write_ul(png_t* png, unsigned in)
+{
+ unsigned char buf[4];
+
+ buf[0] = (in>>24) & 0xff;
+ buf[1] = (in>>16) & 0xff;
+ buf[2] = (in>>8) & 0xff;
+ buf[3] = (in) & 0xff;
+
+ if(file_write(png, buf, 1, 4) != 4)
+ return PNG_FILE_ERROR;
+
+ return PNG_NO_ERROR;
+}
+
+static unsigned get_ul(unsigned char* buf)
+{
+ unsigned result;
+ unsigned char foo[4];
+
+ memcpy(foo, buf, 4);
+
+ result = (foo[0]<<24) | (foo[1]<<16) | (foo[2]<<8) | foo[3];
+
+ return result;
+}
+
+static unsigned set_ul(unsigned char* buf, unsigned in)
+{
+ buf[0] = (in>>24) & 0xff;
+ buf[1] = (in>>16) & 0xff;
+ buf[2] = (in>>8) & 0xff;
+ buf[3] = (in) & 0xff;
+
+ return PNG_NO_ERROR;
+}
+
+int png_init(png_alloc_t pngalloc, png_free_t pngfree)
+{
+ if(pngalloc)
+ png_alloc = pngalloc;
+ else
+ png_alloc = &malloc;
+
+ if(pngfree)
+ png_free = pngfree;
+ else
+ png_free = &free;
+
+ return PNG_NO_ERROR;
+}
+
+static int png_get_bpp(png_t* png)
+{
+ int bpp;
+
+ switch(png->color_type)
+ {
+ case PNG_GREYSCALE:
+ bpp = 1; break;
+ case PNG_TRUECOLOR:
+ bpp = 3; break;
+ case PNG_INDEXED:
+ bpp = 1; break;
+ case PNG_GREYSCALE_ALPHA:
+ bpp = 2; break;
+ case PNG_TRUECOLOR_ALPHA:
+ bpp = 4; break;
+ default:
+ return PNG_FILE_ERROR;
+ }
+
+ bpp *= png->depth/8;
+
+ return bpp;
+}
+
+static int png_read_ihdr(png_t* png)
+{
+ unsigned length;
+#if DO_CRC_CHECKS
+ unsigned orig_crc;
+ unsigned calc_crc;
+#endif
+ unsigned char ihdr[13+4]; /* length should be 13, make room for type (IHDR) */
+
+ file_read_ul(png, &length);
+
+ if(length != 13)
+ {
+ printf("%d\n", length);
+ return PNG_CRC_ERROR;
+ }
+
+ if(file_read(png, ihdr, 1, 13+4) != 13+4)
+ return PNG_EOF_ERROR;
+#if DO_CRC_CHECKS
+ file_read_ul(png, &orig_crc);
+
+ calc_crc = crc32(0L, 0, 0);
+ calc_crc = crc32(calc_crc, ihdr, 13+4);
+
+ if(orig_crc != calc_crc)
+ return PNG_CRC_ERROR;
+#else
+ file_read_ul(png);
+#endif
+
+ png->width = get_ul(ihdr+4);
+ png->height = get_ul(ihdr+8);
+ png->depth = ihdr[12];
+ png->color_type = ihdr[13];
+ png->compression_method = ihdr[14];
+ png->filter_method = ihdr[15];
+ png->interlace_method = ihdr[16];
+
+ if(png->color_type == PNG_INDEXED)
+ return PNG_NOT_SUPPORTED;
+
+ if(png->depth != 8 && png->depth != 16)
+ return PNG_NOT_SUPPORTED;
+
+ if(png->interlace_method)
+ return PNG_NOT_SUPPORTED;
+
+ return PNG_NO_ERROR;
+}
+
+static int png_write_ihdr(png_t* png)
+{
+ unsigned char ihdr[13+4];
+ unsigned char *p = ihdr;
+ unsigned crc;
+
+ file_write(png, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 1, 8);
+
+ file_write_ul(png, 13);
+
+ *p = 'I'; p++;
+ *p = 'H'; p++;
+ *p = 'D'; p++;
+ *p = 'R'; p++;
+ set_ul(p, png->width); p+=4;
+ set_ul(p, png->height); p+=4;
+ *p = png->depth; p++;
+ *p = png->color_type; p++;
+ *p = 0; p++;
+ *p = 0; p++;
+ *p = 0; p++;
+
+ file_write(png, ihdr, 1, 13+4);
+
+ crc = crc32(0L, 0, 0);
+ crc = crc32(crc, ihdr, 13+4);
+
+ file_write_ul(png, crc);
+
+ return PNG_NO_ERROR;
+}
+
+void png_print_info(png_t* png)
+{
+ printf("PNG INFO:\n");
+ printf("\twidth:\t\t%d\n", png->width);
+ printf("\theight:\t\t%d\n", png->height);
+ printf("\tdepth:\t\t%d\n", png->depth);
+ printf("\tcolor:\t\t");
+
+ switch(png->color_type)
+ {
+ case PNG_GREYSCALE: printf("greyscale\n"); break;
+ case PNG_TRUECOLOR: printf("truecolor\n"); break;
+ case PNG_INDEXED: printf("palette\n"); break;
+ case PNG_GREYSCALE_ALPHA: printf("greyscale with alpha\n"); break;
+ case PNG_TRUECOLOR_ALPHA: printf("truecolor with alpha\n"); break;
+ default: printf("unknown, this is not good\n"); break;
+ }
+
+ printf("\tcompression:\t%s\n", png->compression_method?"unknown, this is not good":"inflate/deflate");
+ printf("\tfilter:\t\t%s\n", png->filter_method?"unknown, this is not good":"adaptive");
+ printf("\tinterlace:\t%s\n", png->interlace_method?"interlace":"no interlace");
+}
+
+int png_open_read(png_t* png, png_read_callback_t read_fun, void* user_pointer)
+{
+ char header[8];
+ int result;
+
+ png->read_fun = read_fun;
+ png->write_fun = 0;
+ png->user_pointer = user_pointer;
+
+ if(!read_fun && !user_pointer)
+ return PNG_WRONG_ARGUMENTS;
+
+ if(file_read(png, header, 1, 8) != 8)
+ return PNG_EOF_ERROR;
+
+ if(memcmp(header, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8) != 0)
+ return PNG_HEADER_ERROR;
+
+ result = png_read_ihdr(png);
+
+ png->bpp = (unsigned char)png_get_bpp(png);
+
+ return result;
+}
+
+int png_open_write(png_t* png, png_write_callback_t write_fun, void* user_pointer)
+{
+ png->write_fun = write_fun;
+ png->read_fun = 0;
+ png->user_pointer = user_pointer;
+
+ if(!write_fun && !user_pointer)
+ return PNG_WRONG_ARGUMENTS;
+
+ return PNG_NO_ERROR;
+}
+
+int png_open(png_t* png, png_read_callback_t read_fun, void* user_pointer)
+{
+ return png_open_read(png, read_fun, user_pointer);
+}
+
+int png_open_file_read(png_t *png, const char* filename)
+{
+ FILE* fp = fopen(filename, "rb");
+
+ if(!fp)
+ return PNG_FILE_ERROR;
+
+ return png_open_read(png, 0, fp);
+}
+
+int png_open_file_write(png_t *png, const char* filename)
+{
+ FILE* fp = fopen(filename, "wb");
+
+ if(!fp)
+ return PNG_FILE_ERROR;
+
+ return png_open_write(png, 0, fp);
+}
+
+int png_open_file(png_t *png, const char* filename)
+{
+ return png_open_file_read(png, filename);
+}
+
+int png_close_file(png_t* png)
+{
+ fclose(png->user_pointer);
+
+ return PNG_NO_ERROR;
+}
+
+static int png_init_deflate(png_t* png, unsigned char* data, int datalen)
+{
+ z_stream *stream;
+ png->zs = png_alloc(sizeof(z_stream));
+
+ stream = png->zs;
+
+ if(!stream)
+ return PNG_MEMORY_ERROR;
+
+ memset(stream, 0, sizeof(z_stream));
+
+ if(deflateInit(stream, Z_DEFAULT_COMPRESSION) != Z_OK)
+ return PNG_ZLIB_ERROR;
+
+ stream->next_in = data;
+ stream->avail_in = datalen;
+
+ return PNG_NO_ERROR;
+}
+
+static int png_init_inflate(png_t* png)
+{
+#if USE_ZLIB
+ z_stream *stream;
+ png->zs = png_alloc(sizeof(z_stream));
+#else
+ zl_stream *stream;
+ png->zs = png_alloc(sizeof(zl_stream));
+#endif
+
+ stream = png->zs;
+
+ if(!stream)
+ return PNG_MEMORY_ERROR;
+
+#if USE_ZLIB
+ memset(stream, 0, sizeof(z_stream));
+ if(inflateInit(stream) != Z_OK)
+ return PNG_ZLIB_ERROR;
+#else
+ memset(stream, 0, sizeof(zl_stream));
+ if(z_inflateInit(stream) != Z_OK)
+ return PNG_ZLIB_ERROR;
+#endif
+
+ stream->next_out = png->png_data;
+ stream->avail_out = png->png_datalen;
+
+ return PNG_NO_ERROR;
+}
+
+static int png_end_deflate(png_t* png)
+{
+ z_stream *stream = png->zs;
+
+ if(!stream)
+ return PNG_MEMORY_ERROR;
+
+ deflateEnd(stream);
+
+ png_free(png->zs);
+
+ return PNG_NO_ERROR;
+}
+
+static int png_end_inflate(png_t* png)
+{
+#if USE_ZLIB
+ z_stream *stream = png->zs;
+#else
+ zl_stream *stream = png->zs;
+#endif
+
+ if(!stream)
+ return PNG_MEMORY_ERROR;
+
+#if USE_ZLIB
+ if(inflateEnd(stream) != Z_OK)
+#else
+ if(z_inflateEnd(stream) != Z_OK)
+#endif
+ {
+ printf("ZLIB says: %s\n", stream->msg);
+ return PNG_ZLIB_ERROR;
+ }
+
+ png_free(png->zs);
+
+ return PNG_NO_ERROR;
+}
+
+static int png_inflate(png_t* png, unsigned char* data, int len)
+{
+ int result;
+#if USE_ZLIB
+ z_stream *stream = png->zs;
+#else
+ zl_stream *stream = png->zs;
+#endif
+
+ if(!stream)
+ return PNG_MEMORY_ERROR;
+
+ stream->next_in = data;
+ stream->avail_in = len;
+
+#if USE_ZLIB
+ result = inflate(stream, Z_SYNC_FLUSH);
+#else
+ result = z_inflate(stream);
+#endif
+
+ if(result != Z_STREAM_END && result != Z_OK)
+ {
+ printf("%s\n", stream->msg);
+ return PNG_ZLIB_ERROR;
+ }
+
+ if(stream->avail_in != 0)
+ return PNG_ZLIB_ERROR;
+
+ return PNG_NO_ERROR;
+}
+
+static int png_deflate(png_t* png, char* outdata, int outlen, int *outwritten)
+{
+ int result;
+
+ z_stream *stream = png->zs;
+
+ if(!stream)
+ return PNG_MEMORY_ERROR;
+
+ stream->next_out = (unsigned char*)outdata;
+ stream->avail_out = outlen;
+
+ result = deflate(stream, Z_SYNC_FLUSH);
+
+ *outwritten = outlen - stream->avail_out;
+
+ if(result != Z_STREAM_END && result != Z_OK)
+ {
+ printf("%s\n", stream->msg);
+ return PNG_ZLIB_ERROR;
+ }
+
+ return result;
+}
+
+static int png_write_idats(png_t* png, unsigned char* data)
+{
+ unsigned char *chunk;
+ unsigned long written;
+ unsigned long crc;
+ unsigned size = png->width * png->height * png->bpp + png->height;
+ unsigned chunk_size = compressBound(size);
+
+ (void)png_init_deflate;
+ (void)png_end_deflate;
+ (void)png_deflate;
+
+ chunk = png_alloc(chunk_size + 4);
+ memcpy(chunk, "IDAT", 4);
+
+ written = chunk_size;
+ compress(chunk+4, &written, data, size);
+
+ crc = crc32(0L, Z_NULL, 0);
+ crc = crc32(crc, chunk, written+4);
+ set_ul(chunk+written+4, crc);
+ file_write_ul(png, written);
+ file_write(png, chunk, 1, written+8);
+ png_free(chunk);
+
+ file_write_ul(png, 0);
+ file_write(png, "IEND", 1, 4);
+ crc = crc32(0L, (const unsigned char *)"IEND", 4);
+ file_write_ul(png, crc);
+
+ return PNG_NO_ERROR;
+}
+
+static int png_read_idat(png_t* png, unsigned length)
+{
+#if DO_CRC_CHECKS
+ unsigned orig_crc;
+ unsigned calc_crc;
+#endif
+
+ if(!png->readbuf || png->readbuflen < length)
+ {
+ if (png->readbuf)
+ {
+ png_free(png->readbuf);
+ }
+ png->readbuf = png_alloc(length);
+ png->readbuflen = length;
+ }
+
+ if(!png->readbuf)
+ {
+ return PNG_MEMORY_ERROR;
+ }
+
+ if(file_read(png, png->readbuf, 1, length) != length)
+ {
+ return PNG_FILE_ERROR;
+ }
+
+#if DO_CRC_CHECKS
+ calc_crc = crc32(0L, Z_NULL, 0);
+ calc_crc = crc32(calc_crc, (unsigned char*)"IDAT", 4);
+ calc_crc = crc32(calc_crc, (unsigned char*)png->readbuf, length);
+
+ file_read_ul(png, &orig_crc);
+
+ if(orig_crc != calc_crc)
+ {
+ return PNG_CRC_ERROR;
+ }
+#else
+ file_read_ul(png);
+#endif
+
+ return png_inflate(png, png->readbuf, length);
+}
+
+static int png_process_chunk(png_t* png)
+{
+ int result = PNG_NO_ERROR;
+ unsigned type;
+ unsigned length;
+
+ file_read_ul(png, &length);
+
+ if(file_read(png, &type, 1, 4) != 4)
+ return PNG_FILE_ERROR;
+
+ if(type == *(unsigned int*)"IDAT") /* if we found an idat, all other idats should be followed with no other chunks in between */
+ {
+ if(!png->png_data) /* first IDAT */
+ {
+ png->png_datalen = png->width * png->height * png->bpp + png->height;
+ png->png_data = png_alloc(png->png_datalen);
+ }
+
+ if(!png->png_data)
+ return PNG_MEMORY_ERROR;
+
+ if(!png->zs)
+ {
+ result = png_init_inflate(png);
+ if(result != PNG_NO_ERROR)
+ return result;
+ }
+
+ return png_read_idat(png, length);
+ }
+ else if(type == *(unsigned int*)"IEND")
+ {
+ return PNG_DONE;
+ }
+ else
+ {
+ file_read(png, 0, 1, length + 4); /* unknown chunk */
+ }
+
+ return result;
+}
+
+static void png_filter_sub(int stride, unsigned char* in, unsigned char* out, int len)
+{
+ int i;
+ unsigned char a = 0;
+
+ for(i = 0; i < len; i++)
+ {
+ if(i >= stride)
+ a = out[i - stride];
+
+ out[i] = in[i] + a;
+ }
+}
+
+static void png_filter_up(int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len)
+{
+ int i;
+
+ if(prev_line)
+ {
+ for(i = 0; i < len; i++)
+ out[i] = in[i] + prev_line[i];
+ }
+ else
+ memcpy(out, in, len);
+}
+
+static void png_filter_average(int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len)
+{
+ int i;
+ unsigned char a = 0;
+ unsigned char b = 0;
+ unsigned int sum = 0;
+
+ for(i = 0; i < len; i++)
+ {
+ if(prev_line)
+ b = prev_line[i];
+
+ if(i >= stride)
+ a = out[i - stride];
+
+ sum = a;
+ sum += b;
+
+ out[i] = (char)(in[i] + sum/2);
+ }
+}
+
+static unsigned char png_paeth(unsigned char a, unsigned char b, unsigned char c)
+{
+ int p = (int)a + b - c;
+ int pa = abs(p - a);
+ int pb = abs(p - b);
+ int pc = abs(p - c);
+
+ int pr;
+
+ if(pa <= pb && pa <= pc)
+ pr = a;
+ else if(pb <= pc)
+ pr = b;
+ else
+ pr = c;
+
+ return (char)pr;
+}
+
+static void png_filter_paeth(int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len)
+{
+ int i;
+ unsigned char a;
+ unsigned char b;
+ unsigned char c;
+
+ for(i = 0; i < len; i++)
+ {
+ if(prev_line && i >= stride)
+ {
+ a = out[i - stride];
+ b = prev_line[i];
+ c = prev_line[i - stride];
+ }
+ else
+ {
+ if(prev_line)
+ b = prev_line[i];
+ else
+ b = 0;
+
+ if(i >= stride)
+ a = out[i - stride];
+ else
+ a = 0;
+
+ c = 0;
+ }
+
+ out[i] = in[i] + png_paeth(a, b, c);
+ }
+}
+
+static int png_filter(png_t* png, unsigned char* data)
+{
+ return PNG_NO_ERROR;
+}
+
+static int png_unfilter(png_t* png, unsigned char* data)
+{
+ unsigned i;
+ unsigned pos = 0;
+ unsigned outpos = 0;
+ unsigned char *filtered = png->png_data;
+
+ int stride = png->bpp;
+
+ while(pos < png->png_datalen)
+ {
+ unsigned char filter = filtered[pos];
+
+ pos++;
+
+ if(png->depth == 16)
+ {
+ for(i = 0; i < png->width * stride; i+=2)
+ {
+ *(short*)(filtered+pos+i) = (filtered[pos+i] << 8) | filtered[pos+i+1];
+ }
+ }
+
+ switch(filter)
+ {
+ case 0: /* none */
+ memcpy(data+outpos, filtered+pos, png->width * stride);
+ break;
+ case 1: /* sub */
+ png_filter_sub(stride, filtered+pos, data+outpos, png->width * stride);
+ break;
+ case 2: /* up */
+ if(outpos)
+ png_filter_up(stride, filtered+pos, data+outpos, data + outpos - (png->width*stride), png->width*stride);
+ else
+ png_filter_up(stride, filtered+pos, data+outpos, 0, png->width*stride);
+ break;
+ case 3: /* average */
+ if(outpos)
+ png_filter_average(stride, filtered+pos, data+outpos, data + outpos - (png->width*stride), png->width*stride);
+ else
+ png_filter_average(stride, filtered+pos, data+outpos, 0, png->width*stride);
+ break;
+ case 4: /* paeth */
+ if(outpos)
+ png_filter_paeth(stride, filtered+pos, data+outpos, data + outpos - (png->width*stride), png->width*stride);
+ else
+ png_filter_paeth(stride, filtered+pos, data+outpos, 0, png->width*stride);
+ break;
+ default:
+ return PNG_UNKNOWN_FILTER;
+ }
+
+ outpos += png->width * stride;
+ pos += png->width * stride;
+ }
+
+ return PNG_NO_ERROR;
+}
+
+int png_get_data(png_t* png, unsigned char* data)
+{
+ int result = PNG_NO_ERROR;
+
+ png->zs = NULL;
+ png->png_datalen = 0;
+ png->png_data = NULL;
+ png->readbuf = NULL;
+ png->readbuflen = 0;
+
+ while(result == PNG_NO_ERROR)
+ {
+ result = png_process_chunk(png);
+ }
+
+ if (png->readbuf)
+ {
+ png_free(png->readbuf);
+ png->readbuflen = 0;
+ }
+ if (png->zs)
+ {
+ png_end_inflate(png);
+ }
+
+ if(result != PNG_DONE)
+ {
+ png_free(png->png_data);
+ return result;
+ }
+
+ result = png_unfilter(png, data);
+
+ png_free(png->png_data);
+
+ return result;
+}
+
+int png_set_data(png_t* png, unsigned width, unsigned height, char depth, int color, unsigned char* data)
+{
+ int i;
+ unsigned char *filtered;
+ png->width = width;
+ png->height = height;
+ png->depth = depth;
+ png->color_type = color;
+ png->bpp = png_get_bpp(png);
+
+ filtered = png_alloc(width * height * png->bpp + height);
+
+ for(i = 0; i < png->height; i++)
+ {
+ filtered[i*png->width*png->bpp+i] = 0;
+ memcpy(&filtered[i*png->width*png->bpp+i+1], data + i * png->width*png->bpp, png->width*png->bpp);
+ }
+
+ png_filter(png, filtered);
+ png_write_ihdr(png);
+ png_write_idats(png, filtered);
+
+ png_free(filtered);
+
+ return PNG_NO_ERROR;
+}
+
+char* png_error_string(int error)
+{
+ switch(error)
+ {
+ case PNG_NO_ERROR:
+ return "No error";
+ case PNG_FILE_ERROR:
+ return "Unknown file error.";
+ case PNG_HEADER_ERROR:
+ return "No PNG header found. Are you sure this is a PNG?";
+ case PNG_IO_ERROR:
+ return "Failure while reading file.";
+ case PNG_EOF_ERROR:
+ return "Reached end of file.";
+ case PNG_CRC_ERROR:
+ return "CRC or chunk length error.";
+ case PNG_MEMORY_ERROR:
+ return "Could not allocate memory.";
+ case PNG_ZLIB_ERROR:
+ return "zlib reported an error.";
+ case PNG_UNKNOWN_FILTER:
+ return "Unknown filter method used in scanline.";
+ case PNG_DONE:
+ return "PNG done";
+ case PNG_NOT_SUPPORTED:
+ return "The PNG is unsupported by pnglite, too bad for you!";
+ case PNG_WRONG_ARGUMENTS:
+ return "Wrong combination of arguments passed to png_open. You must use either a read_function or supply a file pointer to use.";
+ default:
+ return "Unknown error.";
+ };
+}
diff --git a/contrib/pnglite/pnglite.h b/contrib/pnglite/pnglite.h
new file mode 100644
index 000000000000..bbb207502409
--- /dev/null
+++ b/contrib/pnglite/pnglite.h
@@ -0,0 +1,232 @@
+/* pnglite.h - Interface for pnglite library
+ Copyright (c) 2007 Daniel Karling
+
+ 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.
+
+ Daniel Karling
+ daniel.karling@gmail.com
+ */
+
+
+#ifndef _PNGLITE_H_
+#define _PNGLITE_H_
+
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/*
+ Enumerations for pnglite.
+ Negative numbers are error codes and 0 and up are okay responses.
+*/
+
+enum
+{
+ PNG_DONE = 1,
+ PNG_NO_ERROR = 0,
+ PNG_FILE_ERROR = -1,
+ PNG_HEADER_ERROR = -2,
+ PNG_IO_ERROR = -3,
+ PNG_EOF_ERROR = -4,
+ PNG_CRC_ERROR = -5,
+ PNG_MEMORY_ERROR = -6,
+ PNG_ZLIB_ERROR = -7,
+ PNG_UNKNOWN_FILTER = -8,
+ PNG_NOT_SUPPORTED = -9,
+ PNG_WRONG_ARGUMENTS = -10
+};
+
+/*
+ The five different kinds of color storage in PNG files.
+*/
+
+enum
+{
+ PNG_GREYSCALE = 0,
+ PNG_TRUECOLOR = 2,
+ PNG_INDEXED = 3,
+ PNG_GREYSCALE_ALPHA = 4,
+ PNG_TRUECOLOR_ALPHA = 6
+};
+
+/*
+ Typedefs for callbacks.
+*/
+
+typedef unsigned (*png_write_callback_t)(void* input, size_t size, size_t numel, void* user_pointer);
+typedef unsigned (*png_read_callback_t)(void* output, size_t size, size_t numel, void* user_pointer);
+typedef void (*png_free_t)(void* p);
+typedef void * (*png_alloc_t)(size_t s);
+
+typedef struct
+{
+ void* zs; /* pointer to z_stream */
+ png_read_callback_t read_fun;
+ png_write_callback_t write_fun;
+ void* user_pointer;
+
+ unsigned char* png_data;
+ unsigned png_datalen;
+
+ unsigned width;
+ unsigned height;
+ unsigned char depth;
+ unsigned char color_type;
+ unsigned char compression_method;
+ unsigned char filter_method;
+ unsigned char interlace_method;
+ unsigned char bpp;
+
+ unsigned char* readbuf;
+ unsigned readbuflen;
+} png_t;
+
+/*
+ Function: png_init
+
+ This function initializes pnglite. The parameters can be used to set your own memory allocation routines following these formats:
+
+ > void* (*custom_alloc)(size_t s)
+ > void (*custom_free)(void* p)
+ Parameters:
+ pngalloc - Pointer to custom allocation routine. If 0 is passed, malloc from libc will be used.
+ pngfree - Pointer to custom free routine. If 0 is passed, free from libc will be used.
+
+ Returns:
+ Always returns PNG_NO_ERROR.
+*/
+
+int png_init(png_alloc_t pngalloc, png_free_t pngfree);
+
+/*
+ Function: png_open_file
+
+ This function is used to open a png file with the internal file IO system. This function should be used instead of
+ png_open if no custom read function is used.
+
+ Parameters:
+ png - Empty png_t struct.
+ filename - Filename of the file to be opened.
+
+ Returns:
+ PNG_NO_ERROR on success, otherwise an error code.
+*/
+
+int png_open_file(png_t *png, const char* filename);
+
+int png_open_file_read(png_t *png, const char* filename);
+int png_open_file_write(png_t *png, const char* filename);
+
+/*
+ Function: png_open
+
+ This function reads or writes a png from/to the specified callback. The callbacks should be of the format:
+
+ > size_t (*png_write_callback_t)(void* input, size_t size, size_t numel, void* user_pointer);
+ > size_t (*png_read_callback_t)(void* output, size_t size, size_t numel, void* user_pointer).
+
+ Only one callback has to be specified. The read callback in case of PNG reading, otherwise the write callback.
+
+ Writing:
+ The callback will be called like fwrite.
+
+ Reading:
+ The callback will be called each time pnglite needs more data. The callback should read as much data as requested,
+ or return 0. This should always be possible if the PNG is sane. If the output-buffer is a null-pointer the callback
+ should only skip ahead the specified number of elements. If the callback is a null-pointer the user_pointer will be
+ treated as a file pointer (use png_open_file instead).
+
+ Parameters:
+ png - png_t struct
+ read_fun - Callback function for reading.
+ user_pointer - User pointer to be passed to read_fun.
+
+ Returns:
+ PNG_NO_ERROR on success, otherwise an error code.
+*/
+
+int png_open(png_t* png, png_read_callback_t read_fun, void* user_pointer);
+
+int png_open_read(png_t* png, png_read_callback_t read_fun, void* user_pointer);
+int png_open_write(png_t* png, png_write_callback_t write_fun, void* user_pointer);
+
+/*
+ Function: png_print_info
+
+ This function prints some info about the opened png file to stdout.
+
+ Parameters:
+ png - png struct to get info from.
+*/
+
+void png_print_info(png_t* png);
+
+/*
+ Function: png_error_string
+
+ This function translates an error code to a human readable string.
+
+ Parameters:
+ error - Error code.
+
+ Returns:
+ Pointer to string.
+*/
+
+char* png_error_string(int error);
+
+/*
+ Function: png_get_data
+
+ This function decodes the opened png file and stores the result in data. data should be big enough to hold the decoded png. Required size will be:
+
+ > width*height*(bytes per pixel)
+
+ Parameters:
+ data - Where to store result.
+
+ Returns:
+ PNG_NO_ERROR on success, otherwise an error code.
+*/
+
+int png_get_data(png_t* png, unsigned char* data);
+
+int png_set_data(png_t* png, unsigned width, unsigned height, char depth, int color, unsigned char* data);
+
+/*
+ Function: png_close_file
+
+ Closes an open png file pointer. Should only be used when the png has been opened with png_open_file.
+
+ Parameters:
+ png - png to close.
+
+ Returns:
+ PNG_NO_ERROR
+*/
+
+int png_close_file(png_t* png);
+
+#ifdef __cplusplus
+}
+#endif
+#endif