148 #ifndef INCLUDE_STB_IMAGE_WRITE_H 149 #define INCLUDE_STB_IMAGE_WRITE_H 153 #ifdef STB_IMAGE_WRITE_STATIC 154 #define STBIWDEF static 157 #define STBIWDEF extern "C" 159 #define STBIWDEF extern 164 #ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations 170 #ifndef STBI_WRITE_NO_STDIO 188 #endif//INCLUDE_STB_IMAGE_WRITE_H 190 #ifdef STB_IMAGE_WRITE_IMPLEMENTATION 193 #ifndef _CRT_SECURE_NO_WARNINGS 194 #define _CRT_SECURE_NO_WARNINGS 196 #ifndef _CRT_NONSTDC_NO_DEPRECATE 197 #define _CRT_NONSTDC_NO_DEPRECATE 201 #ifndef STBI_WRITE_NO_STDIO 203 #endif // STBI_WRITE_NO_STDIO 210 #if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) 212 #elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) 215 #error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." 219 #define STBIW_MALLOC(sz) malloc(sz) 220 #define STBIW_REALLOC(p,newsz) realloc(p,newsz) 221 #define STBIW_FREE(p) free(p) 224 #ifndef STBIW_REALLOC_SIZED 225 #define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) 229 #ifndef STBIW_MEMMOVE 230 #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) 236 #define STBIW_ASSERT(x) assert(x) 239 #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) 241 #ifdef STB_IMAGE_WRITE_STATIC 242 static int stbi__flip_vertically_on_write=0;
248 int stbi__flip_vertically_on_write=0;
255 stbi__flip_vertically_on_write = flag;
262 } stbi__write_context;
265 static void stbi__start_write_callbacks(stbi__write_context *s,
stbi_write_func *c,
void *context)
268 s->context = context;
271 #ifndef STBI_WRITE_NO_STDIO 273 static void stbi__stdio_write(
void *context,
void *
data,
int size)
275 fwrite(data,1,size,(FILE*) context);
278 static int stbi__start_write_file(stbi__write_context *s,
const char *filename)
281 #ifdef STBI_MSC_SECURE_CRT 282 if (fopen_s(&f, filename,
"wb"))
285 f = fopen(filename,
"wb");
287 stbi__start_write_callbacks(s, stbi__stdio_write, (
void *) f);
291 static void stbi__end_write_file(stbi__write_context *s)
293 fclose((FILE *)s->context);
296 #endif // !STBI_WRITE_NO_STDIO 298 typedef unsigned int stbiw_uint32;
299 typedef int stb_image_write_test[
sizeof(stbiw_uint32)==4 ? 1 : -1];
301 static void stbiw__writefv(stbi__write_context *s,
const char *fmt, va_list v)
306 case '1': {
unsigned char x = STBIW_UCHAR(va_arg(v,
int));
307 s->func(s->context,&x,1);
309 case '2': {
int x = va_arg(v,
int);
311 b[0] = STBIW_UCHAR(x);
312 b[1] = STBIW_UCHAR(x>>8);
313 s->func(s->context,b,2);
315 case '4': { stbiw_uint32 x = va_arg(v,
int);
318 b[1]=STBIW_UCHAR(x>>8);
319 b[2]=STBIW_UCHAR(x>>16);
320 b[3]=STBIW_UCHAR(x>>24);
321 s->func(s->context,b,4);
330 static void stbiw__writef(stbi__write_context *s,
const char *fmt, ...)
334 stbiw__writefv(s, fmt, v);
338 static void stbiw__putc(stbi__write_context *s,
unsigned char c)
340 s->func(s->context, &c, 1);
343 static void stbiw__write3(stbi__write_context *s,
unsigned char a,
unsigned char b,
unsigned char c)
345 unsigned char arr[3];
346 arr[0] = a, arr[1] = b, arr[2] = c;
347 s->func(s->context, arr, 3);
350 static void stbiw__write_pixel(stbi__write_context *s,
int rgb_dir,
int comp,
int write_alpha,
int expand_mono,
unsigned char *d)
352 unsigned char bg[3] = { 255, 0, 255}, px[3];
356 s->func(s->context, &d[comp - 1], 1);
362 stbiw__write3(s, d[0], d[0], d[0]);
364 s->func(s->context, d, 1);
369 for (k = 0; k < 3; ++k)
370 px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
371 stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]);
376 stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
380 s->func(s->context, &d[comp - 1], 1);
383 static 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)
385 stbiw_uint32 zero = 0;
391 if (stbi__flip_vertically_on_write)
399 for (; j != j_end; j += vdir) {
400 for (i=0; i < x; ++i) {
401 unsigned char *d = (
unsigned char *) data + (j*x+i)*comp;
402 stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
404 s->func(s->context, &zero, scanline_pad);
408 static 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, ...)
410 if (y < 0 || x < 0) {
415 stbiw__writefv(s, fmt, v);
417 stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono);
422 static int stbi_write_bmp_core(stbi__write_context *s,
int x,
int y,
int comp,
const void *data)
424 int pad = (-x*3) & 3;
425 return stbiw__outfile(s,-1,-1,x,y,comp,1,(
void *) data,0,pad,
426 "11 4 22 4" "4 44 22 444444",
427 'B',
'M', 14+40+(x*3+pad)*y, 0,0, 14+40,
428 40, x,y, 1,24, 0,0,0,0,0,0);
433 stbi__write_context s;
434 stbi__start_write_callbacks(&s, func, context);
435 return stbi_write_bmp_core(&s, x, y, comp, data);
438 #ifndef STBI_WRITE_NO_STDIO 441 stbi__write_context s;
442 if (stbi__start_write_file(&s,filename)) {
443 int r = stbi_write_bmp_core(&s, x, y, comp, data);
444 stbi__end_write_file(&s);
451 static int stbi_write_tga_core(stbi__write_context *s,
int x,
int y,
int comp,
void *data)
453 int has_alpha = (comp == 2 || comp == 4);
454 int colorbytes = has_alpha ? comp-1 : comp;
455 int format = colorbytes < 2 ? 3 : 2;
461 return stbiw__outfile(s, -1, -1, x, y, comp, 0, (
void *) data, has_alpha, 0,
462 "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
467 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);
469 if (stbi__flip_vertically_on_write) {
478 for (; j != jend; j += jdir) {
479 unsigned char *row = (
unsigned char *) data + j * x * comp;
482 for (i = 0; i < x; i += len) {
483 unsigned char *begin = row + i * comp;
489 diff = memcmp(begin, row + (i + 1) * comp, comp);
491 const unsigned char *prev = begin;
492 for (k = i + 2; k < x && len < 128; ++k) {
493 if (memcmp(prev, row + k * comp, comp)) {
502 for (k = i + 2; k < x && len < 128; ++k) {
503 if (!memcmp(begin, row + k * comp, comp)) {
513 unsigned char header = STBIW_UCHAR(len - 1);
514 s->func(s->context, &header, 1);
515 for (k = 0; k < len; ++k) {
516 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
519 unsigned char header = STBIW_UCHAR(len - 129);
520 s->func(s->context, &header, 1);
521 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
531 stbi__write_context s;
532 stbi__start_write_callbacks(&s, func, context);
533 return stbi_write_tga_core(&s, x, y, comp, (
void *) data);
536 #ifndef STBI_WRITE_NO_STDIO 539 stbi__write_context s;
540 if (stbi__start_write_file(&s,filename)) {
541 int r = stbi_write_tga_core(&s, x, y, comp, (
void *) data);
542 stbi__end_write_file(&s);
553 #define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) 555 void stbiw__linear_to_rgbe(
unsigned char *rgbe,
float *linear)
558 float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
560 if (maxcomp < 1e-32f) {
561 rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
563 float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
565 rgbe[0] = (
unsigned char)(linear[0] * normalize);
566 rgbe[1] = (
unsigned char)(linear[1] * normalize);
567 rgbe[2] = (
unsigned char)(linear[2] * normalize);
568 rgbe[3] = (
unsigned char)(exponent + 128);
572 void stbiw__write_run_data(stbi__write_context *s,
int length,
unsigned char databyte)
574 unsigned char lengthbyte = STBIW_UCHAR(length+128);
575 STBIW_ASSERT(length+128 <= 255);
576 s->func(s->context, &lengthbyte, 1);
577 s->func(s->context, &databyte, 1);
580 void stbiw__write_dump_data(stbi__write_context *s,
int length,
unsigned char *data)
582 unsigned char lengthbyte = STBIW_UCHAR(length);
583 STBIW_ASSERT(length <= 128);
584 s->func(s->context, &lengthbyte, 1);
585 s->func(s->context, data, length);
588 void stbiw__write_hdr_scanline(stbi__write_context *s,
int width,
int ncomp,
unsigned char *scratch,
float *scanline)
590 unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
591 unsigned char rgbe[4];
595 scanlineheader[2] = (width&0xff00)>>8;
596 scanlineheader[3] = (width&0x00ff);
599 if (width < 8 || width >= 32768) {
600 for (x=0; x < width; x++) {
603 case 3: linear[2] = scanline[x*ncomp + 2];
604 linear[1] = scanline[x*ncomp + 1];
605 linear[0] = scanline[x*ncomp + 0];
608 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
611 stbiw__linear_to_rgbe(rgbe, linear);
612 s->func(s->context, rgbe, 4);
617 for (x=0; x < width; x++) {
620 case 3: linear[2] = scanline[x*ncomp + 2];
621 linear[1] = scanline[x*ncomp + 1];
622 linear[0] = scanline[x*ncomp + 0];
625 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
628 stbiw__linear_to_rgbe(rgbe, linear);
629 scratch[x + width*0] = rgbe[0];
630 scratch[x + width*1] = rgbe[1];
631 scratch[x + width*2] = rgbe[2];
632 scratch[x + width*3] = rgbe[3];
635 s->func(s->context, scanlineheader, 4);
638 for (c=0; c < 4; c++) {
639 unsigned char *comp = &scratch[width*c];
645 while (r+2 < width) {
646 if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
655 if (len > 128) len = 128;
656 stbiw__write_dump_data(s, len, &comp[x]);
662 while (r < width && comp[r] == comp[x])
667 if (len > 127) len = 127;
668 stbiw__write_run_data(s, len, comp[x]);
677 static int stbi_write_hdr_core(stbi__write_context *s,
int x,
int y,
int comp,
float *data)
679 if (y <= 0 || x <= 0 || data == NULL)
683 unsigned char *scratch = (
unsigned char *) STBIW_MALLOC(x*4);
686 char header[] =
"#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
687 s->func(s->context, header,
sizeof(header)-1);
689 #ifdef STBI_MSC_SECURE_CRT 690 len = sprintf_s(buffer,
"EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
692 len = sprintf(buffer,
"EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
694 s->func(s->context, buffer, len);
697 stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i)*x);
705 stbi__write_context s;
706 stbi__start_write_callbacks(&s, func, context);
707 return stbi_write_hdr_core(&s, x, y, comp, (
float *) data);
710 #ifndef STBI_WRITE_NO_STDIO 713 stbi__write_context s;
714 if (stbi__start_write_file(&s,filename)) {
715 int r = stbi_write_hdr_core(&s, x, y, comp, (
float *) data);
716 stbi__end_write_file(&s);
721 #endif // STBI_WRITE_NO_STDIO 729 #ifndef STBIW_ZLIB_COMPRESS 731 #define stbiw__sbraw(a) ((int *) (a) - 2) 732 #define stbiw__sbm(a) stbiw__sbraw(a)[0] 733 #define stbiw__sbn(a) stbiw__sbraw(a)[1] 735 #define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) 736 #define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) 737 #define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) 739 #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) 740 #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) 741 #define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) 743 static void *stbiw__sbgrowf(
void **arr,
int increment,
int itemsize)
745 int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
746 void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize +
sizeof(
int)*2) : 0, itemsize * m +
sizeof(
int)*2);
749 if (!*arr) ((
int *) p)[1] = 0;
750 *arr = (
void *) ((
int *) p + 2);
751 stbiw__sbm(*arr) = m;
756 static unsigned char *stbiw__zlib_flushf(
unsigned char *data,
unsigned int *bitbuffer,
int *bitcount)
758 while (*bitcount >= 8) {
759 stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
766 static int stbiw__zlib_bitrev(
int code,
int codebits)
770 res = (res << 1) | (code & 1);
776 static unsigned int stbiw__zlib_countm(
unsigned char *a,
unsigned char *b,
int limit)
779 for (i=0; i < limit && i < 258; ++i)
780 if (a[i] != b[i])
break;
784 static unsigned int stbiw__zhash(
unsigned char *data)
786 stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
796 #define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) 797 #define stbiw__zlib_add(code,codebits) \ 798 (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) 799 #define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) 801 #define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) 802 #define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) 803 #define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) 804 #define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) 805 #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)) 806 #define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) 808 #define stbiw__ZHASH 16384 810 #endif // STBIW_ZLIB_COMPRESS 812 unsigned char * stbi_zlib_compress(
unsigned char *data,
int data_len,
int *out_len,
int quality)
814 #ifdef STBIW_ZLIB_COMPRESS 816 return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality);
818 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 };
819 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 };
820 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 };
821 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 };
822 unsigned int bitbuf=0;
824 unsigned char *out = NULL;
825 unsigned char ***hash_table = (
unsigned char***) STBIW_MALLOC(stbiw__ZHASH *
sizeof(
char**));
826 if (hash_table == NULL)
828 if (quality < 5) quality = 5;
830 stbiw__sbpush(out, 0x78);
831 stbiw__sbpush(out, 0x5e);
832 stbiw__zlib_add(1,1);
833 stbiw__zlib_add(1,2);
835 for (i=0; i < stbiw__ZHASH; ++i)
836 hash_table[i] = NULL;
839 while (i < data_len-3) {
841 int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
842 unsigned char *bestloc = 0;
843 unsigned char **hlist = hash_table[h];
844 int n = stbiw__sbcount(hlist);
845 for (j=0; j < n; ++j) {
846 if (hlist[j]-data > i-32768) {
847 int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
848 if (d >= best) best=d,bestloc=hlist[j];
852 if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
853 STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality,
sizeof(hash_table[h][0])*quality);
854 stbiw__sbn(hash_table[h]) = quality;
856 stbiw__sbpush(hash_table[h],data+i);
860 h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
861 hlist = hash_table[h];
862 n = stbiw__sbcount(hlist);
863 for (j=0; j < n; ++j) {
864 if (hlist[j]-data > i-32767) {
865 int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
875 int d = (int) (data+i - bestloc);
876 STBIW_ASSERT(d <= 32767 && best <= 258);
877 for (j=0; best > lengthc[j+1]-1; ++j);
878 stbiw__zlib_huff(j+257);
879 if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
880 for (j=0; d > distc[j+1]-1; ++j);
881 stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
882 if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
885 stbiw__zlib_huffb(data[i]);
890 for (;i < data_len; ++i)
891 stbiw__zlib_huffb(data[i]);
892 stbiw__zlib_huff(256);
895 stbiw__zlib_add(0,1);
897 for (i=0; i < stbiw__ZHASH; ++i)
898 (
void) stbiw__sbfree(hash_table[i]);
899 STBIW_FREE(hash_table);
903 unsigned int s1=1, s2=0;
904 int blocklen = (int) (data_len % 5552);
906 while (j < data_len) {
907 for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
908 s1 %= 65521, s2 %= 65521;
912 stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
913 stbiw__sbpush(out, STBIW_UCHAR(s2));
914 stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
915 stbiw__sbpush(out, STBIW_UCHAR(s1));
917 *out_len = stbiw__sbn(out);
919 STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
920 return (
unsigned char *) stbiw__sbraw(out);
921 #endif // STBIW_ZLIB_COMPRESS 924 static unsigned int stbiw__crc32(
unsigned char *buffer,
int len)
926 static unsigned int crc_table[256] =
928 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
929 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
930 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
931 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
932 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
933 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
934 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
935 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
936 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
937 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
938 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
939 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
940 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
941 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
942 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
943 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
944 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
945 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
946 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
947 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
948 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
949 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
950 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
951 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
952 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
953 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
954 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
955 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
956 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
957 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
958 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
959 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
962 unsigned int crc = ~0u;
964 for (i=0; i < len; ++i)
965 crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
969 #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) 970 #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); 971 #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) 973 static void stbiw__wpcrc(
unsigned char **data,
int len)
975 unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
976 stbiw__wp32(*data, crc);
979 static unsigned char stbiw__paeth(
int a,
int b,
int c)
981 int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
982 if (pa <= pb && pa <= pc)
return STBIW_UCHAR(a);
983 if (pb <= pc)
return STBIW_UCHAR(b);
984 return STBIW_UCHAR(c);
988 static 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)
990 static int mapping[] = { 0,1,2,3,4 };
991 static int firstmap[] = { 0,1,0,5,6 };
992 int *mymap = (y != 0) ? mapping : firstmap;
994 int type = mymap[filter_type];
995 unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y);
996 int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes;
997 for (i = 0; i < n; ++i) {
999 case 0: line_buffer[i] = z[i];
break;
1000 case 1: line_buffer[i] = z[i];
break;
1001 case 2: line_buffer[i] = z[i] - z[i-signed_stride];
break;
1002 case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1);
break;
1003 case 4: line_buffer[i] = (
signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0));
break;
1004 case 5: line_buffer[i] = z[i];
break;
1005 case 6: line_buffer[i] = z[i];
break;
1008 for (i=n; i < width*n; ++i) {
1010 case 0: line_buffer[i] = z[i];
break;
1011 case 1: line_buffer[i] = z[i] - z[i-n];
break;
1012 case 2: line_buffer[i] = z[i] - z[i-signed_stride];
break;
1013 case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1);
break;
1014 case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]);
break;
1015 case 5: line_buffer[i] = z[i] - (z[i-n]>>1);
break;
1016 case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0);
break;
1021 unsigned char *stbi_write_png_to_mem(
unsigned char *pixels,
int stride_bytes,
int x,
int y,
int n,
int *out_len)
1024 int ctype[5] = { -1, 0, 4, 2, 6 };
1025 unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
1026 unsigned char *out,*o, *filt, *zlib;
1027 signed char *line_buffer;
1030 if (stride_bytes == 0)
1031 stride_bytes = x * n;
1033 if (force_filter >= 5) {
1037 filt = (
unsigned char *) STBIW_MALLOC((x*n+1) * y);
if (!filt)
return 0;
1038 line_buffer = (
signed char *) STBIW_MALLOC(x * n);
if (!line_buffer) { STBIW_FREE(filt);
return 0; }
1039 for (j=0; j < y; ++j) {
1041 if (force_filter > -1) {
1042 filter_type = force_filter;
1043 stbiw__encode_png_line(pixels, stride_bytes, x, y, j, n, force_filter, line_buffer);
1045 int best_filter = 0, best_filter_val = 0x7fffffff, est, i;
1046 for (filter_type = 0; filter_type < 5; filter_type++) {
1047 stbiw__encode_png_line(pixels, stride_bytes, x, y, j, n, filter_type, line_buffer);
1051 for (i = 0; i < x*n; ++i) {
1052 est += abs((
signed char) line_buffer[i]);
1054 if (est < best_filter_val) {
1055 best_filter_val = est;
1056 best_filter = filter_type;
1059 if (filter_type != best_filter) {
1060 stbiw__encode_png_line(pixels, stride_bytes, x, y, j, n, best_filter, line_buffer);
1061 filter_type = best_filter;
1065 filt[j*(x*n+1)] = (
unsigned char) filter_type;
1066 STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
1068 STBIW_FREE(line_buffer);
1071 if (!zlib)
return 0;
1074 out = (
unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
1076 *out_len = 8 + 12+13 + 12+zlen + 12;
1079 STBIW_MEMMOVE(o,sig,8); o+= 8;
1081 stbiw__wptag(o,
"IHDR");
1085 *o++ = STBIW_UCHAR(ctype[n]);
1089 stbiw__wpcrc(&o,13);
1091 stbiw__wp32(o, zlen);
1092 stbiw__wptag(o,
"IDAT");
1093 STBIW_MEMMOVE(o, zlib, zlen);
1096 stbiw__wpcrc(&o, zlen);
1099 stbiw__wptag(o,
"IEND");
1102 STBIW_ASSERT(o == out + *out_len);
1107 #ifndef STBI_WRITE_NO_STDIO 1108 STBIWDEF int stbi_write_png(
char const *filename,
int x,
int y,
int comp,
const void *data,
int stride_bytes)
1112 unsigned char *png = stbi_write_png_to_mem((
unsigned char *) data, stride_bytes, x, y, comp, &len);
1113 if (png == NULL)
return 0;
1114 #ifdef STBI_MSC_SECURE_CRT 1115 if (fopen_s(&f, filename,
"wb"))
1118 f = fopen(filename,
"wb");
1120 if (!f) { STBIW_FREE(png);
return 0; }
1121 fwrite(png, 1, len, f);
1131 unsigned char *png = stbi_write_png_to_mem((
unsigned char *) data, stride_bytes, x, y, comp, &len);
1132 if (png == NULL)
return 0;
1133 func(context, png, len);
1147 static 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,
1148 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 };
1150 static void stbiw__jpg_writeBits(stbi__write_context *s,
int *bitBufP,
int *bitCntP,
const unsigned short *bs) {
1151 int bitBuf = *bitBufP, bitCnt = *bitCntP;
1153 bitBuf |= bs[0] << (24 - bitCnt);
1154 while(bitCnt >= 8) {
1155 unsigned char c = (bitBuf >> 16) & 255;
1167 static void stbiw__jpg_DCT(
float *d0p,
float *d1p,
float *d2p,
float *d3p,
float *d4p,
float *d5p,
float *d6p,
float *d7p) {
1168 float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p;
1169 float z1, z2, z3, z4, z5, z11, z13;
1171 float tmp0 = d0 + d7;
1172 float tmp7 = d0 - d7;
1173 float tmp1 = d1 + d6;
1174 float tmp6 = d1 - d6;
1175 float tmp2 = d2 + d5;
1176 float tmp5 = d2 - d5;
1177 float tmp3 = d3 + d4;
1178 float tmp4 = d3 - d4;
1181 float tmp10 = tmp0 + tmp3;
1182 float tmp13 = tmp0 - tmp3;
1183 float tmp11 = tmp1 + tmp2;
1184 float tmp12 = tmp1 - tmp2;
1189 z1 = (tmp12 + tmp13) * 0.707106781f;
1194 tmp10 = tmp4 + tmp5;
1195 tmp11 = tmp5 + tmp6;
1196 tmp12 = tmp6 + tmp7;
1199 z5 = (tmp10 - tmp12) * 0.382683433f;
1200 z2 = tmp10 * 0.541196100f + z5;
1201 z4 = tmp12 * 1.306562965f + z5;
1202 z3 = tmp11 * 0.707106781f;
1212 *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6;
1215 static void stbiw__jpg_calcBits(
int val,
unsigned short bits[2]) {
1216 int tmp1 = val < 0 ? -val : val;
1217 val = val < 0 ? val-1 : val;
1222 bits[0] = val & ((1<<bits[1])-1);
1225 static 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]) {
1226 const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
1227 const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
1228 int dataOff, i, diff, end0pos;
1232 for(dataOff=0; dataOff<64; dataOff+=8) {
1233 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]);
1236 for(dataOff=0; dataOff<8; ++dataOff) {
1237 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]);
1240 for(i=0; i<64; ++i) {
1241 float v = CDU[i]*fdtbl[i];
1244 DU[stbiw__jpg_ZigZag[i]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
1250 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]);
1252 unsigned short bits[2];
1253 stbiw__jpg_calcBits(diff, bits);
1254 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]);
1255 stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1259 for(; (end0pos>0)&&(DU[end0pos]==0); --end0pos) {
1263 stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1266 for(i = 1; i <= end0pos; ++i) {
1269 unsigned short bits[2];
1270 for (; DU[i]==0 && i<=end0pos; ++i) {
1272 nrzeroes = i-startpos;
1273 if ( nrzeroes >= 16 ) {
1274 int lng = nrzeroes>>4;
1276 for (nrmarker=1; nrmarker <= lng; ++nrmarker)
1277 stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes);
1280 stbiw__jpg_calcBits(DU[i], bits);
1281 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]);
1282 stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1285 stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1290 static int stbi_write_jpg_core(stbi__write_context *s,
int width,
int height,
int comp,
const void* data,
int quality) {
1292 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};
1293 static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1294 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};
1295 static const unsigned char std_ac_luminance_values[] = {
1296 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
1297 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
1298 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
1299 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
1300 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
1301 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
1302 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1304 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};
1305 static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1306 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};
1307 static const unsigned char std_ac_chrominance_values[] = {
1308 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
1309 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
1310 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
1311 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
1312 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
1313 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
1314 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1317 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}};
1318 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}};
1319 static const unsigned short YAC_HT[256][2] = {
1320 {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},
1321 {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},
1322 {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},
1323 {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},
1324 {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},
1325 {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},
1326 {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},
1327 {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},
1328 {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},
1329 {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},
1330 {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},
1331 {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},
1332 {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},
1333 {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},
1334 {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},
1335 {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}
1337 static const unsigned short UVAC_HT[256][2] = {
1338 {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},
1339 {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},
1340 {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},
1341 {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},
1342 {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},
1343 {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},
1344 {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},
1345 {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},
1346 {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},
1347 {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},
1348 {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},
1349 {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},
1350 {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},
1351 {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},
1352 {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},
1353 {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}
1355 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,
1356 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};
1357 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,
1358 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};
1359 static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
1360 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f };
1363 float fdtbl_Y[64], fdtbl_UV[64];
1364 unsigned char YTable[64], UVTable[64];
1366 if(!data || !width || !height || comp > 4 || comp < 1) {
1370 quality = quality ? quality : 90;
1371 quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
1372 quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
1374 for(i = 0; i < 64; ++i) {
1375 int uvti, yti = (YQT[i]*quality+50)/100;
1376 YTable[stbiw__jpg_ZigZag[i]] = (
unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti);
1377 uvti = (UVQT[i]*quality+50)/100;
1378 UVTable[stbiw__jpg_ZigZag[i]] = (
unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti);
1381 for(row = 0, k = 0; row < 8; ++row) {
1382 for(col = 0; col < 8; ++col, ++k) {
1383 fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1384 fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1390 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 };
1391 static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
1392 const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(
unsigned char)(height>>8),STBIW_UCHAR(height),(
unsigned char)(width>>8),STBIW_UCHAR(width),
1393 3,1,0x11,0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
1394 s->func(s->context, (
void*)head0,
sizeof(head0));
1395 s->func(s->context, (
void*)YTable,
sizeof(YTable));
1397 s->func(s->context, UVTable,
sizeof(UVTable));
1398 s->func(s->context, (
void*)head1,
sizeof(head1));
1399 s->func(s->context, (
void*)(std_dc_luminance_nrcodes+1),
sizeof(std_dc_luminance_nrcodes)-1);
1400 s->func(s->context, (
void*)std_dc_luminance_values,
sizeof(std_dc_luminance_values));
1401 stbiw__putc(s, 0x10);
1402 s->func(s->context, (
void*)(std_ac_luminance_nrcodes+1),
sizeof(std_ac_luminance_nrcodes)-1);
1403 s->func(s->context, (
void*)std_ac_luminance_values,
sizeof(std_ac_luminance_values));
1405 s->func(s->context, (
void*)(std_dc_chrominance_nrcodes+1),
sizeof(std_dc_chrominance_nrcodes)-1);
1406 s->func(s->context, (
void*)std_dc_chrominance_values,
sizeof(std_dc_chrominance_values));
1407 stbiw__putc(s, 0x11);
1408 s->func(s->context, (
void*)(std_ac_chrominance_nrcodes+1),
sizeof(std_ac_chrominance_nrcodes)-1);
1409 s->func(s->context, (
void*)std_ac_chrominance_values,
sizeof(std_ac_chrominance_values));
1410 s->func(s->context, (
void*)head2,
sizeof(head2));
1415 static const unsigned short fillBits[] = {0x7F, 7};
1416 const unsigned char *imageData = (
const unsigned char *)data;
1417 int DCY=0, DCU=0, DCV=0;
1418 int bitBuf=0, bitCnt=0;
1420 int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
1422 for(y = 0; y < height; y += 8) {
1423 for(x = 0; x < width; x += 8) {
1424 float YDU[64], UDU[64], VDU[64];
1425 for(row = y, pos = 0; row < y+8; ++row) {
1426 for(col = x; col < x+8; ++col, ++pos) {
1427 int p = (stbi__flip_vertically_on_write ? height-1-row : row)*width*comp + col*comp;
1430 p -= width*comp*(row+1 - height);
1433 p -= comp*(col+1 - width);
1437 g = imageData[p+ofsG];
1438 b = imageData[p+ofsB];
1439 YDU[pos]=+0.29900f*r+0.58700f*g+0.11400f*b-128;
1440 UDU[pos]=-0.16874f*r-0.33126f*g+0.50000f*b;
1441 VDU[pos]=+0.50000f*r-0.41869f*g-0.08131f*b;
1445 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, YDU, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1446 DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, UDU, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
1447 DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, VDU, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
1452 stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits);
1456 stbiw__putc(s, 0xFF);
1457 stbiw__putc(s, 0xD9);
1464 stbi__write_context s;
1465 stbi__start_write_callbacks(&s, func, context);
1466 return stbi_write_jpg_core(&s, x, y, comp, (
void *) data, quality);
1470 #ifndef STBI_WRITE_NO_STDIO 1473 stbi__write_context s;
1474 if (stbi__start_write_file(&s,filename)) {
1475 int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
1476 stbi__end_write_file(&s);
1483 #endif // STB_IMAGE_WRITE_IMPLEMENTATION 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)
void stbi_write_func(void *context, void *data, int size)
STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data)
STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data)
STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data)
int stbi_write_force_png_filter
STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
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_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data)
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_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes)
int stbi_write_png_compression_level
STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)
int stbi_write_tga_with_rle