0/* stb_image_write - v1.16 - public domain - http://nothings.org/stb
1 writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015
2 no warranty implied; use at your own risk
4 Before #including,
6 #define STB_IMAGE_WRITE_IMPLEMENTATION
8 in the file that you want to have the implementation.
10 Will probably not work correctly with strict-aliasing optimizations.
12ABOUT:
14 This header file is a library for writing images to C stdio or a callback.
16 The PNG output is not optimal; it is 20-50% larger than the file
17 written by a decent optimizing implementation; though providing a custom
18 zlib compress function (see STBIW_ZLIB_COMPRESS) can mitigate that.
19 This library is designed for source code compactness and simplicity,
20 not optimal image file size or run-time performance.
22BUILDING:
24 You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h.
25 You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace
26 malloc,realloc,free.
27 You can #define STBIW_MEMMOVE() to replace memmove()
28 You can #define STBIW_ZLIB_COMPRESS to use a custom zlib-style compress function
29 for PNG compression (instead of the builtin one), it must have the following signature:
30 unsigned char * my_compress(unsigned char *data, int data_len, int *out_len, int quality);
31 The returned data will be freed with STBIW_FREE() (free() by default),
32 so it must be heap allocated with STBIW_MALLOC() (malloc() by default),
34UNICODE:
36 If compiling for Windows and you wish to use Unicode filenames, compile
37 with
38 #define STBIW_WINDOWS_UTF8
39 and pass utf8-encoded filenames. Call stbiw_convert_wchar_to_utf8 to convert
40 Windows wchar_t filenames to utf8.
42USAGE:
44 There are five functions, one for each image file format:
46 int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
47 int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
48 int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
49 int stbi_write_jpg(char const *filename, int w, int h, int comp, const void *data, int quality);
50 int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
52 void stbi_flip_vertically_on_write(int flag); // flag is non-zero to flip data vertically
54 There are also five equivalent functions that use an arbitrary write function. You are
55 expected to open/close your file-equivalent before and after calling these:
57 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);
58 int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
59 int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
60 int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
61 int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality);
63 where the callback is:
64 void stbi_write_func(void *context, void *data, int size);
66 You can configure it with these global variables:
67 int stbi_write_tga_with_rle; // defaults to true; set to 0 to disable RLE
68 int stbi_write_png_compression_level; // defaults to 8; set to higher for more compression
69 int stbi_write_force_png_filter; // defaults to -1; set to 0..5 to force a filter mode
72 You can define STBI_WRITE_NO_STDIO to disable the file variant of these
73 functions, so the library will not use stdio.h at all. However, this will
74 also disable HDR writing, because it requires stdio for formatted output.
76 Each function returns 0 on failure and non-0 on success.
78 The functions create an image file defined by the parameters. The image
79 is a rectangle of pixels stored from left-to-right, top-to-bottom.
80 Each pixel contains 'comp' channels of data stored interleaved with 8-bits
81 per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is
82 monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall.
83 The *data pointer points to the first byte of the top-left-most pixel.
84 For PNG, "stride_in_bytes" is the distance in bytes from the first byte of
85 a row of pixels to the first byte of the next row of pixels.
87 PNG creates output files with the same number of components as the input.
88 The BMP format expands Y to RGB in the file format and does not
89 output alpha.
91 PNG supports writing rectangles of data even when the bytes storing rows of
92 data are not consecutive in memory (e.g. sub-rectangles of a larger image),
93 by supplying the stride between the beginning of adjacent rows. The other
94 formats do not. (Thus you cannot write a native-format BMP through the BMP
95 writer, both because it is in BGR order and because it may have padding
96 at the end of the line.)
98 PNG allows you to set the deflate compression level by setting the global
99 variable 'stbi_write_png_compression_level' (it defaults to 8).
101 HDR expects linear float data. Since the format is always 32-bit rgb(e)
102 data, alpha (if provided) is discarded, and for monochrome data it is
103 replicated across all three channels.
105 TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed
106 data, set the global variable 'stbi_write_tga_with_rle' to 0.
108 JPEG does ignore alpha channels in input data; quality is between 1 and 100.
109 Higher quality looks better but results in a bigger image.
110 JPEG baseline (no JPEG progressive).
112CREDITS:
115 Sean Barrett - PNG/BMP/TGA
116 Baldur Karlsson - HDR
117 Jean-Sebastien Guay - TGA monochrome
118 Tim Kelsey - misc enhancements
119 Alan Hickman - TGA RLE
120 Emmanuel Julien - initial file IO callback implementation
121 Jon Olick - original jo_jpeg.cpp code
122 Daniel Gibson - integrate JPEG, allow external zlib
123 Aarni Koskela - allow choosing PNG filter
125 bugfixes:
126 github:Chribba
127 Guillaume Chereau
128 github:jry2
129 github:romigrou
130 Sergio Gonzalez
131 Jonas Karlsson
132 Filip Wasil
133 Thatcher Ulrich
134 github:poppolopoppo
135 Patrick Boettcher
136 github:xeekworx
137 Cap Petschulat
138 Simon Rodriguez
139 Ivan Tikhonov
140 github:ignotion
141 Adam Schackart
142 Andrew Kensler
144LICENSE
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
169STBIWDEF int stbi_write_tga_with_rle;
170STBIWDEF int stbi_write_png_compression_level;
171STBIWDEF int stbi_write_force_png_filter;
172#endif
174#ifndef STBI_WRITE_NO_STDIO
175STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
176STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
177STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
178STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
179STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality);
181#ifdef STBIW_WINDOWS_UTF8
182STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
183#endif
184#endif
186typedef void stbi_write_func(void *context, void *data, int size);
188STBIWDEF 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);
189STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
190STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
191STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
192STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality);
194STBIWDEF 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
250static int stbi_write_png_compression_level = 8;
251static int stbi_write_tga_with_rle = 1;
252static int stbi_write_force_png_filter = -1;
253#else
254int stbi_write_png_compression_level = 8;
255int stbi_write_tga_with_rle = 1;
256int stbi_write_force_png_filter = -1;
257#endif
259static int stbi__flip_vertically_on_write = 0;
261STBIWDEF void stbi_flip_vertically_on_write(int flag)
262{
263 stbi__flip_vertically_on_write = flag;
264}
266typedef struct
267{
268 stbi_write_func *func;
269 void *context;
270 unsigned char buffer[64];
271 int buf_used;
272} stbi__write_context;
274// initialize a callback-based context
275static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context)
276{
277 s->func = c;
278 s->context = context;
279}
281#ifndef STBI_WRITE_NO_STDIO
283static void stbi__stdio_write(void *context, void *data, int size)
284{
285 fwrite(data,1,size,(FILE*) context);
286}
288#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
289#ifdef __cplusplus
290#define STBIW_EXTERN extern "C"
291#else
292#define STBIW_EXTERN extern
293#endif
294STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide);
295STBIW_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);
297STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input)
298{
299 return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL);
300}
301#endif
303static FILE *stbiw__fopen(char const *filename, char const *mode)
304{
305 FILE *f;
306#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
307 wchar_t wMode[64];
308 wchar_t wFilename[1024];
309 if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename)))
310 return 0;
312 if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode)))
313 return 0;
315#if defined(_MSC_VER) && _MSC_VER >= 1400
316 if (0 != _wfopen_s(&f, wFilename, wMode))
317 f = 0;
318#else
319 f = _wfopen(wFilename, wMode);
320#endif
322#elif defined(_MSC_VER) && _MSC_VER >= 1400
323 if (0 != fopen_s(&f, filename, mode))
324 f=0;
325#else
326 f = fopen(filename, mode);
327#endif
328 return f;
329}
331static int stbi__start_write_file(stbi__write_context *s, const char *filename)
332{
333 FILE *f = stbiw__fopen(filename, "wb");
334 stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f);
335 return f != NULL;
336}
338static void stbi__end_write_file(stbi__write_context *s)
339{
340 fclose((FILE *)s->context);
341}
343#endif // !STBI_WRITE_NO_STDIO
345typedef unsigned int stbiw_uint32;
346typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
348static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v)
349{
350 while (*fmt) {
351 switch (*fmt++) {
352 case ' ': break;
353 case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int));
354 s->func(s->context,&x,1);
355 break; }
356 case '2': { int x = va_arg(v,int);
357 unsigned char b[2];
358 b[0] = STBIW_UCHAR(x);
359 b[1] = STBIW_UCHAR(x>>8);
360 s->func(s->context,b,2);
361 break; }
362 case '4': { stbiw_uint32 x = va_arg(v,int);
363 unsigned char b[4];
364 b[0]=STBIW_UCHAR(x);
365 b[1]=STBIW_UCHAR(x>>8);
366 b[2]=STBIW_UCHAR(x>>16);
367 b[3]=STBIW_UCHAR(x>>24);
368 s->func(s->context,b,4);
369 break; }
370 default:
371 STBIW_ASSERT(0);
372 return;
373 }
374 }
375}
377static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
378{
379 va_list v;
380 va_start(v, fmt);
381 stbiw__writefv(s, fmt, v);
382 va_end(v);
383}
385static void stbiw__write_flush(stbi__write_context *s)
386{
387 if (s->buf_used) {
388 s->func(s->context, &s->buffer, s->buf_used);
389 s->buf_used = 0;
390 }
391}
393static void stbiw__putc(stbi__write_context *s, unsigned char c)
394{
395 s->func(s->context, &c, 1);
396}
398static void stbiw__write1(stbi__write_context *s, unsigned char a)
399{
400 if ((size_t)s->buf_used + 1 > sizeof(s->buffer))
401 stbiw__write_flush(s);
402 s->buffer[s->buf_used++] = a;
403}
405static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
406{
407 int n;
408 if ((size_t)s->buf_used + 3 > sizeof(s->buffer))
409 stbiw__write_flush(s);
410 n = s->buf_used;
411 s->buf_used = n+3;
412 s->buffer[n+0] = a;
413 s->buffer[n+1] = b;
414 s->buffer[n+2] = c;
415}
417static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
418{
419 unsigned char bg[3] = { 255, 0, 255}, px[3];
420 int k;
422 if (write_alpha < 0)
423 stbiw__write1(s, d[comp - 1]);
425 switch (comp) {
426 case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case
427 case 1:
428 if (expand_mono)
429 stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp
430 else
431 stbiw__write1(s, d[0]); // monochrome TGA
432 break;
433 case 4:
434 if (!write_alpha) {
435 // composite against pink background
436 for (k = 0; k < 3; ++k)
437 px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
438 stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]);
439 break;
440 }
441 /* FALLTHROUGH */
442 case 3:
443 stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
444 break;
445 }
446 if (write_alpha > 0)
447 stbiw__write1(s, d[comp - 1]);
448}
450static 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)
451{
452 stbiw_uint32 zero = 0;
453 int i,j, j_end;
455 if (y <= 0)
456 return;
458 if (stbi__flip_vertically_on_write)
459 vdir *= -1;
461 if (vdir < 0) {
462 j_end = -1; j = y-1;
463 } else {
464 j_end = y; j = 0;
465 }
467 for (; j != j_end; j += vdir) {
468 for (i=0; i < x; ++i) {
469 unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
470 stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
471 }
472 stbiw__write_flush(s);
473 s->func(s->context, &zero, scanline_pad);
474 }
475}
477static 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, ...)
478{
479 if (y < 0 || x < 0) {
480 return 0;
481 } else {
482 va_list v;
483 va_start(v, fmt);
484 stbiw__writefv(s, fmt, v);
485 va_end(v);
486 stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono);
487 return 1;
488 }
489}
491static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
492{
493 if (comp != 4) {
494 // write RGB bitmap
495 int pad = (-x*3) & 3;
496 return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
497 "11 4 22 4" "4 44 22 444444",
498 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
499 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
500 } else {
501 // RGBA bitmaps need a v4 header
502 // use BI_BITFIELDS mode with 32bpp and alpha mask
503 // (straight BI_RGB with alpha mask doesn't work in most readers)
504 return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *)data,1,0,
505 "11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444",
506 'B', 'M', 14+108+x*y*4, 0, 0, 14+108, // file header
507 108, x,y, 1,32, 3,0,0,0,0,0, 0xff0000,0xff00,0xff,0xff000000u, 0, 0,0,0, 0,0,0, 0,0,0, 0,0,0); // bitmap V4 header
508 }
509}
511STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
512{
513 stbi__write_context s = { 0 };
514 stbi__start_write_callbacks(&s, func, context);
515 return stbi_write_bmp_core(&s, x, y, comp, data);
516}
518#ifndef STBI_WRITE_NO_STDIO
519STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
520{
521 stbi__write_context s = { 0 };
522 if (stbi__start_write_file(&s,filename)) {
523 int r = stbi_write_bmp_core(&s, x, y, comp, data);
524 stbi__end_write_file(&s);
525 return r;
526 } else
527 return 0;
528}
529#endif //!STBI_WRITE_NO_STDIO
531static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data)
532{
533 int has_alpha = (comp == 2 || comp == 4);
534 int colorbytes = has_alpha ? comp-1 : comp;
535 int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3
537 if (y < 0 || x < 0)
538 return 0;
540 if (!stbi_write_tga_with_rle) {
541 return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0,
542 "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
543 } else {
544 int i,j,k;
545 int jend, jdir;
547 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);
549 if (stbi__flip_vertically_on_write) {
550 j = 0;
551 jend = y;
552 jdir = 1;
553 } else {
554 j = y-1;
555 jend = -1;
556 jdir = -1;
557 }
558 for (; j != jend; j += jdir) {
559 unsigned char *row = (unsigned char *) data + j * x * comp;
560 int len;
562 for (i = 0; i < x; i += len) {
563 unsigned char *begin = row + i * comp;
564 int diff = 1;
565 len = 1;
567 if (i < x - 1) {
568 ++len;
569 diff = memcmp(begin, row + (i + 1) * comp, comp);
570 if (diff) {
571 const unsigned char *prev = begin;
572 for (k = i + 2; k < x && len < 128; ++k) {
573 if (memcmp(prev, row + k * comp, comp)) {
574 prev += comp;
575 ++len;
576 } else {
577 --len;
578 break;
579 }
580 }
581 } else {
582 for (k = i + 2; k < x && len < 128; ++k) {
583 if (!memcmp(begin, row + k * comp, comp)) {
584 ++len;
585 } else {
586 break;
587 }
588 }
589 }
590 }
592 if (diff) {
593 unsigned char header = STBIW_UCHAR(len - 1);
594 stbiw__write1(s, header);
595 for (k = 0; k < len; ++k) {
596 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
597 }
598 } else {
599 unsigned char header = STBIW_UCHAR(len - 129);
600 stbiw__write1(s, header);
601 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
602 }
603 }
604 }
605 stbiw__write_flush(s);
606 }
607 return 1;
608}
610STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
611{
612 stbi__write_context s = { 0 };
613 stbi__start_write_callbacks(&s, func, context);
614 return stbi_write_tga_core(&s, x, y, comp, (void *) data);
615}
617#ifndef STBI_WRITE_NO_STDIO
618STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
619{
620 stbi__write_context s = { 0 };
621 if (stbi__start_write_file(&s,filename)) {
622 int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
623 stbi__end_write_file(&s);
624 return r;
625 } else
626 return 0;
627}
628#endif
630// *************************************************************************************************
631// Radiance RGBE HDR writer
632// by Baldur Karlsson
634#define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
636#ifndef STBI_WRITE_NO_STDIO
638static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
639{
640 int exponent;
641 float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
643 if (maxcomp < 1e-32f) {
644 rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
645 } else {
646 float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
648 rgbe[0] = (unsigned char)(linear[0] * normalize);
649 rgbe[1] = (unsigned char)(linear[1] * normalize);
650 rgbe[2] = (unsigned char)(linear[2] * normalize);
651 rgbe[3] = (unsigned char)(exponent + 128);
652 }
653}
655static void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
656{
657 unsigned char lengthbyte = STBIW_UCHAR(length+128);
658 STBIW_ASSERT(length+128 <= 255);
659 s->func(s->context, &lengthbyte, 1);
660 s->func(s->context, &databyte, 1);
661}
663static void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
664{
665 unsigned char lengthbyte = STBIW_UCHAR(length);
666 STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
667 s->func(s->context, &lengthbyte, 1);
668 s->func(s->context, data, length);
669}
671static void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline)
672{
673 unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
674 unsigned char rgbe[4];
675 float linear[3];
676 int x;
678 scanlineheader[2] = (width&0xff00)>>8;
679 scanlineheader[3] = (width&0x00ff);
681 /* skip RLE for images too small or large */
682 if (width < 8 || width >= 32768) {
683 for (x=0; x < width; x++) {
684 switch (ncomp) {
685 case 4: /* fallthrough */
686 case 3: linear[2] = scanline[x*ncomp + 2];
687 linear[1] = scanline[x*ncomp + 1];
688 linear[0] = scanline[x*ncomp + 0];
689 break;
690 default:
691 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
692 break;
693 }
694 stbiw__linear_to_rgbe(rgbe, linear);
695 s->func(s->context, rgbe, 4);
696 }
697 } else {
698 int c,r;
699 /* encode into scratch buffer */
700 for (x=0; x < width; x++) {
701 switch(ncomp) {
702 case 4: /* fallthrough */
703 case 3: linear[2] = scanline[x*ncomp + 2];
704 linear[1] = scanline[x*ncomp + 1];
705 linear[0] = scanline[x*ncomp + 0];
706 break;
707 default:
708 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
709 break;
710 }
711 stbiw__linear_to_rgbe(rgbe, linear);
712 scratch[x + width*0] = rgbe[0];
713 scratch[x + width*1] = rgbe[1];
714 scratch[x + width*2] = rgbe[2];
715 scratch[x + width*3] = rgbe[3];
716 }
718 s->func(s->context, scanlineheader, 4);
720 /* RLE each component separately */
721 for (c=0; c < 4; c++) {
722 unsigned char *comp = &scratch[width*c];
724 x = 0;
725 while (x < width) {
726 // find first run
727 r = x;
728 while (r+2 < width) {
729 if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
730 break;
731 ++r;
732 }
733 if (r+2 >= width)
734 r = width;
735 // dump up to first run
736 while (x < r) {
737 int len = r-x;
738 if (len > 128) len = 128;
739 stbiw__write_dump_data(s, len, &comp[x]);
740 x += len;
741 }
742 // if there's a run, output it
743 if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd
744 // find next byte after run
745 while (r < width && comp[r] == comp[x])
746 ++r;
747 // output run up to r
748 while (x < r) {
749 int len = r-x;
750 if (len > 127) len = 127;
751 stbiw__write_run_data(s, len, comp[x]);
752 x += len;
753 }
754 }
755 }
756 }
757 }
758}
760static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data)
761{
762 if (y <= 0 || x <= 0 || data == NULL)
763 return 0;
764 else {
765 // Each component is stored separately. Allocate scratch space for full output scanline.
766 unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
767 int i, len;
768 char buffer[128];
769 char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
770 s->func(s->context, header, sizeof(header)-1);
772#ifdef __STDC_LIB_EXT1__
773 len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
774#else
775 len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
776#endif
777 s->func(s->context, buffer, len);
779 for(i=0; i < y; i++)
780 stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i));
781 STBIW_FREE(scratch);
782 return 1;
783 }
784}
786STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
787{
788 stbi__write_context s = { 0 };
789 stbi__start_write_callbacks(&s, func, context);
790 return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
791}
793STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
794{
795 stbi__write_context s = { 0 };
796 if (stbi__start_write_file(&s,filename)) {
797 int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
798 stbi__end_write_file(&s);
799 return r;
800 } else
801 return 0;
802}
803#endif // STBI_WRITE_NO_STDIO
806//////////////////////////////////////////////////////////////////////////////
807//
808// PNG writer
809//
811#ifndef STBIW_ZLIB_COMPRESS
812// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
813#define stbiw__sbraw(a) ((int *) (void *) (a) - 2)
814#define stbiw__sbm(a) stbiw__sbraw(a)[0]
815#define stbiw__sbn(a) stbiw__sbraw(a)[1]
817#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
818#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
819#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
821#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
822#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
823#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
825static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
826{
827 int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
828 void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2);
829 STBIW_ASSERT(p);
830 if (p) {
831 if (!*arr) ((int *) p)[1] = 0;
832 *arr = (void *) ((int *) p + 2);
833 stbiw__sbm(*arr) = m;
834 }
835 return *arr;
836}
838static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
839{
840 while (*bitcount >= 8) {
841 stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
842 *bitbuffer >>= 8;
843 *bitcount -= 8;
844 }
845 return data;
846}
848static int stbiw__zlib_bitrev(int code, int codebits)
849{
850 int res=0;
851 while (codebits--) {
852 res = (res << 1) | (code & 1);
853 code >>= 1;
854 }
855 return res;
856}
858static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit)
859{
860 int i;
861 for (i=0; i < limit && i < 258; ++i)
862 if (a[i] != b[i]) break;
863 return i;
864}
866static unsigned int stbiw__zhash(unsigned char *data)
867{
868 stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
869 hash ^= hash << 3;
870 hash += hash >> 5;
871 hash ^= hash << 4;
872 hash += hash >> 17;
873 hash ^= hash << 25;
874 hash += hash >> 6;
875 return hash;
876}
878#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
879#define stbiw__zlib_add(code,codebits) \
880 (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
881#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
882// default huffman tables
883#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8)
884#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9)
885#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7)
886#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8)
887#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))
888#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
890#define stbiw__ZHASH 16384
892#endif // STBIW_ZLIB_COMPRESS
894STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
895{
896#ifdef STBIW_ZLIB_COMPRESS
897 // user provided a zlib compress implementation, use that
898 return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality);
899#else // use builtin
900 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 };
901 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 };
902 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 };
903 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 };
904 unsigned int bitbuf=0;
905 int i,j, bitcount=0;
906 unsigned char *out = NULL;
907 unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(unsigned char**));
908 if (hash_table == NULL)
909 return NULL;
910 if (quality < 5) quality = 5;
912 stbiw__sbpush(out, 0x78); // DEFLATE 32K window
913 stbiw__sbpush(out, 0x5e); // FLEVEL = 1
914 stbiw__zlib_add(1,1); // BFINAL = 1
915 stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman
917 for (i=0; i < stbiw__ZHASH; ++i)
918 hash_table[i] = NULL;
920 i=0;
921 while (i < data_len-3) {
922 // hash next 3 bytes of data to be compressed
923 int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
924 unsigned char *bestloc = 0;
925 unsigned char **hlist = hash_table[h];
926 int n = stbiw__sbcount(hlist);
927 for (j=0; j < n; ++j) {
928 if (hlist[j]-data > i-32768) { // if entry lies within window
929 int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
930 if (d >= best) { best=d; bestloc=hlist[j]; }
931 }
932 }
933 // when hash table entry is too long, delete half the entries
934 if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
935 STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
936 stbiw__sbn(hash_table[h]) = quality;
937 }
938 stbiw__sbpush(hash_table[h],data+i);
940 if (bestloc) {
941 // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal
942 h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
943 hlist = hash_table[h];
944 n = stbiw__sbcount(hlist);
945 for (j=0; j < n; ++j) {
946 if (hlist[j]-data > i-32767) {
947 int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
948 if (e > best) { // if next match is better, bail on current match
949 bestloc = NULL;
950 break;
951 }
952 }
953 }
954 }
956 if (bestloc) {
957 int d = (int) (data+i - bestloc); // distance back
958 STBIW_ASSERT(d <= 32767 && best <= 258);
959 for (j=0; best > lengthc[j+1]-1; ++j);
960 stbiw__zlib_huff(j+257);
961 if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
962 for (j=0; d > distc[j+1]-1; ++j);
963 stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
964 if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
965 i += best;
966 } else {
967 stbiw__zlib_huffb(data[i]);
968 ++i;
969 }
970 }
971 // write out final bytes
972 for (;i < data_len; ++i)
973 stbiw__zlib_huffb(data[i]);
974 stbiw__zlib_huff(256); // end of block
975 // pad with 0 bits to byte boundary
976 while (bitcount)
977 stbiw__zlib_add(0,1);
979 for (i=0; i < stbiw__ZHASH; ++i)
980 (void) stbiw__sbfree(hash_table[i]);
981 STBIW_FREE(hash_table);
983 // store uncompressed instead if compression was worse
984 if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) {
985 stbiw__sbn(out) = 2; // truncate to DEFLATE 32K window and FLEVEL = 1
986 for (j = 0; j < data_len;) {
987 int blocklen = data_len - j;
988 if (blocklen > 32767) blocklen = 32767;
989 stbiw__sbpush(out, data_len - j == blocklen); // BFINAL = ?, BTYPE = 0 -- no compression
990 stbiw__sbpush(out, STBIW_UCHAR(blocklen)); // LEN
991 stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8));
992 stbiw__sbpush(out, STBIW_UCHAR(~blocklen)); // NLEN
993 stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8));
994 memcpy(out+stbiw__sbn(out), data+j, blocklen);
995 stbiw__sbn(out) += blocklen;
996 j += blocklen;
997 }
998 }
1000 {
1001 // compute adler32 on input
1002 unsigned int s1=1, s2=0;
1003 int blocklen = (int) (data_len % 5552);
1004 j=0;
1005 while (j < data_len) {
1006 for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; }
1007 s1 %= 65521; s2 %= 65521;
1008 j += blocklen;
1009 blocklen = 5552;
1010 }
1011 stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
1012 stbiw__sbpush(out, STBIW_UCHAR(s2));
1013 stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
1014 stbiw__sbpush(out, STBIW_UCHAR(s1));
1015 }
1016 *out_len = stbiw__sbn(out);
1017 // make returned pointer freeable
1018 STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
1019 return (unsigned char *) stbiw__sbraw(out);
1020#endif // STBIW_ZLIB_COMPRESS
1021}
1023static unsigned int stbiw__crc32(unsigned char *buffer, int len)
1024{
1025#ifdef STBIW_CRC32
1026 return STBIW_CRC32(buffer, len);
1027#else
1028 static unsigned int crc_table[256] =
1029 {
1030 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
1031 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
1032 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
1033 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
1034 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
1035 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
1036 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
1037 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
1038 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
1039 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
1040 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
1041 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
1042 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
1043 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
1044 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
1045 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
1046 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
1047 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
1048 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
1049 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
1050 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
1051 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
1052 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
1053 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
1054 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
1055 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
1056 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
1057 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
1058 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
1059 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
1060 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
1061 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
1062 };
1064 unsigned int crc = ~0u;
1065 int i;
1066 for (i=0; i < len; ++i)
1067 crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
1068 return ~crc;
1069#endif
1070}
1072#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)
1073#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
1074#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
1076static void stbiw__wpcrc(unsigned char **data, int len)
1077{
1078 unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
1079 stbiw__wp32(*data, crc);
1080}
1082static unsigned char stbiw__paeth(int a, int b, int c)
1083{
1084 int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
1085 if (pa <= pb && pa <= pc) return STBIW_UCHAR(a);
1086 if (pb <= pc) return STBIW_UCHAR(b);
1087 return STBIW_UCHAR(c);
1088}
1090// @OPTIMIZE: provide an option that always forces left-predict or paeth predict
1091static 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)
1092{
1093 static int mapping[] = { 0,1,2,3,4 };
1094 static int firstmap[] = { 0,1,0,5,6 };
1095 int *mymap = (y != 0) ? mapping : firstmap;
1096 int i;
1097 int type = mymap[filter_type];
1098 unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y);
1099 int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes;
1101 if (type==0) {
1102 memcpy(line_buffer, z, width*n);
1103 return;
1104 }
1106 // first loop isn't optimized since it's just one pixel
1107 for (i = 0; i < n; ++i) {
1108 switch (type) {
1109 case 1: line_buffer[i] = z[i]; break;
1110 case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break;
1111 case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1); break;
1112 case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0)); break;
1113 case 5: line_buffer[i] = z[i]; break;
1114 case 6: line_buffer[i] = z[i]; break;
1115 }
1116 }
1117 switch (type) {
1118 case 1: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n]; break;
1119 case 2: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride]; break;
1120 case 3: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break;
1121 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;
1122 case 5: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1); break;
1123 case 6: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
1124 }
1125}
1127STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
1128{
1129 int force_filter = stbi_write_force_png_filter;
1130 int ctype[5] = { -1, 0, 4, 2, 6 };
1131 unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
1132 unsigned char *out,*o, *filt, *zlib;
1133 signed char *line_buffer;
1134 int j,zlen;
1136 if (stride_bytes == 0)
1137 stride_bytes = x * n;
1139 if (force_filter >= 5) {
1140 force_filter = -1;
1141 }
1143 filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
1144 line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
1145 for (j=0; j < y; ++j) {
1146 int filter_type;
1147 if (force_filter > -1) {
1148 filter_type = force_filter;
1149 stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer);
1150 } else { // Estimate the best filter by running through all of them:
1151 int best_filter = 0, best_filter_val = 0x7fffffff, est, i;
1152 for (filter_type = 0; filter_type < 5; filter_type++) {
1153 stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer);
1155 // Estimate the entropy of the line using this filter; the less, the better.
1156 est = 0;
1157 for (i = 0; i < x*n; ++i) {
1158 est += abs((signed char) line_buffer[i]);
1159 }
1160 if (est < best_filter_val) {
1161 best_filter_val = est;
1162 best_filter = filter_type;
1163 }
1164 }
1165 if (filter_type != best_filter) { // If the last iteration already got us the best filter, don't redo it
1166 stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer);
1167 filter_type = best_filter;
1168 }
1169 }
1170 // when we get here, filter_type contains the filter type, and line_buffer contains the data
1171 filt[j*(x*n+1)] = (unsigned char) filter_type;
1172 STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
1173 }
1174 STBIW_FREE(line_buffer);
1175 zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_compression_level);
1176 STBIW_FREE(filt);
1177 if (!zlib) return 0;
1179 // each tag requires 12 bytes of overhead
1180 out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
1181 if (!out) return 0;
1182 *out_len = 8 + 12+13 + 12+zlen + 12;
1184 o=out;
1185 STBIW_MEMMOVE(o,sig,8); o+= 8;
1186 stbiw__wp32(o, 13); // header length
1187 stbiw__wptag(o, "IHDR");
1188 stbiw__wp32(o, x);
1189 stbiw__wp32(o, y);
1190 *o++ = 8;
1191 *o++ = STBIW_UCHAR(ctype[n]);
1192 *o++ = 0;
1193 *o++ = 0;
1194 *o++ = 0;
1195 stbiw__wpcrc(&o,13);
1197 stbiw__wp32(o, zlen);
1198 stbiw__wptag(o, "IDAT");
1199 STBIW_MEMMOVE(o, zlib, zlen);
1200 o += zlen;
1201 STBIW_FREE(zlib);
1202 stbiw__wpcrc(&o, zlen);
1204 stbiw__wp32(o,0);
1205 stbiw__wptag(o, "IEND");
1206 stbiw__wpcrc(&o,0);
1208 STBIW_ASSERT(o == out + *out_len);
1210 return out;
1211}
1213#ifndef STBI_WRITE_NO_STDIO
1214STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
1215{
1216 FILE *f;
1217 int len;
1218 unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len);
1219 if (png == NULL) return 0;
1221 f = stbiw__fopen(filename, "wb");
1222 if (!f) { STBIW_FREE(png); return 0; }
1223 fwrite(png, 1, len, f);
1224 fclose(f);
1225 STBIW_FREE(png);
1226 return 1;
1227}
1228#endif
1230STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes)
1231{
1232 int len;
1233 unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len);
1234 if (png == NULL) return 0;
1235 func(context, png, len);
1236 STBIW_FREE(png);
1237 return 1;
1238}
1241/* ***************************************************************************
1242 *
1243 * JPEG writer
1244 *
1245 * This is based on Jon Olick's jo_jpeg.cpp:
1246 * public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html
1247 */
1249static 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,
1250 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 };
1252static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) {
1253 int bitBuf = *bitBufP, bitCnt = *bitCntP;
1254 bitCnt += bs[1];
1255 bitBuf |= bs[0] << (24 - bitCnt);
1256 while(bitCnt >= 8) {
1257 unsigned char c = (bitBuf >> 16) & 255;
1258 stbiw__putc(s, c);
1259 if(c == 255) {
1260 stbiw__putc(s, 0);
1261 }
1262 bitBuf <<= 8;
1263 bitCnt -= 8;
1264 }
1265 *bitBufP = bitBuf;
1266 *bitCntP = bitCnt;
1267}
1269static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) {
1270 float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p;
1271 float z1, z2, z3, z4, z5, z11, z13;
1273 float tmp0 = d0 + d7;
1274 float tmp7 = d0 - d7;
1275 float tmp1 = d1 + d6;
1276 float tmp6 = d1 - d6;
1277 float tmp2 = d2 + d5;
1278 float tmp5 = d2 - d5;
1279 float tmp3 = d3 + d4;
1280 float tmp4 = d3 - d4;
1282 // Even part
1283 float tmp10 = tmp0 + tmp3; // phase 2
1284 float tmp13 = tmp0 - tmp3;
1285 float tmp11 = tmp1 + tmp2;
1286 float tmp12 = tmp1 - tmp2;
1288 d0 = tmp10 + tmp11; // phase 3
1289 d4 = tmp10 - tmp11;
1291 z1 = (tmp12 + tmp13) * 0.707106781f; // c4
1292 d2 = tmp13 + z1; // phase 5
1293 d6 = tmp13 - z1;
1295 // Odd part
1296 tmp10 = tmp4 + tmp5; // phase 2
1297 tmp11 = tmp5 + tmp6;
1298 tmp12 = tmp6 + tmp7;
1300 // The rotator is modified from fig 4-8 to avoid extra negations.
1301 z5 = (tmp10 - tmp12) * 0.382683433f; // c6
1302 z2 = tmp10 * 0.541196100f + z5; // c2-c6
1303 z4 = tmp12 * 1.306562965f + z5; // c2+c6
1304 z3 = tmp11 * 0.707106781f; // c4
1306 z11 = tmp7 + z3; // phase 5
1307 z13 = tmp7 - z3;
1309 *d5p = z13 + z2; // phase 6
1310 *d3p = z13 - z2;
1311 *d1p = z11 + z4;
1312 *d7p = z11 - z4;
1314 *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6;
1315}
1317static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) {
1318 int tmp1 = val < 0 ? -val : val;
1319 val = val < 0 ? val-1 : val;
1320 bits[1] = 1;
1321 while(tmp1 >>= 1) {
1322 ++bits[1];
1323 }
1324 bits[0] = val & ((1<<bits[1])-1);
1325}
1327static int stbiw__jpg_processDU(stbi__write_context *s, int *bitBuf, int *bitCnt, float *CDU, int du_stride, float *fdtbl, int DC, const unsigned short HTDC[256][2], const unsigned short HTAC[256][2]) {
1328 const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
1329 const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
1330 int dataOff, i, j, n, diff, end0pos, x, y;
1331 int DU[64];
1333 // DCT rows
1334 for(dataOff=0, n=du_stride*8; dataOff<n; dataOff+=du_stride) {
1335 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]);
1336 }
1337 // DCT columns
1338 for(dataOff=0; dataOff<8; ++dataOff) {
1339 stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+du_stride], &CDU[dataOff+du_stride*2], &CDU[dataOff+du_stride*3], &CDU[dataOff+du_stride*4],
1340 &CDU[dataOff+du_stride*5], &CDU[dataOff+du_stride*6], &CDU[dataOff+du_stride*7]);
1341 }
1342 // Quantize/descale/zigzag the coefficients
1343 for(y = 0, j=0; y < 8; ++y) {
1344 for(x = 0; x < 8; ++x,++j) {
1345 float v;
1346 i = y*du_stride+x;
1347 v = CDU[i]*fdtbl[j];
1348 // DU[stbiw__jpg_ZigZag[j]] = (int)(v < 0 ? ceilf(v - 0.5f) : floorf(v + 0.5f));
1349 // ceilf() and floorf() are C99, not C89, but I /think/ they're not needed here anyway?
1350 DU[stbiw__jpg_ZigZag[j]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
1351 }
1352 }
1354 // Encode DC
1355 diff = DU[0] - DC;
1356 if (diff == 0) {
1357 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]);
1358 } else {
1359 unsigned short bits[2];
1360 stbiw__jpg_calcBits(diff, bits);
1361 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]);
1362 stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1363 }
1364 // Encode ACs
1365 end0pos = 63;
1366 for(; (end0pos>0)&&(DU[end0pos]==0); --end0pos) {
1367 }
1368 // end0pos = first element in reverse order !=0
1369 if(end0pos == 0) {
1370 stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1371 return DU[0];
1372 }
1373 for(i = 1; i <= end0pos; ++i) {
1374 int startpos = i;
1375 int nrzeroes;
1376 unsigned short bits[2];
1377 for (; DU[i]==0 && i<=end0pos; ++i) {
1378 }
1379 nrzeroes = i-startpos;
1380 if ( nrzeroes >= 16 ) {
1381 int lng = nrzeroes>>4;
1382 int nrmarker;
1383 for (nrmarker=1; nrmarker <= lng; ++nrmarker)
1384 stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes);
1385 nrzeroes &= 15;
1386 }
1387 stbiw__jpg_calcBits(DU[i], bits);
1388 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]);
1389 stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1390 }
1391 if(end0pos != 63) {
1392 stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1393 }
1394 return DU[0];
1395}
1397static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) {
1398 // Constants that don't pollute global namespace
1399 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};
1400 static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1401 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};
1402 static const unsigned char std_ac_luminance_values[] = {
1403 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
1404 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
1405 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
1406 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
1407 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
1408 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
1409 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1410 };
1411 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};
1412 static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1413 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};
1414 static const unsigned char std_ac_chrominance_values[] = {
1415 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
1416 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
1417 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
1418 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
1419 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
1420 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
1421 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1422 };
1423 // Huffman tables
1424 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}};
1425 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}};
1426 static const unsigned short YAC_HT[256][2] = {
1427 {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},
1428 {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},
1429 {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},
1430 {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},
1431 {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},
1432 {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},
1433 {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},
1434 {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},
1435 {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},
1436 {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},
1437 {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},
1438 {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},
1439 {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},
1440 {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},
1441 {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},
1442 {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}
1443 };
1444 static const unsigned short UVAC_HT[256][2] = {
1445 {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},
1446 {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},
1447 {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},
1448 {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},
1449 {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},
1450 {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},
1451 {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},
1452 {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},
1453 {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},
1454 {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},
1455 {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},
1456 {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},
1457 {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},
1458 {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},
1459 {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},
1460 {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}
1461 };
1462 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,
1463 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};
1464 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,
1465 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};
1466 static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
1467 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f };
1469 int row, col, i, k, subsample;
1470 float fdtbl_Y[64], fdtbl_UV[64];
1471 unsigned char YTable[64], UVTable[64];
1473 if(!data || !width || !height || comp > 4 || comp < 1) {
1474 return 0;
1475 }
1477 quality = quality ? quality : 90;
1478 subsample = quality <= 90 ? 1 : 0;
1479 quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
1480 quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
1482 for(i = 0; i < 64; ++i) {
1483 int uvti, yti = (YQT[i]*quality+50)/100;
1484 YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti);
1485 uvti = (UVQT[i]*quality+50)/100;
1486 UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti);
1487 }
1489 for(row = 0, k = 0; row < 8; ++row) {
1490 for(col = 0; col < 8; ++col, ++k) {
1491 fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1492 fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1493 }
1494 }
1496 // Write Headers
1497 {
1498 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 };
1499 static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
1500 const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width),
1501 3,1,(unsigned char)(subsample?0x22:0x11),0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
1502 s->func(s->context, (void*)head0, sizeof(head0));
1503 s->func(s->context, (void*)YTable, sizeof(YTable));
1504 stbiw__putc(s, 1);
1505 s->func(s->context, UVTable, sizeof(UVTable));
1506 s->func(s->context, (void*)head1, sizeof(head1));
1507 s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1);
1508 s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values));
1509 stbiw__putc(s, 0x10); // HTYACinfo
1510 s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1);
1511 s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values));
1512 stbiw__putc(s, 1); // HTUDCinfo
1513 s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1);
1514 s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values));
1515 stbiw__putc(s, 0x11); // HTUACinfo
1516 s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1);
1517 s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values));
1518 s->func(s->context, (void*)head2, sizeof(head2));
1519 }
1521 // Encode 8x8 macroblocks
1522 {
1523 static const unsigned short fillBits[] = {0x7F, 7};
1524 int DCY=0, DCU=0, DCV=0;
1525 int bitBuf=0, bitCnt=0;
1526 // comp == 2 is grey+alpha (alpha is ignored)
1527 int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
1528 const unsigned char *dataR = (const unsigned char *)data;
1529 const unsigned char *dataG = dataR + ofsG;
1530 const unsigned char *dataB = dataR + ofsB;
1531 int x, y, pos;
1532 if(subsample) {
1533 for(y = 0; y < height; y += 16) {
1534 for(x = 0; x < width; x += 16) {
1535 float Y[256], U[256], V[256];
1536 for(row = y, pos = 0; row < y+16; ++row) {
1537 // row >= height => use last input row
1538 int clamped_row = (row < height) ? row : height - 1;
1539 int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
1540 for(col = x; col < x+16; ++col, ++pos) {
1541 // if col >= width => use pixel from last input column
1542 int p = base_p + ((col < width) ? col : (width-1))*comp;
1543 float r = dataR[p], g = dataG[p], b = dataB[p];
1544 Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
1545 U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
1546 V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
1547 }
1548 }
1549 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+0, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1550 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+8, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1551 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1552 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1554 // subsample U,V
1555 {
1556 float subU[64], subV[64];
1557 int yy, xx;
1558 for(yy = 0, pos = 0; yy < 8; ++yy) {
1559 for(xx = 0; xx < 8; ++xx, ++pos) {
1560 int j = yy*32+xx*2;
1561 subU[pos] = (U[j+0] + U[j+1] + U[j+16] + U[j+17]) * 0.25f;
1562 subV[pos] = (V[j+0] + V[j+1] + V[j+16] + V[j+17]) * 0.25f;
1563 }
1564 }
1565 DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
1566 DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
1567 }
1568 }
1569 }
1570 } else {
1571 for(y = 0; y < height; y += 8) {
1572 for(x = 0; x < width; x += 8) {
1573 float Y[64], U[64], V[64];
1574 for(row = y, pos = 0; row < y+8; ++row) {
1575 // row >= height => use last input row
1576 int clamped_row = (row < height) ? row : height - 1;
1577 int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
1578 for(col = x; col < x+8; ++col, ++pos) {
1579 // if col >= width => use pixel from last input column
1580 int p = base_p + ((col < width) ? col : (width-1))*comp;
1581 float r = dataR[p], g = dataG[p], b = dataB[p];
1582 Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
1583 U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
1584 V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
1585 }
1586 }
1588 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1589 DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
1590 DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
1591 }
1592 }
1593 }
1595 // Do the bit alignment of the EOI marker
1596 stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits);
1597 }
1599 // EOI
1600 stbiw__putc(s, 0xFF);
1601 stbiw__putc(s, 0xD9);
1603 return 1;
1604}
1606STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)
1607{
1608 stbi__write_context s = { 0 };
1609 stbi__start_write_callbacks(&s, func, context);
1610 return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality);
1611}
1614#ifndef STBI_WRITE_NO_STDIO
1615STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
1616{
1617 stbi__write_context s = { 0 };
1618 if (stbi__start_write_file(&s,filename)) {
1619 int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
1620 stbi__end_write_file(&s);
1621 return r;
1622 } else
1623 return 0;
1624}
1625#endif
1627#endif // STB_IMAGE_WRITE_IMPLEMENTATION
1629/* Revision history
1630 1.16 (2021-07-11)
1631 make Deflate code emit uncompressed blocks when it would otherwise expand
1632 support writing BMPs with alpha channel
1633 1.15 (2020-07-13) unknown
1634 1.14 (2020-02-02) updated JPEG writer to downsample chroma channels
1635 1.13
1636 1.12
1637 1.11 (2019-08-11)
1639 1.10 (2019-02-07)
1640 support utf8 filenames in Windows; fix warnings and platform ifdefs
1641 1.09 (2018-02-11)
1642 fix typo in zlib quality API, improve STB_I_W_STATIC in C++
1643 1.08 (2018-01-29)
1644 add stbi__flip_vertically_on_write, external zlib, zlib quality, choose PNG filter
1645 1.07 (2017-07-24)
1646 doc fix
1647 1.06 (2017-07-23)
1648 writing JPEG (using Jon Olick's code)
1649 1.05 ???
1650 1.04 (2017-03-03)
1651 monochrome BMP expansion
1652 1.03 ???
1653 1.02 (2016-04-02)
1654 avoid allocating large structures on the stack
1655 1.01 (2016-01-16)
1656 STBIW_REALLOC_SIZED: support allocators with no realloc support
1657 avoid race-condition in crc initialization
1658 minor compile issues
1659 1.00 (2015-09-14)
1660 installable file IO function
1661 0.99 (2015-09-13)
1662 warning fixes; TGA rle support
1663 0.98 (2015-04-08)
1664 added STBIW_MALLOC, STBIW_ASSERT etc
1665 0.97 (2015-01-18)
1666 fixed HDR asserts, rewrote HDR rle logic
1667 0.96 (2015-01-17)
1668 add HDR output
1669 fix monochrome BMP
1670 0.95 (2014-08-17)
1671 add monochrome TGA output
1672 0.94 (2014-05-31)
1673 rename private functions to avoid conflicts with stb_image.h
1674 0.93 (2014-05-27)
1675 warning fixes
1676 0.92 (2010-08-01)
1677 casts to unsigned char to fix warnings
1678 0.91 (2010-07-17)
1679 first public release
1680 0.90 first internal release
1681*/
1683/*
1684------------------------------------------------------------------------------
1685This software is available under 2 licenses -- choose whichever you prefer.
1686------------------------------------------------------------------------------
1687ALTERNATIVE A - MIT License
1688Copyright (c) 2017 Sean Barrett
1689Permission is hereby granted, free of charge, to any person obtaining a copy of
1690this software and associated documentation files (the "Software"), to deal in
1691the Software without restriction, including without limitation the rights to
1692use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
1693of the Software, and to permit persons to whom the Software is furnished to do
1694so, subject to the following conditions:
1695The above copyright notice and this permission notice shall be included in all
1696copies or substantial portions of the Software.
1697THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1698IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1699FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1700AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1701LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1702OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1703SOFTWARE.
1704------------------------------------------------------------------------------
1705ALTERNATIVE B - Public Domain (www.unlicense.org)
1706This is free and unencumbered software released into the public domain.
1707Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
1708software, either in source code form or as a compiled binary, for any purpose,
1709commercial or non-commercial, and by any means.
1710In jurisdictions that recognize copyright laws, the author or authors of this
1711software dedicate any and all copyright interest in the software to the public
1712domain. We make this dedication for the benefit of the public at large and to
1713the detriment of our heirs and successors. We intend this dedication to be an
1714overt act of relinquishment in perpetuity of all present and future rights to
1715this software under copyright law.
1716THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1717IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1718FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1719AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1720ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1721WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1722------------------------------------------------------------------------------
1723*/
index : raylib-jai
---