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
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 #ifndef INCLUDE_STB_IMAGE_WRITE_H
00115 #define INCLUDE_STB_IMAGE_WRITE_H
00116
00117 #ifdef __cplusplus
00118 extern "C" {
00119 #endif
00120
00121 #ifdef STB_IMAGE_WRITE_STATIC
00122 #define STBIWDEF static
00123 #else
00124 #define STBIWDEF extern
00125 extern int stbi_write_tga_with_rle;
00126 #endif
00127
00128 #ifndef STBI_WRITE_NO_STDIO
00129 STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
00130 STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
00131 STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
00132 STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
00133 #endif
00134
00135 typedef void stbi_write_func(void *context, void *data, int size);
00136
00137 STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes);
00138 STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
00139 STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
00140 STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
00141
00142 #ifdef __cplusplus
00143 }
00144 #endif
00145
00146 #endif//INCLUDE_STB_IMAGE_WRITE_H
00147
00148 #ifdef STB_IMAGE_WRITE_IMPLEMENTATION
00149
00150 #ifdef _WIN32
00151 #ifndef _CRT_SECURE_NO_WARNINGS
00152 #define _CRT_SECURE_NO_WARNINGS
00153 #endif
00154 #ifndef _CRT_NONSTDC_NO_DEPRECATE
00155 #define _CRT_NONSTDC_NO_DEPRECATE
00156 #endif
00157 #endif
00158
00159 #ifndef STBI_WRITE_NO_STDIO
00160 #include <stdio.h>
00161 #endif // STBI_WRITE_NO_STDIO
00162
00163 #include <stdarg.h>
00164 #include <stdlib.h>
00165 #include <string.h>
00166 #include <math.h>
00167
00168 #if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED))
00169
00170 #elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED)
00171
00172 #else
00173 #error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)."
00174 #endif
00175
00176 #ifndef STBIW_MALLOC
00177 #define STBIW_MALLOC(sz) malloc(sz)
00178 #define STBIW_REALLOC(p,newsz) realloc(p,newsz)
00179 #define STBIW_FREE(p) free(p)
00180 #endif
00181
00182 #ifndef STBIW_REALLOC_SIZED
00183 #define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz)
00184 #endif
00185
00186
00187 #ifndef STBIW_MEMMOVE
00188 #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
00189 #endif
00190
00191
00192 #ifndef STBIW_ASSERT
00193 #include <assert.h>
00194 #define STBIW_ASSERT(x) assert(x)
00195 #endif
00196
00197 #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
00198
00199 typedef struct
00200 {
00201 stbi_write_func *func;
00202 void *context;
00203 } stbi__write_context;
00204
00205
00206 static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context)
00207 {
00208 s->func = c;
00209 s->context = context;
00210 }
00211
00212 #ifndef STBI_WRITE_NO_STDIO
00213
00214 static void stbi__stdio_write(void *context, void *data, int size)
00215 {
00216 fwrite(data,1,size,(FILE*) context);
00217 }
00218
00219 static int stbi__start_write_file(stbi__write_context *s, const char *filename)
00220 {
00221 FILE *f = fopen(filename, "wb");
00222 stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f);
00223 return f != NULL;
00224 }
00225
00226 static void stbi__end_write_file(stbi__write_context *s)
00227 {
00228 fclose((FILE *)s->context);
00229 }
00230
00231 #endif // !STBI_WRITE_NO_STDIO
00232
00233 typedef unsigned int stbiw_uint32;
00234 typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
00235
00236 #ifdef STB_IMAGE_WRITE_STATIC
00237 static int stbi_write_tga_with_rle = 1;
00238 #else
00239 int stbi_write_tga_with_rle = 1;
00240 #endif
00241
00242 static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v)
00243 {
00244 while (*fmt) {
00245 switch (*fmt++) {
00246 case ' ': break;
00247 case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int));
00248 s->func(s->context,&x,1);
00249 break; }
00250 case '2': { int x = va_arg(v,int);
00251 unsigned char b[2];
00252 b[0] = STBIW_UCHAR(x);
00253 b[1] = STBIW_UCHAR(x>>8);
00254 s->func(s->context,b,2);
00255 break; }
00256 case '4': { stbiw_uint32 x = va_arg(v,int);
00257 unsigned char b[4];
00258 b[0]=STBIW_UCHAR(x);
00259 b[1]=STBIW_UCHAR(x>>8);
00260 b[2]=STBIW_UCHAR(x>>16);
00261 b[3]=STBIW_UCHAR(x>>24);
00262 s->func(s->context,b,4);
00263 break; }
00264 default:
00265 STBIW_ASSERT(0);
00266 return;
00267 }
00268 }
00269 }
00270
00271 static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
00272 {
00273 va_list v;
00274 va_start(v, fmt);
00275 stbiw__writefv(s, fmt, v);
00276 va_end(v);
00277 }
00278
00279 static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
00280 {
00281 unsigned char arr[3];
00282 arr[0] = a, arr[1] = b, arr[2] = c;
00283 s->func(s->context, arr, 3);
00284 }
00285
00286 static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
00287 {
00288 unsigned char bg[3] = { 255, 0, 255}, px[3];
00289 int k;
00290
00291 if (write_alpha < 0)
00292 s->func(s->context, &d[comp - 1], 1);
00293
00294 switch (comp) {
00295 case 1:
00296 s->func(s->context,d,1);
00297 break;
00298 case 2:
00299 if (expand_mono)
00300 stbiw__write3(s, d[0], d[0], d[0]);
00301 else
00302 s->func(s->context, d, 1);
00303 break;
00304 case 4:
00305 if (!write_alpha) {
00306
00307 for (k = 0; k < 3; ++k)
00308 px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
00309 stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]);
00310 break;
00311 }
00312
00313 case 3:
00314 stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
00315 break;
00316 }
00317 if (write_alpha > 0)
00318 s->func(s->context, &d[comp - 1], 1);
00319 }
00320
00321 static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono)
00322 {
00323 stbiw_uint32 zero = 0;
00324 int i,j, j_end;
00325
00326 if (y <= 0)
00327 return;
00328
00329 if (vdir < 0)
00330 j_end = -1, j = y-1;
00331 else
00332 j_end = y, j = 0;
00333
00334 for (; j != j_end; j += vdir) {
00335 for (i=0; i < x; ++i) {
00336 unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
00337 stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
00338 }
00339 s->func(s->context, &zero, scanline_pad);
00340 }
00341 }
00342
00343 static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...)
00344 {
00345 if (y < 0 || x < 0) {
00346 return 0;
00347 } else {
00348 va_list v;
00349 va_start(v, fmt);
00350 stbiw__writefv(s, fmt, v);
00351 va_end(v);
00352 stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono);
00353 return 1;
00354 }
00355 }
00356
00357 static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
00358 {
00359 int pad = (-x*3) & 3;
00360 return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
00361 "11 4 22 4" "4 44 22 444444",
00362 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40,
00363 40, x,y, 1,24, 0,0,0,0,0,0);
00364 }
00365
00366 STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
00367 {
00368 stbi__write_context s;
00369 stbi__start_write_callbacks(&s, func, context);
00370 return stbi_write_bmp_core(&s, x, y, comp, data);
00371 }
00372
00373 #ifndef STBI_WRITE_NO_STDIO
00374 STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
00375 {
00376 stbi__write_context s;
00377 if (stbi__start_write_file(&s,filename)) {
00378 int r = stbi_write_bmp_core(&s, x, y, comp, data);
00379 stbi__end_write_file(&s);
00380 return r;
00381 } else
00382 return 0;
00383 }
00384 #endif //!STBI_WRITE_NO_STDIO
00385
00386 static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data)
00387 {
00388 int has_alpha = (comp == 2 || comp == 4);
00389 int colorbytes = has_alpha ? comp-1 : comp;
00390 int format = colorbytes < 2 ? 3 : 2;
00391
00392 if (y < 0 || x < 0)
00393 return 0;
00394
00395 if (!stbi_write_tga_with_rle) {
00396 return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0,
00397 "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
00398 } else {
00399 int i,j,k;
00400
00401 stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8);
00402
00403 for (j = y - 1; j >= 0; --j) {
00404 unsigned char *row = (unsigned char *) data + j * x * comp;
00405 int len;
00406
00407 for (i = 0; i < x; i += len) {
00408 unsigned char *begin = row + i * comp;
00409 int diff = 1;
00410 len = 1;
00411
00412 if (i < x - 1) {
00413 ++len;
00414 diff = memcmp(begin, row + (i + 1) * comp, comp);
00415 if (diff) {
00416 const unsigned char *prev = begin;
00417 for (k = i + 2; k < x && len < 128; ++k) {
00418 if (memcmp(prev, row + k * comp, comp)) {
00419 prev += comp;
00420 ++len;
00421 } else {
00422 --len;
00423 break;
00424 }
00425 }
00426 } else {
00427 for (k = i + 2; k < x && len < 128; ++k) {
00428 if (!memcmp(begin, row + k * comp, comp)) {
00429 ++len;
00430 } else {
00431 break;
00432 }
00433 }
00434 }
00435 }
00436
00437 if (diff) {
00438 unsigned char header = STBIW_UCHAR(len - 1);
00439 s->func(s->context, &header, 1);
00440 for (k = 0; k < len; ++k) {
00441 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
00442 }
00443 } else {
00444 unsigned char header = STBIW_UCHAR(len - 129);
00445 s->func(s->context, &header, 1);
00446 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
00447 }
00448 }
00449 }
00450 }
00451 return 1;
00452 }
00453
00454 int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
00455 {
00456 stbi__write_context s;
00457 stbi__start_write_callbacks(&s, func, context);
00458 return stbi_write_tga_core(&s, x, y, comp, (void *) data);
00459 }
00460
00461 #ifndef STBI_WRITE_NO_STDIO
00462 int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
00463 {
00464 stbi__write_context s;
00465 if (stbi__start_write_file(&s,filename)) {
00466 int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
00467 stbi__end_write_file(&s);
00468 return r;
00469 } else
00470 return 0;
00471 }
00472 #endif
00473
00474
00475
00476
00477 #ifndef STBI_WRITE_NO_STDIO
00478
00479 #define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
00480
00481 void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
00482 {
00483 int exponent;
00484 float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
00485
00486 if (maxcomp < 1e-32f) {
00487 rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
00488 } else {
00489 float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
00490
00491 rgbe[0] = (unsigned char)(linear[0] * normalize);
00492 rgbe[1] = (unsigned char)(linear[1] * normalize);
00493 rgbe[2] = (unsigned char)(linear[2] * normalize);
00494 rgbe[3] = (unsigned char)(exponent + 128);
00495 }
00496 }
00497
00498 void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
00499 {
00500 unsigned char lengthbyte = STBIW_UCHAR(length+128);
00501 STBIW_ASSERT(length+128 <= 255);
00502 s->func(s->context, &lengthbyte, 1);
00503 s->func(s->context, &databyte, 1);
00504 }
00505
00506 void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
00507 {
00508 unsigned char lengthbyte = STBIW_UCHAR(length);
00509 STBIW_ASSERT(length <= 128);
00510 s->func(s->context, &lengthbyte, 1);
00511 s->func(s->context, data, length);
00512 }
00513
00514 void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline)
00515 {
00516 unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
00517 unsigned char rgbe[4];
00518 float linear[3];
00519 int x;
00520
00521 scanlineheader[2] = (width&0xff00)>>8;
00522 scanlineheader[3] = (width&0x00ff);
00523
00524
00525 if (width < 8 || width >= 32768) {
00526 for (x=0; x < width; x++) {
00527 switch (ncomp) {
00528 case 4:
00529 case 3: linear[2] = scanline[x*ncomp + 2];
00530 linear[1] = scanline[x*ncomp + 1];
00531 linear[0] = scanline[x*ncomp + 0];
00532 break;
00533 default:
00534 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
00535 break;
00536 }
00537 stbiw__linear_to_rgbe(rgbe, linear);
00538 s->func(s->context, rgbe, 4);
00539 }
00540 } else {
00541 int c,r;
00542
00543 for (x=0; x < width; x++) {
00544 switch(ncomp) {
00545 case 4:
00546 case 3: linear[2] = scanline[x*ncomp + 2];
00547 linear[1] = scanline[x*ncomp + 1];
00548 linear[0] = scanline[x*ncomp + 0];
00549 break;
00550 default:
00551 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
00552 break;
00553 }
00554 stbiw__linear_to_rgbe(rgbe, linear);
00555 scratch[x + width*0] = rgbe[0];
00556 scratch[x + width*1] = rgbe[1];
00557 scratch[x + width*2] = rgbe[2];
00558 scratch[x + width*3] = rgbe[3];
00559 }
00560
00561 s->func(s->context, scanlineheader, 4);
00562
00563
00564 for (c=0; c < 4; c++) {
00565 unsigned char *comp = &scratch[width*c];
00566
00567 x = 0;
00568 while (x < width) {
00569
00570 r = x;
00571 while (r+2 < width) {
00572 if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
00573 break;
00574 ++r;
00575 }
00576 if (r+2 >= width)
00577 r = width;
00578
00579 while (x < r) {
00580 int len = r-x;
00581 if (len > 128) len = 128;
00582 stbiw__write_dump_data(s, len, &comp[x]);
00583 x += len;
00584 }
00585
00586 if (r+2 < width) {
00587
00588 while (r < width && comp[r] == comp[x])
00589 ++r;
00590
00591 while (x < r) {
00592 int len = r-x;
00593 if (len > 127) len = 127;
00594 stbiw__write_run_data(s, len, comp[x]);
00595 x += len;
00596 }
00597 }
00598 }
00599 }
00600 }
00601 }
00602
00603 static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data)
00604 {
00605 if (y <= 0 || x <= 0 || data == NULL)
00606 return 0;
00607 else {
00608
00609 unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
00610 int i, len;
00611 char buffer[128];
00612 char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
00613 s->func(s->context, header, sizeof(header)-1);
00614
00615 len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
00616 s->func(s->context, buffer, len);
00617
00618 for(i=0; i < y; i++)
00619 stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x);
00620 STBIW_FREE(scratch);
00621 return 1;
00622 }
00623 }
00624
00625 int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
00626 {
00627 stbi__write_context s;
00628 stbi__start_write_callbacks(&s, func, context);
00629 return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
00630 }
00631
00632 int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
00633 {
00634 stbi__write_context s;
00635 if (stbi__start_write_file(&s,filename)) {
00636 int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
00637 stbi__end_write_file(&s);
00638 return r;
00639 } else
00640 return 0;
00641 }
00642 #endif // STBI_WRITE_NO_STDIO
00643
00644
00646
00647
00648
00649
00650
00651 #define stbiw__sbraw(a) ((int *) (a) - 2)
00652 #define stbiw__sbm(a) stbiw__sbraw(a)[0]
00653 #define stbiw__sbn(a) stbiw__sbraw(a)[1]
00654
00655 #define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
00656 #define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
00657 #define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
00658
00659 #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
00660 #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
00661 #define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
00662
00663 static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
00664 {
00665 int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
00666 void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2);
00667 STBIW_ASSERT(p);
00668 if (p) {
00669 if (!*arr) ((int *) p)[1] = 0;
00670 *arr = (void *) ((int *) p + 2);
00671 stbiw__sbm(*arr) = m;
00672 }
00673 return *arr;
00674 }
00675
00676 static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
00677 {
00678 while (*bitcount >= 8) {
00679 stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
00680 *bitbuffer >>= 8;
00681 *bitcount -= 8;
00682 }
00683 return data;
00684 }
00685
00686 static int stbiw__zlib_bitrev(int code, int codebits)
00687 {
00688 int res=0;
00689 while (codebits--) {
00690 res = (res << 1) | (code & 1);
00691 code >>= 1;
00692 }
00693 return res;
00694 }
00695
00696 static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit)
00697 {
00698 int i;
00699 for (i=0; i < limit && i < 258; ++i)
00700 if (a[i] != b[i]) break;
00701 return i;
00702 }
00703
00704 static unsigned int stbiw__zhash(unsigned char *data)
00705 {
00706 stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
00707 hash ^= hash << 3;
00708 hash += hash >> 5;
00709 hash ^= hash << 4;
00710 hash += hash >> 17;
00711 hash ^= hash << 25;
00712 hash += hash >> 6;
00713 return hash;
00714 }
00715
00716 #define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
00717 #define stbiw__zlib_add(code,codebits) \
00718 (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
00719 #define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
00720
00721 #define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8)
00722 #define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9)
00723 #define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7)
00724 #define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8)
00725 #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))
00726 #define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
00727
00728 #define stbiw__ZHASH 16384
00729
00730 unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
00731 {
00732 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 };
00733 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 };
00734 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 };
00735 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 };
00736 unsigned int bitbuf=0;
00737 int i,j, bitcount=0;
00738 unsigned char *out = NULL;
00739 unsigned char **hash_table[stbiw__ZHASH];
00740 if (quality < 5) quality = 5;
00741
00742 stbiw__sbpush(out, 0x78);
00743 stbiw__sbpush(out, 0x5e);
00744 stbiw__zlib_add(1,1);
00745 stbiw__zlib_add(1,2);
00746
00747 for (i=0; i < stbiw__ZHASH; ++i)
00748 hash_table[i] = NULL;
00749
00750 i=0;
00751 while (i < data_len-3) {
00752
00753 int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
00754 unsigned char *bestloc = 0;
00755 unsigned char **hlist = hash_table[h];
00756 int n = stbiw__sbcount(hlist);
00757 for (j=0; j < n; ++j) {
00758 if (hlist[j]-data > i-32768) {
00759 int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
00760 if (d >= best) best=d,bestloc=hlist[j];
00761 }
00762 }
00763
00764 if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
00765 STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
00766 stbiw__sbn(hash_table[h]) = quality;
00767 }
00768 stbiw__sbpush(hash_table[h],data+i);
00769
00770 if (bestloc) {
00771
00772 h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
00773 hlist = hash_table[h];
00774 n = stbiw__sbcount(hlist);
00775 for (j=0; j < n; ++j) {
00776 if (hlist[j]-data > i-32767) {
00777 int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
00778 if (e > best) {
00779 bestloc = NULL;
00780 break;
00781 }
00782 }
00783 }
00784 }
00785
00786 if (bestloc) {
00787 int d = (int) (data+i - bestloc);
00788 STBIW_ASSERT(d <= 32767 && best <= 258);
00789 for (j=0; best > lengthc[j+1]-1; ++j);
00790 stbiw__zlib_huff(j+257);
00791 if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
00792 for (j=0; d > distc[j+1]-1; ++j);
00793 stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
00794 if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
00795 i += best;
00796 } else {
00797 stbiw__zlib_huffb(data[i]);
00798 ++i;
00799 }
00800 }
00801
00802 for (;i < data_len; ++i)
00803 stbiw__zlib_huffb(data[i]);
00804 stbiw__zlib_huff(256);
00805
00806 while (bitcount)
00807 stbiw__zlib_add(0,1);
00808
00809 for (i=0; i < stbiw__ZHASH; ++i)
00810 (void) stbiw__sbfree(hash_table[i]);
00811
00812 {
00813
00814 unsigned int s1=1, s2=0;
00815 int blocklen = (int) (data_len % 5552);
00816 j=0;
00817 while (j < data_len) {
00818 for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
00819 s1 %= 65521, s2 %= 65521;
00820 j += blocklen;
00821 blocklen = 5552;
00822 }
00823 stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
00824 stbiw__sbpush(out, STBIW_UCHAR(s2));
00825 stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
00826 stbiw__sbpush(out, STBIW_UCHAR(s1));
00827 }
00828 *out_len = stbiw__sbn(out);
00829
00830 STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
00831 return (unsigned char *) stbiw__sbraw(out);
00832 }
00833
00834 static unsigned int stbiw__crc32(unsigned char *buffer, int len)
00835 {
00836 static unsigned int crc_table[256] =
00837 {
00838 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
00839 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
00840 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
00841 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
00842 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
00843 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
00844 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
00845 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
00846 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
00847 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
00848 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
00849 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
00850 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
00851 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
00852 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
00853 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
00854 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
00855 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
00856 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
00857 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
00858 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
00859 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
00860 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
00861 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
00862 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
00863 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
00864 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
00865 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
00866 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
00867 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
00868 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
00869 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
00870 };
00871
00872 unsigned int crc = ~0u;
00873 int i;
00874 for (i=0; i < len; ++i)
00875 crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
00876 return ~crc;
00877 }
00878
00879 #define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4)
00880 #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
00881 #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
00882
00883 static void stbiw__wpcrc(unsigned char **data, int len)
00884 {
00885 unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
00886 stbiw__wp32(*data, crc);
00887 }
00888
00889 static unsigned char stbiw__paeth(int a, int b, int c)
00890 {
00891 int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
00892 if (pa <= pb && pa <= pc) return STBIW_UCHAR(a);
00893 if (pb <= pc) return STBIW_UCHAR(b);
00894 return STBIW_UCHAR(c);
00895 }
00896
00897 unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
00898 {
00899 int ctype[5] = { -1, 0, 4, 2, 6 };
00900 unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
00901 unsigned char *out,*o, *filt, *zlib;
00902 signed char *line_buffer;
00903 int i,j,k,p,zlen;
00904
00905 if (stride_bytes == 0)
00906 stride_bytes = x * n;
00907
00908 filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
00909 line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
00910 for (j=0; j < y; ++j) {
00911 static int mapping[] = { 0,1,2,3,4 };
00912 static int firstmap[] = { 0,1,0,5,6 };
00913 int *mymap = j ? mapping : firstmap;
00914 int best = 0, bestval = 0x7fffffff;
00915 for (p=0; p < 2; ++p) {
00916 for (k= p?best:0; k < 5; ++k) {
00917 int type = mymap[k],est=0;
00918 unsigned char *z = pixels + stride_bytes*j;
00919 for (i=0; i < n; ++i)
00920 switch (type) {
00921 case 0: line_buffer[i] = z[i]; break;
00922 case 1: line_buffer[i] = z[i]; break;
00923 case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
00924 case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break;
00925 case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break;
00926 case 5: line_buffer[i] = z[i]; break;
00927 case 6: line_buffer[i] = z[i]; break;
00928 }
00929 for (i=n; i < x*n; ++i) {
00930 switch (type) {
00931 case 0: line_buffer[i] = z[i]; break;
00932 case 1: line_buffer[i] = z[i] - z[i-n]; break;
00933 case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
00934 case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break;
00935 case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break;
00936 case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break;
00937 case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
00938 }
00939 }
00940 if (p) break;
00941 for (i=0; i < x*n; ++i)
00942 est += abs((signed char) line_buffer[i]);
00943 if (est < bestval) { bestval = est; best = k; }
00944 }
00945 }
00946
00947 filt[j*(x*n+1)] = (unsigned char) best;
00948 STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
00949 }
00950 STBIW_FREE(line_buffer);
00951 zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8);
00952 STBIW_FREE(filt);
00953 if (!zlib) return 0;
00954
00955
00956 out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
00957 if (!out) return 0;
00958 *out_len = 8 + 12+13 + 12+zlen + 12;
00959
00960 o=out;
00961 STBIW_MEMMOVE(o,sig,8); o+= 8;
00962 stbiw__wp32(o, 13);
00963 stbiw__wptag(o, "IHDR");
00964 stbiw__wp32(o, x);
00965 stbiw__wp32(o, y);
00966 *o++ = 8;
00967 *o++ = STBIW_UCHAR(ctype[n]);
00968 *o++ = 0;
00969 *o++ = 0;
00970 *o++ = 0;
00971 stbiw__wpcrc(&o,13);
00972
00973 stbiw__wp32(o, zlen);
00974 stbiw__wptag(o, "IDAT");
00975 STBIW_MEMMOVE(o, zlib, zlen);
00976 o += zlen;
00977 STBIW_FREE(zlib);
00978 stbiw__wpcrc(&o, zlen);
00979
00980 stbiw__wp32(o,0);
00981 stbiw__wptag(o, "IEND");
00982 stbiw__wpcrc(&o,0);
00983
00984 STBIW_ASSERT(o == out + *out_len);
00985
00986 return out;
00987 }
00988
00989 #ifndef STBI_WRITE_NO_STDIO
00990 STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
00991 {
00992 FILE *f;
00993 int len;
00994 unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
00995 if (png == NULL) return 0;
00996 f = fopen(filename, "wb");
00997 if (!f) { STBIW_FREE(png); return 0; }
00998 fwrite(png, 1, len, f);
00999 fclose(f);
01000 STBIW_FREE(png);
01001 return 1;
01002 }
01003 #endif
01004
01005 STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes)
01006 {
01007 int len;
01008 unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
01009 if (png == NULL) return 0;
01010 func(context, png, len);
01011 STBIW_FREE(png);
01012 return 1;
01013 }
01014
01015 #endif // STB_IMAGE_WRITE_IMPLEMENTATION
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044