116#ifndef INCLUDE_STB_IMAGE_WRITE_H
117#define INCLUDE_STB_IMAGE_WRITE_H
123#ifdef STB_IMAGE_WRITE_STATIC
124#define STBIWDEF static
127#define STBIWDEF extern "C"
129#define STBIWDEF extern
134#ifndef STB_IMAGE_WRITE_STATIC
140#ifndef STBI_WRITE_NO_STDIO
147#ifdef STBIW_WINDOWS_UTF8
148STBIWDEF int stbiw_convert_wchar_to_utf8(
char *
buffer,
size_t bufferlen,
const wchar_t* input);
164#ifdef STB_IMAGE_WRITE_IMPLEMENTATION
167 #ifndef _CRT_SECURE_NO_WARNINGS
168 #define _CRT_SECURE_NO_WARNINGS
170 #ifndef _CRT_NONSTDC_NO_DEPRECATE
171 #define _CRT_NONSTDC_NO_DEPRECATE
175#ifndef STBI_WRITE_NO_STDIO
184#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED))
186#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED)
189#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)."
193#define STBIW_MALLOC(sz) malloc(sz)
194#define STBIW_REALLOC(p,newsz) realloc(p,newsz)
195#define STBIW_FREE(p) free(p)
198#ifndef STBIW_REALLOC_SIZED
199#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz)
204#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
210#define STBIW_ASSERT(x) assert(x)
213#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
215#ifdef STB_IMAGE_WRITE_STATIC
225static int stbi__flip_vertically_on_write = 0;
229 stbi__flip_vertically_on_write = flag;
238} stbi__write_context;
241static void stbi__start_write_callbacks(stbi__write_context *s,
stbi_write_func *c,
void *context)
244 s->context = context;
247#ifndef STBI_WRITE_NO_STDIO
249static void stbi__stdio_write(
void *context,
void *data,
int size)
251 fwrite(data,1,size,(FILE*) context);
254#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
256#define STBIW_EXTERN extern "C"
258#define STBIW_EXTERN extern
260STBIW_EXTERN __declspec(dllimport)
int __stdcall MultiByteToWideChar(
unsigned int cp,
unsigned long flags,
const char *str,
int cbmb,
wchar_t *widestr,
int cchwide);
261STBIW_EXTERN __declspec(dllimport)
int __stdcall WideCharToMultiByte(
unsigned int cp,
unsigned long flags,
const wchar_t *widestr,
int cchwide,
char *str,
int cbmb,
const char *defchar,
int *used_default);
263STBIWDEF int stbiw_convert_wchar_to_utf8(
char *
buffer,
size_t bufferlen,
const wchar_t* input)
265 return WideCharToMultiByte(65001 , 0, input, -1,
buffer, (
int) bufferlen, NULL, NULL);
269static FILE *stbiw__fopen(
char const *filename,
char const *mode)
272#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
274 wchar_t wFilename[1024];
275 if (0 == MultiByteToWideChar(65001 , 0, filename, -1, wFilename,
sizeof(wFilename)/
sizeof(*wFilename)))
278 if (0 == MultiByteToWideChar(65001 , 0, mode, -1, wMode,
sizeof(wMode)/
sizeof(*wMode)))
281#if defined(_MSC_VER) && _MSC_VER >= 1400
282 if (0 != _wfopen_s(&f, wFilename, wMode))
285 f = _wfopen(wFilename, wMode);
288#elif defined(_MSC_VER) && _MSC_VER >= 1400
289 if (0 != fopen_s(&f, filename, mode))
292 f = fopen(filename, mode);
297static int stbi__start_write_file(stbi__write_context *s,
const char *filename)
299 FILE *f = stbiw__fopen(filename,
"wb");
300 stbi__start_write_callbacks(s, stbi__stdio_write, (
void *) f);
304static void stbi__end_write_file(stbi__write_context *s)
306 fclose((FILE *)s->context);
311typedef unsigned int stbiw_uint32;
312typedef int stb_image_write_test[
sizeof(stbiw_uint32)==4 ? 1 : -1];
314static void stbiw__writefv(stbi__write_context *s,
const char *
fmt, va_list v)
319 case '1': {
unsigned char x = STBIW_UCHAR(va_arg(v,
int));
320 s->func(s->context,&x,1);
322 case '2': {
int x = va_arg(v,
int);
324 b[0] = STBIW_UCHAR(x);
325 b[1] = STBIW_UCHAR(x>>8);
326 s->func(s->context,
b,2);
328 case '4': { stbiw_uint32 x = va_arg(v,
int);
331 b[1]=STBIW_UCHAR(x>>8);
332 b[2]=STBIW_UCHAR(x>>16);
333 b[3]=STBIW_UCHAR(x>>24);
334 s->func(s->context,
b,4);
343static void stbiw__writef(stbi__write_context *s,
const char *
fmt, ...)
347 stbiw__writefv(s,
fmt, v);
351static void stbiw__write_flush(stbi__write_context *s)
354 s->func(s->context, &s->buffer, s->buf_used);
359static void stbiw__putc(stbi__write_context *s,
unsigned char c)
361 s->func(s->context, &c, 1);
364static void stbiw__write1(stbi__write_context *s,
unsigned char a)
366 if ((
size_t)s->buf_used + 1 >
sizeof(s->buffer))
367 stbiw__write_flush(s);
368 s->buffer[s->buf_used++] = a;
371static void stbiw__write3(stbi__write_context *s,
unsigned char a,
unsigned char b,
unsigned char c)
374 if ((
size_t)s->buf_used + 3 >
sizeof(s->buffer))
375 stbiw__write_flush(s);
383static void stbiw__write_pixel(stbi__write_context *s,
int rgb_dir,
int comp,
int write_alpha,
int expand_mono,
unsigned char *d)
385 unsigned char bg[3] = { 255, 0, 255}, px[3];
389 stbiw__write1(s, d[comp - 1]);
395 stbiw__write3(s, d[0], d[0], d[0]);
397 stbiw__write1(s, d[0]);
402 for (k = 0; k < 3; ++k)
403 px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
404 stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]);
409 stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
413 stbiw__write1(s, d[comp - 1]);
416static 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)
418 stbiw_uint32 zero = 0;
424 if (stbi__flip_vertically_on_write)
433 for (; j != j_end; j += vdir) {
434 for (i=0; i < x; ++i) {
435 unsigned char *d = (
unsigned char *) data + (j*x+i)*comp;
436 stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
438 stbiw__write_flush(s);
439 s->func(s->context, &zero, scanline_pad);
443static 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, ...)
445 if (y < 0 || x < 0) {
450 stbiw__writefv(s,
fmt, v);
452 stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono);
457static int stbi_write_bmp_core(stbi__write_context *s,
int x,
int y,
int comp,
const void *data)
461 int pad = (-x*3) & 3;
462 return stbiw__outfile(s,-1,-1,x,y,comp,1,(
void *) data,0,pad,
463 "11 4 22 4" "4 44 22 444444",
464 'B',
'M', 14+40+(x*3+pad)*y, 0,0, 14+40,
465 40, x,y, 1,24, 0,0,0,0,0,0);
470 return stbiw__outfile(s,-1,-1,x,y,comp,1,(
void *)data,1,0,
471 "11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444",
472 'B',
'M', 14+108+x*y*4, 0, 0, 14+108,
473 108, x,y, 1,32, 3,0,0,0,0,0, 0xff0000,0xff00,0xff,0xff000000u, 0, 0,0,0, 0,0,0, 0,0,0, 0,0,0);
479 stbi__write_context s = { 0 };
480 stbi__start_write_callbacks(&s, func, context);
481 return stbi_write_bmp_core(&s, x, y, comp, data);
484#ifndef STBI_WRITE_NO_STDIO
487 stbi__write_context s = { 0 };
488 if (stbi__start_write_file(&s,filename)) {
489 int r = stbi_write_bmp_core(&s, x, y, comp, data);
490 stbi__end_write_file(&s);
497static int stbi_write_tga_core(stbi__write_context *s,
int x,
int y,
int comp,
void *data)
499 int has_alpha = (comp == 2 || comp == 4);
500 int colorbytes = has_alpha ? comp-1 : comp;
501 int format = colorbytes < 2 ? 3 : 2;
507 return stbiw__outfile(s, -1, -1, x, y, comp, 0, (
void *) data, has_alpha, 0,
508 "111 221 2222 11", 0, 0,
format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
513 stbiw__writef(s,
"111 221 2222 11", 0,0,
format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8);
515 if (stbi__flip_vertically_on_write) {
524 for (; j != jend; j += jdir) {
525 unsigned char *row = (
unsigned char *) data + j * x * comp;
528 for (i = 0; i < x; i += len) {
529 unsigned char *begin = row + i * comp;
535 diff = memcmp(begin, row + (i + 1) * comp, comp);
537 const unsigned char *prev = begin;
538 for (k = i + 2; k < x && len < 128; ++k) {
539 if (memcmp(prev, row + k * comp, comp)) {
548 for (k = i + 2; k < x && len < 128; ++k) {
549 if (!memcmp(begin, row + k * comp, comp)) {
559 unsigned char header = STBIW_UCHAR(len - 1);
560 stbiw__write1(s, header);
561 for (k = 0; k < len; ++k) {
562 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
565 unsigned char header = STBIW_UCHAR(len - 129);
566 stbiw__write1(s, header);
567 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
571 stbiw__write_flush(s);
578 stbi__write_context s = { 0 };
579 stbi__start_write_callbacks(&s, func, context);
580 return stbi_write_tga_core(&s, x, y, comp, (
void *) data);
583#ifndef STBI_WRITE_NO_STDIO
586 stbi__write_context s = { 0 };
587 if (stbi__start_write_file(&s,filename)) {
588 int r = stbi_write_tga_core(&s, x, y, comp, (
void *) data);
589 stbi__end_write_file(&s);
600#define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
602#ifndef STBI_WRITE_NO_STDIO
604static void stbiw__linear_to_rgbe(
unsigned char *rgbe,
float *linear)
607 float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
609 if (maxcomp < 1e-32f) {
610 rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
612 float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
614 rgbe[0] = (
unsigned char)(linear[0] * normalize);
615 rgbe[1] = (
unsigned char)(linear[1] * normalize);
616 rgbe[2] = (
unsigned char)(linear[2] * normalize);
617 rgbe[3] = (
unsigned char)(exponent + 128);
621static void stbiw__write_run_data(stbi__write_context *s,
int length,
unsigned char databyte)
623 unsigned char lengthbyte = STBIW_UCHAR(
length+128);
624 STBIW_ASSERT(
length+128 <= 255);
625 s->func(s->context, &lengthbyte, 1);
626 s->func(s->context, &databyte, 1);
629static void stbiw__write_dump_data(stbi__write_context *s,
int length,
unsigned char *data)
631 unsigned char lengthbyte = STBIW_UCHAR(
length);
632 STBIW_ASSERT(
length <= 128);
633 s->func(s->context, &lengthbyte, 1);
634 s->func(s->context, data,
length);
637static void stbiw__write_hdr_scanline(stbi__write_context *s,
int width,
int ncomp,
unsigned char *scratch,
float *scanline)
639 unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
640 unsigned char rgbe[4];
644 scanlineheader[2] = (width&0xff00)>>8;
645 scanlineheader[3] = (width&0x00ff);
648 if (width < 8 || width >= 32768) {
649 for (x=0; x < width; x++) {
652 case 3: linear[2] = scanline[x*ncomp + 2];
653 linear[1] = scanline[x*ncomp + 1];
654 linear[0] = scanline[x*ncomp + 0];
657 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
660 stbiw__linear_to_rgbe(rgbe, linear);
661 s->func(s->context, rgbe, 4);
666 for (x=0; x < width; x++) {
669 case 3: linear[2] = scanline[x*ncomp + 2];
670 linear[1] = scanline[x*ncomp + 1];
671 linear[0] = scanline[x*ncomp + 0];
674 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
677 stbiw__linear_to_rgbe(rgbe, linear);
678 scratch[x + width*0] = rgbe[0];
679 scratch[x + width*1] = rgbe[1];
680 scratch[x + width*2] = rgbe[2];
681 scratch[x + width*3] = rgbe[3];
684 s->func(s->context, scanlineheader, 4);
687 for (c=0; c < 4; c++) {
688 unsigned char *comp = &scratch[width*c];
694 while (r+2 < width) {
695 if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
704 if (len > 128) len = 128;
705 stbiw__write_dump_data(s, len, &comp[x]);
711 while (r < width && comp[r] == comp[x])
716 if (len > 127) len = 127;
717 stbiw__write_run_data(s, len, comp[x]);
726static int stbi_write_hdr_core(stbi__write_context *s,
int x,
int y,
int comp,
float *data)
728 if (y <= 0 || x <= 0 || data == NULL)
732 unsigned char *scratch = (
unsigned char *) STBIW_MALLOC(x*4);
735 char header[] =
"#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
736 s->func(s->context, header,
sizeof(header)-1);
738#ifdef __STDC_LIB_EXT1__
739 len = sprintf_s(
buffer,
sizeof(
buffer),
"EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
742 len = sprintf_s(
buffer,
"EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
744 len = sprintf(
buffer,
"EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
747 s->func(s->context,
buffer, len);
750 stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i));
758 stbi__write_context s = { 0 };
759 stbi__start_write_callbacks(&s, func, context);
760 return stbi_write_hdr_core(&s, x, y, comp, (
float *) data);
765 stbi__write_context s = { 0 };
766 if (stbi__start_write_file(&s,filename)) {
767 int r = stbi_write_hdr_core(&s, x, y, comp, (
float *) data);
768 stbi__end_write_file(&s);
781#ifndef STBIW_ZLIB_COMPRESS
783#define stbiw__sbraw(a) ((int *) (void *) (a) - 2)
784#define stbiw__sbm(a) stbiw__sbraw(a)[0]
785#define stbiw__sbn(a) stbiw__sbraw(a)[1]
787#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
788#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
789#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
791#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
792#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
793#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
795static void *stbiw__sbgrowf(
void **arr,
int increment,
int itemsize)
797 int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
798 void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2);
801 if (!*arr) ((
int *) p)[1] = 0;
802 *arr = (
void *) ((
int *) p + 2);
803 stbiw__sbm(*arr) = m;
808static unsigned char *stbiw__zlib_flushf(
unsigned char *data,
unsigned int *bitbuffer,
int *bitcount)
810 while (*bitcount >= 8) {
811 stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
818static int stbiw__zlib_bitrev(
int code,
int codebits)
822 res = (res << 1) | (code & 1);
828static unsigned int stbiw__zlib_countm(
unsigned char *a,
unsigned char *
b,
int limit)
831 for (i=0; i < limit && i < 258; ++i)
832 if (a[i] !=
b[i])
break;
836static unsigned int stbiw__zhash(
unsigned char *data)
838 stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
848#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
849#define stbiw__zlib_add(code,codebits) \
850 (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
851#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
853#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8)
854#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9)
855#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7)
856#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8)
857#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))
858#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
860#define stbiw__ZHASH 16384
864STBIWDEF unsigned char * stbi_zlib_compress(
unsigned char *data,
int data_len,
int *out_len,
int quality)
866#ifdef STBIW_ZLIB_COMPRESS
868 return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality);
870 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 };
871 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 };
872 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 };
873 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 };
874 unsigned int bitbuf=0;
876 unsigned char *out = NULL;
877 unsigned char ***hash_table = (
unsigned char***) STBIW_MALLOC(stbiw__ZHASH *
sizeof(
unsigned char**));
878 if (hash_table == NULL)
880 if (quality < 5) quality = 5;
882 stbiw__sbpush(out, 0x78);
883 stbiw__sbpush(out, 0x5e);
884 stbiw__zlib_add(1,1);
885 stbiw__zlib_add(1,2);
887 for (i=0; i < stbiw__ZHASH; ++i)
888 hash_table[i] = NULL;
891 while (i < data_len-3) {
893 int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
894 unsigned char *bestloc = 0;
895 unsigned char **hlist = hash_table[h];
896 int n = stbiw__sbcount(hlist);
897 for (j=0; j < n; ++j) {
898 if (hlist[j]-data > i-32768) {
899 int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
900 if (d >= best) { best=d; bestloc=hlist[j]; }
904 if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
905 STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality,
sizeof(hash_table[h][0])*quality);
906 stbiw__sbn(hash_table[h]) = quality;
908 stbiw__sbpush(hash_table[h],data+i);
912 h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
913 hlist = hash_table[h];
914 n = stbiw__sbcount(hlist);
915 for (j=0; j < n; ++j) {
916 if (hlist[j]-data > i-32767) {
917 int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
927 int d = (int) (data+i - bestloc);
928 STBIW_ASSERT(d <= 32767 && best <= 258);
929 for (j=0; best > lengthc[j+1]-1; ++j);
930 stbiw__zlib_huff(j+257);
931 if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
932 for (j=0; d > distc[j+1]-1; ++j);
933 stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
934 if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
937 stbiw__zlib_huffb(data[i]);
942 for (;i < data_len; ++i)
943 stbiw__zlib_huffb(data[i]);
944 stbiw__zlib_huff(256);
947 stbiw__zlib_add(0,1);
949 for (i=0; i < stbiw__ZHASH; ++i)
950 (
void) stbiw__sbfree(hash_table[i]);
951 STBIW_FREE(hash_table);
954 if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) {
956 for (j = 0; j < data_len;) {
957 int blocklen = data_len - j;
958 if (blocklen > 32767) blocklen = 32767;
959 stbiw__sbpush(out, data_len - j == blocklen);
960 stbiw__sbpush(out, STBIW_UCHAR(blocklen));
961 stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8));
962 stbiw__sbpush(out, STBIW_UCHAR(~blocklen));
963 stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8));
964 memcpy(out+stbiw__sbn(out), data+j, blocklen);
965 stbiw__sbn(out) += blocklen;
972 unsigned int s1=1, s2=0;
973 int blocklen = (int) (data_len % 5552);
975 while (j < data_len) {
976 for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; }
977 s1 %= 65521; s2 %= 65521;
981 stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
982 stbiw__sbpush(out, STBIW_UCHAR(s2));
983 stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
984 stbiw__sbpush(out, STBIW_UCHAR(s1));
986 *out_len = stbiw__sbn(out);
988 STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
989 return (
unsigned char *) stbiw__sbraw(out);
993static unsigned int stbiw__crc32(
unsigned char *
buffer,
int len)
996 return STBIW_CRC32(
buffer, len);
998 static unsigned int crc_table[256] =
1000 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
1001 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
1002 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
1003 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
1004 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
1005 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
1006 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
1007 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
1008 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
1009 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
1010 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
1011 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
1012 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
1013 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
1014 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
1015 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
1016 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
1017 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
1018 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
1019 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
1020 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
1021 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
1022 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
1023 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
1024 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
1025 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
1026 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
1027 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
1028 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
1029 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
1030 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
1031 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
1034 unsigned int crc = ~0u;
1036 for (i=0; i < len; ++i)
1037 crc = (crc >> 8) ^ crc_table[
buffer[i] ^ (crc & 0xff)];
1042#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)
1043#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
1044#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
1046static void stbiw__wpcrc(
unsigned char **data,
int len)
1048 unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
1049 stbiw__wp32(*data, crc);
1052static unsigned char stbiw__paeth(
int a,
int b,
int c)
1054 int p = a +
b - c, pa = abs(p-a), pb = abs(p-
b), pc = abs(p-c);
1055 if (pa <= pb && pa <= pc)
return STBIW_UCHAR(a);
1056 if (pb <= pc)
return STBIW_UCHAR(
b);
1057 return STBIW_UCHAR(c);
1061static 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)
1063 static int mapping[] = { 0,1,2,3,4 };
1064 static int firstmap[] = { 0,1,0,5,6 };
1065 int *mymap = (y != 0) ? mapping : firstmap;
1067 int type = mymap[filter_type];
1068 unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y);
1069 int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes;
1072 memcpy(line_buffer, z, width*n);
1077 for (i = 0; i < n; ++i) {
1079 case 1: line_buffer[i] = z[i];
break;
1080 case 2: line_buffer[i] = z[i] - z[i-signed_stride];
break;
1081 case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1);
break;
1082 case 4: line_buffer[i] = (
signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0));
break;
1083 case 5: line_buffer[i] = z[i];
break;
1084 case 6: line_buffer[i] = z[i];
break;
1088 case 1:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n];
break;
1089 case 2:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride];
break;
1090 case 3:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1);
break;
1091 case 4:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]);
break;
1092 case 5:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1);
break;
1093 case 6:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0);
break;
1097STBIWDEF unsigned char *stbi_write_png_to_mem(
const unsigned char *pixels,
int stride_bytes,
int x,
int y,
int n,
int *out_len)
1100 int ctype[5] = { -1, 0, 4, 2, 6 };
1101 unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
1102 unsigned char *out,*o, *filt, *zlib;
1103 signed char *line_buffer;
1106 if (stride_bytes == 0)
1107 stride_bytes = x * n;
1109 if (force_filter >= 5) {
1113 filt = (
unsigned char *) STBIW_MALLOC((x*n+1) * y);
if (!filt)
return 0;
1114 line_buffer = (
signed char *) STBIW_MALLOC(x * n);
if (!line_buffer) { STBIW_FREE(filt);
return 0; }
1115 for (j=0; j < y; ++j) {
1117 if (force_filter > -1) {
1118 filter_type = force_filter;
1119 stbiw__encode_png_line((
unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer);
1121 int best_filter = 0, best_filter_val = 0x7fffffff, est, i;
1122 for (filter_type = 0; filter_type < 5; filter_type++) {
1123 stbiw__encode_png_line((
unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer);
1127 for (i = 0; i < x*n; ++i) {
1128 est += abs((
signed char) line_buffer[i]);
1130 if (est < best_filter_val) {
1131 best_filter_val = est;
1132 best_filter = filter_type;
1135 if (filter_type != best_filter) {
1136 stbiw__encode_png_line((
unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer);
1137 filter_type = best_filter;
1141 filt[j*(x*n+1)] = (
unsigned char) filter_type;
1142 STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
1144 STBIW_FREE(line_buffer);
1147 if (!zlib)
return 0;
1150 out = (
unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
1152 *out_len = 8 + 12+13 + 12+zlen + 12;
1155 STBIW_MEMMOVE(o,sig,8); o+= 8;
1157 stbiw__wptag(o,
"IHDR");
1161 *o++ = STBIW_UCHAR(ctype[n]);
1165 stbiw__wpcrc(&o,13);
1167 stbiw__wp32(o, zlen);
1168 stbiw__wptag(o,
"IDAT");
1169 STBIW_MEMMOVE(o, zlib, zlen);
1172 stbiw__wpcrc(&o, zlen);
1175 stbiw__wptag(o,
"IEND");
1178 STBIW_ASSERT(o == out + *out_len);
1183#ifndef STBI_WRITE_NO_STDIO
1184STBIWDEF int stbi_write_png(
char const *filename,
int x,
int y,
int comp,
const void *data,
int stride_bytes)
1188 unsigned char *png = stbi_write_png_to_mem((
const unsigned char *) data, stride_bytes, x, y, comp, &len);
1189 if (png == NULL)
return 0;
1191 f = stbiw__fopen(filename,
"wb");
1192 if (!f) { STBIW_FREE(png);
return 0; }
1193 fwrite(png, 1, len, f);
1203 unsigned char *png = stbi_write_png_to_mem((
const unsigned char *) data, stride_bytes, x, y, comp, &len);
1204 if (png == NULL)
return 0;
1205 func(context, png, len);
1219static 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,
1220 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 };
1222static void stbiw__jpg_writeBits(stbi__write_context *s,
int *bitBufP,
int *bitCntP,
const unsigned short *bs) {
1223 int bitBuf = *bitBufP, bitCnt = *bitCntP;
1225 bitBuf |= bs[0] << (24 - bitCnt);
1226 while(bitCnt >= 8) {
1227 unsigned char c = (bitBuf >> 16) & 255;
1239static void stbiw__jpg_DCT(
float *d0p,
float *d1p,
float *d2p,
float *d3p,
float *d4p,
float *d5p,
float *d6p,
float *d7p) {
1240 float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p;
1241 float z1, z2, z3, z4, z5, z11, z13;
1243 float tmp0 = d0 + d7;
1244 float tmp7 = d0 - d7;
1245 float tmp1 = d1 + d6;
1246 float tmp6 = d1 - d6;
1247 float tmp2 = d2 + d5;
1248 float tmp5 = d2 - d5;
1249 float tmp3 = d3 + d4;
1250 float tmp4 = d3 - d4;
1253 float tmp10 = tmp0 + tmp3;
1254 float tmp13 = tmp0 - tmp3;
1255 float tmp11 = tmp1 + tmp2;
1256 float tmp12 = tmp1 - tmp2;
1261 z1 = (tmp12 + tmp13) * 0.707106781f;
1266 tmp10 = tmp4 + tmp5;
1267 tmp11 = tmp5 + tmp6;
1268 tmp12 = tmp6 + tmp7;
1271 z5 = (tmp10 - tmp12) * 0.382683433f;
1272 z2 = tmp10 * 0.541196100f + z5;
1273 z4 = tmp12 * 1.306562965f + z5;
1274 z3 = tmp11 * 0.707106781f;
1284 *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6;
1287static void stbiw__jpg_calcBits(
int val,
unsigned short bits[2]) {
1288 int tmp1 = val < 0 ? -val : val;
1289 val = val < 0 ? val-1 : val;
1294 bits[0] = val & ((1<<bits[1])-1);
1297static int stbiw__jpg_processDU(stbi__write_context *s,
int *bitBuf,
int *bitCnt,
float *CDU,
int du_stride,
float *fdtbl,
int DC,
const unsigned short HTDC[256][2],
const unsigned short HTAC[256][2]) {
1298 const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
1299 const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
1300 int dataOff, i, j, n, diff, end0pos, x, y;
1304 for(dataOff=0, n=du_stride*8; dataOff<n; dataOff+=du_stride) {
1305 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]);
1308 for(dataOff=0; dataOff<8; ++dataOff) {
1309 stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+du_stride], &CDU[dataOff+du_stride*2], &CDU[dataOff+du_stride*3], &CDU[dataOff+du_stride*4],
1310 &CDU[dataOff+du_stride*5], &CDU[dataOff+du_stride*6], &CDU[dataOff+du_stride*7]);
1313 for(y = 0, j=0; y < 8; ++y) {
1314 for(x = 0; x < 8; ++x,++j) {
1317 v = CDU[i]*fdtbl[j];
1320 DU[stbiw__jpg_ZigZag[j]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
1327 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]);
1329 unsigned short bits[2];
1330 stbiw__jpg_calcBits(diff, bits);
1331 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]);
1332 stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1336 for(; (end0pos>0)&&(DU[end0pos]==0); --end0pos) {
1340 stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1343 for(i = 1; i <= end0pos; ++i) {
1346 unsigned short bits[2];
1347 for (; DU[i]==0 && i<=end0pos; ++i) {
1349 nrzeroes = i-startpos;
1350 if ( nrzeroes >= 16 ) {
1351 int lng = nrzeroes>>4;
1353 for (nrmarker=1; nrmarker <= lng; ++nrmarker)
1354 stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes);
1357 stbiw__jpg_calcBits(DU[i], bits);
1358 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]);
1359 stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1362 stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1367static int stbi_write_jpg_core(stbi__write_context *s,
int width,
int height,
int comp,
const void* data,
int quality) {
1369 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};
1370 static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1371 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};
1372 static const unsigned char std_ac_luminance_values[] = {
1373 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
1374 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
1375 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
1376 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
1377 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
1378 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
1379 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1381 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};
1382 static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1383 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};
1384 static const unsigned char std_ac_chrominance_values[] = {
1385 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
1386 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
1387 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
1388 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
1389 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
1390 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
1391 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1394 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}};
1395 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}};
1396 static const unsigned short YAC_HT[256][2] = {
1397 {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},
1398 {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},
1399 {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},
1400 {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},
1401 {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},
1402 {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},
1403 {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},
1404 {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},
1405 {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},
1406 {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},
1407 {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},
1408 {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},
1409 {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},
1410 {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},
1411 {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},
1412 {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}
1414 static const unsigned short UVAC_HT[256][2] = {
1415 {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},
1416 {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},
1417 {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},
1418 {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},
1419 {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},
1420 {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},
1421 {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},
1422 {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},
1423 {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},
1424 {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},
1425 {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},
1426 {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},
1427 {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},
1428 {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},
1429 {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},
1430 {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}
1432 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,
1433 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};
1434 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,
1435 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};
1436 static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
1437 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f };
1439 int row, col, i, k, subsample;
1440 float fdtbl_Y[64], fdtbl_UV[64];
1441 unsigned char YTable[64], UVTable[64];
1443 if(!data || !width || !height || comp > 4 || comp < 1) {
1447 quality = quality ? quality : 90;
1448 subsample = quality <= 90 ? 1 : 0;
1449 quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
1450 quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
1452 for(i = 0; i < 64; ++i) {
1453 int uvti, yti = (YQT[i]*quality+50)/100;
1454 YTable[stbiw__jpg_ZigZag[i]] = (
unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti);
1455 uvti = (UVQT[i]*quality+50)/100;
1456 UVTable[stbiw__jpg_ZigZag[i]] = (
unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti);
1459 for(row = 0, k = 0; row < 8; ++row) {
1460 for(col = 0; col < 8; ++col, ++k) {
1461 fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1462 fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1468 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 };
1469 static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
1470 const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(
unsigned char)(height>>8),STBIW_UCHAR(height),(
unsigned char)(width>>8),STBIW_UCHAR(width),
1471 3,1,(
unsigned char)(subsample?0x22:0x11),0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
1472 s->func(s->context, (
void*)head0,
sizeof(head0));
1473 s->func(s->context, (
void*)YTable,
sizeof(YTable));
1475 s->func(s->context, UVTable,
sizeof(UVTable));
1476 s->func(s->context, (
void*)head1,
sizeof(head1));
1477 s->func(s->context, (
void*)(std_dc_luminance_nrcodes+1),
sizeof(std_dc_luminance_nrcodes)-1);
1478 s->func(s->context, (
void*)std_dc_luminance_values,
sizeof(std_dc_luminance_values));
1479 stbiw__putc(s, 0x10);
1480 s->func(s->context, (
void*)(std_ac_luminance_nrcodes+1),
sizeof(std_ac_luminance_nrcodes)-1);
1481 s->func(s->context, (
void*)std_ac_luminance_values,
sizeof(std_ac_luminance_values));
1483 s->func(s->context, (
void*)(std_dc_chrominance_nrcodes+1),
sizeof(std_dc_chrominance_nrcodes)-1);
1484 s->func(s->context, (
void*)std_dc_chrominance_values,
sizeof(std_dc_chrominance_values));
1485 stbiw__putc(s, 0x11);
1486 s->func(s->context, (
void*)(std_ac_chrominance_nrcodes+1),
sizeof(std_ac_chrominance_nrcodes)-1);
1487 s->func(s->context, (
void*)std_ac_chrominance_values,
sizeof(std_ac_chrominance_values));
1488 s->func(s->context, (
void*)head2,
sizeof(head2));
1493 static const unsigned short fillBits[] = {0x7F, 7};
1494 int DCY=0, DCU=0, DCV=0;
1495 int bitBuf=0, bitCnt=0;
1497 int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
1498 const unsigned char *dataR = (
const unsigned char *)data;
1499 const unsigned char *dataG = dataR + ofsG;
1500 const unsigned char *dataB = dataR + ofsB;
1503 for(y = 0; y < height; y += 16) {
1504 for(x = 0; x < width; x += 16) {
1505 float Y[256], U[256], V[256];
1506 for(row = y, pos = 0; row < y+16; ++row) {
1508 int clamped_row = (row < height) ? row : height - 1;
1509 int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
1510 for(col = x; col < x+16; ++col, ++pos) {
1512 int p = base_p + ((col < width) ? col : (width-1))*comp;
1513 float r = dataR[p], g = dataG[p],
b = dataB[p];
1514 Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*
b - 128;
1515 U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*
b;
1516 V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*
b;
1519 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+0, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1520 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+8, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1521 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1522 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1526 float subU[64], subV[64];
1528 for(yy = 0, pos = 0; yy < 8; ++yy) {
1529 for(xx = 0; xx < 8; ++xx, ++pos) {
1531 subU[pos] = (U[j+0] + U[j+1] + U[j+16] + U[j+17]) * 0.25f;
1532 subV[pos] = (V[j+0] + V[j+1] + V[j+16] + V[j+17]) * 0.25f;
1535 DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
1536 DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
1541 for(y = 0; y < height; y += 8) {
1542 for(x = 0; x < width; x += 8) {
1543 float Y[64], U[64], V[64];
1544 for(row = y, pos = 0; row < y+8; ++row) {
1546 int clamped_row = (row < height) ? row : height - 1;
1547 int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
1548 for(col = x; col < x+8; ++col, ++pos) {
1550 int p = base_p + ((col < width) ? col : (width-1))*comp;
1551 float r = dataR[p], g = dataG[p],
b = dataB[p];
1552 Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*
b - 128;
1553 U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*
b;
1554 V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*
b;
1558 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1559 DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
1560 DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
1566 stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits);
1570 stbiw__putc(s, 0xFF);
1571 stbiw__putc(s, 0xD9);
1578 stbi__write_context s = { 0 };
1579 stbi__start_write_callbacks(&s, func, context);
1580 return stbi_write_jpg_core(&s, x, y, comp, (
void *) data, quality);
1584#ifndef STBI_WRITE_NO_STDIO
1587 stbi__write_context s = { 0 };
1588 if (stbi__start_write_file(&s,filename)) {
1589 int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
1590 stbi__end_write_file(&s);
char const int length
Definition cJSON.h:169
const cJSON *const b
Definition cJSON.h:261
int cJSON_bool fmt
Definition cJSON.h:166
char const int const cJSON_bool format
Definition cJSON.h:169
char * buffer
Definition cJSON.h:169
#define STBIWDEF
Definition stb_image_write.h:129
STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data)
void stbi_write_func(void *context, void *data, int size)
Definition stb_image_write.h:152
STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data)
STBIWDEF int stbi_write_png_compression_level
Definition stb_image_write.h:136
STBIWDEF int stbi_write_force_png_filter
Definition stb_image_write.h:137
STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean)
STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data)
STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes)
STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes)
STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data)
STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data)
STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data)
STBIWDEF int stbi_write_tga_with_rle
Definition stb_image_write.h:135
STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)