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