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
7 #define STB_IMAGE_WRITE_IMPLEMENTATION
9 in the file that you want to have the implementation.
11 Will probably not work correctly with strict-aliasing optimizations.
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.
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.
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
28 You can define STBIW_MEMMOVE() to replace memmove()
32 There are four functions, one for each image file format:
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);
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:
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);
47 where the callback is:
48 void stbi_write_func(void *context, void *data, int size);
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.
54 Each function returns 0 on failure and non-0 on success.
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.
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
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.)
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.
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.
95 initial file IO callback implementation
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.
116 #ifndef INCLUDE_STB_IMAGE_WRITE_H
117 #define INCLUDE_STB_IMAGE_WRITE_H
123 #ifdef STB_IMAGE_WRITE_STATIC
124 #define STBIWDEF static
126 #define STBIWDEF extern
127 extern int stbi_write_tga_with_rle
;
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
);
137 typedef void stbi_write_func(void *context
, void *data
, int size
);
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
);
148 #endif//INCLUDE_STB_IMAGE_WRITE_H
150 #ifdef STB_IMAGE_WRITE_IMPLEMENTATION
153 #ifndef _CRT_SECURE_NO_WARNINGS
154 #define _CRT_SECURE_NO_WARNINGS
156 #ifndef _CRT_NONSTDC_NO_DEPRECATE
157 #define _CRT_NONSTDC_NO_DEPRECATE
161 #ifndef STBI_WRITE_NO_STDIO
163 #endif // STBI_WRITE_NO_STDIO
170 #if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED))
172 #elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED)
175 #error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)."
179 #define STBIW_MALLOC(sz) malloc(sz)
180 #define STBIW_REALLOC(p,newsz) realloc(p,newsz)
181 #define STBIW_FREE(p) free(p)
184 #ifndef STBIW_REALLOC_SIZED
185 #define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz)
189 #ifndef STBIW_MEMMOVE
190 #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
196 #define STBIW_ASSERT(x) assert(x)
199 #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
203 stbi_write_func
*func
;
205 } stbi__write_context
;
207 // initialize a callback-based context
208 static void stbi__start_write_callbacks(stbi__write_context
*s
, stbi_write_func
*c
, void *context
)
211 s
->context
= context
;
214 #ifndef STBI_WRITE_NO_STDIO
216 static void stbi__stdio_write(void *context
, void *data
, int size
)
218 fwrite(data
,1,size
,(FILE*) context
);
221 static int stbi__start_write_file(stbi__write_context
*s
, const char *filename
)
223 FILE *f
= fopen(filename
, "wb");
224 stbi__start_write_callbacks(s
, stbi__stdio_write
, (void *) f
);
228 static void stbi__end_write_file(stbi__write_context
*s
)
230 fclose((FILE *)s
->context
);
233 #endif // !STBI_WRITE_NO_STDIO
235 typedef unsigned int stbiw_uint32
;
236 typedef int stb_image_write_test
[sizeof(stbiw_uint32
)==4 ? 1 : -1];
238 #ifdef STB_IMAGE_WRITE_STATIC
239 static int stbi_write_tga_with_rle
= 1;
241 int stbi_write_tga_with_rle
= 1;
244 static void stbiw__writefv(stbi__write_context
*s
, const char *fmt
, va_list v
)
249 case '1': { unsigned char x
= STBIW_UCHAR(va_arg(v
, int));
250 s
->func(s
->context
,&x
,1);
252 case '2': { int x
= va_arg(v
,int);
254 b
[0] = STBIW_UCHAR(x
);
255 b
[1] = STBIW_UCHAR(x
>>8);
256 s
->func(s
->context
,b
,2);
258 case '4': { stbiw_uint32 x
= va_arg(v
,int);
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);
273 static void stbiw__writef(stbi__write_context
*s
, const char *fmt
, ...)
277 stbiw__writefv(s
, fmt
, v
);
281 static void stbiw__write3(stbi__write_context
*s
, unsigned char a
, unsigned char b
, unsigned char c
)
283 unsigned char arr
[3];
284 arr
[0] = a
, arr
[1] = b
, arr
[2] = c
;
285 s
->func(s
->context
, arr
, 3);
288 static void stbiw__write_pixel(stbi__write_context
*s
, int rgb_dir
, int comp
, int write_alpha
, int expand_mono
, unsigned char *d
)
290 unsigned char bg
[3] = { 255, 0, 255}, px
[3];
294 s
->func(s
->context
, &d
[comp
- 1], 1);
298 s
->func(s
->context
,d
,1);
302 stbiw__write3(s
, d
[0], d
[0], d
[0]); // monochrome bmp
304 s
->func(s
->context
, d
, 1); // monochrome TGA
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
]);
316 stbiw__write3(s
, d
[1 - rgb_dir
], d
[1], d
[1 + rgb_dir
]);
320 s
->func(s
->context
, &d
[comp
- 1], 1);
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
)
325 stbiw_uint32 zero
= 0;
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
);
341 s
->func(s
->context
, &zero
, scanline_pad
);
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
, ...)
347 if (y
< 0 || x
< 0) {
352 stbiw__writefv(s
, fmt
, v
);
354 stbiw__write_pixels(s
,rgb_dir
,vdir
,x
,y
,comp
,data
,alpha
,pad
, expand_mono
);
359 static int stbi_write_bmp_core(stbi__write_context
*s
, int x
, int y
, int comp
, const void *data
)
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
368 STBIWDEF
int stbi_write_bmp_to_func(stbi_write_func
*func
, void *context
, int x
, int y
, int comp
, const void *data
)
370 stbi__write_context s
;
371 stbi__start_write_callbacks(&s
, func
, context
);
372 return stbi_write_bmp_core(&s
, x
, y
, comp
, data
);
375 #ifndef STBI_WRITE_NO_STDIO
376 STBIWDEF
int stbi_write_bmp(char const *filename
, int x
, int y
, int comp
, const void *data
)
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
);
386 #endif //!STBI_WRITE_NO_STDIO
388 static int stbi_write_tga_core(stbi__write_context
*s
, int x
, int y
, int comp
, void *data
)
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
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);
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);
405 for (j
= y
- 1; j
>= 0; --j
) {
406 unsigned char *row
= (unsigned char *) data
+ j
* x
* comp
;
409 for (i
= 0; i
< x
; i
+= len
) {
410 unsigned char *begin
= row
+ i
* comp
;
416 diff
= memcmp(begin
, row
+ (i
+ 1) * comp
, comp
);
418 const unsigned char *prev
= begin
;
419 for (k
= i
+ 2; k
< x
&& len
< 128; ++k
) {
420 if (memcmp(prev
, row
+ k
* comp
, comp
)) {
429 for (k
= i
+ 2; k
< x
&& len
< 128; ++k
) {
430 if (!memcmp(begin
, row
+ k
* comp
, comp
)) {
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
);
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
);
456 int stbi_write_tga_to_func(stbi_write_func
*func
, void *context
, int x
, int y
, int comp
, const void *data
)
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
);
463 #ifndef STBI_WRITE_NO_STDIO
464 int stbi_write_tga(char const *filename
, int x
, int y
, int comp
, const void *data
)
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
);
476 // *************************************************************************************************
477 // Radiance RGBE HDR writer
478 // by Baldur Karlsson
480 #define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
482 void stbiw__linear_to_rgbe(unsigned char *rgbe
, float *linear
)
485 float maxcomp
= stbiw__max(linear
[0], stbiw__max(linear
[1], linear
[2]));
487 if (maxcomp
< 1e-32f
) {
488 rgbe
[0] = rgbe
[1] = rgbe
[2] = rgbe
[3] = 0;
490 float normalize
= (float) frexp(maxcomp
, &exponent
) * 256.0f
/maxcomp
;
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);
499 void stbiw__write_run_data(stbi__write_context
*s
, int length
, unsigned char databyte
)
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);
507 void stbiw__write_dump_data(stbi__write_context
*s
, int length
, unsigned char *data
)
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
);
515 void stbiw__write_hdr_scanline(stbi__write_context
*s
, int width
, int ncomp
, unsigned char *scratch
, float *scanline
)
517 unsigned char scanlineheader
[4] = { 2, 2, 0, 0 };
518 unsigned char rgbe
[4];
522 scanlineheader
[2] = (width
&0xff00)>>8;
523 scanlineheader
[3] = (width
&0x00ff);
525 /* skip RLE for images too small or large */
526 if (width
< 8 || width
>= 32768) {
527 for (x
=0; x
< width
; x
++) {
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];
535 linear
[0] = linear
[1] = linear
[2] = scanline
[x
*ncomp
+ 0];
538 stbiw__linear_to_rgbe(rgbe
, linear
);
539 s
->func(s
->context
, rgbe
, 4);
543 /* encode into scratch buffer */
544 for (x
=0; x
< width
; x
++) {
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];
552 linear
[0] = linear
[1] = linear
[2] = scanline
[x
*ncomp
+ 0];
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];
562 s
->func(s
->context
, scanlineheader
, 4);
564 /* RLE each component separately */
565 for (c
=0; c
< 4; c
++) {
566 unsigned char *comp
= &scratch
[width
*c
];
572 while (r
+2 < width
) {
573 if (comp
[r
] == comp
[r
+1] && comp
[r
] == comp
[r
+2])
579 // dump up to first run
582 if (len
> 128) len
= 128;
583 stbiw__write_dump_data(s
, len
, &comp
[x
]);
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
])
591 // output run up to r
594 if (len
> 127) len
= 127;
595 stbiw__write_run_data(s
, len
, comp
[x
]);
604 static int stbi_write_hdr_core(stbi__write_context
*s
, int x
, int y
, int comp
, float *data
)
606 if (y
<= 0 || x
<= 0 || data
== NULL
)
609 // Each component is stored separately. Allocate scratch space for full output scanline.
610 unsigned char *scratch
= (unsigned char *) STBIW_MALLOC(x
*4);
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);
616 len
= sprintf(buffer
, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y
, x
);
617 s
->func(s
->context
, buffer
, len
);
620 stbiw__write_hdr_scanline(s
, x
, comp
, scratch
, data
+ comp
*i
*x
);
626 int stbi_write_hdr_to_func(stbi_write_func
*func
, void *context
, int x
, int y
, int comp
, const float *data
)
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
);
633 #ifndef STBI_WRITE_NO_STDIO
634 int stbi_write_hdr(char const *filename
, int x
, int y
, int comp
, const float *data
)
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
);
644 #endif // STBI_WRITE_NO_STDIO
647 //////////////////////////////////////////////////////////////////////////////
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]
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)))
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)
665 static void *stbiw__sbgrowf(void **arr
, int increment
, int itemsize
)
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);
671 if (!*arr
) ((int *) p
)[1] = 0;
672 *arr
= (void *) ((int *) p
+ 2);
673 stbiw__sbm(*arr
) = m
;
678 static unsigned char *stbiw__zlib_flushf(unsigned char *data
, unsigned int *bitbuffer
, int *bitcount
)
680 while (*bitcount
>= 8) {
681 stbiw__sbpush(data
, STBIW_UCHAR(*bitbuffer
));
688 static int stbiw__zlib_bitrev(int code
, int codebits
)
692 res
= (res
<< 1) | (code
& 1);
698 static unsigned int stbiw__zlib_countm(unsigned char *a
, unsigned char *b
, int limit
)
701 for (i
=0; i
< limit
&& i
< 258; ++i
)
702 if (a
[i
] != b
[i
]) break;
706 static unsigned int stbiw__zhash(unsigned char *data
)
708 stbiw_uint32 hash
= data
[0] + (data
[1] << 8) + (data
[2] << 16);
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))
730 #define stbiw__ZHASH 16384
732 unsigned char * stbi_zlib_compress(unsigned char *data
, int data_len
, int *out_len
, int quality
)
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;
740 unsigned char *out
= NULL
;
741 unsigned char ***hash_table
= (unsigned char***) STBIW_MALLOC(stbiw__ZHASH
* sizeof(char**));
742 if (quality
< 5) quality
= 5;
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
749 for (i
=0; i
< stbiw__ZHASH
; ++i
)
750 hash_table
[i
] = NULL
;
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
];
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
;
770 stbiw__sbpush(hash_table
[h
],data
+i
);
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
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
]);
799 stbiw__zlib_huffb(data
[i
]);
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
809 stbiw__zlib_add(0,1);
811 for (i
=0; i
< stbiw__ZHASH
; ++i
)
812 (void) stbiw__sbfree(hash_table
[i
]);
813 STBIW_FREE(hash_table
);
816 // compute adler32 on input
817 unsigned int s1
=1, s2
=0;
818 int blocklen
= (int) (data_len
% 5552);
820 while (j
< data_len
) {
821 for (i
=0; i
< blocklen
; ++i
) s1
+= data
[j
+i
], s2
+= s1
;
822 s1
%= 65521, s2
%= 65521;
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
));
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
);
837 static unsigned int stbiw__crc32(unsigned char *buffer
, int len
)
839 static unsigned int crc_table
[256] =
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
875 unsigned int crc
= ~0u;
877 for (i
=0; i
< len
; ++i
)
878 crc
= (crc
>> 8) ^ crc_table
[buffer
[i
] ^ (crc
& 0xff)];
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])
886 static void stbiw__wpcrc(unsigned char **data
, int len
)
888 unsigned int crc
= stbiw__crc32(*data
- len
- 4, len
+4);
889 stbiw__wp32(*data
, crc
);
892 static unsigned char stbiw__paeth(int a
, int b
, int c
)
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
);
900 unsigned char *stbi_write_png_to_mem(unsigned char *pixels
, int stride_bytes
, int x
, int y
, int n
, int *out_len
)
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
;
908 if (stride_bytes
== 0)
909 stride_bytes
= x
* n
;
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
)
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;
932 for (i
=n
; i
< x
*n
; ++i
) {
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;
944 for (i
=0; i
< x
*n
; ++i
)
945 est
+= abs((signed char) line_buffer
[i
]);
946 if (est
< bestval
) { bestval
= est
; best
= k
; }
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
);
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
958 // each tag requires 12 bytes of overhead
959 out
= (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen
+ 12);
961 *out_len
= 8 + 12+13 + 12+zlen
+ 12;
964 STBIW_MEMMOVE(o
,sig
,8); o
+= 8;
965 stbiw__wp32(o
, 13); // header length
966 stbiw__wptag(o
, "IHDR");
970 *o
++ = STBIW_UCHAR(ctype
[n
]);
976 stbiw__wp32(o
, zlen
);
977 stbiw__wptag(o
, "IDAT");
978 STBIW_MEMMOVE(o
, zlib
, zlen
);
981 stbiw__wpcrc(&o
, zlen
);
984 stbiw__wptag(o
, "IEND");
987 STBIW_ASSERT(o
== out
+ *out_len
);
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
)
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
);
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
)
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
);
1018 #endif // STB_IMAGE_WRITE_IMPLEMENTATION
1022 avoid allocating large structures on the stack
1024 STBIW_REALLOC_SIZED: support allocators with no realloc support
1025 avoid race-condition in crc initialization
1026 minor compile issues
1028 installable file IO function
1030 warning fixes; TGA rle support
1032 added STBIW_MALLOC, STBIW_ASSERT etc
1034 fixed HDR asserts, rewrote HDR rle logic
1039 add monochrome TGA output
1041 rename private functions to avoid conflicts with stb_image.h
1045 casts to unsigned char to fix warnings
1047 first public release
1048 0.90 first internal release