File indexing completed on 2026-04-09 07:49:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151 #ifndef INCLUDE_STB_IMAGE_WRITE_H
0152 #define INCLUDE_STB_IMAGE_WRITE_H
0153
0154 #include <stdlib.h>
0155
0156
0157 #ifndef STBIWDEF
0158 #ifdef STB_IMAGE_WRITE_STATIC
0159 #define STBIWDEF static
0160 #else
0161 #ifdef __cplusplus
0162 #define STBIWDEF extern "C"
0163 #else
0164 #define STBIWDEF extern
0165 #endif
0166 #endif
0167 #endif
0168
0169 #ifndef STB_IMAGE_WRITE_STATIC
0170 STBIWDEF int stbi_write_tga_with_rle;
0171 STBIWDEF int stbi_write_png_compression_level;
0172 STBIWDEF int stbi_write_force_png_filter;
0173 #endif
0174
0175 #ifndef STBI_WRITE_NO_STDIO
0176 STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
0177 STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
0178 STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
0179 STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
0180 STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality);
0181
0182 #ifdef STBIW_WINDOWS_UTF8
0183 STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
0184 #endif
0185 #endif
0186
0187 typedef void stbi_write_func(void *context, void *data, int size);
0188
0189 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);
0190 STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
0191 STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data);
0192 STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
0193 STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality);
0194
0195 STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean);
0196
0197 #endif
0198
0199 #ifdef STB_IMAGE_WRITE_IMPLEMENTATION
0200
0201 #ifdef _WIN32
0202 #ifndef _CRT_SECURE_NO_WARNINGS
0203 #define _CRT_SECURE_NO_WARNINGS
0204 #endif
0205 #ifndef _CRT_NONSTDC_NO_DEPRECATE
0206 #define _CRT_NONSTDC_NO_DEPRECATE
0207 #endif
0208 #endif
0209
0210 #ifndef STBI_WRITE_NO_STDIO
0211 #include <stdio.h>
0212 #endif
0213
0214 #include <stdarg.h>
0215 #include <stdlib.h>
0216 #include <string.h>
0217 #include <math.h>
0218
0219 #if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED))
0220
0221 #elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED)
0222
0223 #else
0224 #error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)."
0225 #endif
0226
0227 #ifndef STBIW_MALLOC
0228 #define STBIW_MALLOC(sz) malloc(sz)
0229 #define STBIW_REALLOC(p,newsz) realloc(p,newsz)
0230 #define STBIW_FREE(p) free(p)
0231 #endif
0232
0233 #ifndef STBIW_REALLOC_SIZED
0234 #define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz)
0235 #endif
0236
0237
0238 #ifndef STBIW_MEMMOVE
0239 #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
0240 #endif
0241
0242
0243 #ifndef STBIW_ASSERT
0244 #include <assert.h>
0245 #define STBIW_ASSERT(x) assert(x)
0246 #endif
0247
0248 #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
0249
0250 #ifdef STB_IMAGE_WRITE_STATIC
0251 static int stbi_write_png_compression_level = 8;
0252 static int stbi_write_tga_with_rle = 1;
0253 static int stbi_write_force_png_filter = -1;
0254 #else
0255 int stbi_write_png_compression_level = 8;
0256 int stbi_write_tga_with_rle = 1;
0257 int stbi_write_force_png_filter = -1;
0258 #endif
0259
0260 static int stbi__flip_vertically_on_write = 0;
0261
0262 STBIWDEF void stbi_flip_vertically_on_write(int flag)
0263 {
0264 stbi__flip_vertically_on_write = flag;
0265 }
0266
0267 typedef struct
0268 {
0269 stbi_write_func *func;
0270 void *context;
0271 unsigned char buffer[64];
0272 int buf_used;
0273 } stbi__write_context;
0274
0275
0276 static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context)
0277 {
0278 s->func = c;
0279 s->context = context;
0280 }
0281
0282 #ifndef STBI_WRITE_NO_STDIO
0283
0284 static void stbi__stdio_write(void *context, void *data, int size)
0285 {
0286 fwrite(data,1,size,(FILE*) context);
0287 }
0288
0289 #if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
0290 #ifdef __cplusplus
0291 #define STBIW_EXTERN extern "C"
0292 #else
0293 #define STBIW_EXTERN extern
0294 #endif
0295 STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide);
0296 STBIW_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);
0297
0298 STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input)
0299 {
0300 return WideCharToMultiByte(65001 , 0, input, -1, buffer, (int) bufferlen, NULL, NULL);
0301 }
0302 #endif
0303
0304 static FILE *stbiw__fopen(char const *filename, char const *mode)
0305 {
0306 FILE *f;
0307 #if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
0308 wchar_t wMode[64];
0309 wchar_t wFilename[1024];
0310 if (0 == MultiByteToWideChar(65001 , 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename)))
0311 return 0;
0312
0313 if (0 == MultiByteToWideChar(65001 , 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode)))
0314 return 0;
0315
0316 #if defined(_MSC_VER) && _MSC_VER >= 1400
0317 if (0 != _wfopen_s(&f, wFilename, wMode))
0318 f = 0;
0319 #else
0320 f = _wfopen(wFilename, wMode);
0321 #endif
0322
0323 #elif defined(_MSC_VER) && _MSC_VER >= 1400
0324 if (0 != fopen_s(&f, filename, mode))
0325 f=0;
0326 #else
0327 f = fopen(filename, mode);
0328 #endif
0329 return f;
0330 }
0331
0332 static int stbi__start_write_file(stbi__write_context *s, const char *filename)
0333 {
0334 FILE *f = stbiw__fopen(filename, "wb");
0335 stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f);
0336 return f != NULL;
0337 }
0338
0339 static void stbi__end_write_file(stbi__write_context *s)
0340 {
0341 fclose((FILE *)s->context);
0342 }
0343
0344 #endif
0345
0346 typedef unsigned int stbiw_uint32;
0347 typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
0348
0349 static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v)
0350 {
0351 while (*fmt) {
0352 switch (*fmt++) {
0353 case ' ': break;
0354 case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int));
0355 s->func(s->context,&x,1);
0356 break; }
0357 case '2': { int x = va_arg(v,int);
0358 unsigned char b[2];
0359 b[0] = STBIW_UCHAR(x);
0360 b[1] = STBIW_UCHAR(x>>8);
0361 s->func(s->context,b,2);
0362 break; }
0363 case '4': { stbiw_uint32 x = va_arg(v,int);
0364 unsigned char b[4];
0365 b[0]=STBIW_UCHAR(x);
0366 b[1]=STBIW_UCHAR(x>>8);
0367 b[2]=STBIW_UCHAR(x>>16);
0368 b[3]=STBIW_UCHAR(x>>24);
0369 s->func(s->context,b,4);
0370 break; }
0371 default:
0372 STBIW_ASSERT(0);
0373 return;
0374 }
0375 }
0376 }
0377
0378 static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
0379 {
0380 va_list v;
0381 va_start(v, fmt);
0382 stbiw__writefv(s, fmt, v);
0383 va_end(v);
0384 }
0385
0386 static void stbiw__write_flush(stbi__write_context *s)
0387 {
0388 if (s->buf_used) {
0389 s->func(s->context, &s->buffer, s->buf_used);
0390 s->buf_used = 0;
0391 }
0392 }
0393
0394 static void stbiw__putc(stbi__write_context *s, unsigned char c)
0395 {
0396 s->func(s->context, &c, 1);
0397 }
0398
0399 static void stbiw__write1(stbi__write_context *s, unsigned char a)
0400 {
0401 if ((size_t)s->buf_used + 1 > sizeof(s->buffer))
0402 stbiw__write_flush(s);
0403 s->buffer[s->buf_used++] = a;
0404 }
0405
0406 static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
0407 {
0408 int n;
0409 if ((size_t)s->buf_used + 3 > sizeof(s->buffer))
0410 stbiw__write_flush(s);
0411 n = s->buf_used;
0412 s->buf_used = n+3;
0413 s->buffer[n+0] = a;
0414 s->buffer[n+1] = b;
0415 s->buffer[n+2] = c;
0416 }
0417
0418 static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
0419 {
0420 unsigned char bg[3] = { 255, 0, 255}, px[3];
0421 int k;
0422
0423 if (write_alpha < 0)
0424 stbiw__write1(s, d[comp - 1]);
0425
0426 switch (comp) {
0427 case 2:
0428 case 1:
0429 if (expand_mono)
0430 stbiw__write3(s, d[0], d[0], d[0]);
0431 else
0432 stbiw__write1(s, d[0]);
0433 break;
0434 case 4:
0435 if (!write_alpha) {
0436
0437 for (k = 0; k < 3; ++k)
0438 px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
0439 stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]);
0440 break;
0441 }
0442
0443 case 3:
0444 stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
0445 break;
0446 }
0447 if (write_alpha > 0)
0448 stbiw__write1(s, d[comp - 1]);
0449 }
0450
0451 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)
0452 {
0453 stbiw_uint32 zero = 0;
0454 int i,j, j_end;
0455
0456 if (y <= 0)
0457 return;
0458
0459 if (stbi__flip_vertically_on_write)
0460 vdir *= -1;
0461
0462 if (vdir < 0) {
0463 j_end = -1; j = y-1;
0464 } else {
0465 j_end = y; j = 0;
0466 }
0467
0468 for (; j != j_end; j += vdir) {
0469 for (i=0; i < x; ++i) {
0470 unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
0471 stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
0472 }
0473 stbiw__write_flush(s);
0474 s->func(s->context, &zero, scanline_pad);
0475 }
0476 }
0477
0478 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, ...)
0479 {
0480 if (y < 0 || x < 0) {
0481 return 0;
0482 } else {
0483 va_list v;
0484 va_start(v, fmt);
0485 stbiw__writefv(s, fmt, v);
0486 va_end(v);
0487 stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono);
0488 return 1;
0489 }
0490 }
0491
0492 static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
0493 {
0494 if (comp != 4) {
0495
0496 int pad = (-x*3) & 3;
0497 return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
0498 "11 4 22 4" "4 44 22 444444",
0499 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40,
0500 40, x,y, 1,24, 0,0,0,0,0,0);
0501 } else {
0502
0503
0504
0505 return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *)data,1,0,
0506 "11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444",
0507 'B', 'M', 14+108+x*y*4, 0, 0, 14+108,
0508 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);
0509 }
0510 }
0511
0512 STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
0513 {
0514 stbi__write_context s = { 0 };
0515 stbi__start_write_callbacks(&s, func, context);
0516 return stbi_write_bmp_core(&s, x, y, comp, data);
0517 }
0518
0519 #ifndef STBI_WRITE_NO_STDIO
0520 STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
0521 {
0522 stbi__write_context s = { 0 };
0523 if (stbi__start_write_file(&s,filename)) {
0524 int r = stbi_write_bmp_core(&s, x, y, comp, data);
0525 stbi__end_write_file(&s);
0526 return r;
0527 } else
0528 return 0;
0529 }
0530 #endif
0531
0532 static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data)
0533 {
0534 int has_alpha = (comp == 2 || comp == 4);
0535 int colorbytes = has_alpha ? comp-1 : comp;
0536 int format = colorbytes < 2 ? 3 : 2;
0537
0538 if (y < 0 || x < 0)
0539 return 0;
0540
0541 if (!stbi_write_tga_with_rle) {
0542 return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0,
0543 "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
0544 } else {
0545 int i,j,k;
0546 int jend, jdir;
0547
0548 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);
0549
0550 if (stbi__flip_vertically_on_write) {
0551 j = 0;
0552 jend = y;
0553 jdir = 1;
0554 } else {
0555 j = y-1;
0556 jend = -1;
0557 jdir = -1;
0558 }
0559 for (; j != jend; j += jdir) {
0560 unsigned char *row = (unsigned char *) data + j * x * comp;
0561 int len;
0562
0563 for (i = 0; i < x; i += len) {
0564 unsigned char *begin = row + i * comp;
0565 int diff = 1;
0566 len = 1;
0567
0568 if (i < x - 1) {
0569 ++len;
0570 diff = memcmp(begin, row + (i + 1) * comp, comp);
0571 if (diff) {
0572 const unsigned char *prev = begin;
0573 for (k = i + 2; k < x && len < 128; ++k) {
0574 if (memcmp(prev, row + k * comp, comp)) {
0575 prev += comp;
0576 ++len;
0577 } else {
0578 --len;
0579 break;
0580 }
0581 }
0582 } else {
0583 for (k = i + 2; k < x && len < 128; ++k) {
0584 if (!memcmp(begin, row + k * comp, comp)) {
0585 ++len;
0586 } else {
0587 break;
0588 }
0589 }
0590 }
0591 }
0592
0593 if (diff) {
0594 unsigned char header = STBIW_UCHAR(len - 1);
0595 stbiw__write1(s, header);
0596 for (k = 0; k < len; ++k) {
0597 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
0598 }
0599 } else {
0600 unsigned char header = STBIW_UCHAR(len - 129);
0601 stbiw__write1(s, header);
0602 stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
0603 }
0604 }
0605 }
0606 stbiw__write_flush(s);
0607 }
0608 return 1;
0609 }
0610
0611 STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
0612 {
0613 stbi__write_context s = { 0 };
0614 stbi__start_write_callbacks(&s, func, context);
0615 return stbi_write_tga_core(&s, x, y, comp, (void *) data);
0616 }
0617
0618 #ifndef STBI_WRITE_NO_STDIO
0619 STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
0620 {
0621 stbi__write_context s = { 0 };
0622 if (stbi__start_write_file(&s,filename)) {
0623 int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
0624 stbi__end_write_file(&s);
0625 return r;
0626 } else
0627 return 0;
0628 }
0629 #endif
0630
0631
0632
0633
0634
0635 #define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
0636
0637 #ifndef STBI_WRITE_NO_STDIO
0638
0639 static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
0640 {
0641 int exponent;
0642 float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
0643
0644 if (maxcomp < 1e-32f) {
0645 rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
0646 } else {
0647 float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
0648
0649 rgbe[0] = (unsigned char)(linear[0] * normalize);
0650 rgbe[1] = (unsigned char)(linear[1] * normalize);
0651 rgbe[2] = (unsigned char)(linear[2] * normalize);
0652 rgbe[3] = (unsigned char)(exponent + 128);
0653 }
0654 }
0655
0656 static void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
0657 {
0658 unsigned char lengthbyte = STBIW_UCHAR(length+128);
0659 STBIW_ASSERT(length+128 <= 255);
0660 s->func(s->context, &lengthbyte, 1);
0661 s->func(s->context, &databyte, 1);
0662 }
0663
0664 static void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
0665 {
0666 unsigned char lengthbyte = STBIW_UCHAR(length);
0667 STBIW_ASSERT(length <= 128);
0668 s->func(s->context, &lengthbyte, 1);
0669 s->func(s->context, data, length);
0670 }
0671
0672 static void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline)
0673 {
0674 unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
0675 unsigned char rgbe[4];
0676 float linear[3];
0677 int x;
0678
0679 scanlineheader[2] = (width&0xff00)>>8;
0680 scanlineheader[3] = (width&0x00ff);
0681
0682
0683 if (width < 8 || width >= 32768) {
0684 for (x=0; x < width; x++) {
0685 switch (ncomp) {
0686 case 4:
0687 case 3: linear[2] = scanline[x*ncomp + 2];
0688 linear[1] = scanline[x*ncomp + 1];
0689 linear[0] = scanline[x*ncomp + 0];
0690 break;
0691 default:
0692 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
0693 break;
0694 }
0695 stbiw__linear_to_rgbe(rgbe, linear);
0696 s->func(s->context, rgbe, 4);
0697 }
0698 } else {
0699 int c,r;
0700
0701 for (x=0; x < width; x++) {
0702 switch(ncomp) {
0703 case 4:
0704 case 3: linear[2] = scanline[x*ncomp + 2];
0705 linear[1] = scanline[x*ncomp + 1];
0706 linear[0] = scanline[x*ncomp + 0];
0707 break;
0708 default:
0709 linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
0710 break;
0711 }
0712 stbiw__linear_to_rgbe(rgbe, linear);
0713 scratch[x + width*0] = rgbe[0];
0714 scratch[x + width*1] = rgbe[1];
0715 scratch[x + width*2] = rgbe[2];
0716 scratch[x + width*3] = rgbe[3];
0717 }
0718
0719 s->func(s->context, scanlineheader, 4);
0720
0721
0722 for (c=0; c < 4; c++) {
0723 unsigned char *comp = &scratch[width*c];
0724
0725 x = 0;
0726 while (x < width) {
0727
0728 r = x;
0729 while (r+2 < width) {
0730 if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
0731 break;
0732 ++r;
0733 }
0734 if (r+2 >= width)
0735 r = width;
0736
0737 while (x < r) {
0738 int len = r-x;
0739 if (len > 128) len = 128;
0740 stbiw__write_dump_data(s, len, &comp[x]);
0741 x += len;
0742 }
0743
0744 if (r+2 < width) {
0745
0746 while (r < width && comp[r] == comp[x])
0747 ++r;
0748
0749 while (x < r) {
0750 int len = r-x;
0751 if (len > 127) len = 127;
0752 stbiw__write_run_data(s, len, comp[x]);
0753 x += len;
0754 }
0755 }
0756 }
0757 }
0758 }
0759 }
0760
0761 static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data)
0762 {
0763 if (y <= 0 || x <= 0 || data == NULL)
0764 return 0;
0765 else {
0766
0767 unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
0768 int i, len;
0769 char buffer[128];
0770 char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
0771 s->func(s->context, header, sizeof(header)-1);
0772
0773 #ifdef __STDC_LIB_EXT1__
0774 len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
0775 #else
0776 len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x);
0777 #endif
0778 s->func(s->context, buffer, len);
0779
0780 for(i=0; i < y; i++)
0781 stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i));
0782 STBIW_FREE(scratch);
0783 return 1;
0784 }
0785 }
0786
0787 STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
0788 {
0789 stbi__write_context s = { 0 };
0790 stbi__start_write_callbacks(&s, func, context);
0791 return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
0792 }
0793
0794 STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
0795 {
0796 stbi__write_context s = { 0 };
0797 if (stbi__start_write_file(&s,filename)) {
0798 int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
0799 stbi__end_write_file(&s);
0800 return r;
0801 } else
0802 return 0;
0803 }
0804 #endif
0805
0806
0807
0808
0809
0810
0811
0812 #ifndef STBIW_ZLIB_COMPRESS
0813
0814 #define stbiw__sbraw(a) ((int *) (void *) (a) - 2)
0815 #define stbiw__sbm(a) stbiw__sbraw(a)[0]
0816 #define stbiw__sbn(a) stbiw__sbraw(a)[1]
0817
0818 #define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
0819 #define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
0820 #define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
0821
0822 #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
0823 #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
0824 #define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
0825
0826 static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
0827 {
0828 int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
0829 void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2);
0830 STBIW_ASSERT(p);
0831 if (p) {
0832 if (!*arr) ((int *) p)[1] = 0;
0833 *arr = (void *) ((int *) p + 2);
0834 stbiw__sbm(*arr) = m;
0835 }
0836 return *arr;
0837 }
0838
0839 static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
0840 {
0841 while (*bitcount >= 8) {
0842 stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
0843 *bitbuffer >>= 8;
0844 *bitcount -= 8;
0845 }
0846 return data;
0847 }
0848
0849 static int stbiw__zlib_bitrev(int code, int codebits)
0850 {
0851 int res=0;
0852 while (codebits--) {
0853 res = (res << 1) | (code & 1);
0854 code >>= 1;
0855 }
0856 return res;
0857 }
0858
0859 static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit)
0860 {
0861 int i;
0862 for (i=0; i < limit && i < 258; ++i)
0863 if (a[i] != b[i]) break;
0864 return i;
0865 }
0866
0867 static unsigned int stbiw__zhash(unsigned char *data)
0868 {
0869 stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
0870 hash ^= hash << 3;
0871 hash += hash >> 5;
0872 hash ^= hash << 4;
0873 hash += hash >> 17;
0874 hash ^= hash << 25;
0875 hash += hash >> 6;
0876 return hash;
0877 }
0878
0879 #define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
0880 #define stbiw__zlib_add(code,codebits) \
0881 (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
0882 #define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
0883
0884 #define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8)
0885 #define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9)
0886 #define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7)
0887 #define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8)
0888 #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))
0889 #define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
0890
0891 #define stbiw__ZHASH 16384
0892
0893 #endif
0894
0895 STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
0896 {
0897 #ifdef STBIW_ZLIB_COMPRESS
0898
0899 return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality);
0900 #else
0901 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 };
0902 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 };
0903 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 };
0904 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 };
0905 unsigned int bitbuf=0;
0906 int i,j, bitcount=0;
0907 unsigned char *out = NULL;
0908 unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(unsigned char**));
0909 if (hash_table == NULL)
0910 return NULL;
0911 if (quality < 5) quality = 5;
0912
0913 stbiw__sbpush(out, 0x78);
0914 stbiw__sbpush(out, 0x5e);
0915 stbiw__zlib_add(1,1);
0916 stbiw__zlib_add(1,2);
0917
0918 for (i=0; i < stbiw__ZHASH; ++i)
0919 hash_table[i] = NULL;
0920
0921 i=0;
0922 while (i < data_len-3) {
0923
0924 int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
0925 unsigned char *bestloc = 0;
0926 unsigned char **hlist = hash_table[h];
0927 int n = stbiw__sbcount(hlist);
0928 for (j=0; j < n; ++j) {
0929 if (hlist[j]-data > i-32768) {
0930 int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
0931 if (d >= best) { best=d; bestloc=hlist[j]; }
0932 }
0933 }
0934
0935 if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
0936 STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
0937 stbiw__sbn(hash_table[h]) = quality;
0938 }
0939 stbiw__sbpush(hash_table[h],data+i);
0940
0941 if (bestloc) {
0942
0943 h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
0944 hlist = hash_table[h];
0945 n = stbiw__sbcount(hlist);
0946 for (j=0; j < n; ++j) {
0947 if (hlist[j]-data > i-32767) {
0948 int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
0949 if (e > best) {
0950 bestloc = NULL;
0951 break;
0952 }
0953 }
0954 }
0955 }
0956
0957 if (bestloc) {
0958 int d = (int) (data+i - bestloc);
0959 STBIW_ASSERT(d <= 32767 && best <= 258);
0960 for (j=0; best > lengthc[j+1]-1; ++j);
0961 stbiw__zlib_huff(j+257);
0962 if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
0963 for (j=0; d > distc[j+1]-1; ++j);
0964 stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
0965 if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
0966 i += best;
0967 } else {
0968 stbiw__zlib_huffb(data[i]);
0969 ++i;
0970 }
0971 }
0972
0973 for (;i < data_len; ++i)
0974 stbiw__zlib_huffb(data[i]);
0975 stbiw__zlib_huff(256);
0976
0977 while (bitcount)
0978 stbiw__zlib_add(0,1);
0979
0980 for (i=0; i < stbiw__ZHASH; ++i)
0981 (void) stbiw__sbfree(hash_table[i]);
0982 STBIW_FREE(hash_table);
0983
0984
0985 if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) {
0986 stbiw__sbn(out) = 2;
0987 for (j = 0; j < data_len;) {
0988 int blocklen = data_len - j;
0989 if (blocklen > 32767) blocklen = 32767;
0990 stbiw__sbpush(out, data_len - j == blocklen);
0991 stbiw__sbpush(out, STBIW_UCHAR(blocklen));
0992 stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8));
0993 stbiw__sbpush(out, STBIW_UCHAR(~blocklen));
0994 stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8));
0995 memcpy(out+stbiw__sbn(out), data+j, blocklen);
0996 stbiw__sbn(out) += blocklen;
0997 j += blocklen;
0998 }
0999 }
1000
1001 {
1002
1003 unsigned int s1=1, s2=0;
1004 int blocklen = (int) (data_len % 5552);
1005 j=0;
1006 while (j < data_len) {
1007 for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; }
1008 s1 %= 65521; s2 %= 65521;
1009 j += blocklen;
1010 blocklen = 5552;
1011 }
1012 stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
1013 stbiw__sbpush(out, STBIW_UCHAR(s2));
1014 stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
1015 stbiw__sbpush(out, STBIW_UCHAR(s1));
1016 }
1017 *out_len = stbiw__sbn(out);
1018
1019 STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
1020 return (unsigned char *) stbiw__sbraw(out);
1021 #endif
1022 }
1023
1024 static unsigned int stbiw__crc32(unsigned char *buffer, int len)
1025 {
1026 #ifdef STBIW_CRC32
1027 return STBIW_CRC32(buffer, len);
1028 #else
1029 static unsigned int crc_table[256] =
1030 {
1031 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
1032 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
1033 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
1034 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
1035 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
1036 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
1037 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
1038 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
1039 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
1040 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
1041 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
1042 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
1043 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
1044 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
1045 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
1046 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
1047 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
1048 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
1049 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
1050 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
1051 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
1052 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
1053 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
1054 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
1055 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
1056 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
1057 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
1058 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
1059 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
1060 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
1061 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
1062 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
1063 };
1064
1065 unsigned int crc = ~0u;
1066 int i;
1067 for (i=0; i < len; ++i)
1068 crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
1069 return ~crc;
1070 #endif
1071 }
1072
1073 #define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4)
1074 #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
1075 #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
1076
1077 static void stbiw__wpcrc(unsigned char **data, int len)
1078 {
1079 unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
1080 stbiw__wp32(*data, crc);
1081 }
1082
1083 static unsigned char stbiw__paeth(int a, int b, int c)
1084 {
1085 int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
1086 if (pa <= pb && pa <= pc) return STBIW_UCHAR(a);
1087 if (pb <= pc) return STBIW_UCHAR(b);
1088 return STBIW_UCHAR(c);
1089 }
1090
1091
1092 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)
1093 {
1094 static int mapping[] = { 0,1,2,3,4 };
1095 static int firstmap[] = { 0,1,0,5,6 };
1096 int *mymap = (y != 0) ? mapping : firstmap;
1097 int i;
1098 int type = mymap[filter_type];
1099 unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y);
1100 int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes;
1101
1102 if (type==0) {
1103 memcpy(line_buffer, z, width*n);
1104 return;
1105 }
1106
1107
1108 for (i = 0; i < n; ++i) {
1109 switch (type) {
1110 case 1: line_buffer[i] = z[i]; break;
1111 case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break;
1112 case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1); break;
1113 case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0)); break;
1114 case 5: line_buffer[i] = z[i]; break;
1115 case 6: line_buffer[i] = z[i]; break;
1116 }
1117 }
1118 switch (type) {
1119 case 1: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n]; break;
1120 case 2: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride]; break;
1121 case 3: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break;
1122 case 4: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]); break;
1123 case 5: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1); break;
1124 case 6: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
1125 }
1126 }
1127
1128 STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
1129 {
1130 int force_filter = stbi_write_force_png_filter;
1131 int ctype[5] = { -1, 0, 4, 2, 6 };
1132 unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
1133 unsigned char *out,*o, *filt, *zlib;
1134 signed char *line_buffer;
1135 int j,zlen;
1136
1137 if (stride_bytes == 0)
1138 stride_bytes = x * n;
1139
1140 if (force_filter >= 5) {
1141 force_filter = -1;
1142 }
1143
1144 filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
1145 line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
1146 for (j=0; j < y; ++j) {
1147 int filter_type;
1148 if (force_filter > -1) {
1149 filter_type = force_filter;
1150 stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer);
1151 } else {
1152 int best_filter = 0, best_filter_val = 0x7fffffff, est, i;
1153 for (filter_type = 0; filter_type < 5; filter_type++) {
1154 stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer);
1155
1156
1157 est = 0;
1158 for (i = 0; i < x*n; ++i) {
1159 est += abs((signed char) line_buffer[i]);
1160 }
1161 if (est < best_filter_val) {
1162 best_filter_val = est;
1163 best_filter = filter_type;
1164 }
1165 }
1166 if (filter_type != best_filter) {
1167 stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer);
1168 filter_type = best_filter;
1169 }
1170 }
1171
1172 filt[j*(x*n+1)] = (unsigned char) filter_type;
1173 STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
1174 }
1175 STBIW_FREE(line_buffer);
1176 zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_compression_level);
1177 STBIW_FREE(filt);
1178 if (!zlib) return 0;
1179
1180
1181 out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
1182 if (!out) return 0;
1183 *out_len = 8 + 12+13 + 12+zlen + 12;
1184
1185 o=out;
1186 STBIW_MEMMOVE(o,sig,8); o+= 8;
1187 stbiw__wp32(o, 13);
1188 stbiw__wptag(o, "IHDR");
1189 stbiw__wp32(o, x);
1190 stbiw__wp32(o, y);
1191 *o++ = 8;
1192 *o++ = STBIW_UCHAR(ctype[n]);
1193 *o++ = 0;
1194 *o++ = 0;
1195 *o++ = 0;
1196 stbiw__wpcrc(&o,13);
1197
1198 stbiw__wp32(o, zlen);
1199 stbiw__wptag(o, "IDAT");
1200 STBIW_MEMMOVE(o, zlib, zlen);
1201 o += zlen;
1202 STBIW_FREE(zlib);
1203 stbiw__wpcrc(&o, zlen);
1204
1205 stbiw__wp32(o,0);
1206 stbiw__wptag(o, "IEND");
1207 stbiw__wpcrc(&o,0);
1208
1209 STBIW_ASSERT(o == out + *out_len);
1210
1211 return out;
1212 }
1213
1214 #ifndef STBI_WRITE_NO_STDIO
1215 STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
1216 {
1217 FILE *f;
1218 int len;
1219 unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len);
1220 if (png == NULL) return 0;
1221
1222 f = stbiw__fopen(filename, "wb");
1223 if (!f) { STBIW_FREE(png); return 0; }
1224 fwrite(png, 1, len, f);
1225 fclose(f);
1226 STBIW_FREE(png);
1227 return 1;
1228 }
1229 #endif
1230
1231 STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes)
1232 {
1233 int len;
1234 unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len);
1235 if (png == NULL) return 0;
1236 func(context, png, len);
1237 STBIW_FREE(png);
1238 return 1;
1239 }
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250 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,
1251 24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 };
1252
1253 static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) {
1254 int bitBuf = *bitBufP, bitCnt = *bitCntP;
1255 bitCnt += bs[1];
1256 bitBuf |= bs[0] << (24 - bitCnt);
1257 while(bitCnt >= 8) {
1258 unsigned char c = (bitBuf >> 16) & 255;
1259 stbiw__putc(s, c);
1260 if(c == 255) {
1261 stbiw__putc(s, 0);
1262 }
1263 bitBuf <<= 8;
1264 bitCnt -= 8;
1265 }
1266 *bitBufP = bitBuf;
1267 *bitCntP = bitCnt;
1268 }
1269
1270 static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) {
1271 float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p;
1272 float z1, z2, z3, z4, z5, z11, z13;
1273
1274 float tmp0 = d0 + d7;
1275 float tmp7 = d0 - d7;
1276 float tmp1 = d1 + d6;
1277 float tmp6 = d1 - d6;
1278 float tmp2 = d2 + d5;
1279 float tmp5 = d2 - d5;
1280 float tmp3 = d3 + d4;
1281 float tmp4 = d3 - d4;
1282
1283
1284 float tmp10 = tmp0 + tmp3;
1285 float tmp13 = tmp0 - tmp3;
1286 float tmp11 = tmp1 + tmp2;
1287 float tmp12 = tmp1 - tmp2;
1288
1289 d0 = tmp10 + tmp11;
1290 d4 = tmp10 - tmp11;
1291
1292 z1 = (tmp12 + tmp13) * 0.707106781f;
1293 d2 = tmp13 + z1;
1294 d6 = tmp13 - z1;
1295
1296
1297 tmp10 = tmp4 + tmp5;
1298 tmp11 = tmp5 + tmp6;
1299 tmp12 = tmp6 + tmp7;
1300
1301
1302 z5 = (tmp10 - tmp12) * 0.382683433f;
1303 z2 = tmp10 * 0.541196100f + z5;
1304 z4 = tmp12 * 1.306562965f + z5;
1305 z3 = tmp11 * 0.707106781f;
1306
1307 z11 = tmp7 + z3;
1308 z13 = tmp7 - z3;
1309
1310 *d5p = z13 + z2;
1311 *d3p = z13 - z2;
1312 *d1p = z11 + z4;
1313 *d7p = z11 - z4;
1314
1315 *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6;
1316 }
1317
1318 static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) {
1319 int tmp1 = val < 0 ? -val : val;
1320 val = val < 0 ? val-1 : val;
1321 bits[1] = 1;
1322 while(tmp1 >>= 1) {
1323 ++bits[1];
1324 }
1325 bits[0] = val & ((1<<bits[1])-1);
1326 }
1327
1328 static int stbiw__jpg_processDU(stbi__write_context *s, int *bitBuf, int *bitCnt, float *CDU, int du_stride, float *fdtbl, int DC, const unsigned short HTDC[256][2], const unsigned short HTAC[256][2]) {
1329 const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
1330 const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
1331 int dataOff, i, j, n, diff, end0pos, x, y;
1332 int DU[64];
1333
1334
1335 for(dataOff=0, n=du_stride*8; dataOff<n; dataOff+=du_stride) {
1336 stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+1], &CDU[dataOff+2], &CDU[dataOff+3], &CDU[dataOff+4], &CDU[dataOff+5], &CDU[dataOff+6], &CDU[dataOff+7]);
1337 }
1338
1339 for(dataOff=0; dataOff<8; ++dataOff) {
1340 stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+du_stride], &CDU[dataOff+du_stride*2], &CDU[dataOff+du_stride*3], &CDU[dataOff+du_stride*4],
1341 &CDU[dataOff+du_stride*5], &CDU[dataOff+du_stride*6], &CDU[dataOff+du_stride*7]);
1342 }
1343
1344 for(y = 0, j=0; y < 8; ++y) {
1345 for(x = 0; x < 8; ++x,++j) {
1346 float v;
1347 i = y*du_stride+x;
1348 v = CDU[i]*fdtbl[j];
1349
1350
1351 DU[stbiw__jpg_ZigZag[j]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
1352 }
1353 }
1354
1355
1356 diff = DU[0] - DC;
1357 if (diff == 0) {
1358 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]);
1359 } else {
1360 unsigned short bits[2];
1361 stbiw__jpg_calcBits(diff, bits);
1362 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]);
1363 stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1364 }
1365
1366 end0pos = 63;
1367 for(; (end0pos>0)&&(DU[end0pos]==0); --end0pos) {
1368 }
1369
1370 if(end0pos == 0) {
1371 stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1372 return DU[0];
1373 }
1374 for(i = 1; i <= end0pos; ++i) {
1375 int startpos = i;
1376 int nrzeroes;
1377 unsigned short bits[2];
1378 for (; DU[i]==0 && i<=end0pos; ++i) {
1379 }
1380 nrzeroes = i-startpos;
1381 if ( nrzeroes >= 16 ) {
1382 int lng = nrzeroes>>4;
1383 int nrmarker;
1384 for (nrmarker=1; nrmarker <= lng; ++nrmarker)
1385 stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes);
1386 nrzeroes &= 15;
1387 }
1388 stbiw__jpg_calcBits(DU[i], bits);
1389 stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]);
1390 stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1391 }
1392 if(end0pos != 63) {
1393 stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1394 }
1395 return DU[0];
1396 }
1397
1398 static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) {
1399
1400 static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0};
1401 static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1402 static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d};
1403 static const unsigned char std_ac_luminance_values[] = {
1404 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
1405 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
1406 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
1407 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
1408 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
1409 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
1410 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1411 };
1412 static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0};
1413 static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1414 static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77};
1415 static const unsigned char std_ac_chrominance_values[] = {
1416 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
1417 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
1418 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
1419 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
1420 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
1421 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
1422 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1423 };
1424
1425 static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}};
1426 static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}};
1427 static const unsigned short YAC_HT[256][2] = {
1428 {10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1429 {12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1430 {28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1431 {58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1432 {59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1433 {122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1434 {123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1435 {250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1436 {504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1437 {505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1438 {506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1439 {1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1440 {1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1441 {2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1442 {65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0},
1443 {2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0}
1444 };
1445 static const unsigned short UVAC_HT[256][2] = {
1446 {0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1447 {11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1448 {26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1449 {27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1450 {58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1451 {59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1452 {121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1453 {122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1454 {249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1455 {503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1456 {504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1457 {505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1458 {506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1459 {2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0},
1460 {16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0},
1461 {1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0}
1462 };
1463 static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22,
1464 37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99};
1465 static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99,
1466 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99};
1467 static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
1468 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f };
1469
1470 int row, col, i, k, subsample;
1471 float fdtbl_Y[64], fdtbl_UV[64];
1472 unsigned char YTable[64], UVTable[64];
1473
1474 if(!data || !width || !height || comp > 4 || comp < 1) {
1475 return 0;
1476 }
1477
1478 quality = quality ? quality : 90;
1479 subsample = quality <= 90 ? 1 : 0;
1480 quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
1481 quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
1482
1483 for(i = 0; i < 64; ++i) {
1484 int uvti, yti = (YQT[i]*quality+50)/100;
1485 YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti);
1486 uvti = (UVQT[i]*quality+50)/100;
1487 UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti);
1488 }
1489
1490 for(row = 0, k = 0; row < 8; ++row) {
1491 for(col = 0; col < 8; ++col, ++k) {
1492 fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1493 fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1494 }
1495 }
1496
1497
1498 {
1499 static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 };
1500 static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
1501 const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width),
1502 3,1,(unsigned char)(subsample?0x22:0x11),0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
1503 s->func(s->context, (void*)head0, sizeof(head0));
1504 s->func(s->context, (void*)YTable, sizeof(YTable));
1505 stbiw__putc(s, 1);
1506 s->func(s->context, UVTable, sizeof(UVTable));
1507 s->func(s->context, (void*)head1, sizeof(head1));
1508 s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1);
1509 s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values));
1510 stbiw__putc(s, 0x10);
1511 s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1);
1512 s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values));
1513 stbiw__putc(s, 1);
1514 s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1);
1515 s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values));
1516 stbiw__putc(s, 0x11);
1517 s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1);
1518 s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values));
1519 s->func(s->context, (void*)head2, sizeof(head2));
1520 }
1521
1522
1523 {
1524 static const unsigned short fillBits[] = {0x7F, 7};
1525 int DCY=0, DCU=0, DCV=0;
1526 int bitBuf=0, bitCnt=0;
1527
1528 int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
1529 const unsigned char *dataR = (const unsigned char *)data;
1530 const unsigned char *dataG = dataR + ofsG;
1531 const unsigned char *dataB = dataR + ofsB;
1532 int x, y, pos;
1533 if(subsample) {
1534 for(y = 0; y < height; y += 16) {
1535 for(x = 0; x < width; x += 16) {
1536 float Y[256], U[256], V[256];
1537 for(row = y, pos = 0; row < y+16; ++row) {
1538
1539 int clamped_row = (row < height) ? row : height - 1;
1540 int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
1541 for(col = x; col < x+16; ++col, ++pos) {
1542
1543 int p = base_p + ((col < width) ? col : (width-1))*comp;
1544 float r = dataR[p], g = dataG[p], b = dataB[p];
1545 Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
1546 U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
1547 V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
1548 }
1549 }
1550 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+0, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1551 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+8, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1552 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1553 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1554
1555
1556 {
1557 float subU[64], subV[64];
1558 int yy, xx;
1559 for(yy = 0, pos = 0; yy < 8; ++yy) {
1560 for(xx = 0; xx < 8; ++xx, ++pos) {
1561 int j = yy*32+xx*2;
1562 subU[pos] = (U[j+0] + U[j+1] + U[j+16] + U[j+17]) * 0.25f;
1563 subV[pos] = (V[j+0] + V[j+1] + V[j+16] + V[j+17]) * 0.25f;
1564 }
1565 }
1566 DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
1567 DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
1568 }
1569 }
1570 }
1571 } else {
1572 for(y = 0; y < height; y += 8) {
1573 for(x = 0; x < width; x += 8) {
1574 float Y[64], U[64], V[64];
1575 for(row = y, pos = 0; row < y+8; ++row) {
1576
1577 int clamped_row = (row < height) ? row : height - 1;
1578 int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
1579 for(col = x; col < x+8; ++col, ++pos) {
1580
1581 int p = base_p + ((col < width) ? col : (width-1))*comp;
1582 float r = dataR[p], g = dataG[p], b = dataB[p];
1583 Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
1584 U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
1585 V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
1586 }
1587 }
1588
1589 DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1590 DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
1591 DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
1592 }
1593 }
1594 }
1595
1596
1597 stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits);
1598 }
1599
1600
1601 stbiw__putc(s, 0xFF);
1602 stbiw__putc(s, 0xD9);
1603
1604 return 1;
1605 }
1606
1607 STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)
1608 {
1609 stbi__write_context s = { 0 };
1610 stbi__start_write_callbacks(&s, func, context);
1611 return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality);
1612 }
1613
1614
1615 #ifndef STBI_WRITE_NO_STDIO
1616 STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
1617 {
1618 stbi__write_context s = { 0 };
1619 if (stbi__start_write_file(&s,filename)) {
1620 int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
1621 stbi__end_write_file(&s);
1622 return r;
1623 } else
1624 return 0;
1625 }
1626 #endif
1627
1628 #endif
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724