comments updated
[henge/apc.git] / stb / stb_image_write.h
1 /* stb_image_write - v1.03 - 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 github:poppolopoppo
107
108 LICENSE
109
110 This software is dual-licensed to the public domain and under the following
111 license: you are granted a perpetual, irrevocable license to copy, modify,
112 publish, and distribute this file as you see fit.
113
114 */
115
116 #ifndef INCLUDE_STB_IMAGE_WRITE_H
117 #define INCLUDE_STB_IMAGE_WRITE_H
118
119 #ifdef __cplusplus
120 extern "C" {
121 #endif
122
123 #ifdef STB_IMAGE_WRITE_STATIC
124 #define STBIWDEF static
125 #else
126 #define STBIWDEF extern
127 extern int stbi_write_tga_with_rle;
128 #endif
129
130 #ifndef STBI_WRITE_NO_STDIO
131 STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
132 STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
133 STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
134 STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
135 #endif
136
137 typedef void stbi_write_func(void *context, void *data, int size);
138
139 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);
140 STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
141 STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
142 STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
143
144 #ifdef __cplusplus
145 }
146 #endif
147
148 #endif//INCLUDE_STB_IMAGE_WRITE_H
149
150 #ifdef STB_IMAGE_WRITE_IMPLEMENTATION
151
152 #ifdef _WIN32
153 #ifndef _CRT_SECURE_NO_WARNINGS
154 #define _CRT_SECURE_NO_WARNINGS
155 #endif
156 #ifndef _CRT_NONSTDC_NO_DEPRECATE
157 #define _CRT_NONSTDC_NO_DEPRECATE
158 #endif
159 #endif
160
161 #ifndef STBI_WRITE_NO_STDIO
162 #include <stdio.h>
163 #endif // STBI_WRITE_NO_STDIO
164
165 #include <stdarg.h>
166 #include <stdlib.h>
167 #include <string.h>
168 #include <math.h>
169
170 #if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED))
171 // ok
172 #elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED)
173 // ok
174 #else
175 #error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)."
176 #endif
177
178 #ifndef STBIW_MALLOC
179 #define STBIW_MALLOC(sz) malloc(sz)
180 #define STBIW_REALLOC(p,newsz) realloc(p,newsz)
181 #define STBIW_FREE(p) free(p)
182 #endif
183
184 #ifndef STBIW_REALLOC_SIZED
185 #define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz)
186 #endif
187
188
189 #ifndef STBIW_MEMMOVE
190 #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
191 #endif
192
193
194 #ifndef STBIW_ASSERT
195 #include <assert.h>
196 #define STBIW_ASSERT(x) assert(x)
197 #endif
198
199 #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
200
201 typedef struct
202 {
203 stbi_write_func *func;
204 void *context;
205 } stbi__write_context;
206
207 // initialize a callback-based context
208 static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context)
209 {
210 s->func = c;
211 s->context = context;
212 }
213
214 #ifndef STBI_WRITE_NO_STDIO
215
216 static void stbi__stdio_write(void *context, void *data, int size)
217 {
218 fwrite(data,1,size,(FILE*) context);
219 }
220
221 static int stbi__start_write_file(stbi__write_context *s, const char *filename)
222 {
223 FILE *f = fopen(filename, "wb");
224 stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f);
225 return f != NULL;
226 }
227
228 static void stbi__end_write_file(stbi__write_context *s)
229 {
230 fclose((FILE *)s->context);
231 }
232
233 #endif // !STBI_WRITE_NO_STDIO
234
235 typedef unsigned int stbiw_uint32;
236 typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
237
238 #ifdef STB_IMAGE_WRITE_STATIC
239 static int stbi_write_tga_with_rle = 1;
240 #else
241 int stbi_write_tga_with_rle = 1;
242 #endif
243
244 static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v)
245 {
246 while (*fmt) {
247 switch (*fmt++) {
248 case ' ': break;
249 case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int));
250 s->func(s->context,&x,1);
251 break; }
252 case '2': { int x = va_arg(v,int);
253 unsigned char b[2];
254 b[0] = STBIW_UCHAR(x);
255 b[1] = STBIW_UCHAR(x>>8);
256 s->func(s->context,b,2);
257 break; }
258 case '4': { stbiw_uint32 x = va_arg(v,int);
259 unsigned char b[4];
260 b[0]=STBIW_UCHAR(x);
261 b[1]=STBIW_UCHAR(x>>8);
262 b[2]=STBIW_UCHAR(x>>16);
263 b[3]=STBIW_UCHAR(x>>24);
264 s->func(s->context,b,4);
265 break; }
266 default:
267 STBIW_ASSERT(0);
268 return;
269 }
270 }
271 }
272
273 static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
274 {
275 va_list v;
276 va_start(v, fmt);
277 stbiw__writefv(s, fmt, v);
278 va_end(v);
279 }
280
281 static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
282 {
283 unsigned char arr[3];
284 arr[0] = a, arr[1] = b, arr[2] = c;
285 s->func(s->context, arr, 3);
286 }
287
288 static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
289 {
290 unsigned char bg[3] = { 255, 0, 255}, px[3];
291 int k;
292
293 if (write_alpha < 0)
294 s->func(s->context, &d[comp - 1], 1);
295
296 switch (comp) {
297 case 1:
298 s->func(s->context,d,1);
299 break;
300 case 2:
301 if (expand_mono)
302 stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp
303 else
304 s->func(s->context, d, 1); // monochrome TGA
305 break;
306 case 4:
307 if (!write_alpha) {
308 // composite against pink background
309 for (k = 0; k < 3; ++k)
310 px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
311 stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]);
312 break;
313 }
314 /* FALLTHROUGH */
315 case 3:
316 stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
317 break;
318 }
319 if (write_alpha > 0)
320 s->func(s->context, &d[comp - 1], 1);
321 }
322
323 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)
324 {
325 stbiw_uint32 zero = 0;
326 int i,j, j_end;
327
328 if (y <= 0)
329 return;
330
331 if (vdir < 0)
332 j_end = -1, j = y-1;
333 else
334 j_end = y, j = 0;
335
336 for (; j != j_end; j += vdir) {
337 for (i=0; i < x; ++i) {
338 unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
339 stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
340 }
341 s->func(s->context, &zero, scanline_pad);
342 }
343 }
344
345 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, ...)
346 {
347 if (y < 0 || x < 0) {
348 return 0;
349 } else {
350 va_list v;
351 va_start(v, fmt);
352 stbiw__writefv(s, fmt, v);
353 va_end(v);
354 stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono);
355 return 1;
356 }
357 }
358
359 static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
360 {
361 int pad = (-x*3) & 3;
362 return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
363 "11 4 22 4" "4 44 22 444444",
364 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
365 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
366 }
367
368 STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
369 {
370 stbi__write_context s;
371 stbi__start_write_callbacks(&s, func, context);
372 return stbi_write_bmp_core(&s, x, y, comp, data);
373 }
374
375 #ifndef STBI_WRITE_NO_STDIO
376 STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
377 {
378 stbi__write_context s;
379 if (stbi__start_write_file(&s,filename)) {
380 int r = stbi_write_bmp_core(&s, x, y, comp, data);
381 stbi__end_write_file(&s);
382 return r;
383 } else
384 return 0;
385 }
386 #endif //!STBI_WRITE_NO_STDIO
387
388 static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data)
389 {
390 int has_alpha = (comp == 2 || comp == 4);
391 int colorbytes = has_alpha ? comp-1 : comp;
392 int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3
393
394 if (y < 0 || x < 0)
395 return 0;
396
397 if (!stbi_write_tga_with_rle) {
398 return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0,
399 "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
400 } else {
401 int i,j,k;
402
403 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);
404
405 for (j = y - 1; j >= 0; --j) {
406 unsigned char *row = (unsigned char *) data + j * x * comp;
407 int len;
408
409 for (i = 0; i < x; i += len) {
410 unsigned char *begin = row + i * comp;
411 int diff = 1;
412 len = 1;
413
414 if (i < x - 1) {
415 ++len;
416 diff = memcmp(begin, row + (i + 1) * comp, comp);
417 if (diff) {
418 const unsigned char *prev = begin;
419 for (k = i + 2; k < x && len < 128; ++k) {
420 if (memcmp(prev, row + k * comp, comp)) {
421 prev += comp;
422 ++len;
423 } else {
424 --len;
425 break;
426 }
427 }
428 } else {
429 for (k = i + 2; k < x && len < 128; ++k) {
430 if (!memcmp(begin, row + k * comp, comp)) {
431 ++len;
432 } else {
433 break;
434 }
435 }
436 }
437 }
438
439 if (diff) {
440 unsigned char header = STBIW_UCHAR(len - 1);
441 s->func(s->context, &header, 1);
442 for (k = 0; k < len; ++k) {
443 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
444 }
445 } else {
446 unsigned char header = STBIW_UCHAR(len - 129);
447 s->func(s->context, &header, 1);
448 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
449 }
450 }
451 }
452 }
453 return 1;
454 }
455
456 int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
457 {
458 stbi__write_context s;
459 stbi__start_write_callbacks(&s, func, context);
460 return stbi_write_tga_core(&s, x, y, comp, (void *) data);
461 }
462
463 #ifndef STBI_WRITE_NO_STDIO
464 int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
465 {
466 stbi__write_context s;
467 if (stbi__start_write_file(&s,filename)) {
468 int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
469 stbi__end_write_file(&s);
470 return r;
471 } else
472 return 0;
473 }
474 #endif
475
476 // *************************************************************************************************
477 // Radiance RGBE HDR writer
478 // by Baldur Karlsson
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 #ifndef STBI_WRITE_NO_STDIO
634 int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
635 {
636 stbi__write_context s;
637 if (stbi__start_write_file(&s,filename)) {
638 int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
639 stbi__end_write_file(&s);
640 return r;
641 } else
642 return 0;
643 }
644 #endif // STBI_WRITE_NO_STDIO
645
646
647 //////////////////////////////////////////////////////////////////////////////
648 //
649 // PNG writer
650 //
651
652 // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
653 #define stbiw__sbraw(a) ((int *) (a) - 2)
654 #define stbiw__sbm(a) stbiw__sbraw(a)[0]
655 #define stbiw__sbn(a) stbiw__sbraw(a)[1]
656
657 #define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
658 #define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
659 #define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
660
661 #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
662 #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
663 #define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
664
665 static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
666 {
667 int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
668 void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2);
669 STBIW_ASSERT(p);
670 if (p) {
671 if (!*arr) ((int *) p)[1] = 0;
672 *arr = (void *) ((int *) p + 2);
673 stbiw__sbm(*arr) = m;
674 }
675 return *arr;
676 }
677
678 static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
679 {
680 while (*bitcount >= 8) {
681 stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
682 *bitbuffer >>= 8;
683 *bitcount -= 8;
684 }
685 return data;
686 }
687
688 static int stbiw__zlib_bitrev(int code, int codebits)
689 {
690 int res=0;
691 while (codebits--) {
692 res = (res << 1) | (code & 1);
693 code >>= 1;
694 }
695 return res;
696 }
697
698 static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit)
699 {
700 int i;
701 for (i=0; i < limit && i < 258; ++i)
702 if (a[i] != b[i]) break;
703 return i;
704 }
705
706 static unsigned int stbiw__zhash(unsigned char *data)
707 {
708 stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
709 hash ^= hash << 3;
710 hash += hash >> 5;
711 hash ^= hash << 4;
712 hash += hash >> 17;
713 hash ^= hash << 25;
714 hash += hash >> 6;
715 return hash;
716 }
717
718 #define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
719 #define stbiw__zlib_add(code,codebits) \
720 (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
721 #define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
722 // default huffman tables
723 #define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8)
724 #define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9)
725 #define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7)
726 #define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8)
727 #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))
728 #define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
729
730 #define stbiw__ZHASH 16384
731
732 unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
733 {
734 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 };
735 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 };
736 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 };
737 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 };
738 unsigned int bitbuf=0;
739 int i,j, bitcount=0;
740 unsigned char *out = NULL;
741 unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(char**));
742 if (quality < 5) quality = 5;
743
744 stbiw__sbpush(out, 0x78); // DEFLATE 32K window
745 stbiw__sbpush(out, 0x5e); // FLEVEL = 1
746 stbiw__zlib_add(1,1); // BFINAL = 1
747 stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman
748
749 for (i=0; i < stbiw__ZHASH; ++i)
750 hash_table[i] = NULL;
751
752 i=0;
753 while (i < data_len-3) {
754 // hash next 3 bytes of data to be compressed
755 int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
756 unsigned char *bestloc = 0;
757 unsigned char **hlist = hash_table[h];
758 int n = stbiw__sbcount(hlist);
759 for (j=0; j < n; ++j) {
760 if (hlist[j]-data > i-32768) { // if entry lies within window
761 int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
762 if (d >= best) best=d,bestloc=hlist[j];
763 }
764 }
765 // when hash table entry is too long, delete half the entries
766 if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
767 STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
768 stbiw__sbn(hash_table[h]) = quality;
769 }
770 stbiw__sbpush(hash_table[h],data+i);
771
772 if (bestloc) {
773 // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal
774 h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
775 hlist = hash_table[h];
776 n = stbiw__sbcount(hlist);
777 for (j=0; j < n; ++j) {
778 if (hlist[j]-data > i-32767) {
779 int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
780 if (e > best) { // if next match is better, bail on current match
781 bestloc = NULL;
782 break;
783 }
784 }
785 }
786 }
787
788 if (bestloc) {
789 int d = (int) (data+i - bestloc); // distance back
790 STBIW_ASSERT(d <= 32767 && best <= 258);
791 for (j=0; best > lengthc[j+1]-1; ++j);
792 stbiw__zlib_huff(j+257);
793 if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
794 for (j=0; d > distc[j+1]-1; ++j);
795 stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
796 if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
797 i += best;
798 } else {
799 stbiw__zlib_huffb(data[i]);
800 ++i;
801 }
802 }
803 // write out final bytes
804 for (;i < data_len; ++i)
805 stbiw__zlib_huffb(data[i]);
806 stbiw__zlib_huff(256); // end of block
807 // pad with 0 bits to byte boundary
808 while (bitcount)
809 stbiw__zlib_add(0,1);
810
811 for (i=0; i < stbiw__ZHASH; ++i)
812 (void) stbiw__sbfree(hash_table[i]);
813 STBIW_FREE(hash_table);
814
815 {
816 // compute adler32 on input
817 unsigned int s1=1, s2=0;
818 int blocklen = (int) (data_len % 5552);
819 j=0;
820 while (j < data_len) {
821 for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
822 s1 %= 65521, s2 %= 65521;
823 j += blocklen;
824 blocklen = 5552;
825 }
826 stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
827 stbiw__sbpush(out, STBIW_UCHAR(s2));
828 stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
829 stbiw__sbpush(out, STBIW_UCHAR(s1));
830 }
831 *out_len = stbiw__sbn(out);
832 // make returned pointer freeable
833 STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
834 return (unsigned char *) stbiw__sbraw(out);
835 }
836
837 static unsigned int stbiw__crc32(unsigned char *buffer, int len)
838 {
839 static unsigned int crc_table[256] =
840 {
841 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
842 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
843 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
844 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
845 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
846 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
847 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
848 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
849 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
850 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
851 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
852 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
853 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
854 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
855 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
856 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
857 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
858 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
859 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
860 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
861 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
862 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
863 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
864 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
865 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
866 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
867 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
868 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
869 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
870 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
871 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
872 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
873 };
874
875 unsigned int crc = ~0u;
876 int i;
877 for (i=0; i < len; ++i)
878 crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
879 return ~crc;
880 }
881
882 #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)
883 #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
884 #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
885
886 static void stbiw__wpcrc(unsigned char **data, int len)
887 {
888 unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
889 stbiw__wp32(*data, crc);
890 }
891
892 static unsigned char stbiw__paeth(int a, int b, int c)
893 {
894 int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
895 if (pa <= pb && pa <= pc) return STBIW_UCHAR(a);
896 if (pb <= pc) return STBIW_UCHAR(b);
897 return STBIW_UCHAR(c);
898 }
899
900 unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
901 {
902 int ctype[5] = { -1, 0, 4, 2, 6 };
903 unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
904 unsigned char *out,*o, *filt, *zlib;
905 signed char *line_buffer;
906 int i,j,k,p,zlen;
907
908 if (stride_bytes == 0)
909 stride_bytes = x * n;
910
911 filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
912 line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
913 for (j=0; j < y; ++j) {
914 static int mapping[] = { 0,1,2,3,4 };
915 static int firstmap[] = { 0,1,0,5,6 };
916 int *mymap = j ? mapping : firstmap;
917 int best = 0, bestval = 0x7fffffff;
918 for (p=0; p < 2; ++p) {
919 for (k= p?best:0; k < 5; ++k) {
920 int type = mymap[k],est=0;
921 unsigned char *z = pixels + stride_bytes*j;
922 for (i=0; i < n; ++i)
923 switch (type) {
924 case 0: line_buffer[i] = z[i]; break;
925 case 1: line_buffer[i] = z[i]; break;
926 case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
927 case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break;
928 case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break;
929 case 5: line_buffer[i] = z[i]; break;
930 case 6: line_buffer[i] = z[i]; break;
931 }
932 for (i=n; i < x*n; ++i) {
933 switch (type) {
934 case 0: line_buffer[i] = z[i]; break;
935 case 1: line_buffer[i] = z[i] - z[i-n]; break;
936 case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
937 case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break;
938 case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break;
939 case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break;
940 case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
941 }
942 }
943 if (p) break;
944 for (i=0; i < x*n; ++i)
945 est += abs((signed char) line_buffer[i]);
946 if (est < bestval) { bestval = est; best = k; }
947 }
948 }
949 // when we get here, best contains the filter type, and line_buffer contains the data
950 filt[j*(x*n+1)] = (unsigned char) best;
951 STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
952 }
953 STBIW_FREE(line_buffer);
954 zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory
955 STBIW_FREE(filt);
956 if (!zlib) return 0;
957
958 // each tag requires 12 bytes of overhead
959 out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
960 if (!out) return 0;
961 *out_len = 8 + 12+13 + 12+zlen + 12;
962
963 o=out;
964 STBIW_MEMMOVE(o,sig,8); o+= 8;
965 stbiw__wp32(o, 13); // header length
966 stbiw__wptag(o, "IHDR");
967 stbiw__wp32(o, x);
968 stbiw__wp32(o, y);
969 *o++ = 8;
970 *o++ = STBIW_UCHAR(ctype[n]);
971 *o++ = 0;
972 *o++ = 0;
973 *o++ = 0;
974 stbiw__wpcrc(&o,13);
975
976 stbiw__wp32(o, zlen);
977 stbiw__wptag(o, "IDAT");
978 STBIW_MEMMOVE(o, zlib, zlen);
979 o += zlen;
980 STBIW_FREE(zlib);
981 stbiw__wpcrc(&o, zlen);
982
983 stbiw__wp32(o,0);
984 stbiw__wptag(o, "IEND");
985 stbiw__wpcrc(&o,0);
986
987 STBIW_ASSERT(o == out + *out_len);
988
989 return out;
990 }
991
992 #ifndef STBI_WRITE_NO_STDIO
993 STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
994 {
995 FILE *f;
996 int len;
997 unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
998 if (png == NULL) return 0;
999 f = fopen(filename, "wb");
1000 if (!f) { STBIW_FREE(png); return 0; }
1001 fwrite(png, 1, len, f);
1002 fclose(f);
1003 STBIW_FREE(png);
1004 return 1;
1005 }
1006 #endif
1007
1008 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)
1009 {
1010 int len;
1011 unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
1012 if (png == NULL) return 0;
1013 func(context, png, len);
1014 STBIW_FREE(png);
1015 return 1;
1016 }
1017
1018 #endif // STB_IMAGE_WRITE_IMPLEMENTATION
1019
1020 /* Revision history
1021 1.02 (2016-04-02)
1022 avoid allocating large structures on the stack
1023 1.01 (2016-01-16)
1024 STBIW_REALLOC_SIZED: support allocators with no realloc support
1025 avoid race-condition in crc initialization
1026 minor compile issues
1027 1.00 (2015-09-14)
1028 installable file IO function
1029 0.99 (2015-09-13)
1030 warning fixes; TGA rle support
1031 0.98 (2015-04-08)
1032 added STBIW_MALLOC, STBIW_ASSERT etc
1033 0.97 (2015-01-18)
1034 fixed HDR asserts, rewrote HDR rle logic
1035 0.96 (2015-01-17)
1036 add HDR output
1037 fix monochrome BMP
1038 0.95 (2014-08-17)
1039 add monochrome TGA output
1040 0.94 (2014-05-31)
1041 rename private functions to avoid conflicts with stb_image.h
1042 0.93 (2014-05-27)
1043 warning fixes
1044 0.92 (2010-08-01)
1045 casts to unsigned char to fix warnings
1046 0.91 (2010-07-17)
1047 first public release
1048 0.90 first internal release
1049 */