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