this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Updated stb-image from v0.94 to v1.00.

+568 -92
+568 -92
src/externals/stb_image/stb_image_write.h
··· 1 - /* stb_image_write - v0.94 - public domain - http://nothings.org/stb/stb_image_write.h 2 - writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010 3 - no warranty implied; use at your own risk 1 + /* stb_image_write - v1.00 - 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 4 5 + Before #including, 5 6 6 - Before including, 7 + #define STB_IMAGE_WRITE_IMPLEMENTATION 7 8 8 - #define STB_IMAGE_WRITE_IMPLEMENTATION 9 + in the file that you want to have the implementation. 9 10 10 - in the file that you want to have the implementation. 11 - 12 - Will probably not work correctly with strict-aliasing optimizations. 13 - 11 + Will probably not work correctly with strict-aliasing optimizations. 14 12 15 13 ABOUT: 16 14 ··· 19 17 20 18 The PNG output is not optimal; it is 20-50% larger than the file 21 19 written by a decent optimizing implementation. This library is designed 22 - for source code compactness and simplicitly, not optimal image file size 20 + for source code compactness and simplicity, not optimal image file size 23 21 or run-time performance. 24 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 + 25 30 USAGE: 26 31 27 - There are three functions, one for each image file format: 32 + There are four functions, one for each image file format: 28 33 29 34 int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); 30 35 int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); 31 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 void *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. 32 53 33 54 Each function returns 0 on failure and non-0 on success. 34 - 55 + 35 56 The functions create an image file defined by the parameters. The image 36 57 is a rectangle of pixels stored from left-to-right, top-to-bottom. 37 58 Each pixel contains 'comp' channels of data stored interleaved with 8-bits ··· 42 63 a row of pixels to the first byte of the next row of pixels. 43 64 44 65 PNG creates output files with the same number of components as the input. 45 - The BMP and TGA formats expand Y to RGB in the file format. BMP does not 66 + The BMP format expands Y to RGB in the file format and does not 46 67 output alpha. 47 - 68 + 48 69 PNG supports writing rectangles of data even when the bytes storing rows of 49 70 data are not consecutive in memory (e.g. sub-rectangles of a larger image), 50 71 by supplying the stride between the beginning of adjacent rows. The other 51 72 formats do not. (Thus you cannot write a native-format BMP through the BMP 52 73 writer, both because it is in BGR order and because it may have padding 53 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 + 102 + LICENSE 103 + 104 + This software is in the public domain. Where that dedication is not 105 + recognized, you are granted a perpetual, irrevocable license to copy, 106 + distribute, and modify this file as you see fit. 107 + 54 108 */ 55 109 56 110 #ifndef INCLUDE_STB_IMAGE_WRITE_H ··· 60 114 extern "C" { 61 115 #endif 62 116 63 - extern int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); 64 - extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); 65 - extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); 117 + #ifdef STB_IMAGE_WRITE_STATIC 118 + #define STBIWDEF static 119 + #else 120 + #define STBIWDEF extern 121 + extern int stbi_write_tga_with_rle; 122 + #endif 123 + 124 + #ifndef STBI_WRITE_NO_STDIO 125 + STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); 126 + STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); 127 + STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); 128 + STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); 129 + #endif 130 + 131 + typedef void stbi_write_func(void *context, void *data, int size); 132 + 133 + 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); 134 + STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); 135 + STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); 136 + STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); 66 137 67 138 #ifdef __cplusplus 68 139 } ··· 71 142 #endif//INCLUDE_STB_IMAGE_WRITE_H 72 143 73 144 #ifdef STB_IMAGE_WRITE_IMPLEMENTATION 145 + 146 + #ifdef _WIN32 147 + #define _CRT_SECURE_NO_WARNINGS 148 + #define _CRT_NONSTDC_NO_DEPRECATE 149 + #endif 150 + 151 + #ifndef STBI_WRITE_NO_STDIO 152 + #include <stdio.h> 153 + #endif // STBI_WRITE_NO_STDIO 74 154 75 155 #include <stdarg.h> 76 156 #include <stdlib.h> 77 - #include <stdio.h> 78 157 #include <string.h> 158 + #include <math.h> 159 + 160 + #if defined(STBIW_MALLOC) && defined(STBIW_FREE) && defined(STBIW_REALLOC) 161 + // ok 162 + #elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) 163 + // ok 164 + #else 165 + #error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC." 166 + #endif 167 + 168 + #ifndef STBIW_MALLOC 169 + #define STBIW_MALLOC(sz) malloc(sz) 170 + #define STBIW_REALLOC(p,sz) realloc(p,sz) 171 + #define STBIW_FREE(p) free(p) 172 + #endif 173 + #ifndef STBIW_MEMMOVE 174 + #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) 175 + #endif 176 + 177 + 178 + #ifndef STBIW_ASSERT 79 179 #include <assert.h> 180 + #define STBIW_ASSERT(x) assert(x) 181 + #endif 182 + 183 + typedef struct 184 + { 185 + stbi_write_func *func; 186 + void *context; 187 + } stbi__write_context; 188 + 189 + // initialize a callback-based context 190 + static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) 191 + { 192 + s->func = c; 193 + s->context = context; 194 + } 195 + 196 + #ifndef STBI_WRITE_NO_STDIO 197 + 198 + static void stbi__stdio_write(void *context, void *data, int size) 199 + { 200 + fwrite(data,1,size,(FILE*) context); 201 + } 202 + 203 + static int stbi__start_write_file(stbi__write_context *s, const char *filename) 204 + { 205 + FILE *f = fopen(filename, "wb"); 206 + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); 207 + return f != NULL; 208 + } 209 + 210 + static void stbi__end_write_file(stbi__write_context *s) 211 + { 212 + fclose((FILE *)s->context); 213 + } 214 + 215 + #endif // !STBI_WRITE_NO_STDIO 80 216 81 217 typedef unsigned int stbiw_uint32; 82 218 typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; 83 219 84 - static void writefv(FILE *f, const char *fmt, va_list v) 220 + #ifdef STB_IMAGE_WRITE_STATIC 221 + static int stbi_write_tga_with_rle = 1; 222 + #else 223 + int stbi_write_tga_with_rle = 1; 224 + #endif 225 + 226 + static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) 85 227 { 86 228 while (*fmt) { 87 229 switch (*fmt++) { 88 230 case ' ': break; 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; } 231 + case '1': { unsigned char x = (unsigned char) va_arg(v, int); 232 + s->func(s->context,&x,1); 233 + break; } 234 + case '2': { int x = va_arg(v,int); 235 + unsigned char b[2]; 236 + b[0] = (unsigned char) x; 237 + b[1] = (unsigned char) (x>>8); 238 + s->func(s->context,b,2); 239 + break; } 240 + case '4': { stbiw_uint32 x = va_arg(v,int); 241 + unsigned char b[4]; 242 + b[0]=(unsigned char)x; 243 + b[1]=(unsigned char)(x>>8); 244 + b[2]=(unsigned char)(x>>16); 245 + b[3]=(unsigned char)(x>>24); 246 + s->func(s->context,b,4); 247 + break; } 97 248 default: 98 - assert(0); 249 + STBIW_ASSERT(0); 99 250 return; 100 251 } 101 252 } 102 253 } 103 254 104 - static void write3(FILE *f, unsigned char a, unsigned char b, unsigned char c) 255 + static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) 256 + { 257 + va_list v; 258 + va_start(v, fmt); 259 + stbiw__writefv(s, fmt, v); 260 + va_end(v); 261 + } 262 + 263 + static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) 105 264 { 106 265 unsigned char arr[3]; 107 266 arr[0] = a, arr[1] = b, arr[2] = c; 108 - fwrite(arr, 3, 1, f); 267 + s->func(s->context, arr, 3); 109 268 } 110 269 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) 270 + static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) 112 271 { 113 272 unsigned char bg[3] = { 255, 0, 255}, px[3]; 273 + int k; 274 + 275 + if (write_alpha < 0) 276 + s->func(s->context, &d[comp - 1], 1); 277 + 278 + switch (comp) { 279 + case 1: 280 + s->func(s->context,d,1); 281 + break; 282 + case 2: 283 + if (expand_mono) 284 + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp 285 + else 286 + s->func(s->context, d, 1); // monochrome TGA 287 + break; 288 + case 4: 289 + if (!write_alpha) { 290 + // composite against pink background 291 + for (k = 0; k < 3; ++k) 292 + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; 293 + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); 294 + break; 295 + } 296 + /* FALLTHROUGH */ 297 + case 3: 298 + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); 299 + break; 300 + } 301 + if (write_alpha > 0) 302 + s->func(s->context, &d[comp - 1], 1); 303 + } 304 + 305 + 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) 306 + { 114 307 stbiw_uint32 zero = 0; 115 - int i,j,k, j_end; 308 + int i,j, j_end; 116 309 117 310 if (y <= 0) 118 311 return; 119 312 120 - if (vdir < 0) 313 + if (vdir < 0) 121 314 j_end = -1, j = y-1; 122 315 else 123 316 j_end = y, j = 0; ··· 125 318 for (; j != j_end; j += vdir) { 126 319 for (i=0; i < x; ++i) { 127 320 unsigned char *d = (unsigned char *) data + (j*x+i)*comp; 128 - if (write_alpha < 0) 129 - fwrite(&d[comp-1], 1, 1, f); 130 - switch (comp) { 131 - case 1: 132 - case 2: write3(f, d[0],d[0],d[0]); 133 - break; 134 - case 4: 135 - if (!write_alpha) { 136 - // composite against pink background 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]); 140 - break; 141 - } 142 - /* FALLTHROUGH */ 143 - case 3: 144 - write3(f, d[1-rgb_dir],d[1],d[1+rgb_dir]); 145 - break; 146 - } 147 - if (write_alpha > 0) 148 - fwrite(&d[comp-1], 1, 1, f); 321 + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); 149 322 } 150 - fwrite(&zero,scanline_pad,1,f); 323 + s->func(s->context, &zero, scanline_pad); 151 324 } 152 325 } 153 326 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, ...) 327 + 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, ...) 155 328 { 156 - FILE *f; 157 - if (y < 0 || x < 0) return 0; 158 - f = fopen(filename, "wb"); 159 - if (f) { 329 + if (y < 0 || x < 0) { 330 + return 0; 331 + } else { 160 332 va_list v; 161 333 va_start(v, fmt); 162 - writefv(f, fmt, v); 334 + stbiw__writefv(s, fmt, v); 163 335 va_end(v); 164 - write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad); 165 - fclose(f); 336 + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); 337 + return 1; 166 338 } 167 - return f != NULL; 168 339 } 169 340 170 - int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) 341 + static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) 171 342 { 172 343 int pad = (-x*3) & 3; 173 - return outfile(filename,-1,-1,x,y,comp,(void *) data,0,pad, 344 + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, 174 345 "11 4 22 4" "4 44 22 444444", 175 346 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header 176 347 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header 177 348 } 178 349 350 + STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) 351 + { 352 + stbi__write_context s; 353 + stbi__start_write_callbacks(&s, func, context); 354 + return stbi_write_bmp_core(&s, x, y, comp, data); 355 + } 356 + 357 + #ifndef STBI_WRITE_NO_STDIO 358 + STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) 359 + { 360 + stbi__write_context s; 361 + if (stbi__start_write_file(&s,filename)) { 362 + int r = stbi_write_bmp_core(&s, x, y, comp, data); 363 + stbi__end_write_file(&s); 364 + return r; 365 + } else 366 + return 0; 367 + } 368 + #endif //!STBI_WRITE_NO_STDIO 369 + 370 + static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) 371 + { 372 + int has_alpha = (comp == 2 || comp == 4); 373 + int colorbytes = has_alpha ? comp-1 : comp; 374 + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 375 + 376 + if (y < 0 || x < 0) 377 + return 0; 378 + 379 + if (!stbi_write_tga_with_rle) { 380 + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, 381 + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); 382 + } else { 383 + int i,j,k; 384 + 385 + 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); 386 + 387 + for (j = y - 1; j >= 0; --j) { 388 + unsigned char *row = (unsigned char *) data + j * x * comp; 389 + int len; 390 + 391 + for (i = 0; i < x; i += len) { 392 + unsigned char *begin = row + i * comp; 393 + int diff = 1; 394 + len = 1; 395 + 396 + if (i < x - 1) { 397 + ++len; 398 + diff = memcmp(begin, row + (i + 1) * comp, comp); 399 + if (diff) { 400 + const unsigned char *prev = begin; 401 + for (k = i + 2; k < x && len < 128; ++k) { 402 + if (memcmp(prev, row + k * comp, comp)) { 403 + prev += comp; 404 + ++len; 405 + } else { 406 + --len; 407 + break; 408 + } 409 + } 410 + } else { 411 + for (k = i + 2; k < x && len < 128; ++k) { 412 + if (!memcmp(begin, row + k * comp, comp)) { 413 + ++len; 414 + } else { 415 + break; 416 + } 417 + } 418 + } 419 + } 420 + 421 + if (diff) { 422 + unsigned char header = (unsigned char) (len - 1); 423 + s->func(s->context, &header, 1); 424 + for (k = 0; k < len; ++k) { 425 + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); 426 + } 427 + } else { 428 + unsigned char header = (unsigned char) (len - 129); 429 + s->func(s->context, &header, 1); 430 + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); 431 + } 432 + } 433 + } 434 + } 435 + return 1; 436 + } 437 + 438 + int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) 439 + { 440 + stbi__write_context s; 441 + stbi__start_write_callbacks(&s, func, context); 442 + return stbi_write_tga_core(&s, x, y, comp, (void *) data); 443 + } 444 + 445 + #ifndef STBI_WRITE_NO_STDIO 179 446 int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) 180 447 { 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); 448 + stbi__write_context s; 449 + if (stbi__start_write_file(&s,filename)) { 450 + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); 451 + stbi__end_write_file(&s); 452 + return r; 453 + } else 454 + return 0; 455 + } 456 + #endif 457 + 458 + // ************************************************************************************************* 459 + // Radiance RGBE HDR writer 460 + // by Baldur Karlsson 461 + #ifndef STBI_WRITE_NO_STDIO 462 + 463 + #define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) 464 + 465 + void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) 466 + { 467 + int exponent; 468 + float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); 469 + 470 + if (maxcomp < 1e-32) { 471 + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; 472 + } else { 473 + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; 474 + 475 + rgbe[0] = (unsigned char)(linear[0] * normalize); 476 + rgbe[1] = (unsigned char)(linear[1] * normalize); 477 + rgbe[2] = (unsigned char)(linear[2] * normalize); 478 + rgbe[3] = (unsigned char)(exponent + 128); 479 + } 480 + } 481 + 482 + void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) 483 + { 484 + unsigned char lengthbyte = (unsigned char) (length+128); 485 + STBIW_ASSERT(length+128 <= 255); 486 + s->func(s->context, &lengthbyte, 1); 487 + s->func(s->context, &databyte, 1); 184 488 } 185 489 490 + void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) 491 + { 492 + unsigned char lengthbyte = (unsigned char )(length & 0xff); 493 + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code 494 + s->func(s->context, &lengthbyte, 1); 495 + s->func(s->context, data, length); 496 + } 497 + 498 + void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) 499 + { 500 + unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; 501 + unsigned char rgbe[4]; 502 + float linear[3]; 503 + int x; 504 + 505 + scanlineheader[2] = (width&0xff00)>>8; 506 + scanlineheader[3] = (width&0x00ff); 507 + 508 + /* skip RLE for images too small or large */ 509 + if (width < 8 || width >= 32768) { 510 + for (x=0; x < width; x++) { 511 + switch (ncomp) { 512 + case 4: /* fallthrough */ 513 + case 3: linear[2] = scanline[x*ncomp + 2]; 514 + linear[1] = scanline[x*ncomp + 1]; 515 + linear[0] = scanline[x*ncomp + 0]; 516 + break; 517 + default: 518 + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; 519 + break; 520 + } 521 + stbiw__linear_to_rgbe(rgbe, linear); 522 + s->func(s->context, rgbe, 4); 523 + } 524 + } else { 525 + int c,r; 526 + /* encode into scratch buffer */ 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 + scratch[x + width*0] = rgbe[0]; 540 + scratch[x + width*1] = rgbe[1]; 541 + scratch[x + width*2] = rgbe[2]; 542 + scratch[x + width*3] = rgbe[3]; 543 + } 544 + 545 + s->func(s->context, scanlineheader, 4); 546 + 547 + /* RLE each component separately */ 548 + for (c=0; c < 4; c++) { 549 + unsigned char *comp = &scratch[width*c]; 550 + 551 + x = 0; 552 + while (x < width) { 553 + // find first run 554 + r = x; 555 + while (r+2 < width) { 556 + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) 557 + break; 558 + ++r; 559 + } 560 + if (r+2 >= width) 561 + r = width; 562 + // dump up to first run 563 + while (x < r) { 564 + int len = r-x; 565 + if (len > 128) len = 128; 566 + stbiw__write_dump_data(s, len, &comp[x]); 567 + x += len; 568 + } 569 + // if there's a run, output it 570 + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd 571 + // find next byte after run 572 + while (r < width && comp[r] == comp[x]) 573 + ++r; 574 + // output run up to r 575 + while (x < r) { 576 + int len = r-x; 577 + if (len > 127) len = 127; 578 + stbiw__write_run_data(s, len, comp[x]); 579 + x += len; 580 + } 581 + } 582 + } 583 + } 584 + } 585 + } 586 + 587 + static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) 588 + { 589 + if (y <= 0 || x <= 0 || data == NULL) 590 + return 0; 591 + else { 592 + // Each component is stored separately. Allocate scratch space for full output scanline. 593 + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); 594 + int i, len; 595 + char buffer[128]; 596 + char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; 597 + s->func(s->context, header, sizeof(header)-1); 598 + 599 + len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); 600 + s->func(s->context, buffer, len); 601 + 602 + for(i=0; i < y; i++) 603 + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x); 604 + STBIW_FREE(scratch); 605 + return 1; 606 + } 607 + } 608 + 609 + int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) 610 + { 611 + stbi__write_context s; 612 + stbi__start_write_callbacks(&s, func, context); 613 + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); 614 + } 615 + 616 + int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) 617 + { 618 + stbi__write_context s; 619 + if (stbi__start_write_file(&s,filename)) { 620 + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); 621 + stbi__end_write_file(&s); 622 + return r; 623 + } else 624 + return 0; 625 + } 626 + #endif // STBI_WRITE_NO_STDIO 627 + 628 + 629 + ////////////////////////////////////////////////////////////////////////////// 630 + // 631 + // PNG writer 632 + // 633 + 186 634 // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() 187 635 #define stbiw__sbraw(a) ((int *) (a) - 2) 188 636 #define stbiw__sbm(a) stbiw__sbraw(a)[0] ··· 194 642 195 643 #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) 196 644 #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) 197 - #define stbiw__sbfree(a) ((a) ? free(stbiw__sbraw(a)),0 : 0) 645 + #define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) 198 646 199 647 static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) 200 648 { 201 649 int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; 202 - void *p = realloc(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2); 203 - assert(p); 650 + void *p = STBIW_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2); 651 + STBIW_ASSERT(p); 204 652 if (p) { 205 653 if (!*arr) ((int *) p)[1] = 0; 206 654 *arr = (void *) ((int *) p + 2); ··· 285 733 286 734 i=0; 287 735 while (i < data_len-3) { 288 - // hash next 3 bytes of data to be compressed 736 + // hash next 3 bytes of data to be compressed 289 737 int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; 290 738 unsigned char *bestloc = 0; 291 739 unsigned char **hlist = hash_table[h]; ··· 298 746 } 299 747 // when hash table entry is too long, delete half the entries 300 748 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); 749 + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); 302 750 stbiw__sbn(hash_table[h]) = quality; 303 751 } 304 752 stbiw__sbpush(hash_table[h],data+i); ··· 321 769 322 770 if (bestloc) { 323 771 int d = (int) (data+i - bestloc); // distance back 324 - assert(d <= 32767 && best <= 258); 772 + STBIW_ASSERT(d <= 32767 && best <= 258); 325 773 for (j=0; best > lengthc[j+1]-1; ++j); 326 774 stbiw__zlib_huff(j+257); 327 775 if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); ··· 347 795 348 796 { 349 797 // compute adler32 on input 350 - unsigned int i=0, s1=1, s2=0, blocklen = data_len % 5552; 351 - int j=0; 798 + unsigned int k=0, s1=1, s2=0; 799 + int blocklen = (int) (data_len % 5552); 800 + j=0; 352 801 while (j < data_len) { 353 802 for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1; 354 803 s1 %= 65521, s2 %= 65521; ··· 362 811 } 363 812 *out_len = stbiw__sbn(out); 364 813 // make returned pointer freeable 365 - memmove(stbiw__sbraw(out), out, *out_len); 814 + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); 366 815 return (unsigned char *) stbiw__sbraw(out); 367 816 } 368 817 ··· 409 858 if (stride_bytes == 0) 410 859 stride_bytes = x * n; 411 860 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; } 861 + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; 862 + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } 414 863 for (j=0; j < y; ++j) { 415 864 static int mapping[] = { 0,1,2,3,4 }; 416 865 static int firstmap[] = { 0,1,0,5,6 }; ··· 449 898 } 450 899 // when we get here, best contains the filter type, and line_buffer contains the data 451 900 filt[j*(x*n+1)] = (unsigned char) best; 452 - memcpy(filt+j*(x*n+1)+1, line_buffer, x*n); 901 + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); 453 902 } 454 - free(line_buffer); 903 + STBIW_FREE(line_buffer); 455 904 zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory 456 - free(filt); 905 + STBIW_FREE(filt); 457 906 if (!zlib) return 0; 458 907 459 908 // each tag requires 12 bytes of overhead 460 - out = (unsigned char *) malloc(8 + 12+13 + 12+zlen + 12); 909 + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); 461 910 if (!out) return 0; 462 911 *out_len = 8 + 12+13 + 12+zlen + 12; 463 912 464 913 o=out; 465 - memcpy(o,sig,8); o+= 8; 914 + STBIW_MEMMOVE(o,sig,8); o+= 8; 466 915 stbiw__wp32(o, 13); // header length 467 916 stbiw__wptag(o, "IHDR"); 468 917 stbiw__wp32(o, x); ··· 476 925 477 926 stbiw__wp32(o, zlen); 478 927 stbiw__wptag(o, "IDAT"); 479 - memcpy(o, zlib, zlen); o += zlen; free(zlib); 928 + STBIW_MEMMOVE(o, zlib, zlen); 929 + o += zlen; 930 + STBIW_FREE(zlib); 480 931 stbiw__wpcrc(&o, zlen); 481 932 482 933 stbiw__wp32(o,0); 483 934 stbiw__wptag(o, "IEND"); 484 935 stbiw__wpcrc(&o,0); 485 936 486 - assert(o == out + *out_len); 937 + STBIW_ASSERT(o == out + *out_len); 487 938 488 939 return out; 489 940 } 490 941 491 - int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) 942 + #ifndef STBI_WRITE_NO_STDIO 943 + STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) 492 944 { 493 945 FILE *f; 494 946 int len; 495 947 unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); 496 - if (!png) return 0; 948 + if (png == NULL) return 0; 497 949 f = fopen(filename, "wb"); 498 - if (!f) { free(png); return 0; } 950 + if (!f) { STBIW_FREE(png); return 0; } 499 951 fwrite(png, 1, len, f); 500 952 fclose(f); 501 - free(png); 953 + STBIW_FREE(png); 954 + return 1; 955 + } 956 + #endif 957 + 958 + 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) 959 + { 960 + int len; 961 + unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len); 962 + if (png == NULL) return 0; 963 + func(context, png, len); 964 + STBIW_FREE(png); 502 965 return 1; 503 966 } 967 + 504 968 #endif // STB_IMAGE_WRITE_IMPLEMENTATION 505 969 506 970 /* Revision history 507 - 971 + 1.00 (2015-09-14) 972 + installable file IO function 973 + 0.99 (2015-09-13) 974 + warning fixes; TGA rle support 975 + 0.98 (2015-04-08) 976 + added STBIW_MALLOC, STBIW_ASSERT etc 977 + 0.97 (2015-01-18) 978 + fixed HDR asserts, rewrote HDR rle logic 979 + 0.96 (2015-01-17) 980 + add HDR output 981 + fix monochrome BMP 982 + 0.95 (2014-08-17) 983 + add monochrome TGA output 508 984 0.94 (2014-05-31) 509 985 rename private functions to avoid conflicts with stb_image.h 510 986 0.93 (2014-05-27)