DEADSOFTWARE

thanks git, very cool
[d2df-sdl.git] / src / tools / png2map / stb_image_write.h
1 /* stb_image_write - v1.13 - public domain - http://nothings.org/stb
2 writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015
3 no warranty implied; use at your own risk
5 Before #including,
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.
13 ABOUT:
15 This header file is a library for writing images to C stdio or a callback.
17 The PNG output is not optimal; it is 20-50% larger than the file
18 written by a decent optimizing implementation; though providing a custom
19 zlib compress function (see STBIW_ZLIB_COMPRESS) can mitigate that.
20 This library is designed for source code compactness and simplicity,
21 not optimal image file size or run-time performance.
23 BUILDING:
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 You can #define STBIW_ZLIB_COMPRESS to use a custom zlib-style compress function
30 for PNG compression (instead of the builtin one), it must have the following signature:
31 unsigned char * my_compress(unsigned char *data, int data_len, int *out_len, int quality);
32 The returned data will be freed with STBIW_FREE() (free() by default),
33 so it must be heap allocated with STBIW_MALLOC() (malloc() by default),
35 UNICODE:
37 If compiling for Windows and you wish to use Unicode filenames, compile
38 with
39 #define STBIW_WINDOWS_UTF8
40 and pass utf8-encoded filenames. Call stbiw_convert_wchar_to_utf8 to convert
41 Windows wchar_t filenames to utf8.
43 USAGE:
45 There are five functions, one for each image file format:
47 int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
48 int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
49 int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
50 int stbi_write_jpg(char const *filename, int w, int h, int comp, const void *data, int quality);
51 int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
53 void stbi_flip_vertically_on_write(int flag); // flag is non-zero to flip data vertically
55 There are also five equivalent functions that use an arbitrary write function. You are
56 expected to open/close your file-equivalent before and after calling these:
58 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);
59 int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
60 int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
61 int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
62 int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality);
64 where the callback is:
65 void stbi_write_func(void *context, void *data, int size);
67 You can configure it with these global variables:
68 int stbi_write_tga_with_rle; // defaults to true; set to 0 to disable RLE
69 int stbi_write_png_compression_level; // defaults to 8; set to higher for more compression
70 int stbi_write_force_png_filter; // defaults to -1; set to 0..5 to force a filter mode
73 You can define STBI_WRITE_NO_STDIO to disable the file variant of these
74 functions, so the library will not use stdio.h at all. However, this will
75 also disable HDR writing, because it requires stdio for formatted output.
77 Each function returns 0 on failure and non-0 on success.
79 The functions create an image file defined by the parameters. The image
80 is a rectangle of pixels stored from left-to-right, top-to-bottom.
81 Each pixel contains 'comp' channels of data stored interleaved with 8-bits
82 per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is
83 monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall.
84 The *data pointer points to the first byte of the top-left-most pixel.
85 For PNG, "stride_in_bytes" is the distance in bytes from the first byte of
86 a row of pixels to the first byte of the next row of pixels.
88 PNG creates output files with the same number of components as the input.
89 The BMP format expands Y to RGB in the file format and does not
90 output alpha.
92 PNG supports writing rectangles of data even when the bytes storing rows of
93 data are not consecutive in memory (e.g. sub-rectangles of a larger image),
94 by supplying the stride between the beginning of adjacent rows. The other
95 formats do not. (Thus you cannot write a native-format BMP through the BMP
96 writer, both because it is in BGR order and because it may have padding
97 at the end of the line.)
99 PNG allows you to set the deflate compression level by setting the global
100 variable 'stbi_write_png_compression_level' (it defaults to 8).
102 HDR expects linear float data. Since the format is always 32-bit rgb(e)
103 data, alpha (if provided) is discarded, and for monochrome data it is
104 replicated across all three channels.
106 TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed
107 data, set the global variable 'stbi_write_tga_with_rle' to 0.
109 JPEG does ignore alpha channels in input data; quality is between 1 and 100.
110 Higher quality looks better but results in a bigger image.
111 JPEG baseline (no JPEG progressive).
113 CREDITS:
116 Sean Barrett - PNG/BMP/TGA
117 Baldur Karlsson - HDR
118 Jean-Sebastien Guay - TGA monochrome
119 Tim Kelsey - misc enhancements
120 Alan Hickman - TGA RLE
121 Emmanuel Julien - initial file IO callback implementation
122 Jon Olick - original jo_jpeg.cpp code
123 Daniel Gibson - integrate JPEG, allow external zlib
124 Aarni Koskela - allow choosing PNG filter
126 bugfixes:
127 github:Chribba
128 Guillaume Chereau
129 github:jry2
130 github:romigrou
131 Sergio Gonzalez
132 Jonas Karlsson
133 Filip Wasil
134 Thatcher Ulrich
135 github:poppolopoppo
136 Patrick Boettcher
137 github:xeekworx
138 Cap Petschulat
139 Simon Rodriguez
140 Ivan Tikhonov
141 github:ignotion
142 Adam Schackart
144 LICENSE
146 See end of file for license information.
148 */
150 #ifndef INCLUDE_STB_IMAGE_WRITE_H
151 #define INCLUDE_STB_IMAGE_WRITE_H
153 #include <stdlib.h>
155 // if STB_IMAGE_WRITE_STATIC causes problems, try defining STBIWDEF to 'inline' or 'static inline'
156 #ifndef STBIWDEF
157 #ifdef STB_IMAGE_WRITE_STATIC
158 #define STBIWDEF static
159 #else
160 #ifdef __cplusplus
161 #define STBIWDEF extern "C"
162 #else
163 #define STBIWDEF extern
164 #endif
165 #endif
166 #endif
168 #ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations
169 extern int stbi_write_tga_with_rle;
170 extern int stbi_write_png_compression_level;
171 extern int stbi_write_force_png_filter;
172 #endif
174 #ifndef STBI_WRITE_NO_STDIO
175 STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
176 STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
177 STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
178 STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
179 STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality);
181 #ifdef STBI_WINDOWS_UTF8
182 STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
183 #endif
184 #endif
186 typedef void stbi_write_func(void *context, void *data, int size);
188 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);
189 STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
190 STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
191 STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
192 STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality);
194 STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean);
196 #endif//INCLUDE_STB_IMAGE_WRITE_H
198 #ifdef STB_IMAGE_WRITE_IMPLEMENTATION
200 #ifdef _WIN32
201 #ifndef _CRT_SECURE_NO_WARNINGS
202 #define _CRT_SECURE_NO_WARNINGS
203 #endif
204 #ifndef _CRT_NONSTDC_NO_DEPRECATE
205 #define _CRT_NONSTDC_NO_DEPRECATE
206 #endif
207 #endif
209 #ifndef STBI_WRITE_NO_STDIO
210 #include <stdio.h>
211 #endif // STBI_WRITE_NO_STDIO
213 #include <stdarg.h>
214 #include <stdlib.h>
215 #include <string.h>
216 #include <math.h>
218 #if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED))
219 // ok
220 #elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED)
221 // ok
222 #else
223 #error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)."
224 #endif
226 #ifndef STBIW_MALLOC
227 #define STBIW_MALLOC(sz) malloc(sz)
228 #define STBIW_REALLOC(p,newsz) realloc(p,newsz)
229 #define STBIW_FREE(p) free(p)
230 #endif
232 #ifndef STBIW_REALLOC_SIZED
233 #define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz)
234 #endif
237 #ifndef STBIW_MEMMOVE
238 #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
239 #endif
242 #ifndef STBIW_ASSERT
243 #include <assert.h>
244 #define STBIW_ASSERT(x) assert(x)
245 #endif
247 #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
249 #ifdef STB_IMAGE_WRITE_STATIC
250 static int stbi__flip_vertically_on_write=0;
251 static int stbi_write_png_compression_level = 8;
252 static int stbi_write_tga_with_rle = 1;
253 static int stbi_write_force_png_filter = -1;
254 #else
255 int stbi_write_png_compression_level = 8;
256 int stbi__flip_vertically_on_write=0;
257 int stbi_write_tga_with_rle = 1;
258 int stbi_write_force_png_filter = -1;
259 #endif
261 STBIWDEF void stbi_flip_vertically_on_write(int flag)
263 stbi__flip_vertically_on_write = flag;
266 typedef struct
268 stbi_write_func *func;
269 void *context;
270 } stbi__write_context;
272 // initialize a callback-based context
273 static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context)
275 s->func = c;
276 s->context = context;
279 #ifndef STBI_WRITE_NO_STDIO
281 static void stbi__stdio_write(void *context, void *data, int size)
283 fwrite(data,1,size,(FILE*) context);
286 #if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
287 #ifdef __cplusplus
288 #define STBIW_EXTERN extern "C"
289 #else
290 #define STBIW_EXTERN extern
291 #endif
292 STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide);
293 STBIW_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default);
295 STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input)
297 return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL);
299 #endif
301 static FILE *stbiw__fopen(char const *filename, char const *mode)
303 FILE *f;
304 #if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
305 wchar_t wMode[64];
306 wchar_t wFilename[1024];
307 if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)))
308 return 0;
310 if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)))
311 return 0;
313 #if _MSC_VER >= 1400
314 if (0 != _wfopen_s(&f, wFilename, wMode))
315 f = 0;
316 #else
317 f = _wfopen(wFilename, wMode);
318 #endif
320 #elif defined(_MSC_VER) && _MSC_VER >= 1400
321 if (0 != fopen_s(&f, filename, mode))
322 f=0;
323 #else
324 f = fopen(filename, mode);
325 #endif
326 return f;
329 static int stbi__start_write_file(stbi__write_context *s, const char *filename)
331 FILE *f = stbiw__fopen(filename, "wb");
332 stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f);
333 return f != NULL;
336 static void stbi__end_write_file(stbi__write_context *s)
338 fclose((FILE *)s->context);
341 #endif // !STBI_WRITE_NO_STDIO
343 typedef unsigned int stbiw_uint32;
344 typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
346 static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v)
348 while (*fmt) {
349 switch (*fmt++) {
350 case ' ': break;
351 case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int));
352 s->func(s->context,&x,1);
353 break; }
354 case '2': { int x = va_arg(v,int);
355 unsigned char b[2];
356 b[0] = STBIW_UCHAR(x);
357 b[1] = STBIW_UCHAR(x>>8);
358 s->func(s->context,b,2);
359 break; }
360 case '4': { stbiw_uint32 x = va_arg(v,int);
361 unsigned char b[4];
362 b[0]=STBIW_UCHAR(x);
363 b[1]=STBIW_UCHAR(x>>8);
364 b[2]=STBIW_UCHAR(x>>16);
365 b[3]=STBIW_UCHAR(x>>24);
366 s->func(s->context,b,4);
367 break; }
368 default:
369 STBIW_ASSERT(0);
370 return;
375 static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
377 va_list v;
378 va_start(v, fmt);
379 stbiw__writefv(s, fmt, v);
380 va_end(v);
383 static void stbiw__putc(stbi__write_context *s, unsigned char c)
385 s->func(s->context, &c, 1);
388 static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
390 unsigned char arr[3];
391 arr[0] = a; arr[1] = b; arr[2] = c;
392 s->func(s->context, arr, 3);
395 static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
397 unsigned char bg[3] = { 255, 0, 255}, px[3];
398 int k;
400 if (write_alpha < 0)
401 s->func(s->context, &d[comp - 1], 1);
403 switch (comp) {
404 case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case
405 case 1:
406 if (expand_mono)
407 stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp
408 else
409 s->func(s->context, d, 1); // monochrome TGA
410 break;
411 case 4:
412 if (!write_alpha) {
413 // composite against pink background
414 for (k = 0; k < 3; ++k)
415 px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
416 stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]);
417 break;
419 /* FALLTHROUGH */
420 case 3:
421 stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
422 break;
424 if (write_alpha > 0)
425 s->func(s->context, &d[comp - 1], 1);
428 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)
430 stbiw_uint32 zero = 0;
431 int i,j, j_end;
433 if (y <= 0)
434 return;
436 if (stbi__flip_vertically_on_write)
437 vdir *= -1;
439 if (vdir < 0) {
440 j_end = -1; j = y-1;
441 } else {
442 j_end = y; j = 0;
445 for (; j != j_end; j += vdir) {
446 for (i=0; i < x; ++i) {
447 unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
448 stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
450 s->func(s->context, &zero, scanline_pad);
454 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, ...)
456 if (y < 0 || x < 0) {
457 return 0;
458 } else {
459 va_list v;
460 va_start(v, fmt);
461 stbiw__writefv(s, fmt, v);
462 va_end(v);
463 stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono);
464 return 1;
468 static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
470 int pad = (-x*3) & 3;
471 return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
472 "11 4 22 4" "4 44 22 444444",
473 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
474 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
477 STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
479 stbi__write_context s;
480 stbi__start_write_callbacks(&s, func, context);
481 return stbi_write_bmp_core(&s, x, y, comp, data);
484 #ifndef STBI_WRITE_NO_STDIO
485 STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
487 stbi__write_context s;
488 if (stbi__start_write_file(&s,filename)) {
489 int r = stbi_write_bmp_core(&s, x, y, comp, data);
490 stbi__end_write_file(&s);
491 return r;
492 } else
493 return 0;
495 #endif //!STBI_WRITE_NO_STDIO
497 static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data)
499 int has_alpha = (comp == 2 || comp == 4);
500 int colorbytes = has_alpha ? comp-1 : comp;
501 int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3
503 if (y < 0 || x < 0)
504 return 0;
506 if (!stbi_write_tga_with_rle) {
507 return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0,
508 "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
509 } else {
510 int i,j,k;
511 int jend, jdir;
513 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);
515 if (stbi__flip_vertically_on_write) {
516 j = 0;
517 jend = y;
518 jdir = 1;
519 } else {
520 j = y-1;
521 jend = -1;
522 jdir = -1;
524 for (; j != jend; j += jdir) {
525 unsigned char *row = (unsigned char *) data + j * x * comp;
526 int len;
528 for (i = 0; i < x; i += len) {
529 unsigned char *begin = row + i * comp;
530 int diff = 1;
531 len = 1;
533 if (i < x - 1) {
534 ++len;
535 diff = memcmp(begin, row + (i + 1) * comp, comp);
536 if (diff) {
537 const unsigned char *prev = begin;
538 for (k = i + 2; k < x && len < 128; ++k) {
539 if (memcmp(prev, row + k * comp, comp)) {
540 prev += comp;
541 ++len;
542 } else {
543 --len;
544 break;
547 } else {
548 for (k = i + 2; k < x && len < 128; ++k) {
549 if (!memcmp(begin, row + k * comp, comp)) {
550 ++len;
551 } else {
552 break;
558 if (diff) {
559 unsigned char header = STBIW_UCHAR(len - 1);
560 s->func(s->context, &header, 1);
561 for (k = 0; k < len; ++k) {
562 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
564 } else {
565 unsigned char header = STBIW_UCHAR(len - 129);
566 s->func(s->context, &header, 1);
567 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
572 return 1;
575 STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
577 stbi__write_context s;
578 stbi__start_write_callbacks(&s, func, context);
579 return stbi_write_tga_core(&s, x, y, comp, (void *) data);
582 #ifndef STBI_WRITE_NO_STDIO
583 STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
585 stbi__write_context s;
586 if (stbi__start_write_file(&s,filename)) {
587 int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
588 stbi__end_write_file(&s);
589 return r;
590 } else
591 return 0;
593 #endif
595 // *************************************************************************************************
596 // Radiance RGBE HDR writer
597 // by Baldur Karlsson
599 #define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
601 static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
603 int exponent;
604 float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
606 if (maxcomp < 1e-32f) {
607 rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
608 } else {
609 float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
611 rgbe[0] = (unsigned char)(linear[0] * normalize);
612 rgbe[1] = (unsigned char)(linear[1] * normalize);
613 rgbe[2] = (unsigned char)(linear[2] * normalize);
614 rgbe[3] = (unsigned char)(exponent + 128);
618 static void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
620 unsigned char lengthbyte = STBIW_UCHAR(length+128);
621 STBIW_ASSERT(length+128 <= 255);
622 s->func(s->context, &lengthbyte, 1);
623 s->func(s->context, &databyte, 1);
626 static void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
628 unsigned char lengthbyte = STBIW_UCHAR(length);
629 STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
630 s->func(s->context, &lengthbyte, 1);
631 s->func(s->context, data, length);
634 static void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline)
636 unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
637 unsigned char rgbe[4];
638 float linear[3];
639 int x;
641 scanlineheader[2] = (width&0xff00)>>8;
642 scanlineheader[3] = (width&0x00ff);
644 /* skip RLE for images too small or large */
645 if (width < 8 || width >= 32768) {
646 for (x=0; x < width; x++) {
647 switch (ncomp) {
648 case 4: /* fallthrough */
649 case 3: linear[2] = scanline[x*ncomp + 2];
650 linear[1] = scanline[x*ncomp + 1];
651 linear[0] = scanline[x*ncomp + 0];
652 break;
653 default:
654 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
655 break;
657 stbiw__linear_to_rgbe(rgbe, linear);
658 s->func(s->context, rgbe, 4);
660 } else {
661 int c,r;
662 /* encode into scratch buffer */
663 for (x=0; x < width; x++) {
664 switch(ncomp) {
665 case 4: /* fallthrough */
666 case 3: linear[2] = scanline[x*ncomp + 2];
667 linear[1] = scanline[x*ncomp + 1];
668 linear[0] = scanline[x*ncomp + 0];
669 break;
670 default:
671 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
672 break;
674 stbiw__linear_to_rgbe(rgbe, linear);
675 scratch[x + width*0] = rgbe[0];
676 scratch[x + width*1] = rgbe[1];
677 scratch[x + width*2] = rgbe[2];
678 scratch[x + width*3] = rgbe[3];
681 s->func(s->context, scanlineheader, 4);
683 /* RLE each component separately */
684 for (c=0; c < 4; c++) {
685 unsigned char *comp = &scratch[width*c];
687 x = 0;
688 while (x < width) {
689 // find first run
690 r = x;
691 while (r+2 < width) {
692 if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
693 break;
694 ++r;
696 if (r+2 >= width)
697 r = width;
698 // dump up to first run
699 while (x < r) {
700 int len = r-x;
701 if (len > 128) len = 128;
702 stbiw__write_dump_data(s, len, &comp[x]);
703 x += len;
705 // if there's a run, output it
706 if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd
707 // find next byte after run
708 while (r < width && comp[r] == comp[x])
709 ++r;
710 // output run up to r
711 while (x < r) {
712 int len = r-x;
713 if (len > 127) len = 127;
714 stbiw__write_run_data(s, len, comp[x]);
715 x += len;
723 static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data)
725 if (y <= 0 || x <= 0 || data == NULL)
726 return 0;
727 else {
728 // Each component is stored separately. Allocate scratch space for full output scanline.
729 unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
730 int i, len;
731 char buffer[128];
732 char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
733 s->func(s->context, header, sizeof(header)-1);
735 #ifdef __STDC_WANT_SECURE_LIB__
736 len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
737 #else
738 len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
739 #endif
740 s->func(s->context, buffer, len);
742 for(i=0; i < y; i++)
743 stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i));
744 STBIW_FREE(scratch);
745 return 1;
749 STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
751 stbi__write_context s;
752 stbi__start_write_callbacks(&s, func, context);
753 return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
756 #ifndef STBI_WRITE_NO_STDIO
757 STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
759 stbi__write_context s;
760 if (stbi__start_write_file(&s,filename)) {
761 int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
762 stbi__end_write_file(&s);
763 return r;
764 } else
765 return 0;
767 #endif // STBI_WRITE_NO_STDIO
770 //////////////////////////////////////////////////////////////////////////////
771 //
772 // PNG writer
773 //
775 #ifndef STBIW_ZLIB_COMPRESS
776 // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
777 #define stbiw__sbraw(a) ((int *) (a) - 2)
778 #define stbiw__sbm(a) stbiw__sbraw(a)[0]
779 #define stbiw__sbn(a) stbiw__sbraw(a)[1]
781 #define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
782 #define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
783 #define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
785 #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
786 #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
787 #define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
789 static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
791 int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
792 void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2);
793 STBIW_ASSERT(p);
794 if (p) {
795 if (!*arr) ((int *) p)[1] = 0;
796 *arr = (void *) ((int *) p + 2);
797 stbiw__sbm(*arr) = m;
799 return *arr;
802 static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
804 while (*bitcount >= 8) {
805 stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
806 *bitbuffer >>= 8;
807 *bitcount -= 8;
809 return data;
812 static int stbiw__zlib_bitrev(int code, int codebits)
814 int res=0;
815 while (codebits--) {
816 res = (res << 1) | (code & 1);
817 code >>= 1;
819 return res;
822 static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit)
824 int i;
825 for (i=0; i < limit && i < 258; ++i)
826 if (a[i] != b[i]) break;
827 return i;
830 static unsigned int stbiw__zhash(unsigned char *data)
832 stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
833 hash ^= hash << 3;
834 hash += hash >> 5;
835 hash ^= hash << 4;
836 hash += hash >> 17;
837 hash ^= hash << 25;
838 hash += hash >> 6;
839 return hash;
842 #define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
843 #define stbiw__zlib_add(code,codebits) \
844 (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
845 #define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
846 // default huffman tables
847 #define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8)
848 #define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9)
849 #define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7)
850 #define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8)
851 #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))
852 #define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
854 #define stbiw__ZHASH 16384
856 #endif // STBIW_ZLIB_COMPRESS
858 STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
860 #ifdef STBIW_ZLIB_COMPRESS
861 // user provided a zlib compress implementation, use that
862 return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality);
863 #else // use builtin
864 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 };
865 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 };
866 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 };
867 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 };
868 unsigned int bitbuf=0;
869 int i,j, bitcount=0;
870 unsigned char *out = NULL;
871 unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(unsigned char**));
872 if (hash_table == NULL)
873 return NULL;
874 if (quality < 5) quality = 5;
876 stbiw__sbpush(out, 0x78); // DEFLATE 32K window
877 stbiw__sbpush(out, 0x5e); // FLEVEL = 1
878 stbiw__zlib_add(1,1); // BFINAL = 1
879 stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman
881 for (i=0; i < stbiw__ZHASH; ++i)
882 hash_table[i] = NULL;
884 i=0;
885 while (i < data_len-3) {
886 // hash next 3 bytes of data to be compressed
887 int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
888 unsigned char *bestloc = 0;
889 unsigned char **hlist = hash_table[h];
890 int n = stbiw__sbcount(hlist);
891 for (j=0; j < n; ++j) {
892 if (hlist[j]-data > i-32768) { // if entry lies within window
893 int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
894 if (d >= best) { best=d; bestloc=hlist[j]; }
897 // when hash table entry is too long, delete half the entries
898 if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
899 STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
900 stbiw__sbn(hash_table[h]) = quality;
902 stbiw__sbpush(hash_table[h],data+i);
904 if (bestloc) {
905 // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal
906 h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
907 hlist = hash_table[h];
908 n = stbiw__sbcount(hlist);
909 for (j=0; j < n; ++j) {
910 if (hlist[j]-data > i-32767) {
911 int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
912 if (e > best) { // if next match is better, bail on current match
913 bestloc = NULL;
914 break;
920 if (bestloc) {
921 int d = (int) (data+i - bestloc); // distance back
922 STBIW_ASSERT(d <= 32767 && best <= 258);
923 for (j=0; best > lengthc[j+1]-1; ++j);
924 stbiw__zlib_huff(j+257);
925 if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
926 for (j=0; d > distc[j+1]-1; ++j);
927 stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
928 if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
929 i += best;
930 } else {
931 stbiw__zlib_huffb(data[i]);
932 ++i;
935 // write out final bytes
936 for (;i < data_len; ++i)
937 stbiw__zlib_huffb(data[i]);
938 stbiw__zlib_huff(256); // end of block
939 // pad with 0 bits to byte boundary
940 while (bitcount)
941 stbiw__zlib_add(0,1);
943 for (i=0; i < stbiw__ZHASH; ++i)
944 (void) stbiw__sbfree(hash_table[i]);
945 STBIW_FREE(hash_table);
948 // compute adler32 on input
949 unsigned int s1=1, s2=0;
950 int blocklen = (int) (data_len % 5552);
951 j=0;
952 while (j < data_len) {
953 for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; }
954 s1 %= 65521; s2 %= 65521;
955 j += blocklen;
956 blocklen = 5552;
958 stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
959 stbiw__sbpush(out, STBIW_UCHAR(s2));
960 stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
961 stbiw__sbpush(out, STBIW_UCHAR(s1));
963 *out_len = stbiw__sbn(out);
964 // make returned pointer freeable
965 STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
966 return (unsigned char *) stbiw__sbraw(out);
967 #endif // STBIW_ZLIB_COMPRESS
970 static unsigned int stbiw__crc32(unsigned char *buffer, int len)
972 #ifdef STBIW_CRC32
973 return STBIW_CRC32(buffer, len);
974 #else
975 static unsigned int crc_table[256] =
977 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
978 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
979 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
980 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
981 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
982 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
983 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
984 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
985 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
986 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
987 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
988 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
989 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
990 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
991 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
992 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
993 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
994 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
995 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
996 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
997 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
998 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
999 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
1000 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
1001 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
1002 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
1003 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
1004 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
1005 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
1006 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
1007 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
1008 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
1009 };
1011 unsigned int crc = ~0u;
1012 int i;
1013 for (i=0; i < len; ++i)
1014 crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
1015 return ~crc;
1016 #endif
1019 #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)
1020 #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
1021 #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
1023 static void stbiw__wpcrc(unsigned char **data, int len)
1025 unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
1026 stbiw__wp32(*data, crc);
1029 static unsigned char stbiw__paeth(int a, int b, int c)
1031 int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
1032 if (pa <= pb && pa <= pc) return STBIW_UCHAR(a);
1033 if (pb <= pc) return STBIW_UCHAR(b);
1034 return STBIW_UCHAR(c);
1037 // @OPTIMIZE: provide an option that always forces left-predict or paeth predict
1038 static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int width, int height, int y, int n, int filter_type, signed char *line_buffer)
1040 static int mapping[] = { 0,1,2,3,4 };
1041 static int firstmap[] = { 0,1,0,5,6 };
1042 int *mymap = (y != 0) ? mapping : firstmap;
1043 int i;
1044 int type = mymap[filter_type];
1045 unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y);
1046 int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes;
1048 if (type==0) {
1049 memcpy(line_buffer, z, width*n);
1050 return;
1053 // first loop isn't optimized since it's just one pixel
1054 for (i = 0; i < n; ++i) {
1055 switch (type) {
1056 case 1: line_buffer[i] = z[i]; break;
1057 case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break;
1058 case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1); break;
1059 case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0)); break;
1060 case 5: line_buffer[i] = z[i]; break;
1061 case 6: line_buffer[i] = z[i]; break;
1064 switch (type) {
1065 case 1: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n]; break;
1066 case 2: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride]; break;
1067 case 3: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break;
1068 case 4: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]); break;
1069 case 5: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1); break;
1070 case 6: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
1074 STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
1076 int force_filter = stbi_write_force_png_filter;
1077 int ctype[5] = { -1, 0, 4, 2, 6 };
1078 unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
1079 unsigned char *out,*o, *filt, *zlib;
1080 signed char *line_buffer;
1081 int j,zlen;
1083 if (stride_bytes == 0)
1084 stride_bytes = x * n;
1086 if (force_filter >= 5) {
1087 force_filter = -1;
1090 filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
1091 line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
1092 for (j=0; j < y; ++j) {
1093 int filter_type;
1094 if (force_filter > -1) {
1095 filter_type = force_filter;
1096 stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer);
1097 } else { // Estimate the best filter by running through all of them:
1098 int best_filter = 0, best_filter_val = 0x7fffffff, est, i;
1099 for (filter_type = 0; filter_type < 5; filter_type++) {
1100 stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer);
1102 // Estimate the entropy of the line using this filter; the less, the better.
1103 est = 0;
1104 for (i = 0; i < x*n; ++i) {
1105 est += abs((signed char) line_buffer[i]);
1107 if (est < best_filter_val) {
1108 best_filter_val = est;
1109 best_filter = filter_type;
1112 if (filter_type != best_filter) { // If the last iteration already got us the best filter, don't redo it
1113 stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer);
1114 filter_type = best_filter;
1117 // when we get here, filter_type contains the filter type, and line_buffer contains the data
1118 filt[j*(x*n+1)] = (unsigned char) filter_type;
1119 STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
1121 STBIW_FREE(line_buffer);
1122 zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_compression_level);
1123 STBIW_FREE(filt);
1124 if (!zlib) return 0;
1126 // each tag requires 12 bytes of overhead
1127 out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
1128 if (!out) return 0;
1129 *out_len = 8 + 12+13 + 12+zlen + 12;
1131 o=out;
1132 STBIW_MEMMOVE(o,sig,8); o+= 8;
1133 stbiw__wp32(o, 13); // header length
1134 stbiw__wptag(o, "IHDR");
1135 stbiw__wp32(o, x);
1136 stbiw__wp32(o, y);
1137 *o++ = 8;
1138 *o++ = STBIW_UCHAR(ctype[n]);
1139 *o++ = 0;
1140 *o++ = 0;
1141 *o++ = 0;
1142 stbiw__wpcrc(&o,13);
1144 stbiw__wp32(o, zlen);
1145 stbiw__wptag(o, "IDAT");
1146 STBIW_MEMMOVE(o, zlib, zlen);
1147 o += zlen;
1148 STBIW_FREE(zlib);
1149 stbiw__wpcrc(&o, zlen);
1151 stbiw__wp32(o,0);
1152 stbiw__wptag(o, "IEND");
1153 stbiw__wpcrc(&o,0);
1155 STBIW_ASSERT(o == out + *out_len);
1157 return out;
1160 #ifndef STBI_WRITE_NO_STDIO
1161 STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
1163 FILE *f;
1164 int len;
1165 unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len);
1166 if (png == NULL) return 0;
1168 f = stbiw__fopen(filename, "wb");
1169 if (!f) { STBIW_FREE(png); return 0; }
1170 fwrite(png, 1, len, f);
1171 fclose(f);
1172 STBIW_FREE(png);
1173 return 1;
1175 #endif
1177 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)
1179 int len;
1180 unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len);
1181 if (png == NULL) return 0;
1182 func(context, png, len);
1183 STBIW_FREE(png);
1184 return 1;
1188 /* ***************************************************************************
1190 * JPEG writer
1192 * This is based on Jon Olick's jo_jpeg.cpp:
1193 * public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html
1194 */
1196 static const unsigned char stbiw__jpg_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18,
1197 24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 };
1199 static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) {
1200 int bitBuf = *bitBufP, bitCnt = *bitCntP;
1201 bitCnt += bs[1];
1202 bitBuf |= bs[0] << (24 - bitCnt);
1203 while(bitCnt >= 8) {
1204 unsigned char c = (bitBuf >> 16) & 255;
1205 stbiw__putc(s, c);
1206 if(c == 255) {
1207 stbiw__putc(s, 0);
1209 bitBuf <<= 8;
1210 bitCnt -= 8;
1212 *bitBufP = bitBuf;
1213 *bitCntP = bitCnt;
1216 static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) {
1217 float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p;
1218 float z1, z2, z3, z4, z5, z11, z13;
1220 float tmp0 = d0 + d7;
1221 float tmp7 = d0 - d7;
1222 float tmp1 = d1 + d6;
1223 float tmp6 = d1 - d6;
1224 float tmp2 = d2 + d5;
1225 float tmp5 = d2 - d5;
1226 float tmp3 = d3 + d4;
1227 float tmp4 = d3 - d4;
1229 // Even part
1230 float tmp10 = tmp0 + tmp3; // phase 2
1231 float tmp13 = tmp0 - tmp3;
1232 float tmp11 = tmp1 + tmp2;
1233 float tmp12 = tmp1 - tmp2;
1235 d0 = tmp10 + tmp11; // phase 3
1236 d4 = tmp10 - tmp11;
1238 z1 = (tmp12 + tmp13) * 0.707106781f; // c4
1239 d2 = tmp13 + z1; // phase 5
1240 d6 = tmp13 - z1;
1242 // Odd part
1243 tmp10 = tmp4 + tmp5; // phase 2
1244 tmp11 = tmp5 + tmp6;
1245 tmp12 = tmp6 + tmp7;
1247 // The rotator is modified from fig 4-8 to avoid extra negations.
1248 z5 = (tmp10 - tmp12) * 0.382683433f; // c6
1249 z2 = tmp10 * 0.541196100f + z5; // c2-c6
1250 z4 = tmp12 * 1.306562965f + z5; // c2+c6
1251 z3 = tmp11 * 0.707106781f; // c4
1253 z11 = tmp7 + z3; // phase 5
1254 z13 = tmp7 - z3;
1256 *d5p = z13 + z2; // phase 6
1257 *d3p = z13 - z2;
1258 *d1p = z11 + z4;
1259 *d7p = z11 - z4;
1261 *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6;
1264 static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) {
1265 int tmp1 = val < 0 ? -val : val;
1266 val = val < 0 ? val-1 : val;
1267 bits[1] = 1;
1268 while(tmp1 >>= 1) {
1269 ++bits[1];
1271 bits[0] = val & ((1<<bits[1])-1);
1274 static int stbiw__jpg_processDU(stbi__write_context *s, int *bitBuf, int *bitCnt, float *CDU, float *fdtbl, int DC, const unsigned short HTDC[256][2], const unsigned short HTAC[256][2]) {
1275 const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
1276 const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
1277 int dataOff, i, diff, end0pos;
1278 int DU[64];
1280 // DCT rows
1281 for(dataOff=0; dataOff<64; dataOff+=8) {
1282 stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+1], &CDU[dataOff+2], &CDU[dataOff+3], &CDU[dataOff+4], &CDU[dataOff+5], &CDU[dataOff+6], &CDU[dataOff+7]);
1284 // DCT columns
1285 for(dataOff=0; dataOff<8; ++dataOff) {
1286 stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+8], &CDU[dataOff+16], &CDU[dataOff+24], &CDU[dataOff+32], &CDU[dataOff+40], &CDU[dataOff+48], &CDU[dataOff+56]);
1288 // Quantize/descale/zigzag the coefficients
1289 for(i=0; i<64; ++i) {
1290 float v = CDU[i]*fdtbl[i];
1291 // DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? ceilf(v - 0.5f) : floorf(v + 0.5f));
1292 // ceilf() and floorf() are C99, not C89, but I /think/ they're not needed here anyway?
1293 DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
1296 // Encode DC
1297 diff = DU[0] - DC;
1298 if (diff == 0) {
1299 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]);
1300 } else {
1301 unsigned short bits[2];
1302 stbiw__jpg_calcBits(diff, bits);
1303 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]);
1304 stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1306 // Encode ACs
1307 end0pos = 63;
1308 for(; (end0pos>0)&&(DU[end0pos]==0); --end0pos) {
1310 // end0pos = first element in reverse order !=0
1311 if(end0pos == 0) {
1312 stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1313 return DU[0];
1315 for(i = 1; i <= end0pos; ++i) {
1316 int startpos = i;
1317 int nrzeroes;
1318 unsigned short bits[2];
1319 for (; DU[i]==0 && i<=end0pos; ++i) {
1321 nrzeroes = i-startpos;
1322 if ( nrzeroes >= 16 ) {
1323 int lng = nrzeroes>>4;
1324 int nrmarker;
1325 for (nrmarker=1; nrmarker <= lng; ++nrmarker)
1326 stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes);
1327 nrzeroes &= 15;
1329 stbiw__jpg_calcBits(DU[i], bits);
1330 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]);
1331 stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1333 if(end0pos != 63) {
1334 stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1336 return DU[0];
1339 static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) {
1340 // Constants that don't pollute global namespace
1341 static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0};
1342 static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1343 static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d};
1344 static const unsigned char std_ac_luminance_values[] = {
1345 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
1346 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
1347 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
1348 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
1349 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
1350 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
1351 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1352 };
1353 static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0};
1354 static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1355 static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77};
1356 static const unsigned char std_ac_chrominance_values[] = {
1357 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
1358 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
1359 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
1360 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
1361 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
1362 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
1363 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1364 };
1365 // Huffman tables
1366 static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}};
1367 static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}};
1368 static const unsigned short YAC_HT[256][2] = {
1369 {10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1370 {12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1371 {28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1372 {58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1373 {59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1374 {122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1375 {123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1376 {250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1377 {504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1378 {505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1379 {506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1380 {1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1381 {1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1382 {2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1383 {65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0},
1384 {2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0}
1385 };
1386 static const unsigned short UVAC_HT[256][2] = {
1387 {0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1388 {11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1389 {26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1390 {27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1391 {58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1392 {59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1393 {121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1394 {122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1395 {249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1396 {503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1397 {504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1398 {505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1399 {506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1400 {2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1401 {16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0},
1402 {1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0}
1403 };
1404 static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22,
1405 37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99};
1406 static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99,
1407 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};
1408 static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
1409 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f };
1411 int row, col, i, k;
1412 float fdtbl_Y[64], fdtbl_UV[64];
1413 unsigned char YTable[64], UVTable[64];
1415 if(!data || !width || !height || comp > 4 || comp < 1) {
1416 return 0;
1419 quality = quality ? quality : 90;
1420 quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
1421 quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
1423 for(i = 0; i < 64; ++i) {
1424 int uvti, yti = (YQT[i]*quality+50)/100;
1425 YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti);
1426 uvti = (UVQT[i]*quality+50)/100;
1427 UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti);
1430 for(row = 0, k = 0; row < 8; ++row) {
1431 for(col = 0; col < 8; ++col, ++k) {
1432 fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1433 fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1437 // Write Headers
1439 static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 };
1440 static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
1441 const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width),
1442 3,1,0x11,0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
1443 s->func(s->context, (void*)head0, sizeof(head0));
1444 s->func(s->context, (void*)YTable, sizeof(YTable));
1445 stbiw__putc(s, 1);
1446 s->func(s->context, UVTable, sizeof(UVTable));
1447 s->func(s->context, (void*)head1, sizeof(head1));
1448 s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1);
1449 s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values));
1450 stbiw__putc(s, 0x10); // HTYACinfo
1451 s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1);
1452 s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values));
1453 stbiw__putc(s, 1); // HTUDCinfo
1454 s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1);
1455 s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values));
1456 stbiw__putc(s, 0x11); // HTUACinfo
1457 s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1);
1458 s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values));
1459 s->func(s->context, (void*)head2, sizeof(head2));
1462 // Encode 8x8 macroblocks
1464 static const unsigned short fillBits[] = {0x7F, 7};
1465 const unsigned char *imageData = (const unsigned char *)data;
1466 int DCY=0, DCU=0, DCV=0;
1467 int bitBuf=0, bitCnt=0;
1468 // comp == 2 is grey+alpha (alpha is ignored)
1469 int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
1470 int x, y, pos;
1471 for(y = 0; y < height; y += 8) {
1472 for(x = 0; x < width; x += 8) {
1473 float YDU[64], UDU[64], VDU[64];
1474 for(row = y, pos = 0; row < y+8; ++row) {
1475 // row >= height => use last input row
1476 int clamped_row = (row < height) ? row : height - 1;
1477 int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
1478 for(col = x; col < x+8; ++col, ++pos) {
1479 float r, g, b;
1480 // if col >= width => use pixel from last input column
1481 int p = base_p + ((col < width) ? col : (width-1))*comp;
1483 r = imageData[p+0];
1484 g = imageData[p+ofsG];
1485 b = imageData[p+ofsB];
1486 YDU[pos]=+0.29900f*r+0.58700f*g+0.11400f*b-128;
1487 UDU[pos]=-0.16874f*r-0.33126f*g+0.50000f*b;
1488 VDU[pos]=+0.50000f*r-0.41869f*g-0.08131f*b;
1492 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1493 DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
1494 DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
1498 // Do the bit alignment of the EOI marker
1499 stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits);
1502 // EOI
1503 stbiw__putc(s, 0xFF);
1504 stbiw__putc(s, 0xD9);
1506 return 1;
1509 STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)
1511 stbi__write_context s;
1512 stbi__start_write_callbacks(&s, func, context);
1513 return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality);
1517 #ifndef STBI_WRITE_NO_STDIO
1518 STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
1520 stbi__write_context s;
1521 if (stbi__start_write_file(&s,filename)) {
1522 int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
1523 stbi__end_write_file(&s);
1524 return r;
1525 } else
1526 return 0;
1528 #endif
1530 #endif // STB_IMAGE_WRITE_IMPLEMENTATION
1532 /* Revision history
1533 1.11 (2019-08-11)
1535 1.10 (2019-02-07)
1536 support utf8 filenames in Windows; fix warnings and platform ifdefs
1537 1.09 (2018-02-11)
1538 fix typo in zlib quality API, improve STB_I_W_STATIC in C++
1539 1.08 (2018-01-29)
1540 add stbi__flip_vertically_on_write, external zlib, zlib quality, choose PNG filter
1541 1.07 (2017-07-24)
1542 doc fix
1543 1.06 (2017-07-23)
1544 writing JPEG (using Jon Olick's code)
1545 1.05 ???
1546 1.04 (2017-03-03)
1547 monochrome BMP expansion
1548 1.03 ???
1549 1.02 (2016-04-02)
1550 avoid allocating large structures on the stack
1551 1.01 (2016-01-16)
1552 STBIW_REALLOC_SIZED: support allocators with no realloc support
1553 avoid race-condition in crc initialization
1554 minor compile issues
1555 1.00 (2015-09-14)
1556 installable file IO function
1557 0.99 (2015-09-13)
1558 warning fixes; TGA rle support
1559 0.98 (2015-04-08)
1560 added STBIW_MALLOC, STBIW_ASSERT etc
1561 0.97 (2015-01-18)
1562 fixed HDR asserts, rewrote HDR rle logic
1563 0.96 (2015-01-17)
1564 add HDR output
1565 fix monochrome BMP
1566 0.95 (2014-08-17)
1567 add monochrome TGA output
1568 0.94 (2014-05-31)
1569 rename private functions to avoid conflicts with stb_image.h
1570 0.93 (2014-05-27)
1571 warning fixes
1572 0.92 (2010-08-01)
1573 casts to unsigned char to fix warnings
1574 0.91 (2010-07-17)
1575 first public release
1576 0.90 first internal release
1577 */
1579 /*
1580 ------------------------------------------------------------------------------
1581 This software is available under 2 licenses -- choose whichever you prefer.
1582 ------------------------------------------------------------------------------
1583 ALTERNATIVE A - MIT License
1584 Copyright (c) 2017 Sean Barrett
1585 Permission is hereby granted, free of charge, to any person obtaining a copy of
1586 this software and associated documentation files (the "Software"), to deal in
1587 the Software without restriction, including without limitation the rights to
1588 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
1589 of the Software, and to permit persons to whom the Software is furnished to do
1590 so, subject to the following conditions:
1591 The above copyright notice and this permission notice shall be included in all
1592 copies or substantial portions of the Software.
1593 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1594 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1595 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1596 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1597 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1598 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1599 SOFTWARE.
1600 ------------------------------------------------------------------------------
1601 ALTERNATIVE B - Public Domain (www.unlicense.org)
1602 This is free and unencumbered software released into the public domain.
1603 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
1604 software, either in source code form or as a compiled binary, for any purpose,
1605 commercial or non-commercial, and by any means.
1606 In jurisdictions that recognize copyright laws, the author or authors of this
1607 software dedicate any and all copyright interest in the software to the public
1608 domain. We make this dedication for the benefit of the public at large and to
1609 the detriment of our heirs and successors. We intend this dedication to be an
1610 overt act of relinquishment in perpetuity of all present and future rights to
1611 this software under copyright law.
1612 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1613 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1614 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1615 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1616 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1617 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1618 ------------------------------------------------------------------------------
1619 */