diff options
| author | Magnus Auvinen <magnus.auvinen@gmail.com> | 2007-07-24 22:53:43 +0000 |
|---|---|---|
| committer | Magnus Auvinen <magnus.auvinen@gmail.com> | 2007-07-24 22:53:43 +0000 |
| commit | 5bd2c434f63ff4a039e854d647f02ef660c544d1 (patch) | |
| tree | 3fe99b2e4a7cf5e80243bde4583e10c5650ed913 /src/engine/client/pnglite | |
| parent | 4b098f7711e7cb96eef6797787e3f2f2b4cbb867 (diff) | |
| download | zcatch-5bd2c434f63ff4a039e854d647f02ef660c544d1.tar.gz zcatch-5bd2c434f63ff4a039e854d647f02ef660c544d1.zip | |
epic commit. removed tga support, removed BGR support. fixed one config for editor, server and client, optimized tilemap rendering (this needs some cleanup), added tools to fix alpha outline quirk and glitches in the tilemap reindering
Diffstat (limited to 'src/engine/client/pnglite')
| -rw-r--r-- | src/engine/client/pnglite/pnglite.c | 283 | ||||
| -rw-r--r-- | src/engine/client/pnglite/pnglite.h | 19 |
2 files changed, 292 insertions, 10 deletions
diff --git a/src/engine/client/pnglite/pnglite.c b/src/engine/client/pnglite/pnglite.c index 56e4c259..1874c63a 100644 --- a/src/engine/client/pnglite/pnglite.c +++ b/src/engine/client/pnglite/pnglite.c @@ -1,14 +1,21 @@ /* 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" -#define DO_CRC_CHECKS 1 + static png_alloc_t png_alloc; static png_free_t png_free; @@ -35,6 +42,22 @@ static size_t file_read(png_t* png, void* out, size_t size, size_t numel) 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]; @@ -47,6 +70,22 @@ static int file_read_ul(png_t* png, unsigned *out) 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; @@ -59,6 +98,16 @@ static unsigned get_ul(unsigned char* buf) 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) @@ -121,7 +170,7 @@ static int png_read_ihdr(png_t* png) #if DO_CRC_CHECKS file_read_ul(png, &orig_crc); - calc_crc = crc32(0L, Z_NULL, 0); + calc_crc = crc32(0L, 0, 0); calc_crc = crc32(calc_crc, ihdr, 13+4); if(orig_crc != calc_crc) @@ -150,6 +199,38 @@ static int png_read_ihdr(png_t* png) 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"); @@ -173,13 +254,13 @@ void png_print_info(png_t* png) printf("\tinterlace:\t%s\n", png->interlace_method?"interlace":"no interlace"); } - -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) { char header[8]; int result; png->read_fun = read_fun; + png->write_fun = 0; png->user_pointer = user_pointer; if(!read_fun && !user_pointer) @@ -198,15 +279,47 @@ int png_open(png_t* png, png_read_callback_t read_fun, void* user_pointer) return result; } -int png_open_file(png_t *png, const char* filename) +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(png, 0, fp); -} + 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) { @@ -215,7 +328,7 @@ int png_close_file(png_t* png) return PNG_NO_ERROR; } -static int png_init_inflate(png_t* png) +static int png_init_deflate(png_t* png, unsigned char* data, int datalen) { z_stream *stream; png->zs = png_alloc(sizeof(z_stream)); @@ -227,8 +340,41 @@ static int png_init_inflate(png_t* png) 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; @@ -236,14 +382,36 @@ static int png_init_inflate(png_t* png) 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; @@ -257,7 +425,11 @@ static int png_end_inflate(png_t* png) static int png_inflate(png_t* png, 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; @@ -265,7 +437,11 @@ static int png_inflate(png_t* png, char* data, int len) stream->next_in = (unsigned char*)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) { @@ -279,6 +455,64 @@ static int png_inflate(png_t* png, char* data, int len) 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; + + (void)png_init_deflate; + (void)png_end_deflate; + (void)png_deflate; + + chunk = png_alloc(size); + memcpy(chunk, "IDAT", 4); + + written = 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 firstlen) { unsigned type = 0; @@ -493,6 +727,13 @@ static void png_filter_paeth(int stride, unsigned char* in, unsigned char* out, } } +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; @@ -575,6 +816,31 @@ int png_get_data(png_t* png, unsigned char* 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); + return PNG_NO_ERROR; +} + + char* png_error_string(int error) { switch(error) @@ -607,4 +873,3 @@ char* png_error_string(int error) return "Unknown error."; }; } - diff --git a/src/engine/client/pnglite/pnglite.h b/src/engine/client/pnglite/pnglite.h index 78e1cfe8..f464c46b 100644 --- a/src/engine/client/pnglite/pnglite.h +++ b/src/engine/client/pnglite/pnglite.h @@ -70,6 +70,7 @@ enum 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); @@ -78,6 +79,7 @@ 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; @@ -126,13 +128,23 @@ int png_init(png_alloc_t pngalloc, png_free_t pngfree); 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 a png from the specified callback. The callback should be of the format: + 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 @@ -149,6 +161,9 @@ int png_open_file(png_t *png, const char* filename); 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 @@ -190,6 +205,8 @@ char* png_error_string(int error); 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 |