stb_image_write.h (37685B)
1 /* stb_image_write - v1.02 - public domain - http://nothings.org/stb/stb_image_write.h 2 writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015 3 no warranty implied; use at your own risk 4 5 Before #including, 6 7 #define STB_IMAGE_WRITE_IMPLEMENTATION 8 9 in the file that you want to have the implementation. 10 11 Will probably not work correctly with strict-aliasing optimizations. 12 13 ABOUT: 14 15 This header file is a library for writing images to C stdio. It could be 16 adapted to write to memory or a general streaming interface; let me know. 17 18 The PNG output is not optimal; it is 20-50% larger than the file 19 written by a decent optimizing implementation. This library is designed 20 for source code compactness and simplicity, not optimal image file size 21 or run-time performance. 22 23 BUILDING: 24 25 You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. 26 You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace 27 malloc,realloc,free. 28 You can define STBIW_MEMMOVE() to replace memmove() 29 30 USAGE: 31 32 There are four functions, one for each image file format: 33 34 int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); 35 int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); 36 int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); 37 int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); 38 39 There are also four equivalent functions that use an arbitrary write function. You are 40 expected to open/close your file-equivalent before and after calling these: 41 42 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); 43 int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); 44 int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); 45 int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); 46 47 where the callback is: 48 void stbi_write_func(void *context, void *data, int size); 49 50 You can define STBI_WRITE_NO_STDIO to disable the file variant of these 51 functions, so the library will not use stdio.h at all. However, this will 52 also disable HDR writing, because it requires stdio for formatted output. 53 54 Each function returns 0 on failure and non-0 on success. 55 56 The functions create an image file defined by the parameters. The image 57 is a rectangle of pixels stored from left-to-right, top-to-bottom. 58 Each pixel contains 'comp' channels of data stored interleaved with 8-bits 59 per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is 60 monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. 61 The *data pointer points to the first byte of the top-left-most pixel. 62 For PNG, "stride_in_bytes" is the distance in bytes from the first byte of 63 a row of pixels to the first byte of the next row of pixels. 64 65 PNG creates output files with the same number of components as the input. 66 The BMP format expands Y to RGB in the file format and does not 67 output alpha. 68 69 PNG supports writing rectangles of data even when the bytes storing rows of 70 data are not consecutive in memory (e.g. sub-rectangles of a larger image), 71 by supplying the stride between the beginning of adjacent rows. The other 72 formats do not. (Thus you cannot write a native-format BMP through the BMP 73 writer, both because it is in BGR order and because it may have padding 74 at the end of the line.) 75 76 HDR expects linear float data. Since the format is always 32-bit rgb(e) 77 data, alpha (if provided) is discarded, and for monochrome data it is 78 replicated across all three channels. 79 80 TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed 81 data, set the global variable 'stbi_write_tga_with_rle' to 0. 82 83 CREDITS: 84 85 PNG/BMP/TGA 86 Sean Barrett 87 HDR 88 Baldur Karlsson 89 TGA monochrome: 90 Jean-Sebastien Guay 91 misc enhancements: 92 Tim Kelsey 93 TGA RLE 94 Alan Hickman 95 initial file IO callback implementation 96 Emmanuel Julien 97 bugfixes: 98 github:Chribba 99 Guillaume Chereau 100 github:jry2 101 github:romigrou 102 Sergio Gonzalez 103 Jonas Karlsson 104 Filip Wasil 105 Thatcher Ulrich 106 107 LICENSE 108 109 This software is dual-licensed to the public domain and under the following 110 license: you are granted a perpetual, irrevocable license to copy, modify, 111 publish, and distribute this file as you see fit. 112 113 */ 114 115 #ifndef INCLUDE_STB_IMAGE_WRITE_H 116 #define INCLUDE_STB_IMAGE_WRITE_H 117 118 #ifdef __cplusplus 119 extern "C" { 120 #endif 121 122 #ifdef STB_IMAGE_WRITE_STATIC 123 #define STBIWDEF static 124 #else 125 #define STBIWDEF extern 126 extern int stbi_write_tga_with_rle; 127 #endif 128 129 #ifndef STBI_WRITE_NO_STDIO 130 STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); 131 STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); 132 STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); 133 STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); 134 #endif 135 136 typedef void stbi_write_func(void *context, void *data, int size); 137 138 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); 139 STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); 140 STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); 141 STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); 142 143 #ifdef __cplusplus 144 } 145 #endif 146 147 #endif//INCLUDE_STB_IMAGE_WRITE_H 148 149 #ifdef STB_IMAGE_WRITE_IMPLEMENTATION 150 151 #ifdef _WIN32 152 #ifndef _CRT_SECURE_NO_WARNINGS 153 #define _CRT_SECURE_NO_WARNINGS 154 #endif 155 #ifndef _CRT_NONSTDC_NO_DEPRECATE 156 #define _CRT_NONSTDC_NO_DEPRECATE 157 #endif 158 #endif 159 160 #ifndef STBI_WRITE_NO_STDIO 161 #include <stdio.h> 162 #endif // STBI_WRITE_NO_STDIO 163 164 #include <stdarg.h> 165 #include <stdlib.h> 166 #include <string.h> 167 #include <math.h> 168 169 #if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) 170 // ok 171 #elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) 172 // ok 173 #else 174 #error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." 175 #endif 176 177 #ifndef STBIW_MALLOC 178 #define STBIW_MALLOC(sz) malloc(sz) 179 #define STBIW_REALLOC(p,newsz) realloc(p,newsz) 180 #define STBIW_FREE(p) free(p) 181 #endif 182 183 #ifndef STBIW_REALLOC_SIZED 184 #define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) 185 #endif 186 187 188 #ifndef STBIW_MEMMOVE 189 #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) 190 #endif 191 192 193 #ifndef STBIW_ASSERT 194 #include <assert.h> 195 #define STBIW_ASSERT(x) assert(x) 196 #endif 197 198 #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) 199 200 typedef struct 201 { 202 stbi_write_func *func; 203 void *context; 204 } stbi__write_context; 205 206 // initialize a callback-based context 207 static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) 208 { 209 s->func = c; 210 s->context = context; 211 } 212 213 #ifndef STBI_WRITE_NO_STDIO 214 215 static void stbi__stdio_write(void *context, void *data, int size) 216 { 217 fwrite(data,1,size,(FILE*) context); 218 } 219 220 static int stbi__start_write_file(stbi__write_context *s, const char *filename) 221 { 222 FILE *f = fopen(filename, "wb"); 223 stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); 224 return f != NULL; 225 } 226 227 static void stbi__end_write_file(stbi__write_context *s) 228 { 229 fclose((FILE *)s->context); 230 } 231 232 #endif // !STBI_WRITE_NO_STDIO 233 234 typedef unsigned int stbiw_uint32; 235 typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; 236 237 #ifdef STB_IMAGE_WRITE_STATIC 238 static int stbi_write_tga_with_rle = 1; 239 #else 240 int stbi_write_tga_with_rle = 1; 241 #endif 242 243 static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) 244 { 245 while (*fmt) { 246 switch (*fmt++) { 247 case ' ': break; 248 case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); 249 s->func(s->context,&x,1); 250 break; } 251 case '2': { int x = va_arg(v,int); 252 unsigned char b[2]; 253 b[0] = STBIW_UCHAR(x); 254 b[1] = STBIW_UCHAR(x>>8); 255 s->func(s->context,b,2); 256 break; } 257 case '4': { stbiw_uint32 x = va_arg(v,int); 258 unsigned char b[4]; 259 b[0]=STBIW_UCHAR(x); 260 b[1]=STBIW_UCHAR(x>>8); 261 b[2]=STBIW_UCHAR(x>>16); 262 b[3]=STBIW_UCHAR(x>>24); 263 s->func(s->context,b,4); 264 break; } 265 default: 266 STBIW_ASSERT(0); 267 return; 268 } 269 } 270 } 271 272 static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) 273 { 274 va_list v; 275 va_start(v, fmt); 276 stbiw__writefv(s, fmt, v); 277 va_end(v); 278 } 279 280 static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) 281 { 282 unsigned char arr[3]; 283 arr[0] = a, arr[1] = b, arr[2] = c; 284 s->func(s->context, arr, 3); 285 } 286 287 static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) 288 { 289 unsigned char bg[3] = { 255, 0, 255}, px[3]; 290 int k; 291 292 if (write_alpha < 0) 293 s->func(s->context, &d[comp - 1], 1); 294 295 switch (comp) { 296 case 1: 297 s->func(s->context,d,1); 298 break; 299 case 2: 300 if (expand_mono) 301 stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp 302 else 303 s->func(s->context, d, 1); // monochrome TGA 304 break; 305 case 4: 306 if (!write_alpha) { 307 // composite against pink background 308 for (k = 0; k < 3; ++k) 309 px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; 310 stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); 311 break; 312 } 313 /* FALLTHROUGH */ 314 case 3: 315 stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); 316 break; 317 } 318 if (write_alpha > 0) 319 s->func(s->context, &d[comp - 1], 1); 320 } 321 322 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) 323 { 324 stbiw_uint32 zero = 0; 325 int i,j, j_end; 326 327 if (y <= 0) 328 return; 329 330 if (vdir < 0) 331 j_end = -1, j = y-1; 332 else 333 j_end = y, j = 0; 334 335 for (; j != j_end; j += vdir) { 336 for (i=0; i < x; ++i) { 337 unsigned char *d = (unsigned char *) data + (j*x+i)*comp; 338 stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); 339 } 340 s->func(s->context, &zero, scanline_pad); 341 } 342 } 343 344 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, ...) 345 { 346 if (y < 0 || x < 0) { 347 return 0; 348 } else { 349 va_list v; 350 va_start(v, fmt); 351 stbiw__writefv(s, fmt, v); 352 va_end(v); 353 stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); 354 return 1; 355 } 356 } 357 358 static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) 359 { 360 int pad = (-x*3) & 3; 361 return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, 362 "11 4 22 4" "4 44 22 444444", 363 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header 364 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header 365 } 366 367 STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) 368 { 369 stbi__write_context s; 370 stbi__start_write_callbacks(&s, func, context); 371 return stbi_write_bmp_core(&s, x, y, comp, data); 372 } 373 374 #ifndef STBI_WRITE_NO_STDIO 375 STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) 376 { 377 stbi__write_context s; 378 if (stbi__start_write_file(&s,filename)) { 379 int r = stbi_write_bmp_core(&s, x, y, comp, data); 380 stbi__end_write_file(&s); 381 return r; 382 } else 383 return 0; 384 } 385 #endif //!STBI_WRITE_NO_STDIO 386 387 static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) 388 { 389 int has_alpha = (comp == 2 || comp == 4); 390 int colorbytes = has_alpha ? comp-1 : comp; 391 int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 392 393 if (y < 0 || x < 0) 394 return 0; 395 396 if (!stbi_write_tga_with_rle) { 397 return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, 398 "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); 399 } else { 400 int i,j,k; 401 402 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); 403 404 for (j = y - 1; j >= 0; --j) { 405 unsigned char *row = (unsigned char *) data + j * x * comp; 406 int len; 407 408 for (i = 0; i < x; i += len) { 409 unsigned char *begin = row + i * comp; 410 int diff = 1; 411 len = 1; 412 413 if (i < x - 1) { 414 ++len; 415 diff = memcmp(begin, row + (i + 1) * comp, comp); 416 if (diff) { 417 const unsigned char *prev = begin; 418 for (k = i + 2; k < x && len < 128; ++k) { 419 if (memcmp(prev, row + k * comp, comp)) { 420 prev += comp; 421 ++len; 422 } else { 423 --len; 424 break; 425 } 426 } 427 } else { 428 for (k = i + 2; k < x && len < 128; ++k) { 429 if (!memcmp(begin, row + k * comp, comp)) { 430 ++len; 431 } else { 432 break; 433 } 434 } 435 } 436 } 437 438 if (diff) { 439 unsigned char header = STBIW_UCHAR(len - 1); 440 s->func(s->context, &header, 1); 441 for (k = 0; k < len; ++k) { 442 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); 443 } 444 } else { 445 unsigned char header = STBIW_UCHAR(len - 129); 446 s->func(s->context, &header, 1); 447 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); 448 } 449 } 450 } 451 } 452 return 1; 453 } 454 455 int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) 456 { 457 stbi__write_context s; 458 stbi__start_write_callbacks(&s, func, context); 459 return stbi_write_tga_core(&s, x, y, comp, (void *) data); 460 } 461 462 #ifndef STBI_WRITE_NO_STDIO 463 int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) 464 { 465 stbi__write_context s; 466 if (stbi__start_write_file(&s,filename)) { 467 int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); 468 stbi__end_write_file(&s); 469 return r; 470 } else 471 return 0; 472 } 473 #endif 474 475 // ************************************************************************************************* 476 // Radiance RGBE HDR writer 477 // by Baldur Karlsson 478 #ifndef STBI_WRITE_NO_STDIO 479 480 #define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) 481 482 void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) 483 { 484 int exponent; 485 float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); 486 487 if (maxcomp < 1e-32f) { 488 rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; 489 } else { 490 float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; 491 492 rgbe[0] = (unsigned char)(linear[0] * normalize); 493 rgbe[1] = (unsigned char)(linear[1] * normalize); 494 rgbe[2] = (unsigned char)(linear[2] * normalize); 495 rgbe[3] = (unsigned char)(exponent + 128); 496 } 497 } 498 499 void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) 500 { 501 unsigned char lengthbyte = STBIW_UCHAR(length+128); 502 STBIW_ASSERT(length+128 <= 255); 503 s->func(s->context, &lengthbyte, 1); 504 s->func(s->context, &databyte, 1); 505 } 506 507 void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) 508 { 509 unsigned char lengthbyte = STBIW_UCHAR(length); 510 STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code 511 s->func(s->context, &lengthbyte, 1); 512 s->func(s->context, data, length); 513 } 514 515 void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) 516 { 517 unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; 518 unsigned char rgbe[4]; 519 float linear[3]; 520 int x; 521 522 scanlineheader[2] = (width&0xff00)>>8; 523 scanlineheader[3] = (width&0x00ff); 524 525 /* skip RLE for images too small or large */ 526 if (width < 8 || width >= 32768) { 527 for (x=0; x < width; x++) { 528 switch (ncomp) { 529 case 4: /* fallthrough */ 530 case 3: linear[2] = scanline[x*ncomp + 2]; 531 linear[1] = scanline[x*ncomp + 1]; 532 linear[0] = scanline[x*ncomp + 0]; 533 break; 534 default: 535 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; 536 break; 537 } 538 stbiw__linear_to_rgbe(rgbe, linear); 539 s->func(s->context, rgbe, 4); 540 } 541 } else { 542 int c,r; 543 /* encode into scratch buffer */ 544 for (x=0; x < width; x++) { 545 switch(ncomp) { 546 case 4: /* fallthrough */ 547 case 3: linear[2] = scanline[x*ncomp + 2]; 548 linear[1] = scanline[x*ncomp + 1]; 549 linear[0] = scanline[x*ncomp + 0]; 550 break; 551 default: 552 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; 553 break; 554 } 555 stbiw__linear_to_rgbe(rgbe, linear); 556 scratch[x + width*0] = rgbe[0]; 557 scratch[x + width*1] = rgbe[1]; 558 scratch[x + width*2] = rgbe[2]; 559 scratch[x + width*3] = rgbe[3]; 560 } 561 562 s->func(s->context, scanlineheader, 4); 563 564 /* RLE each component separately */ 565 for (c=0; c < 4; c++) { 566 unsigned char *comp = &scratch[width*c]; 567 568 x = 0; 569 while (x < width) { 570 // find first run 571 r = x; 572 while (r+2 < width) { 573 if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) 574 break; 575 ++r; 576 } 577 if (r+2 >= width) 578 r = width; 579 // dump up to first run 580 while (x < r) { 581 int len = r-x; 582 if (len > 128) len = 128; 583 stbiw__write_dump_data(s, len, &comp[x]); 584 x += len; 585 } 586 // if there's a run, output it 587 if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd 588 // find next byte after run 589 while (r < width && comp[r] == comp[x]) 590 ++r; 591 // output run up to r 592 while (x < r) { 593 int len = r-x; 594 if (len > 127) len = 127; 595 stbiw__write_run_data(s, len, comp[x]); 596 x += len; 597 } 598 } 599 } 600 } 601 } 602 } 603 604 static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) 605 { 606 if (y <= 0 || x <= 0 || data == NULL) 607 return 0; 608 else { 609 // Each component is stored separately. Allocate scratch space for full output scanline. 610 unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); 611 int i, len; 612 char buffer[128]; 613 char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; 614 s->func(s->context, header, sizeof(header)-1); 615 616 len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); 617 s->func(s->context, buffer, len); 618 619 for(i=0; i < y; i++) 620 stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x); 621 STBIW_FREE(scratch); 622 return 1; 623 } 624 } 625 626 int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) 627 { 628 stbi__write_context s; 629 stbi__start_write_callbacks(&s, func, context); 630 return stbi_write_hdr_core(&s, x, y, comp, (float *) data); 631 } 632 633 int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) 634 { 635 stbi__write_context s; 636 if (stbi__start_write_file(&s,filename)) { 637 int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); 638 stbi__end_write_file(&s); 639 return r; 640 } else 641 return 0; 642 } 643 #endif // STBI_WRITE_NO_STDIO 644 645 646 ////////////////////////////////////////////////////////////////////////////// 647 // 648 // PNG writer 649 // 650 651 // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() 652 #define stbiw__sbraw(a) ((int *) (a) - 2) 653 #define stbiw__sbm(a) stbiw__sbraw(a)[0] 654 #define stbiw__sbn(a) stbiw__sbraw(a)[1] 655 656 #define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) 657 #define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) 658 #define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) 659 660 #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) 661 #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) 662 #define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) 663 664 static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) 665 { 666 int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; 667 void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); 668 STBIW_ASSERT(p); 669 if (p) { 670 if (!*arr) ((int *) p)[1] = 0; 671 *arr = (void *) ((int *) p + 2); 672 stbiw__sbm(*arr) = m; 673 } 674 return *arr; 675 } 676 677 static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) 678 { 679 while (*bitcount >= 8) { 680 stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); 681 *bitbuffer >>= 8; 682 *bitcount -= 8; 683 } 684 return data; 685 } 686 687 static int stbiw__zlib_bitrev(int code, int codebits) 688 { 689 int res=0; 690 while (codebits--) { 691 res = (res << 1) | (code & 1); 692 code >>= 1; 693 } 694 return res; 695 } 696 697 static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) 698 { 699 int i; 700 for (i=0; i < limit && i < 258; ++i) 701 if (a[i] != b[i]) break; 702 return i; 703 } 704 705 static unsigned int stbiw__zhash(unsigned char *data) 706 { 707 stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); 708 hash ^= hash << 3; 709 hash += hash >> 5; 710 hash ^= hash << 4; 711 hash += hash >> 17; 712 hash ^= hash << 25; 713 hash += hash >> 6; 714 return hash; 715 } 716 717 #define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) 718 #define stbiw__zlib_add(code,codebits) \ 719 (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) 720 #define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) 721 // default huffman tables 722 #define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) 723 #define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) 724 #define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) 725 #define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) 726 #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)) 727 #define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) 728 729 #define stbiw__ZHASH 16384 730 731 unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) 732 { 733 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 }; 734 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 }; 735 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 }; 736 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 }; 737 unsigned int bitbuf=0; 738 int i,j, bitcount=0; 739 unsigned char *out = NULL; 740 unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**)); 741 if (quality < 5) quality = 5; 742 743 stbiw__sbpush(out, 0x78); // DEFLATE 32K window 744 stbiw__sbpush(out, 0x5e); // FLEVEL = 1 745 stbiw__zlib_add(1,1); // BFINAL = 1 746 stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman 747 748 for (i=0; i < stbiw__ZHASH; ++i) 749 hash_table[i] = NULL; 750 751 i=0; 752 while (i < data_len-3) { 753 // hash next 3 bytes of data to be compressed 754 int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; 755 unsigned char *bestloc = 0; 756 unsigned char **hlist = hash_table[h]; 757 int n = stbiw__sbcount(hlist); 758 for (j=0; j < n; ++j) { 759 if (hlist[j]-data > i-32768) { // if entry lies within window 760 int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); 761 if (d >= best) best=d,bestloc=hlist[j]; 762 } 763 } 764 // when hash table entry is too long, delete half the entries 765 if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { 766 STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); 767 stbiw__sbn(hash_table[h]) = quality; 768 } 769 stbiw__sbpush(hash_table[h],data+i); 770 771 if (bestloc) { 772 // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal 773 h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); 774 hlist = hash_table[h]; 775 n = stbiw__sbcount(hlist); 776 for (j=0; j < n; ++j) { 777 if (hlist[j]-data > i-32767) { 778 int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); 779 if (e > best) { // if next match is better, bail on current match 780 bestloc = NULL; 781 break; 782 } 783 } 784 } 785 } 786 787 if (bestloc) { 788 int d = (int) (data+i - bestloc); // distance back 789 STBIW_ASSERT(d <= 32767 && best <= 258); 790 for (j=0; best > lengthc[j+1]-1; ++j); 791 stbiw__zlib_huff(j+257); 792 if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); 793 for (j=0; d > distc[j+1]-1; ++j); 794 stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); 795 if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); 796 i += best; 797 } else { 798 stbiw__zlib_huffb(data[i]); 799 ++i; 800 } 801 } 802 // write out final bytes 803 for (;i < data_len; ++i) 804 stbiw__zlib_huffb(data[i]); 805 stbiw__zlib_huff(256); // end of block 806 // pad with 0 bits to byte boundary 807 while (bitcount) 808 stbiw__zlib_add(0,1); 809 810 for (i=0; i < stbiw__ZHASH; ++i) 811 (void) stbiw__sbfree(hash_table[i]); 812 STBIW_FREE(hash_table); 813 814 { 815 // compute adler32 on input 816 unsigned int s1=1, s2=0; 817 int blocklen = (int) (data_len % 5552); 818 j=0; 819 while (j < data_len) { 820 for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; 821 s1 %= 65521, s2 %= 65521; 822 j += blocklen; 823 blocklen = 5552; 824 } 825 stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); 826 stbiw__sbpush(out, STBIW_UCHAR(s2)); 827 stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); 828 stbiw__sbpush(out, STBIW_UCHAR(s1)); 829 } 830 *out_len = stbiw__sbn(out); 831 // make returned pointer freeable 832 STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); 833 return (unsigned char *) stbiw__sbraw(out); 834 } 835 836 static unsigned int stbiw__crc32(unsigned char *buffer, int len) 837 { 838 static unsigned int crc_table[256] = 839 { 840 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 841 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 842 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 843 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 844 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 845 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 846 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 847 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 848 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 849 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 850 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 851 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 852 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 853 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 854 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 855 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 856 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 857 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 858 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 859 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 860 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 861 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 862 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 863 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 864 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 865 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 866 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 867 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 868 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 869 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 870 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 871 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D 872 }; 873 874 unsigned int crc = ~0u; 875 int i; 876 for (i=0; i < len; ++i) 877 crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; 878 return ~crc; 879 } 880 881 #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) 882 #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); 883 #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) 884 885 static void stbiw__wpcrc(unsigned char **data, int len) 886 { 887 unsigned int crc = stbiw__crc32(*data - len - 4, len+4); 888 stbiw__wp32(*data, crc); 889 } 890 891 static unsigned char stbiw__paeth(int a, int b, int c) 892 { 893 int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); 894 if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); 895 if (pb <= pc) return STBIW_UCHAR(b); 896 return STBIW_UCHAR(c); 897 } 898 899 unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) 900 { 901 int ctype[5] = { -1, 0, 4, 2, 6 }; 902 unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; 903 unsigned char *out,*o, *filt, *zlib; 904 signed char *line_buffer; 905 int i,j,k,p,zlen; 906 907 if (stride_bytes == 0) 908 stride_bytes = x * n; 909 910 filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; 911 line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } 912 for (j=0; j < y; ++j) { 913 static int mapping[] = { 0,1,2,3,4 }; 914 static int firstmap[] = { 0,1,0,5,6 }; 915 int *mymap = j ? mapping : firstmap; 916 int best = 0, bestval = 0x7fffffff; 917 for (p=0; p < 2; ++p) { 918 for (k= p?best:0; k < 5; ++k) { 919 int type = mymap[k],est=0; 920 unsigned char *z = pixels + stride_bytes*j; 921 for (i=0; i < n; ++i) 922 switch (type) { 923 case 0: line_buffer[i] = z[i]; break; 924 case 1: line_buffer[i] = z[i]; break; 925 case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; 926 case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break; 927 case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break; 928 case 5: line_buffer[i] = z[i]; break; 929 case 6: line_buffer[i] = z[i]; break; 930 } 931 for (i=n; i < x*n; ++i) { 932 switch (type) { 933 case 0: line_buffer[i] = z[i]; break; 934 case 1: line_buffer[i] = z[i] - z[i-n]; break; 935 case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break; 936 case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break; 937 case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break; 938 case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break; 939 case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; 940 } 941 } 942 if (p) break; 943 for (i=0; i < x*n; ++i) 944 est += abs((signed char) line_buffer[i]); 945 if (est < bestval) { bestval = est; best = k; } 946 } 947 } 948 // when we get here, best contains the filter type, and line_buffer contains the data 949 filt[j*(x*n+1)] = (unsigned char) best; 950 STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); 951 } 952 STBIW_FREE(line_buffer); 953 zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory 954 STBIW_FREE(filt); 955 if (!zlib) return 0; 956 957 // each tag requires 12 bytes of overhead 958 out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); 959 if (!out) return 0; 960 *out_len = 8 + 12+13 + 12+zlen + 12; 961 962 o=out; 963 STBIW_MEMMOVE(o,sig,8); o+= 8; 964 stbiw__wp32(o, 13); // header length 965 stbiw__wptag(o, "IHDR"); 966 stbiw__wp32(o, x); 967 stbiw__wp32(o, y); 968 *o++ = 8; 969 *o++ = STBIW_UCHAR(ctype[n]); 970 *o++ = 0; 971 *o++ = 0; 972 *o++ = 0; 973 stbiw__wpcrc(&o,13); 974 975 stbiw__wp32(o, zlen); 976 stbiw__wptag(o, "IDAT"); 977 STBIW_MEMMOVE(o, zlib, zlen); 978 o += zlen; 979 STBIW_FREE(zlib); 980 stbiw__wpcrc(&o, zlen); 981 982 stbiw__wp32(o,0); 983 stbiw__wptag(o, "IEND"); 984 stbiw__wpcrc(&o,0); 985 986 STBIW_ASSERT(o == out + *out_len); 987 988 return out; 989 } 990 991 #ifndef STBI_WRITE_NO_STDIO 992 STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) 993 { 994 FILE *f; 995 int len; 996 unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); 997 if (png == NULL) return 0; 998 f = fopen(filename, "wb"); 999 if (!f) { STBIW_FREE(png); return 0; } 1000 fwrite(png, 1, len, f); 1001 fclose(f); 1002 STBIW_FREE(png); 1003 return 1; 1004 } 1005 #endif 1006 1007 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) 1008 { 1009 int len; 1010 unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); 1011 if (png == NULL) return 0; 1012 func(context, png, len); 1013 STBIW_FREE(png); 1014 return 1; 1015 } 1016 1017 #endif // STB_IMAGE_WRITE_IMPLEMENTATION 1018 1019 /* Revision history 1020 1.02 (2016-04-02) 1021 avoid allocating large structures on the stack 1022 1.01 (2016-01-16) 1023 STBIW_REALLOC_SIZED: support allocators with no realloc support 1024 avoid race-condition in crc initialization 1025 minor compile issues 1026 1.00 (2015-09-14) 1027 installable file IO function 1028 0.99 (2015-09-13) 1029 warning fixes; TGA rle support 1030 0.98 (2015-04-08) 1031 added STBIW_MALLOC, STBIW_ASSERT etc 1032 0.97 (2015-01-18) 1033 fixed HDR asserts, rewrote HDR rle logic 1034 0.96 (2015-01-17) 1035 add HDR output 1036 fix monochrome BMP 1037 0.95 (2014-08-17) 1038 add monochrome TGA output 1039 0.94 (2014-05-31) 1040 rename private functions to avoid conflicts with stb_image.h 1041 0.93 (2014-05-27) 1042 warning fixes 1043 0.92 (2010-08-01) 1044 casts to unsigned char to fix warnings 1045 0.91 (2010-07-17) 1046 first public release 1047 0.90 first internal release 1048 */