blob: 4319c0de1d93d4779909c1b561029b4979364ba6 [file] [log] [blame]
Camilla Berglundac836392016-10-13 17:42:44 +02001/* 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
13ABOUT:
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
23BUILDING:
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
30USAGE:
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
83CREDITS:
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
107LICENSE
108
109This software is dual-licensed to the public domain and under the following
110license: you are granted a perpetual, irrevocable license to copy, modify,
111publish, 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
119extern "C" {
120#endif
121
122#ifdef STB_IMAGE_WRITE_STATIC
123#define STBIWDEF static
124#else
125#define STBIWDEF extern
126extern int stbi_write_tga_with_rle;
127#endif
128
129#ifndef STBI_WRITE_NO_STDIO
130STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
131STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
132STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
133STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
134#endif
135
136typedef void stbi_write_func(void *context, void *data, int size);
137
138STBIWDEF 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);
139STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
140STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
141STBIWDEF 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
200typedef struct
201{
202 stbi_write_func *func;
203 void *context;
204} stbi__write_context;
205
206// initialize a callback-based context
207static 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
215static void stbi__stdio_write(void *context, void *data, int size)
216{
217 fwrite(data,1,size,(FILE*) context);
218}
219
220static 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
227static void stbi__end_write_file(stbi__write_context *s)
228{
229 fclose((FILE *)s->context);
230}
231
232#endif // !STBI_WRITE_NO_STDIO
233
234typedef unsigned int stbiw_uint32;
235typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
236
237#ifdef STB_IMAGE_WRITE_STATIC
238static int stbi_write_tga_with_rle = 1;
239#else
240int stbi_write_tga_with_rle = 1;
241#endif
242
243static 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
272static 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
280static 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
287static 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
322static 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
344static 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
358static 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
367STBIWDEF 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
375STBIWDEF 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
387static 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
455int 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
463int 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
482void 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
499void 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
507void 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
515void 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
604static 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
626int 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
633int 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
664static 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
677static 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
687static 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
697static 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
705static 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
731unsigned 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
836static 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
885static 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
891static 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
899unsigned 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
992STBIWDEF 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
1007STBIWDEF 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*/