155#ifndef INCLUDE_STB_IMAGE_WRITE_H
156#define INCLUDE_STB_IMAGE_WRITE_H
162#ifdef STB_IMAGE_WRITE_STATIC
163#define STBIWDEF static
166#define STBIWDEF extern "C"
168#define STBIWDEF extern
173#ifndef STB_IMAGE_WRITE_STATIC
174extern int stbi_write_tga_with_rle;
175extern int stbi_write_png_compression_level;
176extern int stbi_write_force_png_filter;
179#ifndef STBI_WRITE_NO_STDIO
180STBIWDEF
int stbi_write_png(
char const *filename,
int w,
int h,
int comp,
const void *data,
int stride_in_bytes);
181STBIWDEF
int stbi_write_bmp(
char const *filename,
int w,
int h,
int comp,
const void *data);
182STBIWDEF
int stbi_write_tga(
char const *filename,
int w,
int h,
int comp,
const void *data);
183STBIWDEF
int stbi_write_hdr(
char const *filename,
int w,
int h,
int comp,
const float *data);
184STBIWDEF
int stbi_write_jpg(
char const *filename,
int x,
int y,
int comp,
const void *data,
int quality);
186#ifdef STBI_WINDOWS_UTF8
187STBIWDEF
int stbiw_convert_wchar_to_utf8(
char *buffer,
size_t bufferlen,
const wchar_t* input);
191typedef void stbi_write_func(
void *context,
void *data,
int size);
193STBIWDEF
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);
194STBIWDEF
int stbi_write_bmp_to_func(stbi_write_func *func,
void *context,
int w,
int h,
int comp,
const void *data);
195STBIWDEF
int stbi_write_tga_to_func(stbi_write_func *func,
void *context,
int w,
int h,
int comp,
const void *data);
196STBIWDEF
int stbi_write_hdr_to_func(stbi_write_func *func,
void *context,
int w,
int h,
int comp,
const float *data);
197STBIWDEF
int stbi_write_jpg_to_func(stbi_write_func *func,
void *context,
int x,
int y,
int comp,
const void *data,
int quality);
199STBIWDEF
void stbi_flip_vertically_on_write(
int flip_boolean);
203#ifdef STB_IMAGE_WRITE_IMPLEMENTATION
206 #ifndef _CRT_SECURE_NO_WARNINGS
207 #define _CRT_SECURE_NO_WARNINGS
209 #ifndef _CRT_NONSTDC_NO_DEPRECATE
210 #define _CRT_NONSTDC_NO_DEPRECATE
214#ifndef STBI_WRITE_NO_STDIO
223#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED))
225#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED)
228#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)."
232#define STBIW_MALLOC(sz) malloc(sz)
233#define STBIW_REALLOC(p,newsz) realloc(p,newsz)
234#define STBIW_FREE(p) free(p)
237#ifndef STBIW_REALLOC_SIZED
238#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz)
243#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
249#define STBIW_ASSERT(x) assert(x)
252#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
254#ifdef STB_IMAGE_WRITE_STATIC
255static int stbi__flip_vertically_on_write=0;
256static int stbi_write_png_compression_level = 8;
257static int stbi_write_tga_with_rle = 1;
258static int stbi_write_force_png_filter = -1;
260int stbi_write_png_compression_level = 8;
261int stbi__flip_vertically_on_write=0;
262int stbi_write_tga_with_rle = 1;
263int stbi_write_force_png_filter = -1;
266STBIWDEF
void stbi_flip_vertically_on_write(
int flag)
268 stbi__flip_vertically_on_write = flag;
273 stbi_write_func *func;
275} stbi__write_context;
278static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c,
void *context)
281 s->context = context;
284#ifndef STBI_WRITE_NO_STDIO
286static void stbi__stdio_write(
void *context,
void *data,
int size)
288 fwrite(data,1,size,(FILE*) context);
291#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
293#define STBIW_EXTERN extern "C"
295#define STBIW_EXTERN extern
297STBIW_EXTERN __declspec(dllimport)
int __stdcall MultiByteToWideChar(
unsigned int cp,
unsigned long flags,
const char *str,
int cbmb,
wchar_t *widestr,
int cchwide);
298STBIW_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);
300STBIWDEF
int stbiw_convert_wchar_to_utf8(
char *buffer,
size_t bufferlen,
const wchar_t* input)
302 return WideCharToMultiByte(65001 , 0, input, -1, buffer, (
int) bufferlen, NULL, NULL);
306static FILE *stbiw__fopen(
char const *filename,
char const *mode)
309#if defined(_MSC_VER) && defined(STBI_WINDOWS_UTF8)
311 wchar_t wFilename[1024];
312 if (0 == MultiByteToWideChar(65001 , 0, filename, -1, wFilename,
sizeof(wFilename)))
315 if (0 == MultiByteToWideChar(65001 , 0, mode, -1, wMode,
sizeof(wMode)))
319 if (0 != _wfopen_s(&f, wFilename, wMode))
322 f = _wfopen(wFilename, wMode);
325#elif defined(_MSC_VER) && _MSC_VER >= 1400
326 if (0 != fopen_s(&f, filename, mode))
329 f = fopen(filename, mode);
334static int stbi__start_write_file(stbi__write_context *s,
const char *filename)
336 FILE *f = stbiw__fopen(filename,
"wb");
337 stbi__start_write_callbacks(s, stbi__stdio_write, (
void *) f);
341static void stbi__end_write_file(stbi__write_context *s)
343 fclose((FILE *)s->context);
348typedef unsigned int stbiw_uint32;
349typedef int stb_image_write_test[
sizeof(stbiw_uint32)==4 ? 1 : -1];
351static void stbiw__writefv(stbi__write_context *s,
const char *fmt, va_list v)
356 case '1': {
unsigned char x = STBIW_UCHAR(va_arg(v,
int));
357 s->func(s->context,&x,1);
359 case '2': {
int x = va_arg(v,
int);
361 b[0] = STBIW_UCHAR(x);
362 b[1] = STBIW_UCHAR(x>>8);
363 s->func(s->context,b,2);
365 case '4': { stbiw_uint32 x = va_arg(v,
int);
368 b[1]=STBIW_UCHAR(x>>8);
369 b[2]=STBIW_UCHAR(x>>16);
370 b[3]=STBIW_UCHAR(x>>24);
371 s->func(s->context,b,4);
380static void stbiw__writef(stbi__write_context *s,
const char *fmt, ...)
384 stbiw__writefv(s, fmt, v);
388static void stbiw__putc(stbi__write_context *s,
unsigned char c)
390 s->func(s->context, &c, 1);
393static void stbiw__write3(stbi__write_context *s,
unsigned char a,
unsigned char b,
unsigned char c)
395 unsigned char arr[3];
396 arr[0] = a; arr[1] = b; arr[2] = c;
397 s->func(s->context, arr, 3);
400static void stbiw__write_pixel(stbi__write_context *s,
int rgb_dir,
int comp,
int write_alpha,
int expand_mono,
unsigned char *d)
402 unsigned char bg[3] = { 255, 0, 255}, px[3];
406 s->func(s->context, &d[comp - 1], 1);
412 stbiw__write3(s, d[0], d[0], d[0]);
414 s->func(s->context, d, 1);
419 for (k = 0; k < 3; ++k)
420 px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
421 stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]);
426 stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
430 s->func(s->context, &d[comp - 1], 1);
433static 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)
435 stbiw_uint32 zero = 0;
441 if (stbi__flip_vertically_on_write)
450 for (; j != j_end; j += vdir) {
451 for (i=0; i < x; ++i) {
452 unsigned char *d = (
unsigned char *) data + (j*x+i)*comp;
453 stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
455 s->func(s->context, &zero, scanline_pad);
459static 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, ...)
461 if (y < 0 || x < 0) {
466 stbiw__writefv(s, fmt, v);
468 stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono);
473static int stbi_write_bmp_core(stbi__write_context *s,
int x,
int y,
int comp,
const void *data)
475 int pad = (-x*3) & 3;
476 return stbiw__outfile(s,-1,-1,x,y,comp,1,(
void *) data,0,pad,
477 "11 4 22 4" "4 44 22 444444",
478 'B',
'M', 14+40+(x*3+pad)*y, 0,0, 14+40,
479 40, x,y, 1,24, 0,0,0,0,0,0);
482STBIWDEF
int stbi_write_bmp_to_func(stbi_write_func *func,
void *context,
int x,
int y,
int comp,
const void *data)
484 stbi__write_context s;
485 stbi__start_write_callbacks(&s, func, context);
486 return stbi_write_bmp_core(&s, x, y, comp, data);
489#ifndef STBI_WRITE_NO_STDIO
490STBIWDEF
int stbi_write_bmp(
char const *filename,
int x,
int y,
int comp,
const void *data)
492 stbi__write_context s;
493 if (stbi__start_write_file(&s,filename)) {
494 int r = stbi_write_bmp_core(&s, x, y, comp, data);
495 stbi__end_write_file(&s);
502static int stbi_write_tga_core(stbi__write_context *s,
int x,
int y,
int comp,
void *data)
504 int has_alpha = (comp == 2 || comp == 4);
505 int colorbytes = has_alpha ? comp-1 : comp;
506 int format = colorbytes < 2 ? 3 : 2;
511 if (!stbi_write_tga_with_rle) {
512 return stbiw__outfile(s, -1, -1, x, y, comp, 0, (
void *) data, has_alpha, 0,
513 "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
518 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);
520 if (stbi__flip_vertically_on_write) {
529 for (; j != jend; j += jdir) {
530 unsigned char *row = (
unsigned char *) data + j * x * comp;
533 for (i = 0; i < x; i += len) {
534 unsigned char *begin = row + i * comp;
540 diff = memcmp(begin, row + (i + 1) * comp, comp);
542 const unsigned char *prev = begin;
543 for (k = i + 2; k < x && len < 128; ++k) {
544 if (memcmp(prev, row + k * comp, comp)) {
553 for (k = i + 2; k < x && len < 128; ++k) {
554 if (!memcmp(begin, row + k * comp, comp)) {
564 unsigned char header = STBIW_UCHAR(len - 1);
565 s->func(s->context, &header, 1);
566 for (k = 0; k < len; ++k) {
567 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
570 unsigned char header = STBIW_UCHAR(len - 129);
571 s->func(s->context, &header, 1);
572 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
580STBIWDEF
int stbi_write_tga_to_func(stbi_write_func *func,
void *context,
int x,
int y,
int comp,
const void *data)
582 stbi__write_context s;
583 stbi__start_write_callbacks(&s, func, context);
584 return stbi_write_tga_core(&s, x, y, comp, (
void *) data);
587#ifndef STBI_WRITE_NO_STDIO
588STBIWDEF
int stbi_write_tga(
char const *filename,
int x,
int y,
int comp,
const void *data)
590 stbi__write_context s;
591 if (stbi__start_write_file(&s,filename)) {
592 int r = stbi_write_tga_core(&s, x, y, comp, (
void *) data);
593 stbi__end_write_file(&s);
604#define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
606static void stbiw__linear_to_rgbe(
unsigned char *rgbe,
float *linear)
609 float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
611 if (maxcomp < 1e-32f) {
612 rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
614 float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
616 rgbe[0] = (
unsigned char)(linear[0] * normalize);
617 rgbe[1] = (
unsigned char)(linear[1] * normalize);
618 rgbe[2] = (
unsigned char)(linear[2] * normalize);
619 rgbe[3] = (
unsigned char)(exponent + 128);
623static void stbiw__write_run_data(stbi__write_context *s,
int length,
unsigned char databyte)
625 unsigned char lengthbyte = STBIW_UCHAR(length+128);
626 STBIW_ASSERT(length+128 <= 255);
627 s->func(s->context, &lengthbyte, 1);
628 s->func(s->context, &databyte, 1);
631static void stbiw__write_dump_data(stbi__write_context *s,
int length,
unsigned char *data)
633 unsigned char lengthbyte = STBIW_UCHAR(length);
634 STBIW_ASSERT(length <= 128);
635 s->func(s->context, &lengthbyte, 1);
636 s->func(s->context, data, length);
639static void stbiw__write_hdr_scanline(stbi__write_context *s,
int width,
int ncomp,
unsigned char *scratch,
float *scanline)
641 unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
642 unsigned char rgbe[4];
646 scanlineheader[2] = (width&0xff00)>>8;
647 scanlineheader[3] = (width&0x00ff);
650 if (width < 8 || width >= 32768) {
651 for (x=0; x < width; x++) {
654 case 3: linear[2] = scanline[x*ncomp + 2];
655 linear[1] = scanline[x*ncomp + 1];
656 linear[0] = scanline[x*ncomp + 0];
659 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
662 stbiw__linear_to_rgbe(rgbe, linear);
663 s->func(s->context, rgbe, 4);
668 for (x=0; x < width; x++) {
671 case 3: linear[2] = scanline[x*ncomp + 2];
672 linear[1] = scanline[x*ncomp + 1];
673 linear[0] = scanline[x*ncomp + 0];
676 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
679 stbiw__linear_to_rgbe(rgbe, linear);
680 scratch[x + width*0] = rgbe[0];
681 scratch[x + width*1] = rgbe[1];
682 scratch[x + width*2] = rgbe[2];
683 scratch[x + width*3] = rgbe[3];
686 s->func(s->context, scanlineheader, 4);
689 for (c=0; c < 4; c++) {
690 unsigned char *comp = &scratch[width*c];
696 while (r+2 < width) {
697 if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
706 if (len > 128) len = 128;
707 stbiw__write_dump_data(s, len, &comp[x]);
713 while (r < width && comp[r] == comp[x])
718 if (len > 127) len = 127;
719 stbiw__write_run_data(s, len, comp[x]);
728static int stbi_write_hdr_core(stbi__write_context *s,
int x,
int y,
int comp,
float *data)
730 if (y <= 0 || x <= 0 || data == NULL)
734 unsigned char *scratch = (
unsigned char *) STBIW_MALLOC(x*4);
737 char header[] =
"#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
738 s->func(s->context, header,
sizeof(header)-1);
740#ifdef __STDC_WANT_SECURE_LIB__
741 len = sprintf_s(buffer,
sizeof(buffer),
"EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
743 len = sprintf(buffer,
"EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
745 s->func(s->context, buffer, len);
748 stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i));
754STBIWDEF
int stbi_write_hdr_to_func(stbi_write_func *func,
void *context,
int x,
int y,
int comp,
const float *data)
756 stbi__write_context s;
757 stbi__start_write_callbacks(&s, func, context);
758 return stbi_write_hdr_core(&s, x, y, comp, (
float *) data);
761#ifndef STBI_WRITE_NO_STDIO
762STBIWDEF
int stbi_write_hdr(
char const *filename,
int x,
int y,
int comp,
const float *data)
764 stbi__write_context s;
765 if (stbi__start_write_file(&s,filename)) {
766 int r = stbi_write_hdr_core(&s, x, y, comp, (
float *) data);
767 stbi__end_write_file(&s);
780#ifndef STBIW_ZLIB_COMPRESS
782#define stbiw__sbraw(a) ((int *) (a) - 2)
783#define stbiw__sbm(a) stbiw__sbraw(a)[0]
784#define stbiw__sbn(a) stbiw__sbraw(a)[1]
786#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
787#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
788#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
790#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
791#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
792#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
794static void *stbiw__sbgrowf(
void **arr,
int increment,
int itemsize)
796 int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
797 void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2);
800 if (!*arr) ((
int *) p)[1] = 0;
801 *arr = (
void *) ((
int *) p + 2);
802 stbiw__sbm(*arr) = m;
807static unsigned char *stbiw__zlib_flushf(
unsigned char *data,
unsigned int *bitbuffer,
int *bitcount)
809 while (*bitcount >= 8) {
810 stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
817static int stbiw__zlib_bitrev(
int code,
int codebits)
821 res = (res << 1) | (code & 1);
827static unsigned int stbiw__zlib_countm(
unsigned char *a,
unsigned char *b,
int limit)
830 for (i=0; i < limit && i < 258; ++i)
831 if (a[i] != b[i])
break;
835static unsigned int stbiw__zhash(
unsigned char *data)
837 stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
847#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
848#define stbiw__zlib_add(code,codebits) \
849 (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
850#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
852#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8)
853#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9)
854#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7)
855#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8)
856#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))
857#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
859#define stbiw__ZHASH 16384
863STBIWDEF
unsigned char * stbi_zlib_compress(
unsigned char *data,
int data_len,
int *out_len,
int quality)
865#ifdef STBIW_ZLIB_COMPRESS
867 return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality);
869 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 };
870 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 };
871 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 };
872 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 };
873 unsigned int bitbuf=0;
875 unsigned char *out = NULL;
876 unsigned char ***hash_table = (
unsigned char***) STBIW_MALLOC(stbiw__ZHASH *
sizeof(
char**));
877 if (hash_table == NULL)
879 if (quality < 5) quality = 5;
881 stbiw__sbpush(out, 0x78);
882 stbiw__sbpush(out, 0x5e);
883 stbiw__zlib_add(1,1);
884 stbiw__zlib_add(1,2);
886 for (i=0; i < stbiw__ZHASH; ++i)
887 hash_table[i] = NULL;
890 while (i < data_len-3) {
892 int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
893 unsigned char *bestloc = 0;
894 unsigned char **hlist = hash_table[h];
895 int n = stbiw__sbcount(hlist);
896 for (j=0; j < n; ++j) {
897 if (hlist[j]-data > i-32768) {
898 int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
899 if (d >= best) { best=d; bestloc=hlist[j]; }
903 if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
904 STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality,
sizeof(hash_table[h][0])*quality);
905 stbiw__sbn(hash_table[h]) = quality;
907 stbiw__sbpush(hash_table[h],data+i);
911 h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
912 hlist = hash_table[h];
913 n = stbiw__sbcount(hlist);
914 for (j=0; j < n; ++j) {
915 if (hlist[j]-data > i-32767) {
916 int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
926 int d = (int) (data+i - bestloc);
927 STBIW_ASSERT(d <= 32767 && best <= 258);
928 for (j=0; best > lengthc[j+1]-1; ++j);
929 stbiw__zlib_huff(j+257);
930 if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
931 for (j=0; d > distc[j+1]-1; ++j);
932 stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
933 if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
936 stbiw__zlib_huffb(data[i]);
941 for (;i < data_len; ++i)
942 stbiw__zlib_huffb(data[i]);
943 stbiw__zlib_huff(256);
946 stbiw__zlib_add(0,1);
948 for (i=0; i < stbiw__ZHASH; ++i)
949 (
void) stbiw__sbfree(hash_table[i]);
950 STBIW_FREE(hash_table);
954 unsigned int s1=1, s2=0;
955 int blocklen = (int) (data_len % 5552);
957 while (j < data_len) {
958 for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; }
959 s1 %= 65521; s2 %= 65521;
963 stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
964 stbiw__sbpush(out, STBIW_UCHAR(s2));
965 stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
966 stbiw__sbpush(out, STBIW_UCHAR(s1));
968 *out_len = stbiw__sbn(out);
970 STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
971 return (
unsigned char *) stbiw__sbraw(out);
975static unsigned int stbiw__crc32(
unsigned char *buffer,
int len)
978 return STBIW_CRC32(buffer, len);
980 static unsigned int crc_table[256] =
982 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
983 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
984 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
985 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
986 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
987 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
988 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
989 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
990 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
991 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
992 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
993 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
994 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
995 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
996 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
997 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
998 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
999 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
1000 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
1001 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
1002 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
1003 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
1004 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
1005 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
1006 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
1007 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
1008 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
1009 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
1010 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
1011 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
1012 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
1013 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
1016 unsigned int crc = ~0u;
1018 for (i=0; i < len; ++i)
1019 crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
1024#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)
1025#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
1026#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
1028static void stbiw__wpcrc(
unsigned char **data,
int len)
1030 unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
1031 stbiw__wp32(*data, crc);
1034static unsigned char stbiw__paeth(
int a,
int b,
int c)
1036 int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
1037 if (pa <= pb && pa <= pc)
return STBIW_UCHAR(a);
1038 if (pb <= pc)
return STBIW_UCHAR(b);
1039 return STBIW_UCHAR(c);
1043static 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)
1045 static int mapping[] = { 0,1,2,3,4 };
1046 static int firstmap[] = { 0,1,0,5,6 };
1047 int *mymap = (y != 0) ? mapping : firstmap;
1049 int type = mymap[filter_type];
1050 unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y);
1051 int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes;
1054 memcpy(line_buffer, z, width*n);
1059 for (i = 0; i < n; ++i) {
1061 case 1: line_buffer[i] = z[i];
break;
1062 case 2: line_buffer[i] = z[i] - z[i-signed_stride];
break;
1063 case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1);
break;
1064 case 4: line_buffer[i] = (
signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0));
break;
1065 case 5: line_buffer[i] = z[i];
break;
1066 case 6: line_buffer[i] = z[i];
break;
1070 case 1:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n];
break;
1071 case 2:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride];
break;
1072 case 3:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1);
break;
1073 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;
1074 case 5:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1);
break;
1075 case 6:
for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0);
break;
1079STBIWDEF
unsigned char *stbi_write_png_to_mem(
const unsigned char *pixels,
int stride_bytes,
int x,
int y,
int n,
int *out_len)
1081 int force_filter = stbi_write_force_png_filter;
1082 int ctype[5] = { -1, 0, 4, 2, 6 };
1083 unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
1084 unsigned char *out,*o, *filt, *zlib;
1085 signed char *line_buffer;
1088 if (stride_bytes == 0)
1089 stride_bytes = x * n;
1091 if (force_filter >= 5) {
1095 filt = (
unsigned char *) STBIW_MALLOC((x*n+1) * y);
if (!filt)
return 0;
1096 line_buffer = (
signed char *) STBIW_MALLOC(x * n);
if (!line_buffer) { STBIW_FREE(filt);
return 0; }
1097 for (j=0; j < y; ++j) {
1099 if (force_filter > -1) {
1100 filter_type = force_filter;
1101 stbiw__encode_png_line((
unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer);
1103 int best_filter = 0, best_filter_val = 0x7fffffff, est, i;
1104 for (filter_type = 0; filter_type < 5; filter_type++) {
1105 stbiw__encode_png_line((
unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer);
1109 for (i = 0; i < x*n; ++i) {
1110 est += abs((
signed char) line_buffer[i]);
1112 if (est < best_filter_val) {
1113 best_filter_val = est;
1114 best_filter = filter_type;
1117 if (filter_type != best_filter) {
1118 stbiw__encode_png_line((
unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer);
1119 filter_type = best_filter;
1123 filt[j*(x*n+1)] = (
unsigned char) filter_type;
1124 STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
1126 STBIW_FREE(line_buffer);
1127 zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_compression_level);
1129 if (!zlib)
return 0;
1132 out = (
unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
1134 *out_len = 8 + 12+13 + 12+zlen + 12;
1137 STBIW_MEMMOVE(o,sig,8); o+= 8;
1139 stbiw__wptag(o,
"IHDR");
1143 *o++ = STBIW_UCHAR(ctype[n]);
1147 stbiw__wpcrc(&o,13);
1149 stbiw__wp32(o, zlen);
1150 stbiw__wptag(o,
"IDAT");
1151 STBIW_MEMMOVE(o, zlib, zlen);
1154 stbiw__wpcrc(&o, zlen);
1157 stbiw__wptag(o,
"IEND");
1160 STBIW_ASSERT(o == out + *out_len);
1165#ifndef STBI_WRITE_NO_STDIO
1166STBIWDEF
int stbi_write_png(
char const *filename,
int x,
int y,
int comp,
const void *data,
int stride_bytes)
1170 unsigned char *png = stbi_write_png_to_mem((
const unsigned char *) data, stride_bytes, x, y, comp, &len);
1171 if (png == NULL)
return 0;
1173 f = stbiw__fopen(filename,
"wb");
1174 if (!f) { STBIW_FREE(png);
return 0; }
1175 fwrite(png, 1, len, f);
1182STBIWDEF
int stbi_write_png_to_func(stbi_write_func *func,
void *context,
int x,
int y,
int comp,
const void *data,
int stride_bytes)
1185 unsigned char *png = stbi_write_png_to_mem((
const unsigned char *) data, stride_bytes, x, y, comp, &len);
1186 if (png == NULL)
return 0;
1187 func(context, png, len);
1201static 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,
1202 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 };
1204static void stbiw__jpg_writeBits(stbi__write_context *s,
int *bitBufP,
int *bitCntP,
const unsigned short *bs) {
1205 int bitBuf = *bitBufP, bitCnt = *bitCntP;
1207 bitBuf |= bs[0] << (24 - bitCnt);
1208 while(bitCnt >= 8) {
1209 unsigned char c = (bitBuf >> 16) & 255;
1221static void stbiw__jpg_DCT(
float *d0p,
float *d1p,
float *d2p,
float *d3p,
float *d4p,
float *d5p,
float *d6p,
float *d7p) {
1222 float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p;
1223 float z1, z2, z3, z4, z5, z11, z13;
1225 float tmp0 = d0 + d7;
1226 float tmp7 = d0 - d7;
1227 float tmp1 = d1 + d6;
1228 float tmp6 = d1 - d6;
1229 float tmp2 = d2 + d5;
1230 float tmp5 = d2 - d5;
1231 float tmp3 = d3 + d4;
1232 float tmp4 = d3 - d4;
1235 float tmp10 = tmp0 + tmp3;
1236 float tmp13 = tmp0 - tmp3;
1237 float tmp11 = tmp1 + tmp2;
1238 float tmp12 = tmp1 - tmp2;
1243 z1 = (tmp12 + tmp13) * 0.707106781f;
1248 tmp10 = tmp4 + tmp5;
1249 tmp11 = tmp5 + tmp6;
1250 tmp12 = tmp6 + tmp7;
1253 z5 = (tmp10 - tmp12) * 0.382683433f;
1254 z2 = tmp10 * 0.541196100f + z5;
1255 z4 = tmp12 * 1.306562965f + z5;
1256 z3 = tmp11 * 0.707106781f;
1266 *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6;
1269static void stbiw__jpg_calcBits(
int val,
unsigned short bits[2]) {
1270 int tmp1 = val < 0 ? -val : val;
1271 val = val < 0 ? val-1 : val;
1276 bits[0] = val & ((1<<bits[1])-1);
1279static int stbiw__jpg_processDU(stbi__write_context *s,
int *bitBuf,
int *bitCnt,
float *CDU,
float *fdtbl,
int DC,
const unsigned short HTDC[256][2],
const unsigned short HTAC[256][2]) {
1280 const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
1281 const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
1282 int dataOff, i, diff, end0pos;
1286 for(dataOff=0; dataOff<64; dataOff+=8) {
1287 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]);
1290 for(dataOff=0; dataOff<8; ++dataOff) {
1291 stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+8], &CDU[dataOff+16], &CDU[dataOff+24], &CDU[dataOff+32], &CDU[dataOff+40], &CDU[dataOff+48], &CDU[dataOff+56]);
1294 for(i=0; i<64; ++i) {
1295 float v = CDU[i]*fdtbl[i];
1298 DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
1304 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]);
1306 unsigned short bits[2];
1307 stbiw__jpg_calcBits(diff, bits);
1308 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]);
1309 stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1313 for(; (end0pos>0)&&(DU[end0pos]==0); --end0pos) {
1317 stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1320 for(i = 1; i <= end0pos; ++i) {
1323 unsigned short bits[2];
1324 for (; DU[i]==0 && i<=end0pos; ++i) {
1326 nrzeroes = i-startpos;
1327 if ( nrzeroes >= 16 ) {
1328 int lng = nrzeroes>>4;
1330 for (nrmarker=1; nrmarker <= lng; ++nrmarker)
1331 stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes);
1334 stbiw__jpg_calcBits(DU[i], bits);
1335 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]);
1336 stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1339 stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1344static int stbi_write_jpg_core(stbi__write_context *s,
int width,
int height,
int comp,
const void* data,
int quality) {
1346 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};
1347 static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1348 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};
1349 static const unsigned char std_ac_luminance_values[] = {
1350 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
1351 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
1352 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
1353 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
1354 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
1355 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
1356 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1358 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};
1359 static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1360 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};
1361 static const unsigned char std_ac_chrominance_values[] = {
1362 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
1363 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
1364 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
1365 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
1366 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
1367 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
1368 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1371 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}};
1372 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}};
1373 static const unsigned short YAC_HT[256][2] = {
1374 {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},
1375 {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},
1376 {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},
1377 {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},
1378 {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},
1379 {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},
1380 {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},
1381 {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},
1382 {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},
1383 {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},
1384 {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},
1385 {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},
1386 {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},
1387 {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},
1388 {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},
1389 {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}
1391 static const unsigned short UVAC_HT[256][2] = {
1392 {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},
1393 {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},
1394 {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},
1395 {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},
1396 {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},
1397 {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},
1398 {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},
1399 {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},
1400 {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},
1401 {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},
1402 {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},
1403 {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},
1404 {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},
1405 {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},
1406 {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},
1407 {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}
1409 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,
1410 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};
1411 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,
1412 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};
1413 static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
1414 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f };
1417 float fdtbl_Y[64], fdtbl_UV[64];
1418 unsigned char YTable[64], UVTable[64];
1420 if(!data || !width || !height || comp > 4 || comp < 1) {
1424 quality = quality ? quality : 90;
1425 quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
1426 quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
1428 for(i = 0; i < 64; ++i) {
1429 int uvti, yti = (YQT[i]*quality+50)/100;
1430 YTable[stbiw__jpg_ZigZag[i]] = (
unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti);
1431 uvti = (UVQT[i]*quality+50)/100;
1432 UVTable[stbiw__jpg_ZigZag[i]] = (
unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti);
1435 for(row = 0, k = 0; row < 8; ++row) {
1436 for(col = 0; col < 8; ++col, ++k) {
1437 fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1438 fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1444 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 };
1445 static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
1446 const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(
unsigned char)(height>>8),STBIW_UCHAR(height),(
unsigned char)(width>>8),STBIW_UCHAR(width),
1447 3,1,0x11,0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
1448 s->func(s->context, (
void*)head0,
sizeof(head0));
1449 s->func(s->context, (
void*)YTable,
sizeof(YTable));
1451 s->func(s->context, UVTable,
sizeof(UVTable));
1452 s->func(s->context, (
void*)head1,
sizeof(head1));
1453 s->func(s->context, (
void*)(std_dc_luminance_nrcodes+1),
sizeof(std_dc_luminance_nrcodes)-1);
1454 s->func(s->context, (
void*)std_dc_luminance_values,
sizeof(std_dc_luminance_values));
1455 stbiw__putc(s, 0x10);
1456 s->func(s->context, (
void*)(std_ac_luminance_nrcodes+1),
sizeof(std_ac_luminance_nrcodes)-1);
1457 s->func(s->context, (
void*)std_ac_luminance_values,
sizeof(std_ac_luminance_values));
1459 s->func(s->context, (
void*)(std_dc_chrominance_nrcodes+1),
sizeof(std_dc_chrominance_nrcodes)-1);
1460 s->func(s->context, (
void*)std_dc_chrominance_values,
sizeof(std_dc_chrominance_values));
1461 stbiw__putc(s, 0x11);
1462 s->func(s->context, (
void*)(std_ac_chrominance_nrcodes+1),
sizeof(std_ac_chrominance_nrcodes)-1);
1463 s->func(s->context, (
void*)std_ac_chrominance_values,
sizeof(std_ac_chrominance_values));
1464 s->func(s->context, (
void*)head2,
sizeof(head2));
1469 static const unsigned short fillBits[] = {0x7F, 7};
1470 const unsigned char *imageData = (
const unsigned char *)data;
1471 int DCY=0, DCU=0, DCV=0;
1472 int bitBuf=0, bitCnt=0;
1474 int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
1476 for(y = 0; y < height; y += 8) {
1477 for(x = 0; x < width; x += 8) {
1478 float YDU[64], UDU[64], VDU[64];
1479 for(row = y, pos = 0; row < y+8; ++row) {
1481 int clamped_row = (row < height) ? row : height - 1;
1482 int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
1483 for(col = x; col < x+8; ++col, ++pos) {
1486 int p = base_p + ((col < width) ? col : (width-1))*comp;
1489 g = imageData[p+ofsG];
1490 b = imageData[p+ofsB];
1491 YDU[pos]=+0.29900f*r+0.58700f*g+0.11400f*b-128;
1492 UDU[pos]=-0.16874f*r-0.33126f*g+0.50000f*b;
1493 VDU[pos]=+0.50000f*r-0.41869f*g-0.08131f*b;
1497 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1498 DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
1499 DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
1504 stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits);
1508 stbiw__putc(s, 0xFF);
1509 stbiw__putc(s, 0xD9);
1514STBIWDEF
int stbi_write_jpg_to_func(stbi_write_func *func,
void *context,
int x,
int y,
int comp,
const void *data,
int quality)
1516 stbi__write_context s;
1517 stbi__start_write_callbacks(&s, func, context);
1518 return stbi_write_jpg_core(&s, x, y, comp, (
void *) data, quality);
1522#ifndef STBI_WRITE_NO_STDIO
1523STBIWDEF
int stbi_write_jpg(
char const *filename,
int x,
int y,
int comp,
const void *data,
int quality)
1525 stbi__write_context s;
1526 if (stbi__start_write_file(&s,filename)) {
1527 int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
1528 stbi__end_write_file(&s);