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