00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 #ifndef INCLUDE_STB_IMAGE_WRITE_H
00081 #define INCLUDE_STB_IMAGE_WRITE_H
00082
00083 #ifdef __cplusplus
00084 extern "C" {
00085 #endif
00086
00087 extern int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
00088 extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
00089 extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
00090 extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
00091
00092 #ifdef __cplusplus
00093 }
00094 #endif
00095
00096 #endif//INCLUDE_STB_IMAGE_WRITE_H
00097
00098 #ifdef STB_IMAGE_WRITE_IMPLEMENTATION
00099
00100 #include <stdarg.h>
00101 #include <stdlib.h>
00102 #include <stdio.h>
00103 #include <string.h>
00104 #include <math.h>
00105
00106 #if defined(STBIW_MALLOC) && defined(STBIW_FREE) && defined(STBIW_REALLOC)
00107
00108 #elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC)
00109
00110 #else
00111 #error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC."
00112 #endif
00113
00114 #ifndef STBIW_MALLOC
00115 #define STBIW_MALLOC(sz) malloc(sz)
00116 #define STBIW_REALLOC(p,sz) realloc(p,sz)
00117 #define STBIW_FREE(p) free(p)
00118 #endif
00119 #ifndef STBIW_MEMMOVE
00120 #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
00121 #endif
00122
00123
00124 #ifndef STBIW_ASSERT
00125 #include <assert.h>
00126 #define STBIW_ASSERT(x) assert(x)
00127 #endif
00128
00129 typedef unsigned int stbiw_uint32;
00130 typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
00131
00132 static void writefv(FILE *f, const char *fmt, va_list v)
00133 {
00134 while (*fmt) {
00135 switch (*fmt++) {
00136 case ' ': break;
00137 case '1': { unsigned char x = (unsigned char) va_arg(v, int); fputc(x,f); break; }
00138 case '2': { int x = va_arg(v,int); unsigned char b[2];
00139 b[0] = (unsigned char) x; b[1] = (unsigned char) (x>>8);
00140 fwrite(b,2,1,f); break; }
00141 case '4': { stbiw_uint32 x = va_arg(v,int); unsigned char b[4];
00142 b[0]=(unsigned char)x; b[1]=(unsigned char)(x>>8);
00143 b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24);
00144 fwrite(b,4,1,f); break; }
00145 default:
00146 STBIW_ASSERT(0);
00147 return;
00148 }
00149 }
00150 }
00151
00152 static void write3(FILE *f, unsigned char a, unsigned char b, unsigned char c)
00153 {
00154 unsigned char arr[3];
00155 arr[0] = a, arr[1] = b, arr[2] = c;
00156 fwrite(arr, 3, 1, f);
00157 }
00158
00159 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, int expand_mono)
00160 {
00161 unsigned char bg[3] = { 255, 0, 255}, px[3];
00162 stbiw_uint32 zero = 0;
00163 int i,j,k, j_end;
00164
00165 if (y <= 0)
00166 return;
00167
00168 if (vdir < 0)
00169 j_end = -1, j = y-1;
00170 else
00171 j_end = y, j = 0;
00172
00173 for (; j != j_end; j += vdir) {
00174 for (i=0; i < x; ++i) {
00175 unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
00176 if (write_alpha < 0)
00177 fwrite(&d[comp-1], 1, 1, f);
00178 switch (comp) {
00179 case 1: fwrite(d, 1, 1, f);
00180 break;
00181 case 2: if (expand_mono)
00182 write3(f, d[0],d[0],d[0]);
00183 else
00184 fwrite(d, 1, 1, f);
00185 break;
00186 case 4:
00187 if (!write_alpha) {
00188
00189 for (k=0; k < 3; ++k)
00190 px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255;
00191 write3(f, px[1-rgb_dir],px[1],px[1+rgb_dir]);
00192 break;
00193 }
00194
00195 case 3:
00196 write3(f, d[1-rgb_dir],d[1],d[1+rgb_dir]);
00197 break;
00198 }
00199 if (write_alpha > 0)
00200 fwrite(&d[comp-1], 1, 1, f);
00201 }
00202 fwrite(&zero,scanline_pad,1,f);
00203 }
00204 }
00205
00206 static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...)
00207 {
00208 FILE *f;
00209 if (y < 0 || x < 0) return 0;
00210 f = fopen(filename, "wb");
00211 if (f) {
00212 va_list v;
00213 va_start(v, fmt);
00214 writefv(f, fmt, v);
00215 va_end(v);
00216 write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad,expand_mono);
00217 fclose(f);
00218 }
00219 return f != NULL;
00220 }
00221
00222 int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
00223 {
00224 int pad = (-x*3) & 3;
00225 return outfile(filename,-1,-1,x,y,comp,1,(void *) data,0,pad,
00226 "11 4 22 4" "4 44 22 444444",
00227 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40,
00228 40, x,y, 1,24, 0,0,0,0,0,0);
00229 }
00230
00231 int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
00232 {
00233 int has_alpha = (comp == 2 || comp == 4);
00234 int colorbytes = has_alpha ? comp-1 : comp;
00235 int format = colorbytes < 2 ? 3 : 2;
00236 return outfile(filename, -1,-1, x, y, comp, 0, (void *) data, has_alpha, 0,
00237 "111 221 2222 11", 0,0,format, 0,0,0, 0,0,x,y, (colorbytes+has_alpha)*8, has_alpha*8);
00238 }
00239
00240
00241
00242
00243 #define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
00244
00245 void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
00246 {
00247 int exponent;
00248 float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
00249
00250 if (maxcomp < 1e-32) {
00251 rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
00252 } else {
00253 float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
00254
00255 rgbe[0] = (unsigned char)(linear[0] * normalize);
00256 rgbe[1] = (unsigned char)(linear[1] * normalize);
00257 rgbe[2] = (unsigned char)(linear[2] * normalize);
00258 rgbe[3] = (unsigned char)(exponent + 128);
00259 }
00260 }
00261
00262 void stbiw__write_run_data(FILE *f, int length, unsigned char databyte)
00263 {
00264 unsigned char lengthbyte = (unsigned char) (length+128);
00265 STBIW_ASSERT(length+128 <= 255);
00266 fwrite(&lengthbyte, 1, 1, f);
00267 fwrite(&databyte, 1, 1, f);
00268 }
00269
00270 void stbiw__write_dump_data(FILE *f, int length, unsigned char *data)
00271 {
00272 unsigned char lengthbyte = (unsigned char )(length & 0xff);
00273 STBIW_ASSERT(length <= 128);
00274 fwrite(&lengthbyte, 1, 1, f);
00275 fwrite(data, length, 1, f);
00276 }
00277
00278 void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scratch, const float *scanline)
00279 {
00280 unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
00281 unsigned char rgbe[4];
00282 float linear[3] = {0};
00283 int x;
00284
00285 scanlineheader[2] = (width&0xff00)>>8;
00286 scanlineheader[3] = (width&0x00ff);
00287
00288
00289 if (width < 8 || width >= 32768) {
00290 for (x=0; x < width; x++) {
00291 switch (comp) {
00292 case 4:
00293 case 3: linear[2] = scanline[x*comp + 2];
00294 linear[1] = scanline[x*comp + 1];
00295 linear[0] = scanline[x*comp + 0];
00296 break;
00297 case 2:
00298 case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0];
00299 break;
00300 }
00301 stbiw__linear_to_rgbe(rgbe, linear);
00302 fwrite(rgbe, 4, 1, f);
00303 }
00304 } else {
00305 int c,r;
00306
00307 for (x=0; x < width; x++) {
00308 switch(comp) {
00309 case 4:
00310 case 3: linear[2] = scanline[x*comp + 2];
00311 linear[1] = scanline[x*comp + 1];
00312 linear[0] = scanline[x*comp + 0];
00313 break;
00314 case 2:
00315 case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0];
00316 break;
00317 }
00318 stbiw__linear_to_rgbe(rgbe, linear);
00319 scratch[x + width*0] = rgbe[0];
00320 scratch[x + width*1] = rgbe[1];
00321 scratch[x + width*2] = rgbe[2];
00322 scratch[x + width*3] = rgbe[3];
00323 }
00324
00325 fwrite(scanlineheader, 4, 1, f);
00326
00327
00328 for (c=0; c < 4; c++) {
00329 unsigned char *comp = &scratch[width*c];
00330
00331 x = 0;
00332 while (x < width) {
00333
00334 r = x;
00335 while (r+2 < width) {
00336 if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
00337 break;
00338 ++r;
00339 }
00340 if (r+2 >= width)
00341 r = width;
00342
00343 while (x < r) {
00344 int len = r-x;
00345 if (len > 128) len = 128;
00346 stbiw__write_dump_data(f, len, &comp[x]);
00347 x += len;
00348 }
00349
00350 if (r+2 < width) {
00351
00352 while (r < width && comp[r] == comp[x])
00353 ++r;
00354
00355 while (x < r) {
00356 int len = r-x;
00357 if (len > 127) len = 127;
00358 stbiw__write_run_data(f, len, comp[x]);
00359 x += len;
00360 }
00361 }
00362 }
00363 }
00364 }
00365 }
00366
00367 int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
00368 {
00369 int i;
00370 FILE *f;
00371 if (y <= 0 || x <= 0 || data == NULL) return 0;
00372 f = fopen(filename, "wb");
00373 if (f) {
00374
00375 unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
00376 fprintf(f, "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n" );
00377 fprintf(f, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n" , y, x);
00378 for(i=0; i < y; i++)
00379 stbiw__write_hdr_scanline(f, x, comp, scratch, data + comp*i*x);
00380 STBIW_FREE(scratch);
00381 fclose(f);
00382 }
00383 return f != NULL;
00384 }
00385
00387
00388
00389
00390 #define stbiw__sbraw(a) ((int *) (a) - 2)
00391 #define stbiw__sbm(a) stbiw__sbraw(a)[0]
00392 #define stbiw__sbn(a) stbiw__sbraw(a)[1]
00393
00394 #define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
00395 #define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
00396 #define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
00397
00398 #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
00399 #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
00400 #define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
00401
00402 static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
00403 {
00404 int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
00405 void *p = STBIW_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2);
00406 STBIW_ASSERT(p);
00407 if (p) {
00408 if (!*arr) ((int *) p)[1] = 0;
00409 *arr = (void *) ((int *) p + 2);
00410 stbiw__sbm(*arr) = m;
00411 }
00412 return *arr;
00413 }
00414
00415 static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
00416 {
00417 while (*bitcount >= 8) {
00418 stbiw__sbpush(data, (unsigned char) *bitbuffer);
00419 *bitbuffer >>= 8;
00420 *bitcount -= 8;
00421 }
00422 return data;
00423 }
00424
00425 static int stbiw__zlib_bitrev(int code, int codebits)
00426 {
00427 int res=0;
00428 while (codebits--) {
00429 res = (res << 1) | (code & 1);
00430 code >>= 1;
00431 }
00432 return res;
00433 }
00434
00435 static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit)
00436 {
00437 int i;
00438 for (i=0; i < limit && i < 258; ++i)
00439 if (a[i] != b[i]) break;
00440 return i;
00441 }
00442
00443 static unsigned int stbiw__zhash(unsigned char *data)
00444 {
00445 stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
00446 hash ^= hash << 3;
00447 hash += hash >> 5;
00448 hash ^= hash << 4;
00449 hash += hash >> 17;
00450 hash ^= hash << 25;
00451 hash += hash >> 6;
00452 return hash;
00453 }
00454
00455 #define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
00456 #define stbiw__zlib_add(code,codebits) \
00457 (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
00458 #define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
00459
00460 #define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8)
00461 #define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9)
00462 #define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7)
00463 #define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8)
00464 #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))
00465 #define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
00466
00467 #define stbiw__ZHASH 16384
00468
00469 unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
00470 {
00471 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 };
00472 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 };
00473 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 };
00474 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 };
00475 unsigned int bitbuf=0;
00476 int i,j, bitcount=0;
00477 unsigned char *out = NULL;
00478 unsigned char **hash_table[stbiw__ZHASH];
00479 if (quality < 5) quality = 5;
00480
00481 stbiw__sbpush(out, 0x78);
00482 stbiw__sbpush(out, 0x5e);
00483 stbiw__zlib_add(1,1);
00484 stbiw__zlib_add(1,2);
00485
00486 for (i=0; i < stbiw__ZHASH; ++i)
00487 hash_table[i] = NULL;
00488
00489 i=0;
00490 while (i < data_len-3) {
00491
00492 int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
00493 unsigned char *bestloc = 0;
00494 unsigned char **hlist = hash_table[h];
00495 int n = stbiw__sbcount(hlist);
00496 for (j=0; j < n; ++j) {
00497 if (hlist[j]-data > i-32768) {
00498 int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
00499 if (d >= best) best=d,bestloc=hlist[j];
00500 }
00501 }
00502
00503 if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
00504 STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
00505 stbiw__sbn(hash_table[h]) = quality;
00506 }
00507 stbiw__sbpush(hash_table[h],data+i);
00508
00509 if (bestloc) {
00510
00511 h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
00512 hlist = hash_table[h];
00513 n = stbiw__sbcount(hlist);
00514 for (j=0; j < n; ++j) {
00515 if (hlist[j]-data > i-32767) {
00516 int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
00517 if (e > best) {
00518 bestloc = NULL;
00519 break;
00520 }
00521 }
00522 }
00523 }
00524
00525 if (bestloc) {
00526 int d = (int) (data+i - bestloc);
00527 STBIW_ASSERT(d <= 32767 && best <= 258);
00528 for (j=0; best > lengthc[j+1]-1; ++j);
00529 stbiw__zlib_huff(j+257);
00530 if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
00531 for (j=0; d > distc[j+1]-1; ++j);
00532 stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
00533 if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
00534 i += best;
00535 } else {
00536 stbiw__zlib_huffb(data[i]);
00537 ++i;
00538 }
00539 }
00540
00541 for (;i < data_len; ++i)
00542 stbiw__zlib_huffb(data[i]);
00543 stbiw__zlib_huff(256);
00544
00545 while (bitcount)
00546 stbiw__zlib_add(0,1);
00547
00548 for (i=0; i < stbiw__ZHASH; ++i)
00549 (void) stbiw__sbfree(hash_table[i]);
00550
00551 {
00552
00553 unsigned int i=0, s1=1, s2=0, blocklen = data_len % 5552;
00554 int j=0;
00555 while (j < data_len) {
00556 for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
00557 s1 %= 65521, s2 %= 65521;
00558 j += blocklen;
00559 blocklen = 5552;
00560 }
00561 stbiw__sbpush(out, (unsigned char) (s2 >> 8));
00562 stbiw__sbpush(out, (unsigned char) s2);
00563 stbiw__sbpush(out, (unsigned char) (s1 >> 8));
00564 stbiw__sbpush(out, (unsigned char) s1);
00565 }
00566 *out_len = stbiw__sbn(out);
00567
00568 STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
00569 return (unsigned char *) stbiw__sbraw(out);
00570 }
00571
00572 unsigned int stbiw__crc32(unsigned char *buffer, int len)
00573 {
00574 static unsigned int crc_table[256];
00575 unsigned int crc = ~0u;
00576 int i,j;
00577 if (crc_table[1] == 0)
00578 for(i=0; i < 256; i++)
00579 for (crc_table[i]=i, j=0; j < 8; ++j)
00580 crc_table[i] = (crc_table[i] >> 1) ^ (crc_table[i] & 1 ? 0xedb88320 : 0);
00581 for (i=0; i < len; ++i)
00582 crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
00583 return ~crc;
00584 }
00585
00586 #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)
00587 #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
00588 #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
00589
00590 static void stbiw__wpcrc(unsigned char **data, int len)
00591 {
00592 unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
00593 stbiw__wp32(*data, crc);
00594 }
00595
00596 static unsigned char stbiw__paeth(int a, int b, int c)
00597 {
00598 int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
00599 if (pa <= pb && pa <= pc) return (unsigned char) a;
00600 if (pb <= pc) return (unsigned char) b;
00601 return (unsigned char) c;
00602 }
00603
00604 unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
00605 {
00606 int ctype[5] = { -1, 0, 4, 2, 6 };
00607 unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
00608 unsigned char *out,*o, *filt, *zlib;
00609 signed char *line_buffer;
00610 int i,j,k,p,zlen;
00611
00612 if (stride_bytes == 0)
00613 stride_bytes = x * n;
00614
00615 filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
00616 line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
00617 for (j=0; j < y; ++j) {
00618 static int mapping[] = { 0,1,2,3,4 };
00619 static int firstmap[] = { 0,1,0,5,6 };
00620 int *mymap = j ? mapping : firstmap;
00621 int best = 0, bestval = 0x7fffffff;
00622 for (p=0; p < 2; ++p) {
00623 for (k= p?best:0; k < 5; ++k) {
00624 int type = mymap[k],est=0;
00625 unsigned char *z = pixels + stride_bytes*j;
00626 for (i=0; i < n; ++i)
00627 switch (type) {
00628 case 0: line_buffer[i] = z[i]; break;
00629 case 1: line_buffer[i] = z[i]; break;
00630 case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
00631 case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break;
00632 case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break;
00633 case 5: line_buffer[i] = z[i]; break;
00634 case 6: line_buffer[i] = z[i]; break;
00635 }
00636 for (i=n; i < x*n; ++i) {
00637 switch (type) {
00638 case 0: line_buffer[i] = z[i]; break;
00639 case 1: line_buffer[i] = z[i] - z[i-n]; break;
00640 case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
00641 case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break;
00642 case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break;
00643 case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break;
00644 case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
00645 }
00646 }
00647 if (p) break;
00648 for (i=0; i < x*n; ++i)
00649 est += abs((signed char) line_buffer[i]);
00650 if (est < bestval) { bestval = est; best = k; }
00651 }
00652 }
00653
00654 filt[j*(x*n+1)] = (unsigned char) best;
00655 STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
00656 }
00657 STBIW_FREE(line_buffer);
00658 zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8);
00659 STBIW_FREE(filt);
00660 if (!zlib) return 0;
00661
00662
00663 out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
00664 if (!out) return 0;
00665 *out_len = 8 + 12+13 + 12+zlen + 12;
00666
00667 o=out;
00668 STBIW_MEMMOVE(o,sig,8); o+= 8;
00669 stbiw__wp32(o, 13);
00670 stbiw__wptag(o, "IHDR");
00671 stbiw__wp32(o, x);
00672 stbiw__wp32(o, y);
00673 *o++ = 8;
00674 *o++ = (unsigned char) ctype[n];
00675 *o++ = 0;
00676 *o++ = 0;
00677 *o++ = 0;
00678 stbiw__wpcrc(&o,13);
00679
00680 stbiw__wp32(o, zlen);
00681 stbiw__wptag(o, "IDAT");
00682 STBIW_MEMMOVE(o, zlib, zlen);
00683 o += zlen;
00684 STBIW_FREE(zlib);
00685 stbiw__wpcrc(&o, zlen);
00686
00687 stbiw__wp32(o,0);
00688 stbiw__wptag(o, "IEND");
00689 stbiw__wpcrc(&o,0);
00690
00691 STBIW_ASSERT(o == out + *out_len);
00692
00693 return out;
00694 }
00695
00696 int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
00697 {
00698 FILE *f;
00699 int len;
00700 unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
00701 if (!png) return 0;
00702 f = fopen(filename, "wb");
00703 if (!f) { STBIW_FREE(png); return 0; }
00704 fwrite(png, 1, len, f);
00705 fclose(f);
00706 STBIW_FREE(png);
00707 return 1;
00708 }
00709 #endif // STB_IMAGE_WRITE_IMPLEMENTATION
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730