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