Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
folium-app
GitHub Repository: folium-app/Folium
Path: blob/a-new-beginning/SharedDependencies/Sources/stb/include/stb_image_write.h
2 views
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
13
ABOUT:
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
23
BUILDING:
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
35
UNICODE:
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
43
USAGE:
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
113
CREDITS:
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
144
LICENSE
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
169
extern int stbi_write_tga_with_rle;
170
extern int stbi_write_png_compression_level;
171
extern int stbi_write_force_png_filter;
172
#endif
173
174
#ifndef STBI_WRITE_NO_STDIO
175
STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
176
STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
177
STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
178
STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
179
STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality);
180
181
#ifdef STBI_WINDOWS_UTF8
182
STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
183
#endif
184
#endif
185
186
typedef void stbi_write_func(void *context, void *data, int size);
187
188
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);
189
STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
190
STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
191
STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
192
STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality);
193
194
STBIWDEF 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
250
static int stbi__flip_vertically_on_write=0;
251
static int stbi_write_png_compression_level = 8;
252
static int stbi_write_tga_with_rle = 1;
253
static int stbi_write_force_png_filter = -1;
254
#else
255
int stbi_write_png_compression_level = 8;
256
int stbi__flip_vertically_on_write=0;
257
int stbi_write_tga_with_rle = 1;
258
int stbi_write_force_png_filter = -1;
259
#endif
260
261
STBIWDEF void stbi_flip_vertically_on_write(int flag)
262
{
263
stbi__flip_vertically_on_write = flag;
264
}
265
266
typedef struct
267
{
268
stbi_write_func *func;
269
void *context;
270
} stbi__write_context;
271
272
// initialize a callback-based context
273
static 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
281
static 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
292
STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide);
293
STBIW_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
295
STBIWDEF 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
301
static 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
329
static 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
336
static void stbi__end_write_file(stbi__write_context *s)
337
{
338
fclose((FILE *)s->context);
339
}
340
341
#endif // !STBI_WRITE_NO_STDIO
342
343
typedef unsigned int stbiw_uint32;
344
typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
345
346
static 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
375
static 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
383
static void stbiw__putc(stbi__write_context *s, unsigned char c)
384
{
385
s->func(s->context, &c, 1);
386
}
387
388
static 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
395
static 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
428
static 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
454
static 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
468
static 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
477
STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
478
{
479
stbi__write_context s;
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
485
STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
486
{
487
stbi__write_context s;
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 //!STBI_WRITE_NO_STDIO
496
497
static 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
506
if (!stbi_write_tga_with_rle) {
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
575
STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
576
{
577
stbi__write_context s;
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
583
STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
584
{
585
stbi__write_context s;
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
601
static 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
618
static 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
626
static 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
634
static 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
723
static 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
749
STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
750
{
751
stbi__write_context s;
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
757
STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
758
{
759
stbi__write_context s;
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
770
//////////////////////////////////////////////////////////////////////////////
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
789
static 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
802
static 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
812
static 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
822
static 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
830
static 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
858
STBIWDEF 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
970
static 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
1023
static 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
1029
static 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
1038
static 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
1074
STBIWDEF 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
1161
STBIWDEF 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
1177
STBIWDEF 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
1196
static 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
1199
static 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
1216
static 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
1264
static 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
1274
static 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
1339
static 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
1509
STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)
1510
{
1511
stbi__write_context s;
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
1518
STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
1519
{
1520
stbi__write_context s;
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
------------------------------------------------------------------------------
1581
This software is available under 2 licenses -- choose whichever you prefer.
1582
------------------------------------------------------------------------------
1583
ALTERNATIVE A - MIT License
1584
Copyright (c) 2017 Sean Barrett
1585
Permission is hereby granted, free of charge, to any person obtaining a copy of
1586
this software and associated documentation files (the "Software"), to deal in
1587
the Software without restriction, including without limitation the rights to
1588
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
1589
of the Software, and to permit persons to whom the Software is furnished to do
1590
so, subject to the following conditions:
1591
The above copyright notice and this permission notice shall be included in all
1592
copies or substantial portions of the Software.
1593
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1594
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1595
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1596
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1597
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1598
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1599
SOFTWARE.
1600
------------------------------------------------------------------------------
1601
ALTERNATIVE B - Public Domain (www.unlicense.org)
1602
This is free and unencumbered software released into the public domain.
1603
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
1604
software, either in source code form or as a compiled binary, for any purpose,
1605
commercial or non-commercial, and by any means.
1606
In jurisdictions that recognize copyright laws, the author or authors of this
1607
software dedicate any and all copyright interest in the software to the public
1608
domain. We make this dedication for the benefit of the public at large and to
1609
the detriment of our heirs and successors. We intend this dedication to be an
1610
overt act of relinquishment in perpetuity of all present and future rights to
1611
this software under copyright law.
1612
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1613
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1614
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1615
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1616
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1617
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1618
------------------------------------------------------------------------------
1619
*/
1620
1621