From 80176ae4a144d142756aae3176eb8372da3bcb6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20P=2E=20Tjern=C3=B8?= Date: Tue, 24 Mar 2015 11:22:20 -0700 Subject: [PATCH 1/3] Remove unused variables in write_hdr_scanline. Fixes #90. --- stb_image_write.h | 1 - 1 file changed, 1 deletion(-) diff --git a/stb_image_write.h b/stb_image_write.h index 5a449d9..35dea0c 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -297,7 +297,6 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra /* RLE each component separately */ for (c=0; c < 4; c++) { unsigned char *comp = &scratch[width*c]; - int runstart = 0, head = 0, rlerun = 0; x = 0; while (x < width) { From 8b1d835e16c8600a913ec56864b0e66369db9f37 Mon Sep 17 00:00:00 2001 From: Tim Kelsey Date: Wed, 8 Apr 2015 15:24:46 +0100 Subject: [PATCH 2/3] Adding memory and assert defines to stb_image_write --- stb_image_write.h | 87 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 30 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 5a449d9..5eb6c3f 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -1,4 +1,4 @@ -/* stb_image_write - v0.97 - public domain - http://nothings.org/stb/stb_image_write.h +/* stb_image_write - v0.98 - public domain - http://nothings.org/stb/stb_image_write.h writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010 no warranty implied; use at your own risk @@ -9,6 +9,10 @@ in the file that you want to have the implementation. + You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. + And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free + You can optionally define STBI_MEMMOVE and STBI_MEMCPY if the default semantics of + memmove and memcpy would be incompatible with your choice of malloc et al. Will probably not work correctly with strict-aliasing optimizations. @@ -32,7 +36,7 @@ USAGE: int stbi_write_hdr(char const *filename, int w, int h, int comp, const void *data); Each function returns 0 on failure and non-0 on success. - + The functions create an image file defined by the parameters. The image is a rectangle of pixels stored from left-to-right, top-to-bottom. Each pixel contains 'comp' channels of data stored interleaved with 8-bits @@ -45,7 +49,7 @@ USAGE: PNG creates output files with the same number of components as the input. The BMP format expands Y to RGB in the file format and does not output alpha. - + PNG supports writing rectangles of data even when the bytes storing rows of data are not consecutive in memory (e.g. sub-rectangles of a larger image), by supplying the stride between the beginning of adjacent rows. The other @@ -67,6 +71,8 @@ CREDITS: Jean-Sebastien Guay Bugfixes: Chribba@github + STBI_MALLOC etc: + callidus@github */ #ifndef INCLUDE_STB_IMAGE_WRITE_H @@ -93,9 +99,29 @@ extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const fl #include #include #include -#include #include +#if defined(STBI_MALLOC) && defined(STBI_FREE) && defined(STBI_REALLOC) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,sz) realloc(p,sz) +#define STBI_FREE(p) free(p) +#define STBI_MEMMOVE(a,b,sz) memmove(a,b,sz) +#define STBI_MEMCPY(a,b,sz) memcpy(a,b,sz) +#endif + +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif + typedef unsigned int stbiw_uint32; typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; @@ -113,7 +139,7 @@ static void writefv(FILE *f, const char *fmt, va_list v) b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24); fwrite(b,4,1,f); break; } default: - assert(0); + STBI_ASSERT(0); return; } } @@ -135,7 +161,7 @@ static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, if (y <= 0) return; - if (vdir < 0) + if (vdir < 0) j_end = -1, j = y-1; else j_end = y, j = 0; @@ -232,7 +258,7 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) void stbiw__write_run_data(FILE *f, int length, unsigned char databyte) { unsigned char lengthbyte = (unsigned char) (length+128); - assert(length+128 <= 255); + STBI_ASSERT(length+128 <= 255); fwrite(&lengthbyte, 1, 1, f); fwrite(&databyte, 1, 1, f); } @@ -240,7 +266,7 @@ void stbiw__write_run_data(FILE *f, int length, unsigned char databyte) void stbiw__write_dump_data(FILE *f, int length, unsigned char *data) { unsigned char lengthbyte = (unsigned char )(length & 0xff); - assert(length <= 128); // inconsistent with spec but consistent with official code + STBI_ASSERT(length <= 128); // inconsistent with spec but consistent with official code fwrite(&lengthbyte, 1, 1, f); fwrite(data, length, 1, f); } @@ -321,7 +347,7 @@ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scra if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd // find next byte after run while (r < width && comp[r] == comp[x]) - ++r; + ++r; // output run up to r while (x < r) { int len = r-x; @@ -343,12 +369,12 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da f = fopen(filename, "wb"); if (f) { /* Each component is stored separately. Allocate scratch space for full output scanline. */ - unsigned char *scratch = (unsigned char *) malloc(x*4); + unsigned char *scratch = (unsigned char *) STBI_MALLOC(x*4); fprintf(f, "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n" ); fprintf(f, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n" , y, x); for(i=0; i < y; i++) stbiw__write_hdr_scanline(f, x, comp, scratch, data + comp*i*x); - free(scratch); + STBI_FREE(scratch); fclose(f); } return f != NULL; @@ -368,13 +394,13 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) -#define stbiw__sbfree(a) ((a) ? free(stbiw__sbraw(a)),0 : 0) +#define stbiw__sbfree(a) ((a) ? STBI_FREE(stbiw__sbraw(a)),0 : 0) static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) { int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; - void *p = realloc(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2); - assert(p); + void *p = STBI_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2); + STBI_ASSERT(p); if (p) { if (!*arr) ((int *) p)[1] = 0; *arr = (void *) ((int *) p + 2); @@ -459,7 +485,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l i=0; while (i < data_len-3) { - // hash next 3 bytes of data to be compressed + // hash next 3 bytes of data to be compressed int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; unsigned char *bestloc = 0; unsigned char **hlist = hash_table[h]; @@ -472,7 +498,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l } // when hash table entry is too long, delete half the entries if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { - memcpy(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + STBI_MEMCPY(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); stbiw__sbn(hash_table[h]) = quality; } stbiw__sbpush(hash_table[h],data+i); @@ -495,7 +521,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l if (bestloc) { int d = (int) (data+i - bestloc); // distance back - assert(d <= 32767 && best <= 258); + STBI_ASSERT(d <= 32767 && best <= 258); for (j=0; best > lengthc[j+1]-1; ++j); stbiw__zlib_huff(j+257); if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); @@ -536,7 +562,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l } *out_len = stbiw__sbn(out); // make returned pointer freeable - memmove(stbiw__sbraw(out), out, *out_len); + STBI_MEMMOVE(stbiw__sbraw(out), out, *out_len); return (unsigned char *) stbiw__sbraw(out); } @@ -583,8 +609,8 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in if (stride_bytes == 0) stride_bytes = x * n; - filt = (unsigned char *) malloc((x*n+1) * y); if (!filt) return 0; - line_buffer = (signed char *) malloc(x * n); if (!line_buffer) { free(filt); return 0; } + filt = (unsigned char *) STBI_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBI_MALLOC(x * n); if (!line_buffer) { STBI_FREE(filt); return 0; } for (j=0; j < y; ++j) { static int mapping[] = { 0,1,2,3,4 }; static int firstmap[] = { 0,1,0,5,6 }; @@ -623,20 +649,20 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in } // when we get here, best contains the filter type, and line_buffer contains the data filt[j*(x*n+1)] = (unsigned char) best; - memcpy(filt+j*(x*n+1)+1, line_buffer, x*n); + STBI_MEMCPY(filt+j*(x*n+1)+1, line_buffer, x*n); } - free(line_buffer); + STBI_FREE(line_buffer); zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory - free(filt); + STBI_FREE(filt); if (!zlib) return 0; // each tag requires 12 bytes of overhead - out = (unsigned char *) malloc(8 + 12+13 + 12+zlen + 12); + out = (unsigned char *) STBI_MALLOC(8 + 12+13 + 12+zlen + 12); if (!out) return 0; *out_len = 8 + 12+13 + 12+zlen + 12; o=out; - memcpy(o,sig,8); o+= 8; + STBI_MEMCPY(o,sig,8); o+= 8; stbiw__wp32(o, 13); // header length stbiw__wptag(o, "IHDR"); stbiw__wp32(o, x); @@ -650,14 +676,14 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in stbiw__wp32(o, zlen); stbiw__wptag(o, "IDAT"); - memcpy(o, zlib, zlen); o += zlen; free(zlib); + STBI_MEMCPY(o, zlib, zlen); o += zlen; STBI_FREE(zlib); stbiw__wpcrc(&o, zlen); stbiw__wp32(o,0); stbiw__wptag(o, "IEND"); stbiw__wpcrc(&o,0); - assert(o == out + *out_len); + STBI_ASSERT(o == out + *out_len); return out; } @@ -669,16 +695,17 @@ int stbi_write_png(char const *filename, int x, int y, int comp, const void *dat unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); if (!png) return 0; f = fopen(filename, "wb"); - if (!f) { free(png); return 0; } + if (!f) { STBI_FREE(png); return 0; } fwrite(png, 1, len, f); fclose(f); - free(png); + STBI_FREE(png); return 1; } #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history - + 0.98 (2015-04-08) + added STBI_MALLOC, STBI_ASSERT etc 0.97 (2015-01-18) fixed HDR asserts, rewrote HDR rle logic 0.96 (2015-01-17) From 00b1797a2398c8b7a92b195f30224efbf247bdf8 Mon Sep 17 00:00:00 2001 From: Sean Barrett Date: Mon, 13 Apr 2015 11:55:24 -0700 Subject: [PATCH 3/3] switch memcpy to memmove for simplicity; rename all STBI_ config macros to STBIW_ to avoid conflict with stb_image.h --- stb_image_write.h | 92 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 43 deletions(-) diff --git a/stb_image_write.h b/stb_image_write.h index 0bc5708..1048970 100644 --- a/stb_image_write.h +++ b/stb_image_write.h @@ -9,11 +9,6 @@ in the file that you want to have the implementation. - You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. - And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free - You can optionally define STBI_MEMMOVE and STBI_MEMCPY if the default semantics of - memmove and memcpy would be incompatible with your choice of malloc et al. - Will probably not work correctly with strict-aliasing optimizations. ABOUT: @@ -26,6 +21,13 @@ ABOUT: for source code compactness and simplicitly, not optimal image file size or run-time performance. +BUILDING: + + 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 + malloc,realloc,free. + You can define STBIW_MEMMOVE() to replace memmove() + USAGE: There are four functions, one for each image file format: @@ -69,10 +71,10 @@ CREDITS: Baldur Karlsson TGA monochrome: Jean-Sebastien Guay - Bugfixes: - Chribba@github - STBI_MALLOC etc: - callidus@github + misc enhancements: + Tim Kelsey + bugfixes: + github:Chribba */ #ifndef INCLUDE_STB_IMAGE_WRITE_H @@ -101,25 +103,27 @@ extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const fl #include #include -#if defined(STBI_MALLOC) && defined(STBI_FREE) && defined(STBI_REALLOC) +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && defined(STBIW_REALLOC) // ok -#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) // ok #else -#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC." +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC." #endif -#ifndef STBI_MALLOC -#define STBI_MALLOC(sz) malloc(sz) -#define STBI_REALLOC(p,sz) realloc(p,sz) -#define STBI_FREE(p) free(p) -#define STBI_MEMMOVE(a,b,sz) memmove(a,b,sz) -#define STBI_MEMCPY(a,b,sz) memcpy(a,b,sz) +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,sz) realloc(p,sz) +#define STBIW_FREE(p) free(p) +#endif +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) #endif -#ifndef STBI_ASSERT + +#ifndef STBIW_ASSERT #include -#define STBI_ASSERT(x) assert(x) +#define STBIW_ASSERT(x) assert(x) #endif typedef unsigned int stbiw_uint32; @@ -139,7 +143,7 @@ static void writefv(FILE *f, const char *fmt, va_list v) b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24); fwrite(b,4,1,f); break; } default: - STBI_ASSERT(0); + STBIW_ASSERT(0); return; } } @@ -258,7 +262,7 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) void stbiw__write_run_data(FILE *f, int length, unsigned char databyte) { unsigned char lengthbyte = (unsigned char) (length+128); - STBI_ASSERT(length+128 <= 255); + STBIW_ASSERT(length+128 <= 255); fwrite(&lengthbyte, 1, 1, f); fwrite(&databyte, 1, 1, f); } @@ -266,7 +270,7 @@ void stbiw__write_run_data(FILE *f, int length, unsigned char databyte) void stbiw__write_dump_data(FILE *f, int length, unsigned char *data) { unsigned char lengthbyte = (unsigned char )(length & 0xff); - STBI_ASSERT(length <= 128); // inconsistent with spec but consistent with official code + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code fwrite(&lengthbyte, 1, 1, f); fwrite(data, length, 1, f); } @@ -368,12 +372,12 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da f = fopen(filename, "wb"); if (f) { /* Each component is stored separately. Allocate scratch space for full output scanline. */ - unsigned char *scratch = (unsigned char *) STBI_MALLOC(x*4); + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); fprintf(f, "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n" ); fprintf(f, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n" , y, x); for(i=0; i < y; i++) stbiw__write_hdr_scanline(f, x, comp, scratch, data + comp*i*x); - STBI_FREE(scratch); + STBIW_FREE(scratch); fclose(f); } return f != NULL; @@ -393,13 +397,13 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) -#define stbiw__sbfree(a) ((a) ? STBI_FREE(stbiw__sbraw(a)),0 : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) { int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; - void *p = STBI_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2); - STBI_ASSERT(p); + void *p = STBIW_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); if (p) { if (!*arr) ((int *) p)[1] = 0; *arr = (void *) ((int *) p + 2); @@ -497,7 +501,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l } // when hash table entry is too long, delete half the entries if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { - STBI_MEMCPY(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); stbiw__sbn(hash_table[h]) = quality; } stbiw__sbpush(hash_table[h],data+i); @@ -520,7 +524,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l if (bestloc) { int d = (int) (data+i - bestloc); // distance back - STBI_ASSERT(d <= 32767 && best <= 258); + STBIW_ASSERT(d <= 32767 && best <= 258); for (j=0; best > lengthc[j+1]-1; ++j); stbiw__zlib_huff(j+257); if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); @@ -561,7 +565,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l } *out_len = stbiw__sbn(out); // make returned pointer freeable - STBI_MEMMOVE(stbiw__sbraw(out), out, *out_len); + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); return (unsigned char *) stbiw__sbraw(out); } @@ -608,8 +612,8 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in if (stride_bytes == 0) stride_bytes = x * n; - filt = (unsigned char *) STBI_MALLOC((x*n+1) * y); if (!filt) return 0; - line_buffer = (signed char *) STBI_MALLOC(x * n); if (!line_buffer) { STBI_FREE(filt); return 0; } + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } for (j=0; j < y; ++j) { static int mapping[] = { 0,1,2,3,4 }; static int firstmap[] = { 0,1,0,5,6 }; @@ -648,20 +652,20 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in } // when we get here, best contains the filter type, and line_buffer contains the data filt[j*(x*n+1)] = (unsigned char) best; - STBI_MEMCPY(filt+j*(x*n+1)+1, line_buffer, x*n); + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); } - STBI_FREE(line_buffer); + STBIW_FREE(line_buffer); zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory - STBI_FREE(filt); + STBIW_FREE(filt); if (!zlib) return 0; // each tag requires 12 bytes of overhead - out = (unsigned char *) STBI_MALLOC(8 + 12+13 + 12+zlen + 12); + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); if (!out) return 0; *out_len = 8 + 12+13 + 12+zlen + 12; o=out; - STBI_MEMCPY(o,sig,8); o+= 8; + STBIW_MEMMOVE(o,sig,8); o+= 8; stbiw__wp32(o, 13); // header length stbiw__wptag(o, "IHDR"); stbiw__wp32(o, x); @@ -675,14 +679,16 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in stbiw__wp32(o, zlen); stbiw__wptag(o, "IDAT"); - STBI_MEMCPY(o, zlib, zlen); o += zlen; STBI_FREE(zlib); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); stbiw__wpcrc(&o, zlen); stbiw__wp32(o,0); stbiw__wptag(o, "IEND"); stbiw__wpcrc(&o,0); - STBI_ASSERT(o == out + *out_len); + STBIW_ASSERT(o == out + *out_len); return out; } @@ -694,17 +700,17 @@ int stbi_write_png(char const *filename, int x, int y, int comp, const void *dat unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); if (!png) return 0; f = fopen(filename, "wb"); - if (!f) { STBI_FREE(png); return 0; } + if (!f) { STBIW_FREE(png); return 0; } fwrite(png, 1, len, f); fclose(f); - STBI_FREE(png); + STBIW_FREE(png); return 1; } #endif // STB_IMAGE_WRITE_IMPLEMENTATION /* Revision history 0.98 (2015-04-08) - added STBI_MALLOC, STBI_ASSERT etc + added STBIW_MALLOC, STBIW_ASSERT etc 0.97 (2015-01-18) fixed HDR asserts, rewrote HDR rle logic 0.96 (2015-01-17)