stb_image_write.h

   1#ifndef INCLUDE_STB_IMAGE_WRITE_H
   2#define INCLUDE_STB_IMAGE_WRITE_H
   3
   4#include <stdlib.h>
   5
   6#ifndef STBIWDEF
   7#ifdef STB_IMAGE_WRITE_STATIC
   8#define STBIWDEF  static
   9#else
  10#ifdef __cplusplus
  11#define STBIWDEF  extern "C"
  12#else
  13#define STBIWDEF  extern
  14#endif
  15#endif
  16#endif
  17
  18#ifndef STB_IMAGE_WRITE_STATIC
  19STBIWDEF int stbi_write_tga_with_rle;
  20STBIWDEF int stbi_write_png_compression_level;
  21STBIWDEF int stbi_write_force_png_filter;
  22#endif
  23
  24#ifndef STBI_WRITE_NO_STDIO
  25STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void  *data, int stride_in_bytes);
  26STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void  *data);
  27STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void  *data);
  28STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
  29STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void  *data, int quality);
  30
  31#ifdef STBIW_WINDOWS_UTF8
  32STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input);
  33#endif
  34#endif
  35
  36typedef void stbi_write_func(void *context, void *data, int size);
  37
  38STBIWDEF 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);
  39STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
  40STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
  41STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
  42STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void  *data, int quality);
  43
  44STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean);
  45
  46#endif
  47
  48#ifdef STB_IMAGE_WRITE_IMPLEMENTATION
  49
  50#ifdef _WIN32
  51   #ifndef _CRT_SECURE_NO_WARNINGS
  52   #define _CRT_SECURE_NO_WARNINGS
  53   #endif
  54   #ifndef _CRT_NONSTDC_NO_DEPRECATE
  55   #define _CRT_NONSTDC_NO_DEPRECATE
  56   #endif
  57#endif
  58
  59#ifndef STBI_WRITE_NO_STDIO
  60#include <stdio.h>
  61#endif
  62
  63#include <stdarg.h>
  64#include <stdlib.h>
  65#include <string.h>
  66#include <math.h>
  67
  68#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED))
  69
  70#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED)
  71
  72#else
  73#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)."
  74#endif
  75
  76#ifndef STBIW_MALLOC
  77#define STBIW_MALLOC(sz)        malloc(sz)
  78#define STBIW_REALLOC(p,newsz)  realloc(p,newsz)
  79#define STBIW_FREE(p)           free(p)
  80#endif
  81
  82#ifndef STBIW_REALLOC_SIZED
  83#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz)
  84#endif
  85
  86#ifndef STBIW_MEMMOVE
  87#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
  88#endif
  89
  90#ifndef STBIW_ASSERT
  91#include <assert.h>
  92#define STBIW_ASSERT(x) assert(x)
  93#endif
  94
  95#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
  96
  97#ifdef STB_IMAGE_WRITE_STATIC
  98static int stbi_write_png_compression_level = 8;
  99static int stbi_write_tga_with_rle = 1;
 100static int stbi_write_force_png_filter = -1;
 101#else
 102int stbi_write_png_compression_level = 8;
 103int stbi_write_tga_with_rle = 1;
 104int stbi_write_force_png_filter = -1;
 105#endif
 106
 107static int stbi__flip_vertically_on_write = 0;
 108
 109STBIWDEF void stbi_flip_vertically_on_write(int flag)
 110{
 111   stbi__flip_vertically_on_write = flag;
 112}
 113
 114typedef struct
 115{
 116   stbi_write_func *func;
 117   void *context;
 118   unsigned char buffer[64];
 119   int buf_used;
 120} stbi__write_context;
 121
 122static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context)
 123{
 124   s->func    = c;
 125   s->context = context;
 126}
 127
 128#ifndef STBI_WRITE_NO_STDIO
 129
 130static void stbi__stdio_write(void *context, void *data, int size)
 131{
 132   fwrite(data,1,size,(FILE*) context);
 133}
 134
 135#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
 136#ifdef __cplusplus
 137#define STBIW_EXTERN extern "C"
 138#else
 139#define STBIW_EXTERN extern
 140#endif
 141STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide);
 142STBIW_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);
 143
 144STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input)
 145{
 146   return WideCharToMultiByte(65001 , 0, input, -1, buffer, (int) bufferlen, NULL, NULL);
 147}
 148#endif
 149
 150static FILE *stbiw__fopen(char const *filename, char const *mode)
 151{
 152   FILE *f;
 153#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8)
 154   wchar_t wMode[64];
 155   wchar_t wFilename[1024];
 156   if (0 == MultiByteToWideChar(65001 , 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename)))
 157      return 0;
 158
 159   if (0 == MultiByteToWideChar(65001 , 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode)))
 160      return 0;
 161
 162#if defined(_MSC_VER) && _MSC_VER >= 1400
 163   if (0 != _wfopen_s(&f, wFilename, wMode))
 164      f = 0;
 165#else
 166   f = _wfopen(wFilename, wMode);
 167#endif
 168
 169#elif defined(_MSC_VER) && _MSC_VER >= 1400
 170   if (0 != fopen_s(&f, filename, mode))
 171      f=0;
 172#else
 173   f = fopen(filename, mode);
 174#endif
 175   return f;
 176}
 177
 178static int stbi__start_write_file(stbi__write_context *s, const char *filename)
 179{
 180   FILE *f = stbiw__fopen(filename, "wb");
 181   stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f);
 182   return f != NULL;
 183}
 184
 185static void stbi__end_write_file(stbi__write_context *s)
 186{
 187   fclose((FILE *)s->context);
 188}
 189
 190#endif
 191
 192typedef unsigned int stbiw_uint32;
 193typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
 194
 195static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v)
 196{
 197   while (*fmt) {
 198      switch (*fmt++) {
 199         case ' ': break;
 200         case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int));
 201                     s->func(s->context,&x,1);
 202                     break; }
 203         case '2': { int x = va_arg(v,int);
 204                     unsigned char b[2];
 205                     b[0] = STBIW_UCHAR(x);
 206                     b[1] = STBIW_UCHAR(x>>8);
 207                     s->func(s->context,b,2);
 208                     break; }
 209         case '4': { stbiw_uint32 x = va_arg(v,int);
 210                     unsigned char b[4];
 211                     b[0]=STBIW_UCHAR(x);
 212                     b[1]=STBIW_UCHAR(x>>8);
 213                     b[2]=STBIW_UCHAR(x>>16);
 214                     b[3]=STBIW_UCHAR(x>>24);
 215                     s->func(s->context,b,4);
 216                     break; }
 217         default:
 218            STBIW_ASSERT(0);
 219            return;
 220      }
 221   }
 222}
 223
 224static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
 225{
 226   va_list v;
 227   va_start(v, fmt);
 228   stbiw__writefv(s, fmt, v);
 229   va_end(v);
 230}
 231
 232static void stbiw__write_flush(stbi__write_context *s)
 233{
 234   if (s->buf_used) {
 235      s->func(s->context, &s->buffer, s->buf_used);
 236      s->buf_used = 0;
 237   }
 238}
 239
 240static void stbiw__putc(stbi__write_context *s, unsigned char c)
 241{
 242   s->func(s->context, &c, 1);
 243}
 244
 245static void stbiw__write1(stbi__write_context *s, unsigned char a)
 246{
 247   if ((size_t)s->buf_used + 1 > sizeof(s->buffer))
 248      stbiw__write_flush(s);
 249   s->buffer[s->buf_used++] = a;
 250}
 251
 252static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
 253{
 254   int n;
 255   if ((size_t)s->buf_used + 3 > sizeof(s->buffer))
 256      stbiw__write_flush(s);
 257   n = s->buf_used;
 258   s->buf_used = n+3;
 259   s->buffer[n+0] = a;
 260   s->buffer[n+1] = b;
 261   s->buffer[n+2] = c;
 262}
 263
 264static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
 265{
 266   unsigned char bg[3] = { 255, 0, 255}, px[3];
 267   int k;
 268
 269   if (write_alpha < 0)
 270      stbiw__write1(s, d[comp - 1]);
 271
 272   switch (comp) {
 273      case 2:
 274      case 1:
 275         if (expand_mono)
 276            stbiw__write3(s, d[0], d[0], d[0]);
 277         else
 278            stbiw__write1(s, d[0]);
 279         break;
 280      case 4:
 281         if (!write_alpha) {
 282
 283            for (k = 0; k < 3; ++k)
 284               px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
 285            stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]);
 286            break;
 287         }
 288
 289      case 3:
 290         stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
 291         break;
 292   }
 293   if (write_alpha > 0)
 294      stbiw__write1(s, d[comp - 1]);
 295}
 296
 297static 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)
 298{
 299   stbiw_uint32 zero = 0;
 300   int i,j, j_end;
 301
 302   if (y <= 0)
 303      return;
 304
 305   if (stbi__flip_vertically_on_write)
 306      vdir *= -1;
 307
 308   if (vdir < 0) {
 309      j_end = -1; j = y-1;
 310   } else {
 311      j_end =  y; j = 0;
 312   }
 313
 314   for (; j != j_end; j += vdir) {
 315      for (i=0; i < x; ++i) {
 316         unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
 317         stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
 318      }
 319      stbiw__write_flush(s);
 320      s->func(s->context, &zero, scanline_pad);
 321   }
 322}
 323
 324static 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, ...)
 325{
 326   if (y < 0 || x < 0) {
 327      return 0;
 328   } else {
 329      va_list v;
 330      va_start(v, fmt);
 331      stbiw__writefv(s, fmt, v);
 332      va_end(v);
 333      stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono);
 334      return 1;
 335   }
 336}
 337
 338static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
 339{
 340   if (comp != 4) {
 341
 342      int pad = (-x*3) & 3;
 343      return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
 344              "11 4 22 4" "4 44 22 444444",
 345              'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40,
 346               40, x,y, 1,24, 0,0,0,0,0,0);
 347   } else {
 348
 349      return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *)data,1,0,
 350         "11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444",
 351         'B', 'M', 14+108+x*y*4, 0, 0, 14+108,
 352         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);
 353   }
 354}
 355
 356STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
 357{
 358   stbi__write_context s = { 0 };
 359   stbi__start_write_callbacks(&s, func, context);
 360   return stbi_write_bmp_core(&s, x, y, comp, data);
 361}
 362
 363#ifndef STBI_WRITE_NO_STDIO
 364STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
 365{
 366   stbi__write_context s = { 0 };
 367   if (stbi__start_write_file(&s,filename)) {
 368      int r = stbi_write_bmp_core(&s, x, y, comp, data);
 369      stbi__end_write_file(&s);
 370      return r;
 371   } else
 372      return 0;
 373}
 374#endif
 375
 376static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data)
 377{
 378   int has_alpha = (comp == 2 || comp == 4);
 379   int colorbytes = has_alpha ? comp-1 : comp;
 380   int format = colorbytes < 2 ? 3 : 2;
 381
 382   if (y < 0 || x < 0)
 383      return 0;
 384
 385   if (!stbi_write_tga_with_rle) {
 386      return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0,
 387         "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
 388   } else {
 389      int i,j,k;
 390      int jend, jdir;
 391
 392      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);
 393
 394      if (stbi__flip_vertically_on_write) {
 395         j = 0;
 396         jend = y;
 397         jdir = 1;
 398      } else {
 399         j = y-1;
 400         jend = -1;
 401         jdir = -1;
 402      }
 403      for (; j != jend; j += jdir) {
 404         unsigned char *row = (unsigned char *) data + j * x * comp;
 405         int len;
 406
 407         for (i = 0; i < x; i += len) {
 408            unsigned char *begin = row + i * comp;
 409            int diff = 1;
 410            len = 1;
 411
 412            if (i < x - 1) {
 413               ++len;
 414               diff = memcmp(begin, row + (i + 1) * comp, comp);
 415               if (diff) {
 416                  const unsigned char *prev = begin;
 417                  for (k = i + 2; k < x && len < 128; ++k) {
 418                     if (memcmp(prev, row + k * comp, comp)) {
 419                        prev += comp;
 420                        ++len;
 421                     } else {
 422                        --len;
 423                        break;
 424                     }
 425                  }
 426               } else {
 427                  for (k = i + 2; k < x && len < 128; ++k) {
 428                     if (!memcmp(begin, row + k * comp, comp)) {
 429                        ++len;
 430                     } else {
 431                        break;
 432                     }
 433                  }
 434               }
 435            }
 436
 437            if (diff) {
 438               unsigned char header = STBIW_UCHAR(len - 1);
 439               stbiw__write1(s, header);
 440               for (k = 0; k < len; ++k) {
 441                  stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
 442               }
 443            } else {
 444               unsigned char header = STBIW_UCHAR(len - 129);
 445               stbiw__write1(s, header);
 446               stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
 447            }
 448         }
 449      }
 450      stbiw__write_flush(s);
 451   }
 452   return 1;
 453}
 454
 455STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
 456{
 457   stbi__write_context s = { 0 };
 458   stbi__start_write_callbacks(&s, func, context);
 459   return stbi_write_tga_core(&s, x, y, comp, (void *) data);
 460}
 461
 462#ifndef STBI_WRITE_NO_STDIO
 463STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
 464{
 465   stbi__write_context s = { 0 };
 466   if (stbi__start_write_file(&s,filename)) {
 467      int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
 468      stbi__end_write_file(&s);
 469      return r;
 470   } else
 471      return 0;
 472}
 473#endif
 474
 475#define stbiw__max(a, b)  ((a) > (b) ? (a) : (b))
 476
 477#ifndef STBI_WRITE_NO_STDIO
 478
 479static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
 480{
 481   int exponent;
 482   float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
 483
 484   if (maxcomp < 1e-32f) {
 485      rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
 486   } else {
 487      float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
 488
 489      rgbe[0] = (unsigned char)(linear[0] * normalize);
 490      rgbe[1] = (unsigned char)(linear[1] * normalize);
 491      rgbe[2] = (unsigned char)(linear[2] * normalize);
 492      rgbe[3] = (unsigned char)(exponent + 128);
 493   }
 494}
 495
 496static void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
 497{
 498   unsigned char lengthbyte = STBIW_UCHAR(length+128);
 499   STBIW_ASSERT(length+128 <= 255);
 500   s->func(s->context, &lengthbyte, 1);
 501   s->func(s->context, &databyte, 1);
 502}
 503
 504static void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
 505{
 506   unsigned char lengthbyte = STBIW_UCHAR(length);
 507   STBIW_ASSERT(length <= 128);
 508   s->func(s->context, &lengthbyte, 1);
 509   s->func(s->context, data, length);
 510}
 511
 512static void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline)
 513{
 514   unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
 515   unsigned char rgbe[4];
 516   float linear[3];
 517   int x;
 518
 519   scanlineheader[2] = (width&0xff00)>>8;
 520   scanlineheader[3] = (width&0x00ff);
 521
 522   if (width < 8 || width >= 32768) {
 523      for (x=0; x < width; x++) {
 524         switch (ncomp) {
 525            case 4:
 526            case 3: linear[2] = scanline[x*ncomp + 2];
 527                    linear[1] = scanline[x*ncomp + 1];
 528                    linear[0] = scanline[x*ncomp + 0];
 529                    break;
 530            default:
 531                    linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
 532                    break;
 533         }
 534         stbiw__linear_to_rgbe(rgbe, linear);
 535         s->func(s->context, rgbe, 4);
 536      }
 537   } else {
 538      int c,r;
 539
 540      for (x=0; x < width; x++) {
 541         switch(ncomp) {
 542            case 4:
 543            case 3: linear[2] = scanline[x*ncomp + 2];
 544                    linear[1] = scanline[x*ncomp + 1];
 545                    linear[0] = scanline[x*ncomp + 0];
 546                    break;
 547            default:
 548                    linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
 549                    break;
 550         }
 551         stbiw__linear_to_rgbe(rgbe, linear);
 552         scratch[x + width*0] = rgbe[0];
 553         scratch[x + width*1] = rgbe[1];
 554         scratch[x + width*2] = rgbe[2];
 555         scratch[x + width*3] = rgbe[3];
 556      }
 557
 558      s->func(s->context, scanlineheader, 4);
 559
 560      for (c=0; c < 4; c++) {
 561         unsigned char *comp = &scratch[width*c];
 562
 563         x = 0;
 564         while (x < width) {
 565
 566            r = x;
 567            while (r+2 < width) {
 568               if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
 569                  break;
 570               ++r;
 571            }
 572            if (r+2 >= width)
 573               r = width;
 574
 575            while (x < r) {
 576               int len = r-x;
 577               if (len > 128) len = 128;
 578               stbiw__write_dump_data(s, len, &comp[x]);
 579               x += len;
 580            }
 581
 582            if (r+2 < width) {
 583
 584               while (r < width && comp[r] == comp[x])
 585                  ++r;
 586
 587               while (x < r) {
 588                  int len = r-x;
 589                  if (len > 127) len = 127;
 590                  stbiw__write_run_data(s, len, comp[x]);
 591                  x += len;
 592               }
 593            }
 594         }
 595      }
 596   }
 597}
 598
 599static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data)
 600{
 601   if (y <= 0 || x <= 0 || data == NULL)
 602      return 0;
 603   else {
 604
 605      unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
 606      int i, len;
 607      char buffer[128];
 608      char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
 609      s->func(s->context, header, sizeof(header)-1);
 610
 611#ifdef __STDC_LIB_EXT1__
 612      len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE=          1.0000000000000\n\n-Y %d +X %d\n", y, x);
 613#else
 614      len = sprintf(buffer, "EXPOSURE=          1.0000000000000\n\n-Y %d +X %d\n", y, x);
 615#endif
 616      s->func(s->context, buffer, len);
 617
 618      for(i=0; i < y; i++)
 619         stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i));
 620      STBIW_FREE(scratch);
 621      return 1;
 622   }
 623}
 624
 625STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
 626{
 627   stbi__write_context s = { 0 };
 628   stbi__start_write_callbacks(&s, func, context);
 629   return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
 630}
 631
 632STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
 633{
 634   stbi__write_context s = { 0 };
 635   if (stbi__start_write_file(&s,filename)) {
 636      int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
 637      stbi__end_write_file(&s);
 638      return r;
 639   } else
 640      return 0;
 641}
 642#endif
 643
 644#ifndef STBIW_ZLIB_COMPRESS
 645
 646#define stbiw__sbraw(a) ((int *) (void *) (a) - 2)
 647#define stbiw__sbm(a)   stbiw__sbraw(a)[0]
 648#define stbiw__sbn(a)   stbiw__sbraw(a)[1]
 649
 650#define stbiw__sbneedgrow(a,n)  ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
 651#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
 652#define stbiw__sbgrow(a,n)  stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
 653
 654#define stbiw__sbpush(a, v)      (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
 655#define stbiw__sbcount(a)        ((a) ? stbiw__sbn(a) : 0)
 656#define stbiw__sbfree(a)         ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
 657
 658static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
 659{
 660   int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
 661   void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2);
 662   STBIW_ASSERT(p);
 663   if (p) {
 664      if (!*arr) ((int *) p)[1] = 0;
 665      *arr = (void *) ((int *) p + 2);
 666      stbiw__sbm(*arr) = m;
 667   }
 668   return *arr;
 669}
 670
 671static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
 672{
 673   while (*bitcount >= 8) {
 674      stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
 675      *bitbuffer >>= 8;
 676      *bitcount -= 8;
 677   }
 678   return data;
 679}
 680
 681static int stbiw__zlib_bitrev(int code, int codebits)
 682{
 683   int res=0;
 684   while (codebits--) {
 685      res = (res << 1) | (code & 1);
 686      code >>= 1;
 687   }
 688   return res;
 689}
 690
 691static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit)
 692{
 693   int i;
 694   for (i=0; i < limit && i < 258; ++i)
 695      if (a[i] != b[i]) break;
 696   return i;
 697}
 698
 699static unsigned int stbiw__zhash(unsigned char *data)
 700{
 701   stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
 702   hash ^= hash << 3;
 703   hash += hash >> 5;
 704   hash ^= hash << 4;
 705   hash += hash >> 17;
 706   hash ^= hash << 25;
 707   hash += hash >> 6;
 708   return hash;
 709}
 710
 711#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
 712#define stbiw__zlib_add(code,codebits) \
 713      (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
 714#define stbiw__zlib_huffa(b,c)  stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
 715
 716#define stbiw__zlib_huff1(n)  stbiw__zlib_huffa(0x30 + (n), 8)
 717#define stbiw__zlib_huff2(n)  stbiw__zlib_huffa(0x190 + (n)-144, 9)
 718#define stbiw__zlib_huff3(n)  stbiw__zlib_huffa(0 + (n)-256,7)
 719#define stbiw__zlib_huff4(n)  stbiw__zlib_huffa(0xc0 + (n)-280,8)
 720#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))
 721#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
 722
 723#define stbiw__ZHASH   16384
 724
 725#endif
 726
 727STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
 728{
 729#ifdef STBIW_ZLIB_COMPRESS
 730
 731   return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality);
 732#else
 733   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 };
 734   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 };
 735   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 };
 736   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 };
 737   unsigned int bitbuf=0;
 738   int i,j, bitcount=0;
 739   unsigned char *out = NULL;
 740   unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(unsigned char**));
 741   if (hash_table == NULL)
 742      return NULL;
 743   if (quality < 5) quality = 5;
 744
 745   stbiw__sbpush(out, 0x78);
 746   stbiw__sbpush(out, 0x5e);
 747   stbiw__zlib_add(1,1);
 748   stbiw__zlib_add(1,2);
 749
 750   for (i=0; i < stbiw__ZHASH; ++i)
 751      hash_table[i] = NULL;
 752
 753   i=0;
 754   while (i < data_len-3) {
 755
 756      int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
 757      unsigned char *bestloc = 0;
 758      unsigned char **hlist = hash_table[h];
 759      int n = stbiw__sbcount(hlist);
 760      for (j=0; j < n; ++j) {
 761         if (hlist[j]-data > i-32768) {
 762            int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
 763            if (d >= best) { best=d; bestloc=hlist[j]; }
 764         }
 765      }
 766
 767      if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
 768         STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
 769         stbiw__sbn(hash_table[h]) = quality;
 770      }
 771      stbiw__sbpush(hash_table[h],data+i);
 772
 773      if (bestloc) {
 774
 775         h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
 776         hlist = hash_table[h];
 777         n = stbiw__sbcount(hlist);
 778         for (j=0; j < n; ++j) {
 779            if (hlist[j]-data > i-32767) {
 780               int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
 781               if (e > best) {
 782                  bestloc = NULL;
 783                  break;
 784               }
 785            }
 786         }
 787      }
 788
 789      if (bestloc) {
 790         int d = (int) (data+i - bestloc);
 791         STBIW_ASSERT(d <= 32767 && best <= 258);
 792         for (j=0; best > lengthc[j+1]-1; ++j);
 793         stbiw__zlib_huff(j+257);
 794         if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
 795         for (j=0; d > distc[j+1]-1; ++j);
 796         stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
 797         if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
 798         i += best;
 799      } else {
 800         stbiw__zlib_huffb(data[i]);
 801         ++i;
 802      }
 803   }
 804
 805   for (;i < data_len; ++i)
 806      stbiw__zlib_huffb(data[i]);
 807   stbiw__zlib_huff(256);
 808
 809   while (bitcount)
 810      stbiw__zlib_add(0,1);
 811
 812   for (i=0; i < stbiw__ZHASH; ++i)
 813      (void) stbiw__sbfree(hash_table[i]);
 814   STBIW_FREE(hash_table);
 815
 816   if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) {
 817      stbiw__sbn(out) = 2;
 818      for (j = 0; j < data_len;) {
 819         int blocklen = data_len - j;
 820         if (blocklen > 32767) blocklen = 32767;
 821         stbiw__sbpush(out, data_len - j == blocklen);
 822         stbiw__sbpush(out, STBIW_UCHAR(blocklen));
 823         stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8));
 824         stbiw__sbpush(out, STBIW_UCHAR(~blocklen));
 825         stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8));
 826         memcpy(out+stbiw__sbn(out), data+j, blocklen);
 827         stbiw__sbn(out) += blocklen;
 828         j += blocklen;
 829      }
 830   }
 831
 832   {
 833
 834      unsigned int s1=1, s2=0;
 835      int blocklen = (int) (data_len % 5552);
 836      j=0;
 837      while (j < data_len) {
 838         for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; }
 839         s1 %= 65521; s2 %= 65521;
 840         j += blocklen;
 841         blocklen = 5552;
 842      }
 843      stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
 844      stbiw__sbpush(out, STBIW_UCHAR(s2));
 845      stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
 846      stbiw__sbpush(out, STBIW_UCHAR(s1));
 847   }
 848   *out_len = stbiw__sbn(out);
 849
 850   STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
 851   return (unsigned char *) stbiw__sbraw(out);
 852#endif
 853}
 854
 855static unsigned int stbiw__crc32(unsigned char *buffer, int len)
 856{
 857#ifdef STBIW_CRC32
 858    return STBIW_CRC32(buffer, len);
 859#else
 860   static unsigned int crc_table[256] =
 861   {
 862      0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
 863      0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
 864      0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
 865      0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
 866      0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
 867      0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
 868      0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
 869      0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
 870      0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
 871      0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
 872      0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
 873      0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
 874      0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
 875      0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
 876      0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
 877      0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
 878      0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
 879      0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
 880      0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
 881      0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
 882      0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
 883      0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
 884      0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
 885      0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
 886      0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
 887      0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
 888      0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
 889      0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
 890      0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
 891      0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
 892      0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
 893      0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
 894   };
 895
 896   unsigned int crc = ~0u;
 897   int i;
 898   for (i=0; i < len; ++i)
 899      crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
 900   return ~crc;
 901#endif
 902}
 903
 904#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)
 905#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
 906#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
 907
 908static void stbiw__wpcrc(unsigned char **data, int len)
 909{
 910   unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
 911   stbiw__wp32(*data, crc);
 912}
 913
 914static unsigned char stbiw__paeth(int a, int b, int c)
 915{
 916   int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
 917   if (pa <= pb && pa <= pc) return STBIW_UCHAR(a);
 918   if (pb <= pc) return STBIW_UCHAR(b);
 919   return STBIW_UCHAR(c);
 920}
 921
 922static 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)
 923{
 924   static int mapping[] = { 0,1,2,3,4 };
 925   static int firstmap[] = { 0,1,0,5,6 };
 926   int *mymap = (y != 0) ? mapping : firstmap;
 927   int i;
 928   int type = mymap[filter_type];
 929   unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y);
 930   int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes;
 931
 932   if (type==0) {
 933      memcpy(line_buffer, z, width*n);
 934      return;
 935   }
 936
 937   for (i = 0; i < n; ++i) {
 938      switch (type) {
 939         case 1: line_buffer[i] = z[i]; break;
 940         case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break;
 941         case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1); break;
 942         case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0)); break;
 943         case 5: line_buffer[i] = z[i]; break;
 944         case 6: line_buffer[i] = z[i]; break;
 945      }
 946   }
 947   switch (type) {
 948      case 1: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n]; break;
 949      case 2: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride]; break;
 950      case 3: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break;
 951      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;
 952      case 5: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1); break;
 953      case 6: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
 954   }
 955}
 956
 957STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
 958{
 959   int force_filter = stbi_write_force_png_filter;
 960   int ctype[5] = { -1, 0, 4, 2, 6 };
 961   unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
 962   unsigned char *out,*o, *filt, *zlib;
 963   signed char *line_buffer;
 964   int j,zlen;
 965
 966   if (stride_bytes == 0)
 967      stride_bytes = x * n;
 968
 969   if (force_filter >= 5) {
 970      force_filter = -1;
 971   }
 972
 973   filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
 974   line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
 975   for (j=0; j < y; ++j) {
 976      int filter_type;
 977      if (force_filter > -1) {
 978         filter_type = force_filter;
 979         stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer);
 980      } else {
 981         int best_filter = 0, best_filter_val = 0x7fffffff, est, i;
 982         for (filter_type = 0; filter_type < 5; filter_type++) {
 983            stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer);
 984
 985            est = 0;
 986            for (i = 0; i < x*n; ++i) {
 987               est += abs((signed char) line_buffer[i]);
 988            }
 989            if (est < best_filter_val) {
 990               best_filter_val = est;
 991               best_filter = filter_type;
 992            }
 993         }
 994         if (filter_type != best_filter) {
 995            stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer);
 996            filter_type = best_filter;
 997         }
 998      }
 999
