56 #ifndef INCLUDE_STB_IMAGE_WRITE_H
57 #define INCLUDE_STB_IMAGE_WRITE_H
63 extern int stbi_write_png(
char const *filename,
int w,
int h,
int comp,
const void *
data,
int stride_in_bytes);
71 #endif//INCLUDE_STB_IMAGE_WRITE_H
73 #ifdef STB_IMAGE_WRITE_IMPLEMENTATION
81 typedef unsigned int stbiw_uint32;
82 typedef int stb_image_write_test[
sizeof(stbiw_uint32)==4 ? 1 : -1];
84 static void writefv(FILE *
f,
const char *fmt, va_list
v)
89 case '1': {
unsigned char x = (
unsigned char) va_arg(v,
int); fputc(x,f);
break; }
90 case '2': {
int x = va_arg(v,
int);
unsigned char b[2];
91 b[0] = (
unsigned char) x; b[1] = (
unsigned char) (x>>8);
92 fwrite(b,2,1,f);
break; }
93 case '4': { stbiw_uint32 x = va_arg(v,
int);
unsigned char b[4];
94 b[0]=(
unsigned char)x; b[1]=(
unsigned char)(x>>8);
95 b[2]=(
unsigned char)(x>>16); b[3]=(
unsigned char)(x>>24);
96 fwrite(b,4,1,f);
break; }
104 static void write3(FILE *f,
unsigned char a,
unsigned char b,
unsigned char c)
106 unsigned char arr[3];
107 arr[0] =
a, arr[1] =
b, arr[2] =
c;
108 fwrite(arr, 3, 1, f);
111 static void write_pixels(FILE *f,
int rgb_dir,
int vdir,
int x,
int y,
int comp,
void *
data,
int write_alpha,
int scanline_pad)
113 unsigned char bg[3] = { 255, 0, 255}, px[3];
114 stbiw_uint32 zero = 0;
125 for (; j != j_end; j += vdir) {
126 for (i=0; i <
x; ++
i) {
127 unsigned char *
d = (
unsigned char *) data + (j*x+i)*comp;
129 fwrite(&d[comp-1], 1, 1, f);
132 case 2: write3(f, d[0],d[0],d[0]);
137 for (k=0; k < 3; ++k)
138 px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255;
139 write3(f, px[1-rgb_dir],px[1],px[1+rgb_dir]);
144 write3(f, d[1-rgb_dir],d[1],d[1+rgb_dir]);
148 fwrite(&d[comp-1], 1, 1, f);
150 fwrite(&zero,scanline_pad,1,f);
154 static int outfile(
char const *filename,
int rgb_dir,
int vdir,
int x,
int y,
int comp,
void *data,
int alpha,
int pad,
const char *fmt, ...)
157 if (y < 0 || x < 0)
return 0;
158 f = fopen(filename,
"wb");
164 write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad);
170 int stbi_write_bmp(
char const *filename,
int x,
int y,
int comp,
const void *data)
172 int pad = (-x*3) & 3;
173 return outfile(filename,-1,-1,x,y,comp,(
void *) data,0,pad,
174 "11 4 22 4" "4 44 22 444444",
175 'B',
'M', 14+40+(x*3+pad)*y, 0,0, 14+40,
176 40, x,y, 1,24, 0,0,0,0,0,0);
179 int stbi_write_tga(
char const *filename,
int x,
int y,
int comp,
const void *data)
181 int has_alpha = !(comp & 1);
182 return outfile(filename, -1,-1, x, y, comp, (
void *) data, has_alpha, 0,
183 "111 221 2222 11", 0,0,2, 0,0,0, 0,0,x,y, 24+8*has_alpha, 8*has_alpha);
187 #define stbiw__sbraw(a) ((int *) (a) - 2)
188 #define stbiw__sbm(a) stbiw__sbraw(a)[0]
189 #define stbiw__sbn(a) stbiw__sbraw(a)[1]
191 #define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
192 #define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
193 #define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
195 #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
196 #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
197 #define stbiw__sbfree(a) ((a) ? free(stbiw__sbraw(a)),0 : 0)
199 static void *stbiw__sbgrowf(
void **arr,
int increment,
int itemsize)
201 int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
202 void *
p = realloc(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m +
sizeof(
int)*2);
205 if (!*arr) ((
int *) p)[1] = 0;
206 *arr = (
void *) ((
int *) p + 2);
207 stbiw__sbm(*arr) =
m;
212 static unsigned char *stbiw__zlib_flushf(
unsigned char *data,
unsigned int *bitbuffer,
int *bitcount)
214 while (*bitcount >= 8) {
215 stbiw__sbpush(data, (
unsigned char) *bitbuffer);
222 static int stbiw__zlib_bitrev(
int code,
int codebits)
226 res = (res << 1) | (code & 1);
232 static unsigned int stbiw__zlib_countm(
unsigned char *
a,
unsigned char *b,
int limit)
235 for (i=0; i < limit && i < 258; ++
i)
236 if (a[i] != b[i])
break;
240 static unsigned int stbiw__zhash(
unsigned char *data)
242 stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
252 #define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
253 #define stbiw__zlib_add(code,codebits) \
254 (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
255 #define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
257 #define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8)
258 #define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9)
259 #define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7)
260 #define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8)
261 #define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n))
262 #define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
264 #define stbiw__ZHASH 16384
266 unsigned char * stbi_zlib_compress(
unsigned char *data,
int data_len,
int *out_len,
int quality)
268 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 };
269 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 };
270 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 };
271 static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 };
272 unsigned int bitbuf=0;
274 unsigned char *out = NULL;
275 unsigned char **hash_table[stbiw__ZHASH];
276 if (quality < 5) quality = 5;
278 stbiw__sbpush(out, 0x78);
279 stbiw__sbpush(out, 0x5e);
280 stbiw__zlib_add(1,1);
281 stbiw__zlib_add(1,2);
283 for (i=0; i < stbiw__ZHASH; ++
i)
284 hash_table[i] = NULL;
287 while (i < data_len-3) {
289 int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
290 unsigned char *bestloc = 0;
291 unsigned char **hlist = hash_table[
h];
292 int n = stbiw__sbcount(hlist);
293 for (j=0; j <
n; ++j) {
294 if (hlist[j]-data > i-32768) {
295 int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
296 if (d >= best) best=
d,bestloc=hlist[j];
300 if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
301 memcpy(hash_table[h], hash_table[h]+quality,
sizeof(hash_table[h][0])*quality);
302 stbiw__sbn(hash_table[h]) = quality;
304 stbiw__sbpush(hash_table[h],data+i);
308 h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
309 hlist = hash_table[
h];
310 n = stbiw__sbcount(hlist);
311 for (j=0; j <
n; ++j) {
312 if (hlist[j]-data > i-32767) {
313 int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
323 int d = (
int) (data+i - bestloc);
324 assert(d <= 32767 && best <= 258);
325 for (j=0; best > lengthc[j+1]-1; ++j);
326 stbiw__zlib_huff(j+257);
327 if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
328 for (j=0; d > distc[j+1]-1; ++j);
329 stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
330 if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
333 stbiw__zlib_huffb(data[i]);
338 for (;i < data_len; ++
i)
339 stbiw__zlib_huffb(data[i]);
340 stbiw__zlib_huff(256);
343 stbiw__zlib_add(0,1);
345 for (i=0; i < stbiw__ZHASH; ++
i)
346 (
void) stbiw__sbfree(hash_table[i]);
350 unsigned int i=0, s1=1, s2=0, blocklen = data_len % 5552;
352 while (j < data_len) {
353 for (i=0; i < blocklen; ++
i) s1 += data[j+i], s2 += s1;
354 s1 %= 65521, s2 %= 65521;
358 stbiw__sbpush(out, (
unsigned char) (s2 >> 8));
359 stbiw__sbpush(out, (
unsigned char) s2);
360 stbiw__sbpush(out, (
unsigned char) (s1 >> 8));
361 stbiw__sbpush(out, (
unsigned char) s1);
363 *out_len = stbiw__sbn(out);
365 memmove(stbiw__sbraw(out), out, *out_len);
366 return (
unsigned char *) stbiw__sbraw(out);
369 unsigned int stbiw__crc32(
unsigned char *
buffer,
int len)
371 static unsigned int crc_table[256];
372 unsigned int crc = ~0u;
374 if (crc_table[1] == 0)
375 for(i=0; i < 256; i++)
376 for (crc_table[i]=i, j=0; j < 8; ++j)
377 crc_table[i] = (crc_table[i] >> 1) ^ (crc_table[
i] & 1 ? 0xedb88320 : 0);
378 for (i=0; i <
len; ++
i)
379 crc = (crc >> 8) ^ crc_table[buffer[
i] ^ (crc & 0xff)];
383 #define stbiw__wpng4(o,a,b,c,d) ((o)[0]=(unsigned char)(a),(o)[1]=(unsigned char)(b),(o)[2]=(unsigned char)(c),(o)[3]=(unsigned char)(d),(o)+=4)
384 #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
385 #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
387 static void stbiw__wpcrc(
unsigned char **data,
int len)
389 unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
390 stbiw__wp32(*data, crc);
393 static unsigned char stbiw__paeth(
int a,
int b,
int c)
395 int p = a + b -
c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
396 if (pa <= pb && pa <= pc)
return (
unsigned char)
a;
397 if (pb <= pc)
return (
unsigned char)
b;
398 return (
unsigned char)
c;
401 unsigned char *stbi_write_png_to_mem(
unsigned char *
pixels,
int stride_bytes,
int x,
int y,
int n,
int *out_len)
403 int ctype[5] = { -1, 0, 4, 2, 6 };
404 unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
405 unsigned char *out,*o, *filt, *zlib;
406 signed char *line_buffer;
409 if (stride_bytes == 0)
410 stride_bytes = x *
n;
412 filt = (
unsigned char *) malloc((x*n+1) *
y);
if (!filt)
return 0;
413 line_buffer = (
signed char *) malloc(x * n);
if (!line_buffer) { free(filt);
return 0; }
414 for (j=0; j <
y; ++j) {
415 static int mapping[] = { 0,1,2,3,4 };
416 static int firstmap[] = { 0,1,0,5,6 };
417 int *mymap = j ? mapping : firstmap;
418 int best = 0, bestval = 0x7fffffff;
419 for (p=0; p < 2; ++
p) {
420 for (k= p?best:0; k < 5; ++k) {
421 int type = mymap[k],est=0;
422 unsigned char *
z = pixels + stride_bytes*j;
423 for (i=0; i <
n; ++
i)
425 case 0: line_buffer[
i] = z[
i];
break;
426 case 1: line_buffer[
i] = z[
i];
break;
427 case 2: line_buffer[
i] = z[
i] - z[i-stride_bytes];
break;
428 case 3: line_buffer[
i] = z[
i] - (z[i-stride_bytes]>>1);
break;
429 case 4: line_buffer[
i] = (
signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0));
break;
430 case 5: line_buffer[
i] = z[
i];
break;
431 case 6: line_buffer[
i] = z[
i];
break;
433 for (i=n; i < x*
n; ++
i) {
435 case 0: line_buffer[
i] = z[
i];
break;
436 case 1: line_buffer[
i] = z[
i] - z[i-
n];
break;
437 case 2: line_buffer[
i] = z[
i] - z[i-stride_bytes];
break;
438 case 3: line_buffer[
i] = z[
i] - ((z[i-
n] + z[i-stride_bytes])>>1);
break;
439 case 4: line_buffer[
i] = z[
i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]);
break;
440 case 5: line_buffer[
i] = z[
i] - (z[i-
n]>>1);
break;
441 case 6: line_buffer[
i] = z[
i] - stbiw__paeth(z[i-n], 0,0);
break;
445 for (i=0; i < x*
n; ++
i)
446 est += abs((
signed char) line_buffer[i]);
447 if (est < bestval) { bestval = est; best = k; }
451 filt[j*(x*n+1)] = (
unsigned char) best;
452 memcpy(filt+j*(x*n+1)+1, line_buffer, x*n);
455 zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8);
460 out = (
unsigned char *) malloc(8 + 12+13 + 12+zlen + 12);
462 *out_len = 8 + 12+13 + 12+zlen + 12;
465 memcpy(o,sig,8); o+= 8;
467 stbiw__wptag(o,
"IHDR");
471 *o++ = (
unsigned char) ctype[n];
477 stbiw__wp32(o, zlen);
478 stbiw__wptag(o,
"IDAT");
479 memcpy(o, zlib, zlen); o += zlen; free(zlib);
480 stbiw__wpcrc(&o, zlen);
483 stbiw__wptag(o,
"IEND");
486 assert(o == out + *out_len);
491 int stbi_write_png(
char const *filename,
int x,
int y,
int comp,
const void *data,
int stride_bytes)
495 unsigned char *png = stbi_write_png_to_mem((
unsigned char *) data, stride_bytes, x, y, comp, &len);
497 f = fopen(filename,
"wb");
498 if (!f) { free(png);
return 0; }
499 fwrite(png, 1, len, f);
504 #endif // STB_IMAGE_WRITE_IMPLEMENTATION
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
GLuint GLuint GLsizei GLenum type
int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data)
GLint GLint GLint GLint GLint GLint y
GLint GLenum GLsizei GLint GLsizei const GLvoid * data
GLdouble GLdouble GLdouble b
int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes)
GLubyte GLubyte GLubyte GLubyte w
GLboolean GLboolean GLboolean GLboolean a
GLclampf GLclampf GLclampf alpha
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
GLenum GLenum GLenum GLenum mapping
GLfloat GLfloat GLfloat GLfloat h
GLint GLint GLint GLint GLint x
int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data)