提交 00b1797a 编写于 作者: S Sean Barrett

switch memcpy to memmove for simplicity;

rename all STBI_ config macros to STBIW_ to avoid conflict with stb_image.h
上级 019236a6
...@@ -9,11 +9,6 @@ ...@@ -9,11 +9,6 @@
in the file that you want to have the implementation. 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. Will probably not work correctly with strict-aliasing optimizations.
ABOUT: ABOUT:
...@@ -26,6 +21,13 @@ ABOUT: ...@@ -26,6 +21,13 @@ ABOUT:
for source code compactness and simplicitly, not optimal image file size for source code compactness and simplicitly, not optimal image file size
or run-time performance. 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: USAGE:
There are four functions, one for each image file format: There are four functions, one for each image file format:
...@@ -69,10 +71,10 @@ CREDITS: ...@@ -69,10 +71,10 @@ CREDITS:
Baldur Karlsson Baldur Karlsson
TGA monochrome: TGA monochrome:
Jean-Sebastien Guay Jean-Sebastien Guay
Bugfixes: misc enhancements:
Chribba@github Tim Kelsey
STBI_MALLOC etc: bugfixes:
callidus@github github:Chribba
*/ */
#ifndef INCLUDE_STB_IMAGE_WRITE_H #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 ...@@ -101,25 +103,27 @@ extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const fl
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#if defined(STBI_MALLOC) && defined(STBI_FREE) && defined(STBI_REALLOC) #if defined(STBIW_MALLOC) && defined(STBIW_FREE) && defined(STBIW_REALLOC)
// ok // ok
#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) #elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC)
// ok // ok
#else #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 #endif
#ifndef STBI_MALLOC #ifndef STBIW_MALLOC
#define STBI_MALLOC(sz) malloc(sz) #define STBIW_MALLOC(sz) malloc(sz)
#define STBI_REALLOC(p,sz) realloc(p,sz) #define STBIW_REALLOC(p,sz) realloc(p,sz)
#define STBI_FREE(p) free(p) #define STBIW_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 #endif
#ifndef STBIW_MEMMOVE
#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
#endif
#ifndef STBI_ASSERT #ifndef STBIW_ASSERT
#include <assert.h> #include <assert.h>
#define STBI_ASSERT(x) assert(x) #define STBIW_ASSERT(x) assert(x)
#endif #endif
typedef unsigned int stbiw_uint32; typedef unsigned int stbiw_uint32;
...@@ -139,7 +143,7 @@ static void writefv(FILE *f, const char *fmt, va_list v) ...@@ -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); b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24);
fwrite(b,4,1,f); break; } fwrite(b,4,1,f); break; }
default: default:
STBI_ASSERT(0); STBIW_ASSERT(0);
return; return;
} }
} }
...@@ -258,7 +262,7 @@ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) ...@@ -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) void stbiw__write_run_data(FILE *f, int length, unsigned char databyte)
{ {
unsigned char lengthbyte = (unsigned char) (length+128); unsigned char lengthbyte = (unsigned char) (length+128);
STBI_ASSERT(length+128 <= 255); STBIW_ASSERT(length+128 <= 255);
fwrite(&lengthbyte, 1, 1, f); fwrite(&lengthbyte, 1, 1, f);
fwrite(&databyte, 1, 1, f); fwrite(&databyte, 1, 1, f);
} }
...@@ -266,7 +270,7 @@ void stbiw__write_run_data(FILE *f, int length, unsigned char databyte) ...@@ -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) void stbiw__write_dump_data(FILE *f, int length, unsigned char *data)
{ {
unsigned char lengthbyte = (unsigned char )(length & 0xff); 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(&lengthbyte, 1, 1, f);
fwrite(data, length, 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 ...@@ -368,12 +372,12 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da
f = fopen(filename, "wb"); f = fopen(filename, "wb");
if (f) { if (f) {
/* Each component is stored separately. Allocate scratch space for full output scanline. */ /* 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, "#?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); fprintf(f, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n" , y, x);
for(i=0; i < y; i++) for(i=0; i < y; i++)
stbiw__write_hdr_scanline(f, x, comp, scratch, data + comp*i*x); stbiw__write_hdr_scanline(f, x, comp, scratch, data + comp*i*x);
STBI_FREE(scratch); STBIW_FREE(scratch);
fclose(f); fclose(f);
} }
return f != NULL; return f != NULL;
...@@ -393,13 +397,13 @@ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *da ...@@ -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__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) #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) static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
{ {
int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
void *p = STBI_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2); void *p = STBIW_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2);
STBI_ASSERT(p); STBIW_ASSERT(p);
if (p) { if (p) {
if (!*arr) ((int *) p)[1] = 0; if (!*arr) ((int *) p)[1] = 0;
*arr = (void *) ((int *) p + 2); *arr = (void *) ((int *) p + 2);
...@@ -497,7 +501,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l ...@@ -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 // when hash table entry is too long, delete half the entries
if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { 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__sbn(hash_table[h]) = quality;
} }
stbiw__sbpush(hash_table[h],data+i); 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 ...@@ -520,7 +524,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
if (bestloc) { if (bestloc) {
int d = (int) (data+i - bestloc); // distance back 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); for (j=0; best > lengthc[j+1]-1; ++j);
stbiw__zlib_huff(j+257); stbiw__zlib_huff(j+257);
if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); 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 ...@@ -561,7 +565,7 @@ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_l
} }
*out_len = stbiw__sbn(out); *out_len = stbiw__sbn(out);
// make returned pointer freeable // 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); return (unsigned char *) stbiw__sbraw(out);
} }
...@@ -608,8 +612,8 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in ...@@ -608,8 +612,8 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in
if (stride_bytes == 0) if (stride_bytes == 0)
stride_bytes = x * n; stride_bytes = x * n;
filt = (unsigned char *) STBI_MALLOC((x*n+1) * y); if (!filt) return 0; filt = (unsigned char *) STBIW_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; } line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
for (j=0; j < y; ++j) { for (j=0; j < y; ++j) {
static int mapping[] = { 0,1,2,3,4 }; static int mapping[] = { 0,1,2,3,4 };
static int firstmap[] = { 0,1,0,5,6 }; 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 ...@@ -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 // when we get here, best contains the filter type, and line_buffer contains the data
filt[j*(x*n+1)] = (unsigned char) best; 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 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; if (!zlib) return 0;
// each tag requires 12 bytes of overhead // 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; if (!out) return 0;
*out_len = 8 + 12+13 + 12+zlen + 12; *out_len = 8 + 12+13 + 12+zlen + 12;
o=out; o=out;
STBI_MEMCPY(o,sig,8); o+= 8; STBIW_MEMMOVE(o,sig,8); o+= 8;
stbiw__wp32(o, 13); // header length stbiw__wp32(o, 13); // header length
stbiw__wptag(o, "IHDR"); stbiw__wptag(o, "IHDR");
stbiw__wp32(o, x); stbiw__wp32(o, x);
...@@ -675,14 +679,16 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in ...@@ -675,14 +679,16 @@ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, in
stbiw__wp32(o, zlen); stbiw__wp32(o, zlen);
stbiw__wptag(o, "IDAT"); 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__wpcrc(&o, zlen);
stbiw__wp32(o,0); stbiw__wp32(o,0);
stbiw__wptag(o, "IEND"); stbiw__wptag(o, "IEND");
stbiw__wpcrc(&o,0); stbiw__wpcrc(&o,0);
STBI_ASSERT(o == out + *out_len); STBIW_ASSERT(o == out + *out_len);
return out; return out;
} }
...@@ -694,17 +700,17 @@ int stbi_write_png(char const *filename, int x, int y, int comp, const void *dat ...@@ -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); unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
if (!png) return 0; if (!png) return 0;
f = fopen(filename, "wb"); f = fopen(filename, "wb");
if (!f) { STBI_FREE(png); return 0; } if (!f) { STBIW_FREE(png); return 0; }
fwrite(png, 1, len, f); fwrite(png, 1, len, f);
fclose(f); fclose(f);
STBI_FREE(png); STBIW_FREE(png);
return 1; return 1;
} }
#endif // STB_IMAGE_WRITE_IMPLEMENTATION #endif // STB_IMAGE_WRITE_IMPLEMENTATION
/* Revision history /* Revision history
0.98 (2015-04-08) 0.98 (2015-04-08)
added STBI_MALLOC, STBI_ASSERT etc added STBIW_MALLOC, STBIW_ASSERT etc
0.97 (2015-01-18) 0.97 (2015-01-18)
fixed HDR asserts, rewrote HDR rle logic fixed HDR asserts, rewrote HDR rle logic
0.96 (2015-01-17) 0.96 (2015-01-17)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册