151#ifndef INCLUDE_STB_IMAGE_WRITE_H
152#define INCLUDE_STB_IMAGE_WRITE_H
158#ifdef STB_IMAGE_WRITE_STATIC
159#define STBIWDEF static
162#define STBIWDEF extern "C"
164#define STBIWDEF extern
169#ifndef STB_IMAGE_WRITE_STATIC
175#ifndef STBI_WRITE_NO_STDIO
182#ifdef STBIW_WINDOWS_UTF8
183STBIWDEF int stbiw_convert_wchar_to_utf8(
char *buffer,
size_t bufferlen,
const wchar_t* input);
199#ifdef STB_IMAGE_WRITE_IMPLEMENTATION
202 #ifndef _CRT_SECURE_NO_WARNINGS
203 #define _CRT_SECURE_NO_WARNINGS
205 #ifndef _CRT_NONSTDC_NO_DEPRECATE
206 #define _CRT_NONSTDC_NO_DEPRECATE
210#ifndef STBI_WRITE_NO_STDIO
219#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED))
221#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED)
224#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)."
228#define STBIW_MALLOC(sz) malloc(sz)
229#define STBIW_REALLOC(p,newsz) realloc(p,newsz)
230#define STBIW_FREE(p) free(p)
233#ifndef STBIW_REALLOC_SIZED
234#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz)
239#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
245#define STBIW_ASSERT(x) assert(x)
248#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
250#ifdef STB_IMAGE_WRITE_STATIC
260static int stbi__flip_vertically_on_write = 0;
264 stbi__flip_vertically_on_write = flag;
271 unsigned char buffer[64];
273} stbi__write_context;
276static void stbi__start_write_callbacks(stbi__write_context *s,
stbi_write_func *c,
void *context)
279 s->context = context;
282#ifndef STBI_WRITE_NO_STDIO
284static void stbi__stdio_write(
void *context,
void *data,
int size)
286 fwrite(data,1,size,(FILE*) context);
289#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
291#define STBIW_EXTERN extern "C"
293#define STBIW_EXTERN extern
295STBIW_EXTERN __declspec(dllimport)
int __stdcall MultiByteToWideChar(
unsigned int cp,
unsigned long flags,
const char *str,
int cbmb,
wchar_t *widestr,
int cchwide);
296STBIW_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);
298STBIWDEF int stbiw_convert_wchar_to_utf8(
char *buffer,
size_t bufferlen,
const wchar_t* input)
300 return WideCharToMultiByte(65001 , 0, input, -1, buffer, (
int) bufferlen,
NULL,
NULL);
304static FILE *stbiw__fopen(
char const *filename,
char const *mode)
307#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
309 wchar_t wFilename[1024];
310 if (0 == MultiByteToWideChar(65001 , 0, filename, -1, wFilename,
sizeof(wFilename)/
sizeof(*wFilename)))
313 if (0 == MultiByteToWideChar(65001 , 0, mode, -1, wMode,
sizeof(wMode)/
sizeof(*wMode)))
316#if defined(_MSC_VER) && _MSC_VER >= 1400
317 if (0 != _wfopen_s(&f, wFilename, wMode))
320 f = _wfopen(wFilename, wMode);
323#elif defined(_MSC_VER) && _MSC_VER >= 1400
324 if (0 != fopen_s(&f, filename, mode))
327 f = fopen(filename, mode);
332static int stbi__start_write_file(stbi__write_context *s,
const char *filename)
334 FILE *f = stbiw__fopen(filename,
"wb");
335 stbi__start_write_callbacks(s, stbi__stdio_write, (
void *) f);
339static void stbi__end_write_file(stbi__write_context *s)
341 fclose((FILE *)s->context);
346typedef unsigned int stbiw_uint32;
347typedef int stb_image_write_test[
sizeof(stbiw_uint32)==4 ? 1 : -1];
349static void stbiw__writefv(stbi__write_context *s,
const char *fmt, va_list v)
354 case '1': {
unsigned char x = STBIW_UCHAR(va_arg(v,
int));
355 s->func(s->context,&x,1);
357 case '2': {
int x = va_arg(v,
int);
359 b[0] = STBIW_UCHAR(x);
360 b[1] = STBIW_UCHAR(x>>8);
361 s->func(s->context,b,2);
363 case '4': { stbiw_uint32 x = va_arg(v,
int);
366 b[1]=STBIW_UCHAR(x>>8);
367 b[2]=STBIW_UCHAR(x>>16);
368 b[3]=STBIW_UCHAR(x>>24);
369 s->func(s->context,b,4);
378static void stbiw__writef(stbi__write_context *s,
const char *fmt, ...)
382 stbiw__writefv(s, fmt, v);
386static void stbiw__write_flush(stbi__write_context *s)
389 s->func(s->context, &s->buffer, s->buf_used);
394static void stbiw__putc(stbi__write_context *s,
unsigned char c)
396 s->func(s->context, &c, 1);
399static void stbiw__write1(stbi__write_context *s,
unsigned char a)
401 if ((
size_t)s->buf_used + 1 >
sizeof(s->buffer))
402 stbiw__write_flush(s);
403 s->buffer[s->buf_used++] = a;
406static void stbiw__write3(stbi__write_context *s,
unsigned char a,
unsigned char b,
unsigned char c)
409 if ((
size_t)s->buf_used + 3 >
sizeof(s->buffer))
410 stbiw__write_flush(s);
418static void stbiw__write_pixel(stbi__write_context *s,
int rgb_dir,
int comp,
int write_alpha,
int expand_mono,
unsigned char *d)
420 unsigned char bg[3] = { 255, 0, 255}, px[3];
424 stbiw__write1(s, d[comp - 1]);
430 stbiw__write3(s, d[0], d[0], d[0]);
432 stbiw__write1(s, d[0]);
437 for (k = 0; k < 3; ++k)
438 px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
439 stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]);
444 stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
448 stbiw__write1(s, d[comp - 1]);
451static 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)
453 stbiw_uint32 zero = 0;
459 if (stbi__flip_vertically_on_write)
468 for (; j != j_end; j += vdir) {
469 for (i=0; i < x; ++i) {
470 unsigned char *d = (
unsigned char *) data + (j*x+i)*comp;
471 stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
473 stbiw__write_flush(s);
474 s->func(s->context, &zero, scanline_pad);
478static 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, ...)
480 if (y < 0 || x < 0) {
485 stbiw__writefv(s, fmt, v);
487 stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono);
492static int stbi_write_bmp_core(stbi__write_context *s,
int x,
int y,
int comp,
const void *data)
496 int pad = (-x*3) & 3;
497 return stbiw__outfile(s,-1,-1,x,y,comp,1,(
void *) data,0,pad,
498 "11 4 22 4" "4 44 22 444444",
499 'B',
'M', 14+40+(x*3+pad)*y, 0,0, 14+40,
500 40, x,y, 1,24, 0,0,0,0,0,0);
505 return stbiw__outfile(s,-1,-1,x,y,comp,1,(
void *)data,1,0,
506 "11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444",
507 'B',
'M', 14+108+x*y*4, 0, 0, 14+108,
508 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);
514 stbi__write_context s = { 0 };
515 stbi__start_write_callbacks(&s, func, context);
516 return stbi_write_bmp_core(&s, x, y, comp, data);
519#ifndef STBI_WRITE_NO_STDIO
522 stbi__write_context s = { 0 };
523 if (stbi__start_write_file(&s,filename)) {
524 int r = stbi_write_bmp_core(&s, x, y, comp, data);
525 stbi__end_write_file(&s);
532static int stbi_write_tga_core(stbi__write_context *s,
int x,
int y,
int comp,
void *data)
534 int has_alpha = (comp == 2 || comp == 4);
535 int colorbytes = has_alpha ? comp-1 : comp;
536 int format = colorbytes < 2 ? 3 : 2;
542 return stbiw__outfile(s, -1, -1, x, y, comp, 0, (
void *) data, has_alpha, 0,
543 "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
548 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);
550 if (stbi__flip_vertically_on_write) {
559 for (; j != jend; j += jdir) {
560 unsigned char *row = (
unsigned char *) data + j * x * comp;
563 for (i = 0; i < x; i += len) {
564 unsigned char *begin = row + i * comp;
570 diff = memcmp(begin, row + (i + 1) * comp, comp);
572 const unsigned char *prev = begin;
573 for (k = i + 2; k < x && len < 128; ++k) {
574 if (memcmp(prev, row + k * comp, comp)) {
583 for (k = i + 2; k < x && len < 128; ++k) {
584 if (!memcmp(begin, row + k * comp, comp)) {
594 unsigned char header = STBIW_UCHAR(len - 1);
595 stbiw__write1(s, header);
596 for (k = 0; k < len; ++k) {
597 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
600 unsigned char header = STBIW_UCHAR(len - 129);
601 stbiw__write1(s, header);
602 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
606 stbiw__write_flush(s);
613 stbi__write_context s = { 0 };
614 stbi__start_write_callbacks(&s, func, context);
615 return stbi_write_tga_core(&s, x, y, comp, (
void *) data);
618#ifndef STBI_WRITE_NO_STDIO
621 stbi__write_context s = { 0 };
622 if (stbi__start_write_file(&s,filename)) {
623 int r = stbi_write_tga_core(&s, x, y, comp, (
void *) data);
624 stbi__end_write_file(&s);
635#define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
637#ifndef STBI_WRITE_NO_STDIO
639static void stbiw__linear_to_rgbe(
unsigned char *rgbe,
float *linear)
642 float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
644 if (maxcomp < 1e-32f) {
645 rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
647 float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
649 rgbe[0] = (
unsigned char)(linear[0] * normalize);
650 rgbe[1] = (
unsigned char)(linear[1] * normalize);
651 rgbe[2] = (
unsigned char)(linear[2] * normalize);
652 rgbe[3] = (
unsigned char)(exponent + 128);
656static void stbiw__write_run_data(stbi__write_context *s,
int length,
unsigned char databyte)
658 unsigned char lengthbyte = STBIW_UCHAR(length+128);
659 STBIW_ASSERT(length+128 <= 255);
660 s->func(s->context, &lengthbyte, 1);
661 s->func(s->context, &databyte, 1);
664static void stbiw__write_dump_data(stbi__write_context *s,
int length,
unsigned char *data)
666 unsigned char lengthbyte = STBIW_UCHAR(length);
667 STBIW_ASSERT(length <= 128);
668 s->func(s->context, &lengthbyte, 1);
669 s->func(s->context, data, length);
672static void stbiw__write_hdr_scanline(stbi__write_context *s,
int width,
int ncomp,
unsigned char *scratch,
float *scanline)
674 unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
675 unsigned char rgbe[4];
679 scanlineheader[2] = (width&0xff00)>>8;
680 scanlineheader[3] = (width&0x00ff);
683 if (width < 8 || width >= 32768) {
684 for (x=0; x < width; x++) {
687 case 3: linear[2] = scanline[x*ncomp + 2];
688 linear[1] = scanline[x*ncomp + 1];
689 linear[0] = scanline[x*ncomp + 0];
692 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
695 stbiw__linear_to_rgbe(rgbe, linear);
696 s->func(s->context, rgbe, 4);
701 for (x=0; x < width; x++) {
704 case 3: linear[2] = scanline[x*ncomp + 2];
705 linear[1] = scanline[x*ncomp + 1];
706 linear[0] = scanline[x*ncomp + 0];
709 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
712 stbiw__linear_to_rgbe(rgbe, linear);
713 scratch[x + width*0] = rgbe[0];
714 scratch[x + width*1] = rgbe[1];
715 scratch[x + width*2] = rgbe[2];
716 scratch[x + width*3] = rgbe[3];
719 s->func(s->context, scanlineheader, 4);
722 for (c=0; c < 4; c++) {
723 unsigned char *comp = &scratch[width*c];
729 while (r+2 < width) {
730 if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
739 if (len > 128) len = 128;
740 stbiw__write_dump_data(s, len, &comp[x]);
746 while (r < width && comp[r] == comp[x])
751 if (len > 127) len = 127;
752 stbiw__write_run_data(s, len, comp[x]);
761static int stbi_write_hdr_core(stbi__write_context *s,
int x,
int y,
int comp,
float *data)
763 if (y <= 0 || x <= 0 || data ==
NULL)
767 unsigned char *scratch = (
unsigned char *)
STBIW_MALLOC(x*4);
770 char header[] =
"#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
771 s->func(s->context, header,
sizeof(header)-1);
773#ifdef __STDC_LIB_EXT1__
774 len = sprintf_s(buffer,
sizeof(buffer),
"EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
776 len = sprintf(buffer,
"EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
778 s->func(s->context, buffer, len);
781 stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i));
789 stbi__write_context s = { 0 };
790 stbi__start_write_callbacks(&s, func, context);
791 return stbi_write_hdr_core(&s, x, y, comp, (
float *) data);
796 stbi__write_context s = { 0 };
797 if (stbi__start_write_file(&s,filename)) {
798 int r = stbi_write_hdr_core(&s, x, y, comp, (
float *) data);
799 stbi__end_write_file(&s);
812#ifndef STBIW_ZLIB_COMPRESS
814#define stbiw__sbraw(a) ((int *) (void *) (a) - 2)
815#define stbiw__sbm(a) stbiw__sbraw(a)[0]
816#define stbiw__sbn(a) stbiw__sbraw(a)[1]
818#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
819#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
820#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
822#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
823#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
824#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
826static void *stbiw__sbgrowf(
void **arr,
int increment,
int itemsize)
828 int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
829 void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize +
sizeof(
int)*2) : 0, itemsize * m +
sizeof(
int)*2);
832 if (!*arr) ((
int *) p)[1] = 0;
833 *arr = (
void *) ((
int *) p + 2);
834 stbiw__sbm(*arr) = m;
839static unsigned char *stbiw__zlib_flushf(
unsigned char *data,
unsigned int *bitbuffer,
int *bitcount)
841 while (*bitcount >= 8) {
842 stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
849static int stbiw__zlib_bitrev(
int code,
int codebits)
853 res = (res << 1) | (code & 1);
859static unsigned int stbiw__zlib_countm(
unsigned char *a,
unsigned char *b,
int limit)
862 for (i=0; i < limit && i < 258; ++i)
863 if (a[i] != b[i])
break;
867static unsigned int stbiw__zhash(
unsigned char *data)
869 stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
879#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
880#define stbiw__zlib_add(code,codebits) \
881 (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
882#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
884#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8)
885#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9)
886#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7)
887#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8)
888#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))
889#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
891#define stbiw__ZHASH 16384
895STBIWDEF unsigned char * stbi_zlib_compress(
unsigned char *data,
int data_len,
int *out_len,
int quality)
897#ifdef STBIW_ZLIB_COMPRESS
899 return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality);
901 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 };
902 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 };
903 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 };
904 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 };
905 unsigned int bitbuf=0;
907 unsigned char *out =
NULL;
908 unsigned char ***hash_table = (
unsigned char***)
STBIW_MALLOC(stbiw__ZHASH *
sizeof(
unsigned char**));
909 if (hash_table ==
NULL)
911 if (quality < 5) quality = 5;
913 stbiw__sbpush(out, 0x78);
914 stbiw__sbpush(out, 0x5e);
915 stbiw__zlib_add(1,1);
916 stbiw__zlib_add(1,2);
918 for (i=0; i < stbiw__ZHASH; ++i)
919 hash_table[i] =
NULL;
922 while (i < data_len-3) {
924 int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
925 unsigned char *bestloc = 0;
926 unsigned char **hlist = hash_table[h];
927 int n = stbiw__sbcount(hlist);
928 for (j=0; j < n; ++j) {
929 if (hlist[j]-data > i-32768) {
930 int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
931 if (d >= best) { best=d; bestloc=hlist[j]; }
935 if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
936 STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality,
sizeof(hash_table[h][0])*quality);
937 stbiw__sbn(hash_table[h]) = quality;
939 stbiw__sbpush(hash_table[h],data+i);
943 h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
944 hlist = hash_table[h];
945 n = stbiw__sbcount(hlist);
946 for (j=0; j < n; ++j) {
947 if (hlist[j]-data > i-32767) {
948 int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
958 int d = (int) (data+i - bestloc);
959 STBIW_ASSERT(d <= 32767 && best <= 258);
960 for (j=0; best > lengthc[j+1]-1; ++j);
961 stbiw__zlib_huff(j+257);
962 if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
963 for (j=0; d > distc[j+1]-1; ++j);
964 stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
965 if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
968 stbiw__zlib_huffb(data[i]);
973 for (;i < data_len; ++i)
974 stbiw__zlib_huffb(data[i]);
975 stbiw__zlib_huff(256);
978 stbiw__zlib_add(0,1);
980 for (i=0; i < stbiw__ZHASH; ++i)
981 (
void) stbiw__sbfree(hash_table[i]);
985 if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) {
987 for (j = 0; j < data_len;) {
988 int blocklen = data_len - j;
989 if (blocklen > 32767) blocklen = 32767;
990 stbiw__sbpush(out, data_len - j == blocklen);
991 stbiw__sbpush(out, STBIW_UCHAR(blocklen));
992 stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8));
993 stbiw__sbpush(out, STBIW_UCHAR(~blocklen));
994 stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8));
995 memcpy(out+stbiw__sbn(out), data+j, blocklen);
996 stbiw__sbn(out) += blocklen;
1003 unsigned int s1=1, s2=0;
1004 int blocklen = (int) (data_len % 5552);
1006 while (j < data_len) {
1007 for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; }
1008 s1 %= 65521; s2 %= 65521;
1012 stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
1013 stbiw__sbpush(out, STBIW_UCHAR(s2));
1014 stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
1015 stbiw__sbpush(out, STBIW_UCHAR(s1));
1017 *out_len = stbiw__sbn(out);
1019 STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
1020 return (
unsigned char *) stbiw__sbraw(out);
1024static unsigned int stbiw__crc32(
unsigned char *buffer,
int len)
1027 return STBIW_CRC32(buffer, len);
1029 static unsigned int crc_table[256] =
1031 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
1032 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
1033 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
1034 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
1035 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
1036 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
1037 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
1038 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
1039 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
1040 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
1041 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
1042 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
1043 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
1044 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
1045 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
1046 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
1047 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
1048 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
1049 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
1050 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
1051 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
1052 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
1053 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
1054 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
1055 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
1056 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
1057 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
1058 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
1059 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
1060 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
1061 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
1062 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
1065 unsigned int crc = ~0u;
1067 for (i=0; i < len; ++i)
1068 crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
1073#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)
1074#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
1075#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
1077static void stbiw__wpcrc(
unsigned char **data,
int len)
1079 unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
1080 stbiw__wp32(*data, crc);
1083static unsigned char stbiw__paeth(
int a,
int b,
int c)
1085 int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
1086 if (pa <= pb && pa <= pc)
return STBIW_UCHAR(a);
1087 if (pb <= pc)
return STBIW_UCHAR(b);
1088 return STBIW_UCHAR(c);
1092static 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)
1094 static int mapping[] = { 0,1,2,3,4 };
1095 static int firstmap[] = { 0,1,0,5,6 };
1096 int *mymap = (y != 0) ? mapping : firstmap;
1098 int type = mymap[filter_type];
1099 unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y);
1100 int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes;
1103 memcpy(line_buffer, z, width*n);
1108 for (i = 0; i < n; ++i) {
1110 case 1: line_buffer[i] = z[i];
break;
1111 case 2: line_buffer[i] = z[i] - z[i-signed_stride];
break;
1112 case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1);
break;
1113 case 4: line_buffer[i] = (
signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0));
break;
1114 case 5: line_buffer[i] = z[i];
break;
1115 case 6: line_buffer[i] = z[i];
break;
1119 case 1:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n];
break;
1120 case 2:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride];
break;
1121 case 3:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1);
break;
1122 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;
1123 case 5:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1);
break;
1124 case 6:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0);
break;
1128STBIWDEF unsigned char *stbi_write_png_to_mem(
const unsigned char *pixels,
int stride_bytes,
int x,
int y,
int n,
int *out_len)
1131 int ctype[5] = { -1, 0, 4, 2, 6 };
1132 unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
1133 unsigned char *out,*o, *filt, *zlib;
1134 signed char *line_buffer;
1137 if (stride_bytes == 0)
1138 stride_bytes = x * n;
1140 if (force_filter >= 5) {
1144 filt = (
unsigned char *)
STBIW_MALLOC((x*n+1) * y);
if (!filt)
return 0;
1146 for (j=0; j < y; ++j) {
1148 if (force_filter > -1) {
1149 filter_type = force_filter;
1150 stbiw__encode_png_line((
unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer);
1152 int best_filter = 0, best_filter_val = 0x7fffffff, est, i;
1153 for (filter_type = 0; filter_type < 5; filter_type++) {
1154 stbiw__encode_png_line((
unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer);
1158 for (i = 0; i < x*n; ++i) {
1159 est += abs((
signed char) line_buffer[i]);
1161 if (est < best_filter_val) {
1162 best_filter_val = est;
1163 best_filter = filter_type;
1166 if (filter_type != best_filter) {
1167 stbiw__encode_png_line((
unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer);
1168 filter_type = best_filter;
1172 filt[j*(x*n+1)] = (
unsigned char) filter_type;
1173 STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
1178 if (!zlib)
return 0;
1181 out = (
unsigned char *)
STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
1183 *out_len = 8 + 12+13 + 12+zlen + 12;
1186 STBIW_MEMMOVE(o,sig,8); o+= 8;
1188 stbiw__wptag(o,
"IHDR");
1192 *o++ = STBIW_UCHAR(ctype[n]);
1196 stbiw__wpcrc(&o,13);
1198 stbiw__wp32(o, zlen);
1199 stbiw__wptag(o,
"IDAT");
1200 STBIW_MEMMOVE(o, zlib, zlen);
1203 stbiw__wpcrc(&o, zlen);
1206 stbiw__wptag(o,
"IEND");
1209 STBIW_ASSERT(o == out + *out_len);
1214#ifndef STBI_WRITE_NO_STDIO
1215STBIWDEF int stbi_write_png(
char const *filename,
int x,
int y,
int comp,
const void *data,
int stride_bytes)
1219 unsigned char *png = stbi_write_png_to_mem((
const unsigned char *) data, stride_bytes, x, y, comp, &len);
1220 if (png ==
NULL)
return 0;
1222 f = stbiw__fopen(filename,
"wb");
1224 fwrite(png, 1, len, f);
1234 unsigned char *png = stbi_write_png_to_mem((
const unsigned char *) data, stride_bytes, x, y, comp, &len);
1235 if (png ==
NULL)
return 0;
1236 func(context, png, len);
1250static 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,
1251 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 };
1253static void stbiw__jpg_writeBits(stbi__write_context *s,
int *bitBufP,
int *bitCntP,
const unsigned short *bs) {
1254 int bitBuf = *bitBufP, bitCnt = *bitCntP;
1256 bitBuf |= bs[0] << (24 - bitCnt);
1257 while(bitCnt >= 8) {
1258 unsigned char c = (bitBuf >> 16) & 255;
1270static void stbiw__jpg_DCT(
float *d0p,
float *d1p,
float *d2p,
float *d3p,
float *d4p,
float *d5p,
float *d6p,
float *d7p) {
1271 float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p;
1272 float z1, z2, z3, z4, z5, z11, z13;
1274 float tmp0 = d0 + d7;
1275 float tmp7 = d0 - d7;
1276 float tmp1 = d1 + d6;
1277 float tmp6 = d1 - d6;
1278 float tmp2 = d2 + d5;
1279 float tmp5 = d2 - d5;
1280 float tmp3 = d3 + d4;
1281 float tmp4 = d3 - d4;
1284 float tmp10 = tmp0 + tmp3;
1285 float tmp13 = tmp0 - tmp3;
1286 float tmp11 = tmp1 + tmp2;
1287 float tmp12 = tmp1 - tmp2;
1292 z1 = (tmp12 + tmp13) * 0.707106781f;
1297 tmp10 = tmp4 + tmp5;
1298 tmp11 = tmp5 + tmp6;
1299 tmp12 = tmp6 + tmp7;
1302 z5 = (tmp10 - tmp12) * 0.382683433f;
1303 z2 = tmp10 * 0.541196100f + z5;
1304 z4 = tmp12 * 1.306562965f + z5;
1305 z3 = tmp11 * 0.707106781f;
1315 *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6;
1318static void stbiw__jpg_calcBits(
int val,
unsigned short bits[2]) {
1319 int tmp1 = val < 0 ? -val : val;
1320 val = val < 0 ? val-1 : val;
1325 bits[0] = val & ((1<<bits[1])-1);
1328static 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]) {
1329 const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
1330 const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
1331 int dataOff, i, j, n, diff, end0pos, x, y;
1335 for(dataOff=0, n=du_stride*8; dataOff<n; dataOff+=du_stride) {
1336 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]);
1339 for(dataOff=0; dataOff<8; ++dataOff) {
1340 stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+du_stride], &CDU[dataOff+du_stride*2], &CDU[dataOff+du_stride*3], &CDU[dataOff+du_stride*4],
1341 &CDU[dataOff+du_stride*5], &CDU[dataOff+du_stride*6], &CDU[dataOff+du_stride*7]);
1344 for(y = 0, j=0; y < 8; ++y) {
1345 for(x = 0; x < 8; ++x,++j) {
1348 v = CDU[i]*fdtbl[j];
1351 DU[stbiw__jpg_ZigZag[j]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
1358 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]);
1360 unsigned short bits[2];
1361 stbiw__jpg_calcBits(diff, bits);
1362 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]);
1363 stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1367 for(; (end0pos>0)&&(DU[end0pos]==0); --end0pos) {
1371 stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1374 for(i = 1; i <= end0pos; ++i) {
1377 unsigned short bits[2];
1378 for (; DU[i]==0 && i<=end0pos; ++i) {
1380 nrzeroes = i-startpos;
1381 if ( nrzeroes >= 16 ) {
1382 int lng = nrzeroes>>4;
1384 for (nrmarker=1; nrmarker <= lng; ++nrmarker)
1385 stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes);
1388 stbiw__jpg_calcBits(DU[i], bits);
1389 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]);
1390 stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1393 stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1398static int stbi_write_jpg_core(stbi__write_context *s,
int width,
int height,
int comp,
const void* data,
int quality) {
1400 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};
1401 static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1402 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};
1403 static const unsigned char std_ac_luminance_values[] = {
1404 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
1405 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
1406 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
1407 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
1408 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
1409 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
1410 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1412 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};
1413 static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1414 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};
1415 static const unsigned char std_ac_chrominance_values[] = {
1416 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
1417 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
1418 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
1419 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
1420 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
1421 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
1422 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1425 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}};
1426 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}};
1427 static const unsigned short YAC_HT[256][2] = {
1428 {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},
1429 {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},
1430 {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},
1431 {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},
1432 {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},
1433 {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},
1434 {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},
1435 {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},
1436 {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},
1437 {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},
1438 {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},
1439 {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},
1440 {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},
1441 {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},
1442 {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},
1443 {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}
1445 static const unsigned short UVAC_HT[256][2] = {
1446 {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},
1447 {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},
1448 {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},
1449 {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},
1450 {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},
1451 {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},
1452 {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},
1453 {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},
1454 {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},
1455 {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},
1456 {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},
1457 {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},
1458 {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},
1459 {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},
1460 {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},
1461 {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}
1463 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,
1464 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};
1465 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,
1466 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};
1467 static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
1468 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f };
1470 int row, col, i, k, subsample;
1471 float fdtbl_Y[64], fdtbl_UV[64];
1472 unsigned char YTable[64], UVTable[64];
1474 if(!data || !width || !height || comp > 4 || comp < 1) {
1478 quality = quality ? quality : 90;
1479 subsample = quality <= 90 ? 1 : 0;
1480 quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
1481 quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
1483 for(i = 0; i < 64; ++i) {
1484 int uvti, yti = (YQT[i]*quality+50)/100;
1485 YTable[stbiw__jpg_ZigZag[i]] = (
unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti);
1486 uvti = (UVQT[i]*quality+50)/100;
1487 UVTable[stbiw__jpg_ZigZag[i]] = (
unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti);
1490 for(row = 0, k = 0; row < 8; ++row) {
1491 for(col = 0; col < 8; ++col, ++k) {
1492 fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1493 fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1499 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 };
1500 static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
1501 const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(
unsigned char)(height>>8),STBIW_UCHAR(height),(
unsigned char)(width>>8),STBIW_UCHAR(width),
1502 3,1,(
unsigned char)(subsample?0x22:0x11),0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
1503 s->func(s->context, (
void*)head0,
sizeof(head0));
1504 s->func(s->context, (
void*)YTable,
sizeof(YTable));
1506 s->func(s->context, UVTable,
sizeof(UVTable));
1507 s->func(s->context, (
void*)head1,
sizeof(head1));
1508 s->func(s->context, (
void*)(std_dc_luminance_nrcodes+1),
sizeof(std_dc_luminance_nrcodes)-1);
1509 s->func(s->context, (
void*)std_dc_luminance_values,
sizeof(std_dc_luminance_values));
1510 stbiw__putc(s, 0x10);
1511 s->func(s->context, (
void*)(std_ac_luminance_nrcodes+1),
sizeof(std_ac_luminance_nrcodes)-1);
1512 s->func(s->context, (
void*)std_ac_luminance_values,
sizeof(std_ac_luminance_values));
1514 s->func(s->context, (
void*)(std_dc_chrominance_nrcodes+1),
sizeof(std_dc_chrominance_nrcodes)-1);
1515 s->func(s->context, (
void*)std_dc_chrominance_values,
sizeof(std_dc_chrominance_values));
1516 stbiw__putc(s, 0x11);
1517 s->func(s->context, (
void*)(std_ac_chrominance_nrcodes+1),
sizeof(std_ac_chrominance_nrcodes)-1);
1518 s->func(s->context, (
void*)std_ac_chrominance_values,
sizeof(std_ac_chrominance_values));
1519 s->func(s->context, (
void*)head2,
sizeof(head2));
1524 static const unsigned short fillBits[] = {0x7F, 7};
1525 int DCY=0, DCU=0, DCV=0;
1526 int bitBuf=0, bitCnt=0;
1528 int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
1529 const unsigned char *dataR = (
const unsigned char *)data;
1530 const unsigned char *dataG = dataR + ofsG;
1531 const unsigned char *dataB = dataR + ofsB;
1534 for(y = 0; y < height; y += 16) {
1535 for(x = 0; x < width; x += 16) {
1536 float Y[256], U[256], V[256];
1537 for(row = y, pos = 0; row < y+16; ++row) {
1539 int clamped_row = (row < height) ? row : height - 1;
1540 int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
1541 for(col = x; col < x+16; ++col, ++pos) {
1543 int p = base_p + ((col < width) ? col : (width-1))*comp;
1544 float r = dataR[p], g = dataG[p], b = dataB[p];
1545 Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
1546 U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
1547 V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
1550 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+0, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1551 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+8, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1552 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1553 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1557 float subU[64], subV[64];
1559 for(yy = 0, pos = 0; yy < 8; ++yy) {
1560 for(xx = 0; xx < 8; ++xx, ++pos) {
1562 subU[pos] = (U[j+0] + U[j+1] + U[j+16] + U[j+17]) * 0.25f;
1563 subV[pos] = (V[j+0] + V[j+1] + V[j+16] + V[j+17]) * 0.25f;
1566 DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
1567 DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
1572 for(y = 0; y < height; y += 8) {
1573 for(x = 0; x < width; x += 8) {
1574 float Y[64], U[64], V[64];
1575 for(row = y, pos = 0; row < y+8; ++row) {
1577 int clamped_row = (row < height) ? row : height - 1;
1578 int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
1579 for(col = x; col < x+8; ++col, ++pos) {
1581 int p = base_p + ((col < width) ? col : (width-1))*comp;
1582 float r = dataR[p], g = dataG[p], b = dataB[p];
1583 Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
1584 U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
1585 V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
1589 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1590 DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
1591 DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
1597 stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits);
1601 stbiw__putc(s, 0xFF);
1602 stbiw__putc(s, 0xD9);
1609 stbi__write_context s = { 0 };
1610 stbi__start_write_callbacks(&s, func, context);
1611 return stbi_write_jpg_core(&s, x, y, comp, (
void *) data, quality);
1615#ifndef STBI_WRITE_NO_STDIO
1618 stbi__write_context s = { 0 };
1619 if (stbi__start_write_file(&s,filename)) {
1620 int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
1621 stbi__end_write_file(&s);
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)
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
STBIWDEF int stbi_write_force_png_filter
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
STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)