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