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