stb_image_write.h: Allow setting custom zlib compress function for PNG
The builtin stbi_zlib_compress does not compress as well as zlib or miniz (which is not too surprising as it's <200 LOC), thus PNGs created by stb_image_write are about 20-50% bigger than PNGs compressed with libpng. This change lets the user supply a custom deflate/zlib-style compress function, which improves compression a lot. This was requested in #113. Example for zlib: #include <zlib.h> unsigned char* compress_for_stbiw(unsigned char *data, int data_len, int *out_len, int quality) { uLongf bufSize = compressBound(data_len); // note that buf will be free'd by stb_image_write.h // with STBIW_FREE() (plain free() by default) unsigned char* buf = malloc(bufSize); if(buf == NULL) return NULL; if(compress2(buf, &bufSize, data, data_len, quality) != Z_OK) { free(buf); return NULL; } *out_len = bufSize; return buf; } #define STBIW_ZLIB_COMPRESS compress_for_stbiw #define STB_IMAGE_WRITE_IMPLEMENTATION #include "stb_image_write.h" // ...
This commit is contained in:
parent
e6bbecd3a9
commit
be21113512
@ -16,16 +16,22 @@ ABOUT:
|
|||||||
adapted to write to memory or a general streaming interface; let me know.
|
adapted to write to memory or a general streaming interface; let me know.
|
||||||
|
|
||||||
The PNG output is not optimal; it is 20-50% larger than the file
|
The PNG output is not optimal; it is 20-50% larger than the file
|
||||||
written by a decent optimizing implementation. This library is designed
|
written by a decent optimizing implementation; though providing a custom
|
||||||
for source code compactness and simplicity, not optimal image file size
|
zlib compress function (see STBIW_ZLIB_COMPRESS) can mitigate that.
|
||||||
or run-time performance.
|
This library is designed for source code compactness and simplicity,
|
||||||
|
not optimal image file size or run-time performance.
|
||||||
|
|
||||||
BUILDING:
|
BUILDING:
|
||||||
|
|
||||||
You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h.
|
You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h.
|
||||||
You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace
|
You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace
|
||||||
malloc,realloc,free.
|
malloc,realloc,free.
|
||||||
You can define STBIW_MEMMOVE() to replace memmove()
|
You can #define STBIW_MEMMOVE() to replace memmove()
|
||||||
|
You can #define STBIW_ZLIB_COMPRESS to use a custom zlib-style compress function
|
||||||
|
for PNG compression (instead of the builtin one), it must have the following signature:
|
||||||
|
unsigned char * my_compress(unsigned char *data, int data_len, int *out_len, int quality);
|
||||||
|
The returned data will be freed with STBIW_FREE() (free() by default),
|
||||||
|
so it must be heap allocated with STBIW_MALLOC() (malloc() by default),
|
||||||
|
|
||||||
USAGE:
|
USAGE:
|
||||||
|
|
||||||
@ -650,6 +656,7 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da
|
|||||||
// PNG writer
|
// PNG writer
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#ifndef STBIW_ZLIB_COMPRESS
|
||||||
// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
|
// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
|
||||||
#define stbiw__sbraw(a) ((int *) (a) - 2)
|
#define stbiw__sbraw(a) ((int *) (a) - 2)
|
||||||
#define stbiw__sbm(a) stbiw__sbraw(a)[0]
|
#define stbiw__sbm(a) stbiw__sbraw(a)[0]
|
||||||
@ -730,8 +737,14 @@ static unsigned int stbiw__zhash(unsigned char *data)
|
|||||||
|
|
||||||
#define stbiw__ZHASH 16384
|
#define stbiw__ZHASH 16384
|
||||||
|
|
||||||
|
#endif // STBIW_ZLIB_COMPRESS
|
||||||
|
|
||||||
unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
|
unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
|
||||||
{
|
{
|
||||||
|
#ifdef STBIW_ZLIB_COMPRESS
|
||||||
|
// user provided a zlib compress implementation, use that
|
||||||
|
return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality);
|
||||||
|
#else // use builtin
|
||||||
static unsigned short lengthc[] = { 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, 259 };
|
static unsigned short lengthc[] = { 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, 259 };
|
||||||
static unsigned char lengtheb[]= { 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 };
|
static unsigned char lengtheb[]= { 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 };
|
||||||
static unsigned short distc[] = { 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, 32768 };
|
static unsigned short distc[] = { 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, 32768 };
|
||||||
@ -833,6 +846,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
|
|||||||
// make returned pointer freeable
|
// make returned pointer freeable
|
||||||
STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
|
STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
|
||||||
return (unsigned char *) stbiw__sbraw(out);
|
return (unsigned char *) stbiw__sbraw(out);
|
||||||
|
#endif // STBIW_ZLIB_COMPRESS
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int stbiw__crc32(unsigned char *buffer, int len)
|
static unsigned int stbiw__crc32(unsigned char *buffer, int len)
|
||||||
|
Loading…
Reference in New Issue
Block a user