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
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;
650 for (i = 0; i < 3; i++)
652 if (linear[i] < 0.0f) linear[i] = 0.0f;
655 rgbe[0] = (
unsigned char)(linear[0] * normalize);
656 rgbe[1] = (
unsigned char)(linear[1] * normalize);
657 rgbe[2] = (
unsigned char)(linear[2] * normalize);
658 rgbe[3] = (
unsigned char)(exponent + 128);
662static void stbiw__write_run_data(stbi__write_context *s,
int length,
unsigned char databyte)
664 unsigned char lengthbyte = STBIW_UCHAR(length+128);
665 STBIW_ASSERT(length+128 <= 255);
666 s->func(s->context, &lengthbyte, 1);
667 s->func(s->context, &databyte, 1);
670static void stbiw__write_dump_data(stbi__write_context *s,
int length,
unsigned char *data)
672 unsigned char lengthbyte = STBIW_UCHAR(length);
673 STBIW_ASSERT(length <= 128);
674 s->func(s->context, &lengthbyte, 1);
675 s->func(s->context, data, length);
678static void stbiw__write_hdr_scanline(stbi__write_context *s,
int width,
int ncomp,
unsigned char *scratch,
float *scanline)
680 unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
681 unsigned char rgbe[4];
685 scanlineheader[2] = (width&0xff00)>>8;
686 scanlineheader[3] = (width&0x00ff);
689 if (width < 8 || width >= 32768) {
690 for (
x=0;
x < width;
x++) {
693 case 3: linear[2] = scanline[
x*ncomp + 2];
694 linear[1] = scanline[
x*ncomp + 1];
695 linear[0] = scanline[
x*ncomp + 0];
698 linear[0] = linear[1] = linear[2] = scanline[
x*ncomp + 0];
701 stbiw__linear_to_rgbe(rgbe, linear);
702 s->func(s->context, rgbe, 4);
707 for (
x=0;
x < width;
x++) {
710 case 3: linear[2] = scanline[
x*ncomp + 2];
711 linear[1] = scanline[
x*ncomp + 1];
712 linear[0] = scanline[
x*ncomp + 0];
715 linear[0] = linear[1] = linear[2] = scanline[
x*ncomp + 0];
718 stbiw__linear_to_rgbe(rgbe, linear);
719 scratch[
x + width*0] = rgbe[0];
720 scratch[
x + width*1] = rgbe[1];
721 scratch[
x + width*2] = rgbe[2];
722 scratch[
x + width*3] = rgbe[3];
725 s->func(s->context, scanlineheader, 4);
728 for (c=0; c < 4; c++) {
729 unsigned char *comp = &scratch[width*c];
735 while (r+2 < width) {
736 if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
745 if (len > 128) len = 128;
746 stbiw__write_dump_data(s, len, &comp[
x]);
752 while (r < width && comp[r] == comp[
x])
757 if (len > 127) len = 127;
758 stbiw__write_run_data(s, len, comp[
x]);
767static int stbi_write_hdr_core(stbi__write_context *s,
int x,
int y,
int comp,
float *data)
769 if (
y <= 0 ||
x <= 0 || data == NULL)
773 unsigned char *scratch = (
unsigned char *) STBIW_MALLOC(
x*4);
776 char header[] =
"#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
777 s->func(s->context, header,
sizeof(header)-1);
779#ifdef __STDC_LIB_EXT1__
780 len = sprintf_s(buffer,
sizeof(buffer),
"EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n",
y,
x);
782 len = sprintf(buffer,
"EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n",
y,
x);
784 s->func(s->context, buffer, len);
787 stbiw__write_hdr_scanline(s,
x, comp, scratch, data + comp*
x*(stbi__flip_vertically_on_write ?
y-1-i : i));
795 stbi__write_context s = { 0 };
796 stbi__start_write_callbacks(&s, func, context);
797 return stbi_write_hdr_core(&s,
x,
y, comp, (
float *) data);
802 stbi__write_context s = { 0 };
803 if (stbi__start_write_file(&s,
filename)) {
804 int r = stbi_write_hdr_core(&s,
x,
y, comp, (
float *) data);
805 stbi__end_write_file(&s);
818#ifndef STBIW_ZLIB_COMPRESS
820#define stbiw__sbraw(a) ((int *) (void *) (a) - 2)
821#define stbiw__sbm(a) stbiw__sbraw(a)[0]
822#define stbiw__sbn(a) stbiw__sbraw(a)[1]
824#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
825#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
826#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
828#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
829#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
830#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
832static void *stbiw__sbgrowf(
void **arr,
int increment,
int itemsize)
834 int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
835 void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize +
sizeof(
int)*2) : 0, itemsize * m +
sizeof(
int)*2);
838 if (!*arr) ((
int *) p)[1] = 0;
839 *arr = (
void *) ((
int *) p + 2);
840 stbiw__sbm(*arr) = m;
845static unsigned char *stbiw__zlib_flushf(
unsigned char *data,
unsigned int *bitbuffer,
int *bitcount)
847 while (*bitcount >= 8) {
848 stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
855static int stbiw__zlib_bitrev(
int code,
int codebits)
859 res = (res << 1) | (code & 1);
865static unsigned int stbiw__zlib_countm(
unsigned char *a,
unsigned char *b,
int limit)
868 for (i=0; i < limit && i < 258; ++i)
869 if (a[i] != b[i])
break;
873static unsigned int stbiw__zhash(
unsigned char *data)
875 stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
885#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
886#define stbiw__zlib_add(code,codebits) \
887 (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
888#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
890#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8)
891#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9)
892#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7)
893#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8)
894#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))
895#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
897#define stbiw__ZHASH 16384
901STBIWDEF unsigned char * stbi_zlib_compress(
unsigned char *data,
int data_len,
int *out_len,
int quality)
903#ifdef STBIW_ZLIB_COMPRESS
905 return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality);
907 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 };
908 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 };
909 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 };
910 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 };
911 unsigned int bitbuf=0;
913 unsigned char *out = NULL;
914 unsigned char ***hash_table = (
unsigned char***) STBIW_MALLOC(stbiw__ZHASH *
sizeof(
unsigned char**));
915 if (hash_table == NULL)
917 if (quality < 5) quality = 5;
919 stbiw__sbpush(out, 0x78);
920 stbiw__sbpush(out, 0x5e);
921 stbiw__zlib_add(1,1);
922 stbiw__zlib_add(1,2);
924 for (i=0; i < stbiw__ZHASH; ++i)
925 hash_table[i] = NULL;
928 while (i < data_len-3) {
930 int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
931 unsigned char *bestloc = 0;
932 unsigned char **hlist = hash_table[h];
933 int n = stbiw__sbcount(hlist);
934 for (j=0; j < n; ++j) {
935 if (hlist[j]-data > i-32768) {
936 int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
937 if (d >= best) { best=d; bestloc=hlist[j]; }
941 if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
942 STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality,
sizeof(hash_table[h][0])*quality);
943 stbiw__sbn(hash_table[h]) = quality;
945 stbiw__sbpush(hash_table[h],data+i);
949 h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
950 hlist = hash_table[h];
951 n = stbiw__sbcount(hlist);
952 for (j=0; j < n; ++j) {
953 if (hlist[j]-data > i-32767) {
954 int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
964 int d = (
int) (data+i - bestloc);
965 STBIW_ASSERT(d <= 32767 && best <= 258);
966 for (j=0; best > lengthc[j+1]-1; ++j);
967 stbiw__zlib_huff(j+257);
968 if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
969 for (j=0; d > distc[j+1]-1; ++j);
970 stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
971 if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
974 stbiw__zlib_huffb(data[i]);
979 for (;i < data_len; ++i)
980 stbiw__zlib_huffb(data[i]);
981 stbiw__zlib_huff(256);
984 stbiw__zlib_add(0,1);
986 for (i=0; i < stbiw__ZHASH; ++i)
987 (
void) stbiw__sbfree(hash_table[i]);
988 STBIW_FREE(hash_table);
991 if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) {
993 for (j = 0; j < data_len;) {
994 int blocklen = data_len - j;
995 if (blocklen > 32767) blocklen = 32767;
996 stbiw__sbpush(out, data_len - j == blocklen);
997 stbiw__sbpush(out, STBIW_UCHAR(blocklen));
998 stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8));
999 stbiw__sbpush(out, STBIW_UCHAR(~blocklen));
1000 stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8));
1001 memcpy(out+stbiw__sbn(out), data+j, blocklen);
1002 stbiw__sbn(out) += blocklen;
1009 unsigned int s1=1, s2=0;
1010 int blocklen = (
int) (data_len % 5552);
1012 while (j < data_len) {
1013 for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; }
1014 s1 %= 65521; s2 %= 65521;
1018 stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
1019 stbiw__sbpush(out, STBIW_UCHAR(s2));
1020 stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
1021 stbiw__sbpush(out, STBIW_UCHAR(s1));
1023 *out_len = stbiw__sbn(out);
1025 STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
1026 return (
unsigned char *) stbiw__sbraw(out);
1030static unsigned int stbiw__crc32(
unsigned char *buffer,
int len)
1033 return STBIW_CRC32(buffer, len);
1035 static unsigned int crc_table[256] =
1037 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
1038 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
1039 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
1040 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
1041 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
1042 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
1043 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
1044 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
1045 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
1046 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
1047 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
1048 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
1049 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
1050 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
1051 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
1052 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
1053 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
1054 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
1055 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
1056 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
1057 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
1058 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
1059 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
1060 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
1061 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
1062 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
1063 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
1064 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
1065 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
1066 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
1067 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
1068 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
1071 unsigned int crc = ~0u;
1073 for (i=0; i < len; ++i)
1074 crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
1079#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)
1080#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
1081#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
1083static void stbiw__wpcrc(
unsigned char **data,
int len)
1085 unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
1086 stbiw__wp32(*data, crc);
1089static unsigned char stbiw__paeth(
int a,
int b,
int c)
1091 int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
1092 if (pa <= pb && pa <= pc)
return STBIW_UCHAR(a);
1093 if (pb <= pc)
return STBIW_UCHAR(b);
1094 return STBIW_UCHAR(c);
1098static 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)
1100 static int mapping[] = { 0,1,2,3,4 };
1101 static int firstmap[] = { 0,1,0,5,6 };
1102 int *mymap = (
y != 0) ? mapping : firstmap;
1104 int type = mymap[filter_type];
1105 unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-
y :
y);
1106 int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes;
1109 memcpy(line_buffer, z, width*n);
1114 for (i = 0; i < n; ++i) {
1116 case 1: line_buffer[i] = z[i];
break;
1117 case 2: line_buffer[i] = z[i] - z[i-signed_stride];
break;
1118 case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1);
break;
1119 case 4: line_buffer[i] = (
signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0));
break;
1120 case 5: line_buffer[i] = z[i];
break;
1121 case 6: line_buffer[i] = z[i];
break;
1125 case 1:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n];
break;
1126 case 2:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride];
break;
1127 case 3:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1);
break;
1128 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;
1129 case 5:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1);
break;
1130 case 6:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0);
break;
1134STBIWDEF unsigned char *stbi_write_png_to_mem(
const unsigned char *pixels,
int stride_bytes,
int x,
int y,
int n,
int *out_len)
1137 int ctype[5] = { -1, 0, 4, 2, 6 };
1138 unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
1139 unsigned char *out,*o, *filt, *zlib;
1140 signed char *line_buffer;
1143 if (stride_bytes == 0)
1144 stride_bytes =
x * n;
1146 if (force_filter >= 5) {
1150 filt = (
unsigned char *) STBIW_MALLOC((
x*n+1) *
y);
if (!filt)
return 0;
1151 line_buffer = (
signed char *) STBIW_MALLOC(
x * n);
if (!line_buffer) { STBIW_FREE(filt);
return 0; }
1152 for (j=0; j <
y; ++j) {
1154 if (force_filter > -1) {
1155 filter_type = force_filter;
1156 stbiw__encode_png_line((
unsigned char*)(pixels), stride_bytes,
x,
y, j, n, force_filter, line_buffer);
1158 int best_filter = 0, best_filter_val = 0x7fffffff, est, i;
1159 for (filter_type = 0; filter_type < 5; filter_type++) {
1160 stbiw__encode_png_line((
unsigned char*)(pixels), stride_bytes,
x,
y, j, n, filter_type, line_buffer);
1164 for (i = 0; i <
x*n; ++i) {
1165 est += abs((
signed char) line_buffer[i]);
1167 if (est < best_filter_val) {
1168 best_filter_val = est;
1169 best_filter = filter_type;
1172 if (filter_type != best_filter) {
1173 stbiw__encode_png_line((
unsigned char*)(pixels), stride_bytes,
x,
y, j, n, best_filter, line_buffer);
1174 filter_type = best_filter;
1178 filt[j*(
x*n+1)] = (
unsigned char) filter_type;
1179 STBIW_MEMMOVE(filt+j*(
x*n+1)+1, line_buffer,
x*n);
1181 STBIW_FREE(line_buffer);
1184 if (!zlib)
return 0;
1187 out = (
unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
1189 *out_len = 8 + 12+13 + 12+zlen + 12;
1192 STBIW_MEMMOVE(o,sig,8); o+= 8;
1194 stbiw__wptag(o,
"IHDR");
1198 *o++ = STBIW_UCHAR(ctype[n]);
1202 stbiw__wpcrc(&o,13);
1204 stbiw__wp32(o, zlen);
1205 stbiw__wptag(o,
"IDAT");
1206 STBIW_MEMMOVE(o, zlib, zlen);
1209 stbiw__wpcrc(&o, zlen);
1212 stbiw__wptag(o,
"IEND");
1215 STBIW_ASSERT(o == out + *out_len);
1220#ifndef STBI_WRITE_NO_STDIO
1225 unsigned char *png = stbi_write_png_to_mem((
const unsigned char *) data, stride_bytes,
x,
y, comp, &len);
1226 if (png == NULL)
return 0;
1229 if (!f) { STBIW_FREE(png);
return 0; }
1230 fwrite(png, 1, len, f);
1240 unsigned char *png = stbi_write_png_to_mem((
const unsigned char *) data, stride_bytes,
x,
y, comp, &len);
1241 if (png == NULL)
return 0;
1242 func(context, png, len);
1256static 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,
1257 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 };
1259static void stbiw__jpg_writeBits(stbi__write_context *s,
int *bitBufP,
int *bitCntP,
const unsigned short *bs) {
1260 int bitBuf = *bitBufP, bitCnt = *bitCntP;
1262 bitBuf |= bs[0] << (24 - bitCnt);
1263 while(bitCnt >= 8) {
1264 unsigned char c = (bitBuf >> 16) & 255;
1276static void stbiw__jpg_DCT(
float *d0p,
float *d1p,
float *d2p,
float *d3p,
float *d4p,
float *d5p,
float *d6p,
float *d7p) {
1277 float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p;
1278 float z1, z2, z3, z4, z5, z11, z13;
1280 float tmp0 = d0 + d7;
1281 float tmp7 = d0 - d7;
1282 float tmp1 = d1 + d6;
1283 float tmp6 = d1 - d6;
1284 float tmp2 = d2 + d5;
1285 float tmp5 = d2 - d5;
1286 float tmp3 = d3 + d4;
1287 float tmp4 = d3 - d4;
1290 float tmp10 = tmp0 + tmp3;
1291 float tmp13 = tmp0 - tmp3;
1292 float tmp11 = tmp1 + tmp2;
1293 float tmp12 = tmp1 - tmp2;
1298 z1 = (tmp12 + tmp13) * 0.707106781f;
1303 tmp10 = tmp4 + tmp5;
1304 tmp11 = tmp5 + tmp6;
1305 tmp12 = tmp6 + tmp7;
1308 z5 = (tmp10 - tmp12) * 0.382683433f;
1309 z2 = tmp10 * 0.541196100f + z5;
1310 z4 = tmp12 * 1.306562965f + z5;
1311 z3 = tmp11 * 0.707106781f;
1321 *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6;
1324static void stbiw__jpg_calcBits(
int val,
unsigned short bits[2]) {
1325 int tmp1 = val < 0 ? -val : val;
1326 val = val < 0 ? val-1 : val;
1331 bits[0] = val & ((1<<bits[1])-1);
1334static 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]) {
1335 const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
1336 const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
1337 int dataOff, i, j, n, diff, end0pos,
x,
y;
1341 for(dataOff=0, n=du_stride*8; dataOff<n; dataOff+=du_stride) {
1342 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]);
1345 for(dataOff=0; dataOff<8; ++dataOff) {
1346 stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+du_stride], &CDU[dataOff+du_stride*2], &CDU[dataOff+du_stride*3], &CDU[dataOff+du_stride*4],
1347 &CDU[dataOff+du_stride*5], &CDU[dataOff+du_stride*6], &CDU[dataOff+du_stride*7]);
1350 for(
y = 0, j=0;
y < 8; ++
y) {
1351 for(
x = 0;
x < 8; ++
x,++j) {
1354 v = CDU[i]*fdtbl[j];
1357 DU[stbiw__jpg_ZigZag[j]] = (
int)(v < 0 ? v - 0.5f : v + 0.5f);
1364 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]);
1366 unsigned short bits[2];
1367 stbiw__jpg_calcBits(diff, bits);
1368 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]);
1369 stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1373 for(; (end0pos>0)&&(DU[end0pos]==0); --end0pos) {
1377 stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1380 for(i = 1; i <= end0pos; ++i) {
1383 unsigned short bits[2];
1384 for (; DU[i]==0 && i<=end0pos; ++i) {
1386 nrzeroes = i-startpos;
1387 if ( nrzeroes >= 16 ) {
1388 int lng = nrzeroes>>4;
1390 for (nrmarker=1; nrmarker <= lng; ++nrmarker)
1391 stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes);
1394 stbiw__jpg_calcBits(DU[i], bits);
1395 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]);
1396 stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1399 stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1404static int stbi_write_jpg_core(stbi__write_context *s,
int width,
int height,
int comp,
const void* data,
int quality) {
1406 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};
1407 static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1408 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};
1409 static const unsigned char std_ac_luminance_values[] = {
1410 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
1411 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
1412 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
1413 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
1414 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
1415 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
1416 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1418 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};
1419 static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1420 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};
1421 static const unsigned char std_ac_chrominance_values[] = {
1422 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
1423 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
1424 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
1425 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
1426 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
1427 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
1428 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1431 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}};
1432 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}};
1433 static const unsigned short YAC_HT[256][2] = {
1434 {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},
1435 {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},
1436 {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},
1437 {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},
1438 {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},
1439 {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},
1440 {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},
1441 {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},
1442 {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},
1443 {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},
1444 {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},
1445 {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},
1446 {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},
1447 {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},
1448 {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},
1449 {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}
1451 static const unsigned short UVAC_HT[256][2] = {
1452 {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},
1453 {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},
1454 {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},
1455 {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},
1456 {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},
1457 {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},
1458 {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},
1459 {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},
1460 {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},
1461 {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},
1462 {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},
1463 {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},
1464 {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},
1465 {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},
1466 {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},
1467 {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}
1469 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,
1470 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};
1471 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,
1472 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};
1473 static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
1474 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f };
1476 int row, col, i, k, subsample;
1477 float fdtbl_Y[64], fdtbl_UV[64];
1478 unsigned char YTable[64], UVTable[64];
1480 if(!data || !width || !height || comp > 4 || comp < 1) {
1484 quality = quality ? quality : 90;
1485 subsample = quality <= 90 ? 1 : 0;
1486 quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
1487 quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
1489 for(i = 0; i < 64; ++i) {
1490 int uvti, yti = (YQT[i]*quality+50)/100;
1491 YTable[stbiw__jpg_ZigZag[i]] = (
unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti);
1492 uvti = (UVQT[i]*quality+50)/100;
1493 UVTable[stbiw__jpg_ZigZag[i]] = (
unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti);
1496 for(row = 0, k = 0; row < 8; ++row) {
1497 for(col = 0; col < 8; ++col, ++k) {
1498 fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1499 fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1505 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 };
1506 static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
1507 const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(
unsigned char)(height>>8),STBIW_UCHAR(height),(
unsigned char)(width>>8),STBIW_UCHAR(width),
1508 3,1,(
unsigned char)(subsample?0x22:0x11),0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
1509 s->func(s->context, (
void*)head0,
sizeof(head0));
1510 s->func(s->context, (
void*)YTable,
sizeof(YTable));
1512 s->func(s->context, UVTable,
sizeof(UVTable));
1513 s->func(s->context, (
void*)head1,
sizeof(head1));
1514 s->func(s->context, (
void*)(std_dc_luminance_nrcodes+1),
sizeof(std_dc_luminance_nrcodes)-1);
1515 s->func(s->context, (
void*)std_dc_luminance_values,
sizeof(std_dc_luminance_values));
1516 stbiw__putc(s, 0x10);
1517 s->func(s->context, (
void*)(std_ac_luminance_nrcodes+1),
sizeof(std_ac_luminance_nrcodes)-1);
1518 s->func(s->context, (
void*)std_ac_luminance_values,
sizeof(std_ac_luminance_values));
1520 s->func(s->context, (
void*)(std_dc_chrominance_nrcodes+1),
sizeof(std_dc_chrominance_nrcodes)-1);
1521 s->func(s->context, (
void*)std_dc_chrominance_values,
sizeof(std_dc_chrominance_values));
1522 stbiw__putc(s, 0x11);
1523 s->func(s->context, (
void*)(std_ac_chrominance_nrcodes+1),
sizeof(std_ac_chrominance_nrcodes)-1);
1524 s->func(s->context, (
void*)std_ac_chrominance_values,
sizeof(std_ac_chrominance_values));
1525 s->func(s->context, (
void*)head2,
sizeof(head2));
1530 static const unsigned short fillBits[] = {0x7F, 7};
1531 int DCY=0, DCU=0, DCV=0;
1532 int bitBuf=0, bitCnt=0;
1534 int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
1535 const unsigned char *dataR = (
const unsigned char *)data;
1536 const unsigned char *dataG = dataR + ofsG;
1537 const unsigned char *dataB = dataR + ofsB;
1540 for(
y = 0;
y < height;
y += 16) {
1541 for(
x = 0;
x < width;
x += 16) {
1542 float Y[256], U[256], V[256];
1543 for(row =
y, pos = 0; row <
y+16; ++row) {
1545 int clamped_row = (row < height) ? row : height - 1;
1546 int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
1547 for(col =
x; col <
x+16; ++col, ++pos) {
1549 int p = base_p + ((col < width) ? col : (width-1))*comp;
1550 float r = dataR[p], g = dataG[p], b = dataB[p];
1551 Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
1552 U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
1553 V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
1556 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+0, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1557 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+8, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1558 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1559 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1563 float subU[64], subV[64];
1565 for(yy = 0, pos = 0; yy < 8; ++yy) {
1566 for(xx = 0; xx < 8; ++xx, ++pos) {
1568 subU[pos] = (U[j+0] + U[j+1] + U[j+16] + U[j+17]) * 0.25f;
1569 subV[pos] = (V[j+0] + V[j+1] + V[j+16] + V[j+17]) * 0.25f;
1572 DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
1573 DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
1578 for(
y = 0;
y < height;
y += 8) {
1579 for(
x = 0;
x < width;
x += 8) {
1580 float Y[64], U[64], V[64];
1581 for(row =
y, pos = 0; row <
y+8; ++row) {
1583 int clamped_row = (row < height) ? row : height - 1;
1584 int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
1585 for(col =
x; col <
x+8; ++col, ++pos) {
1587 int p = base_p + ((col < width) ? col : (width-1))*comp;
1588 float r = dataR[p], g = dataG[p], b = dataB[p];
1589 Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
1590 U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
1591 V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
1595 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1596 DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
1597 DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
1603 stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits);
1607 stbiw__putc(s, 0xFF);
1608 stbiw__putc(s, 0xD9);
1615 stbi__write_context s = { 0 };
1616 stbi__start_write_callbacks(&s, func, context);
1617 return stbi_write_jpg_core(&s,
x,
y, comp, (
void *) data, quality);
1621#ifndef STBI_WRITE_NO_STDIO
1624 stbi__write_context s = { 0 };
1625 if (stbi__start_write_file(&s,
filename)) {
1626 int r = stbi_write_jpg_core(&s,
x,
y, comp, data, quality);
1627 stbi__end_write_file(&s);
typedef int(ZCALLBACK *close_file_func) OF((voidpf opaque
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)