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