1000      filt[j*(x*n+1)] = (unsigned char) filter_type;
1001      STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
1002   }
1003   STBIW_FREE(line_buffer);
1004   zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_compression_level);
1005   STBIW_FREE(filt);
1006   if (!zlib) return 0;
1007
1008   out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
1009   if (!out) return 0;
1010   *out_len = 8 + 12+13 + 12+zlen + 12;
1011
1012   o=out;
1013   STBIW_MEMMOVE(o,sig,8); o+= 8;
1014   stbiw__wp32(o, 13);
1015   stbiw__wptag(o, "IHDR");
1016   stbiw__wp32(o, x);
1017   stbiw__wp32(o, y);
1018   *o++ = 8;
1019   *o++ = STBIW_UCHAR(ctype[n]);
1020   *o++ = 0;
1021   *o++ = 0;
1022   *o++ = 0;
1023   stbiw__wpcrc(&o,13);
1024
1025   stbiw__wp32(o, zlen);
1026   stbiw__wptag(o, "IDAT");
1027   STBIW_MEMMOVE(o, zlib, zlen);
1028   o += zlen;
1029   STBIW_FREE(zlib);
1030   stbiw__wpcrc(&o, zlen);
1031
1032   stbiw__wp32(o,0);
1033   stbiw__wptag(o, "IEND");
1034   stbiw__wpcrc(&o,0);
1035
1036   STBIW_ASSERT(o == out + *out_len);
1037
1038   return out;
1039}
1040
1041#ifndef STBI_WRITE_NO_STDIO
1042STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
1043{
1044   FILE *f;
1045   int len;
1046   unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len);
1047   if (png == NULL) return 0;
1048
1049   f = stbiw__fopen(filename, "wb");
1050   if (!f) { STBIW_FREE(png); return 0; }
1051   fwrite(png, 1, len, f);
1052   fclose(f);
1053   STBIW_FREE(png);
1054   return 1;
1055}
1056#endif
1057
1058STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes)
1059{
1060   int len;
1061   unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len);
1062   if (png == NULL) return 0;
1063   func(context, png, len);
1064   STBIW_FREE(png);
1065   return 1;
1066}
1067
1068static 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,
1069      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 };
1070
1071static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) {
1072   int bitBuf = *bitBufP, bitCnt = *bitCntP;
1073   bitCnt += bs[1];
1074   bitBuf |= bs[0] << (24 - bitCnt);
1075   while(bitCnt >= 8) {
1076      unsigned char c = (bitBuf >> 16) & 255;
1077      stbiw__putc(s, c);
1078      if(c == 255) {
1079         stbiw__putc(s, 0);
1080      }
1081      bitBuf <<= 8;
1082      bitCnt -= 8;
1083   }
1084   *bitBufP = bitBuf;
1085   *bitCntP = bitCnt;
1086}
1087
1088static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) {
1089   float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p;
1090   float z1, z2, z3, z4, z5, z11, z13;
1091
1092   float tmp0 = d0 + d7;
1093   float tmp7 = d0 - d7;
1094   float tmp1 = d1 + d6;
1095   float tmp6 = d1 - d6;
1096   float tmp2 = d2 + d5;
1097   float tmp5 = d2 - d5;
1098   float tmp3 = d3 + d4;
1099   float tmp4 = d3 - d4;
1100
1101   float tmp10 = tmp0 + tmp3;
1102   float tmp13 = tmp0 - tmp3;
1103   float tmp11 = tmp1 + tmp2;
1104   float tmp12 = tmp1 - tmp2;
1105
1106   d0 = tmp10 + tmp11;
1107   d4 = tmp10 - tmp11;
1108
1109   z1 = (tmp12 + tmp13) * 0.707106781f;
1110   d2 = tmp13 + z1;
1111   d6 = tmp13 - z1;
1112
1113   tmp10 = tmp4 + tmp5;
1114   tmp11 = tmp5 + tmp6;
1115   tmp12 = tmp6 + tmp7;
1116
1117   z5 = (tmp10 - tmp12) * 0.382683433f;
1118   z2 = tmp10 * 0.541196100f + z5;
1119   z4 = tmp12 * 1.306562965f + z5;
1120   z3 = tmp11 * 0.707106781f;
1121
1122   z11 = tmp7 + z3;
1123   z13 = tmp7 - z3;
1124
1125   *d5p = z13 + z2;
1126   *d3p = z13 - z2;
1127   *d1p = z11 + z4;
1128   *d7p = z11 - z4;
1129
1130   *d0p = d0;  *d2p = d2;  *d4p = d4;  *d6p = d6;
1131}
1132
1133static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) {
1134   int tmp1 = val < 0 ? -val : val;
1135   val = val < 0 ? val-1 : val;
1136   bits[1] = 1;
1137   while(tmp1 >>= 1) {
1138      ++bits[1];
1139   }
1140   bits[0] = val & ((1<<bits[1])-1);
1141}
1142
1143static 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]) {
1144   const unsigned short EOB[2] = { HTAC[0x00][0], HTAC[0x00][1] };
1145   const unsigned short M16zeroes[2] = { HTAC[0xF0][0], HTAC[0xF0][1] };
1146   int dataOff, i, j, n, diff, end0pos, x, y;
1147   int DU[64];
1148
1149   for(dataOff=0, n=du_stride*8; dataOff<n; dataOff+=du_stride) {
1150      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]);
1151   }
1152
1153   for(dataOff=0; dataOff<8; ++dataOff) {
1154      stbiw__jpg_DCT(&CDU[dataOff], &CDU[dataOff+du_stride], &CDU[dataOff+du_stride*2], &CDU[dataOff+du_stride*3], &CDU[dataOff+du_stride*4],
1155                     &CDU[dataOff+du_stride*5], &CDU[dataOff+du_stride*6], &CDU[dataOff+du_stride*7]);
1156   }
1157
1158   for(y = 0, j=0; y < 8; ++y) {
1159      for(x = 0; x < 8; ++x,++j) {
1160         float v;
1161         i = y*du_stride+x;
1162         v = CDU[i]*fdtbl[j];
1163
1164         DU[stbiw__jpg_ZigZag[j]] = (int)(v < 0 ? v - 0.5f : v + 0.5f);
1165      }
1166   }
1167
1168   diff = DU[0] - DC;
1169   if (diff == 0) {
1170      stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[0]);
1171   } else {
1172      unsigned short bits[2];
1173      stbiw__jpg_calcBits(diff, bits);
1174      stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTDC[bits[1]]);
1175      stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1176   }
1177
1178   end0pos = 63;
1179   for(; (end0pos>0)&&(DU[end0pos]==0); --end0pos) {
1180   }
1181
1182   if(end0pos == 0) {
1183      stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1184      return DU[0];
1185   }
1186   for(i = 1; i <= end0pos; ++i) {
1187      int startpos = i;
1188      int nrzeroes;
1189      unsigned short bits[2];
1190      for (; DU[i]==0 && i<=end0pos; ++i) {
1191      }
1192      nrzeroes = i-startpos;
1193      if ( nrzeroes >= 16 ) {
1194         int lng = nrzeroes>>4;
1195         int nrmarker;
1196         for (nrmarker=1; nrmarker <= lng; ++nrmarker)
1197            stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes);
1198         nrzeroes &= 15;
1199      }
1200      stbiw__jpg_calcBits(DU[i], bits);
1201      stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]);
1202      stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits);
1203   }
1204   if(end0pos != 63) {
1205      stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB);
1206   }
1207   return DU[0];
1208}
1209
1210static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) {
1211
1212   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};
1213   static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1214   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};
1215   static const unsigned char std_ac_luminance_values[] = {
1216      0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,
1217      0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,
1218      0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,
1219      0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,
1220      0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,
1221      0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,
1222      0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1223   };
1224   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};
1225   static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11};
1226   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};
1227   static const unsigned char std_ac_chrominance_values[] = {
1228      0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,
1229      0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,
1230      0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,
1231      0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,
1232      0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,
1233      0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,
1234      0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa
1235   };
1236
1237   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}};
1238   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}};
1239   static const unsigned short YAC_HT[256][2] = {
1240      {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},
1241      {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},
1242      {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},
1243      {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},
1244      {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},
1245      {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},
1246      {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},
1247      {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},
1248      {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},
1249      {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},
1250      {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},
1251      {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},
1252      {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},
1253      {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},
1254      {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},
1255      {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}
1256   };
1257   static const unsigned short UVAC_HT[256][2] = {
1258      {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},
1259      {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},
1260      {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},
1261      {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},
1262      {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},
1263      {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},
1264      {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},
1265      {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},
1266      {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},
1267      {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},
1268      {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},
1269      {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},
1270      {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},
1271      {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},
1272      {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},
1273      {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}
1274   };
1275   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,
1276                             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};
1277   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,
1278                              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};
1279   static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f,
1280                                 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f };
1281
1282   int row, col, i, k, subsample;
1283   float fdtbl_Y[64], fdtbl_UV[64];
1284   unsigned char YTable[64], UVTable[64];
1285
1286   if(!data || !width || !height || comp > 4 || comp < 1) {
1287      return 0;
1288   }
1289
1290   quality = quality ? quality : 90;
1291   subsample = quality <= 90 ? 1 : 0;
1292   quality = quality < 1 ? 1 : quality > 100 ? 100 : quality;
1293   quality = quality < 50 ? 5000 / quality : 200 - quality * 2;
1294
1295   for(i = 0; i < 64; ++i) {
1296      int uvti, yti = (YQT[i]*quality+50)/100;
1297      YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti);
1298      uvti = (UVQT[i]*quality+50)/100;
1299      UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti);
1300   }
1301
1302   for(row = 0, k = 0; row < 8; ++row) {
1303      for(col = 0; col < 8; ++col, ++k) {
1304         fdtbl_Y[k]  = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1305         fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]);
1306      }
1307   }
1308
1309   {
1310      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 };
1311      static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 };
1312      const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width),
1313                                      3,1,(unsigned char)(subsample?0x22:0x11),0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 };
1314      s->func(s->context, (void*)head0, sizeof(head0));
1315      s->func(s->context, (void*)YTable, sizeof(YTable));
1316      stbiw__putc(s, 1);
1317      s->func(s->context, UVTable, sizeof(UVTable));
1318      s->func(s->context, (void*)head1, sizeof(head1));
1319      s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1);
1320      s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values));
1321      stbiw__putc(s, 0x10);
1322      s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1);
1323      s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values));
1324      stbiw__putc(s, 1);
1325      s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1);
1326      s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values));
1327      stbiw__putc(s, 0x11);
1328      s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1);
1329      s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values));
1330      s->func(s->context, (void*)head2, sizeof(head2));
1331   }
1332
1333   {
1334      static const unsigned short fillBits[] = {0x7F, 7};
1335      int DCY=0, DCU=0, DCV=0;
1336      int bitBuf=0, bitCnt=0;
1337
1338      int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0;
1339      const unsigned char *dataR = (const unsigned char *)data;
1340      const unsigned char *dataG = dataR + ofsG;
1341      const unsigned char *dataB = dataR + ofsB;
1342      int x, y, pos;
1343      if(subsample) {
1344         for(y = 0; y < height; y += 16) {
1345            for(x = 0; x < width; x += 16) {
1346               float Y[256], U[256], V[256];
1347               for(row = y, pos = 0; row < y+16; ++row) {
1348
1349                  int clamped_row = (row < height) ? row : height - 1;
1350                  int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
1351                  for(col = x; col < x+16; ++col, ++pos) {
1352
1353                     int p = base_p + ((col < width) ? col : (width-1))*comp;
1354                     float r = dataR[p], g = dataG[p], b = dataB[p];
1355                     Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
1356                     U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
1357                     V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
1358                  }
1359               }
1360               DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+0,   16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1361               DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+8,   16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1362               DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1363               DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT);
1364
1365               {
1366                  float subU[64], subV[64];
1367                  int yy, xx;
1368                  for(yy = 0, pos = 0; yy < 8; ++yy) {
1369                     for(xx = 0; xx < 8; ++xx, ++pos) {
1370                        int j = yy*32+xx*2;
1371                        subU[pos] = (U[j+0] + U[j+1] + U[j+16] + U[j+17]) * 0.25f;
1372                        subV[pos] = (V[j+0] + V[j+1] + V[j+16] + V[j+17]) * 0.25f;
1373                     }
1374                  }
1375                  DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
1376                  DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
1377               }
1378            }
1379         }
1380      } else {
1381         for(y = 0; y < height; y += 8) {
1382            for(x = 0; x < width; x += 8) {
1383               float Y[64], U[64], V[64];
1384               for(row = y, pos = 0; row < y+8; ++row) {
1385
1386                  int clamped_row = (row < height) ? row : height - 1;
1387                  int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp;
1388                  for(col = x; col < x+8; ++col, ++pos) {
1389
1390                     int p = base_p + ((col < width) ? col : (width-1))*comp;
1391                     float r = dataR[p], g = dataG[p], b = dataB[p];
1392                     Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128;
1393                     U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b;
1394                     V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b;
1395                  }
1396               }
1397
1398               DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y,  DCY, YDC_HT, YAC_HT);
1399               DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT);
1400               DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT);
1401            }
1402         }
1403      }
1404
1405      stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits);
1406   }
1407
1408   stbiw__putc(s, 0xFF);
1409   stbiw__putc(s, 0xD9);
1410
1411   return 1;
1412}
1413
1414STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality)
1415{
1416   stbi__write_context s = { 0 };
1417   stbi__start_write_callbacks(&s, func, context);
1418   return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality);
1419}
1420
1421#ifndef STBI_WRITE_NO_STDIO
1422STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality)
1423{
1424   stbi__write_context s = { 0 };
1425   if (stbi__start_write_file(&s,filename)) {
1426      int r = stbi_write_jpg_core(&s, x, y, comp, data, quality);
1427      stbi__end_write_file(&s);
1428      return r;
1429   } else
1430      return 0;
1431}
1432#endif
1433
1434#endif