stb_image_write.h 33.0 KB
Newer Older
S
Sean Barrett 已提交
1
/* stb_image_write - v1.00 - public domain - http://nothings.org/stb/stb_image_write.h
2
   writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015
3
                                     no warranty implied; use at your own risk
S
Sean Barrett 已提交
4

5
   Before #including,
S
Sean Barrett 已提交
6

7
       #define STB_IMAGE_WRITE_IMPLEMENTATION
S
Sean Barrett 已提交
8

9
   in the file that you want to have the implementation.
S
Sean Barrett 已提交
10

11
   Will probably not work correctly with strict-aliasing optimizations.
S
Sean Barrett 已提交
12 13 14 15 16 17 18 19

ABOUT:

   This header file is a library for writing images to C stdio. It could be
   adapted to write to memory or a general streaming interface; let me know.

   The PNG output is not optimal; it is 20-50% larger than the file
   written by a decent optimizing implementation. This library is designed
20
   for source code compactness and simplicity, not optimal image file size
S
Sean Barrett 已提交
21 22
   or run-time performance.

23 24 25 26 27 28 29
BUILDING:

   You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h.
   You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace
   malloc,realloc,free.
   You can define STBIW_MEMMOVE() to replace memmove()

S
Sean Barrett 已提交
30 31
USAGE:

B
baldurk 已提交
32
   There are four functions, one for each image file format:
S
Sean Barrett 已提交
33 34 35 36

     int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
     int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
     int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
B
baldurk 已提交
37
     int stbi_write_hdr(char const *filename, int w, int h, int comp, const void *data);
S
Sean Barrett 已提交
38

39 40
   There are also four equivalent functions that use an arbitrary write function. You are
   expected to open/close your file-equivalent before and after calling these:
41

42 43 44 45
     int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data, int stride_in_bytes);
     int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
     int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
     int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
46

47 48 49
   where the callback is:
      void stbi_write_func(void *context, void *data, int size);

50
   You can define STBI_WRITE_NO_STDIO to disable the file variant of these
51 52
   functions, so the library will not use stdio.h at all. However, this will
   also disable HDR writing, because it requires stdio for formatted output.
S
Sean Barrett 已提交
53 54

   Each function returns 0 on failure and non-0 on success.
55

S
Sean Barrett 已提交
56 57 58 59 60 61 62 63 64 65
   The functions create an image file defined by the parameters. The image
   is a rectangle of pixels stored from left-to-right, top-to-bottom.
   Each pixel contains 'comp' channels of data stored interleaved with 8-bits
   per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is
   monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall.
   The *data pointer points to the first byte of the top-left-most pixel.
   For PNG, "stride_in_bytes" is the distance in bytes from the first byte of
   a row of pixels to the first byte of the next row of pixels.

   PNG creates output files with the same number of components as the input.
66
   The BMP format expands Y to RGB in the file format and does not
S
Sean Barrett 已提交
67
   output alpha.
68

S
Sean Barrett 已提交
69 70 71 72 73 74
   PNG supports writing rectangles of data even when the bytes storing rows of
   data are not consecutive in memory (e.g. sub-rectangles of a larger image),
   by supplying the stride between the beginning of adjacent rows. The other
   formats do not. (Thus you cannot write a native-format BMP through the BMP
   writer, both because it is in BGR order and because it may have padding
   at the end of the line.)
B
baldurk 已提交
75 76 77 78

   HDR expects linear float data. Since the format is always 32-bit rgb(e)
   data, alpha (if provided) is discarded, and for monochrome data it is
   replicated across all three channels.
79

S
Sean Barrett 已提交
80 81 82
   TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed
   data, set the global variable 'stbi_write_tga_with_rle' to 0.

83 84 85 86 87 88 89 90
CREDITS:

   PNG/BMP/TGA
      Sean Barrett
   HDR
      Baldur Karlsson
   TGA monochrome:
      Jean-Sebastien Guay
91 92
   misc enhancements:
      Tim Kelsey
S
Sean Barrett 已提交
93 94
   TGA RLE
      Alan Hickman
S
Sean Barrett 已提交
95
   initial file IO callback implementation
96
      Emmanuel Julien
97 98
   bugfixes:
      github:Chribba
S
credits  
Sean Barrett 已提交
99
      Guillaume Chereau
S
Sean Barrett 已提交
100
      github:jry2
101 102 103 104 105 106
      
LICENSE

This software is in the public domain. Where that dedication is not
recognized, you are granted a perpetual, irrevocable license to copy,
distribute, and modify this file as you see fit.      
107

S
Sean Barrett 已提交
108 109 110 111 112 113 114 115 116
*/

#ifndef INCLUDE_STB_IMAGE_WRITE_H
#define INCLUDE_STB_IMAGE_WRITE_H

#ifdef __cplusplus
extern "C" {
#endif

117 118 119 120
#ifdef STB_IMAGE_WRITE_STATIC
#define STBIWDEF static
#else
#define STBIWDEF extern
S
Sean Barrett 已提交
121
extern int stbi_write_tga_with_rle;
122 123
#endif

124
#ifndef STBI_WRITE_NO_STDIO
125 126 127 128
STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void  *data, int stride_in_bytes);
STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void  *data);
STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void  *data);
STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
129
#endif
130

131
typedef void stbi_write_func(void *context, void *data, int size);
132

133 134 135 136
STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data, int stride_in_bytes);
STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
S
Sean Barrett 已提交
137 138 139 140 141 142 143 144 145

#ifdef __cplusplus
}
#endif

#endif//INCLUDE_STB_IMAGE_WRITE_H

#ifdef STB_IMAGE_WRITE_IMPLEMENTATION

S
Sean Barrett 已提交
146 147 148 149 150
#ifdef _WIN32
   #define _CRT_SECURE_NO_WARNINGS
   #define _CRT_NONSTDC_NO_DEPRECATE
#endif

151 152 153
#ifndef STBI_WRITE_NO_STDIO
#include <stdio.h>
#endif // STBI_WRITE_NO_STDIO
154

S
Sean Barrett 已提交
155 156 157
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
158
#include <math.h>
S
Sean Barrett 已提交
159

160
#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && defined(STBIW_REALLOC)
161
// ok
162
#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC)
163 164
// ok
#else
165
#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC."
166 167
#endif

168 169 170 171
#ifndef STBIW_MALLOC
#define STBIW_MALLOC(sz)    malloc(sz)
#define STBIW_REALLOC(p,sz) realloc(p,sz)
#define STBIW_FREE(p)       free(p)
172
#endif
173 174 175 176
#ifndef STBIW_MEMMOVE
#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
#endif

177

178
#ifndef STBIW_ASSERT
179
#include <assert.h>
180
#define STBIW_ASSERT(x) assert(x)
181 182
#endif

183 184
typedef struct
{
185 186
   stbi_write_func *func;
   void *context;
187 188 189
} stbi__write_context;

// initialize a callback-based context
190
static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context)
191
{
192 193
   s->func    = c;
   s->context = context;
194 195 196 197
}

#ifndef STBI_WRITE_NO_STDIO

198
static void stbi__stdio_write(void *context, void *data, int size)
199
{
200
   fwrite(data,1,size,(FILE*) context);
201 202
}

S
Sean Barrett 已提交
203
static int stbi__start_write_file(stbi__write_context *s, const char *filename)
204 205
{
   FILE *f = fopen(filename, "wb");
206
   stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f);
S
Sean Barrett 已提交
207
   return f != NULL;
208 209 210 211
}

static void stbi__end_write_file(stbi__write_context *s)
{
212
   fclose((FILE *)s->context);
213 214 215 216
}

#endif // !STBI_WRITE_NO_STDIO

S
Sean Barrett 已提交
217 218 219
typedef unsigned int stbiw_uint32;
typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];

S
Sean Barrett 已提交
220 221 222 223 224
#ifdef STB_IMAGE_WRITE_STATIC
static int stbi_write_tga_with_rle = 1;
#else
int stbi_write_tga_with_rle = 1;
#endif
F
fahickman 已提交
225

S
Sean Barrett 已提交
226
static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v)
S
Sean Barrett 已提交
227 228 229 230
{
   while (*fmt) {
      switch (*fmt++) {
         case ' ': break;
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
         case '1': { unsigned char x = (unsigned char) va_arg(v, int);
                     s->func(s->context,&x,1);
                     break; }
         case '2': { int x = va_arg(v,int);
                     unsigned char b[2];
                     b[0] = (unsigned char) x;
                     b[1] = (unsigned char) (x>>8);
                     s->func(s->context,b,2);
                     break; }
         case '4': { stbiw_uint32 x = va_arg(v,int);
                     unsigned char b[4];
                     b[0]=(unsigned char)x;
                     b[1]=(unsigned char)(x>>8);
                     b[2]=(unsigned char)(x>>16);
                     b[3]=(unsigned char)(x>>24);
                     s->func(s->context,b,4);
                     break; }
S
Sean Barrett 已提交
248
         default:
249
            STBIW_ASSERT(0);
S
Sean Barrett 已提交
250 251 252 253 254
            return;
      }
   }
}

S
Sean Barrett 已提交
255
static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
F
fahickman 已提交
256 257 258
{
   va_list v;
   va_start(v, fmt);
S
Sean Barrett 已提交
259
   stbiw__writefv(s, fmt, v);
F
fahickman 已提交
260 261 262
   va_end(v);
}

S
Sean Barrett 已提交
263
static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
S
Sean Barrett 已提交
264 265 266
{
   unsigned char arr[3];
   arr[0] = a, arr[1] = b, arr[2] = c;
267
   s->func(s->context, arr, 3);
S
Sean Barrett 已提交
268 269
}

S
Sean Barrett 已提交
270
static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
S
Sean Barrett 已提交
271 272
{
   unsigned char bg[3] = { 255, 0, 255}, px[3];
F
fahickman 已提交
273 274 275
   int k;

   if (write_alpha < 0)
276 277
      s->func(s->context, &d[comp - 1], 1);

F
fahickman 已提交
278
   switch (comp) {
279 280 281 282 283
      case 1:
         s->func(s->context,d,1);
         break;
      case 2:
         if (expand_mono)
S
Sean Barrett 已提交
284
            stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp
285 286 287 288 289 290 291 292
         else
            s->func(s->context, d, 1);  // monochrome TGA
         break;
      case 4:
         if (!write_alpha) {
            // composite against pink background
            for (k = 0; k < 3; ++k)
               px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
S
Sean Barrett 已提交
293
            stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]);
294 295 296 297
            break;
         }
         /* FALLTHROUGH */
      case 3:
S
Sean Barrett 已提交
298
         stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
F
fahickman 已提交
299 300 301
         break;
   }
   if (write_alpha > 0)
302
      s->func(s->context, &d[comp - 1], 1);
F
fahickman 已提交
303 304
}

S
Sean Barrett 已提交
305
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)
F
fahickman 已提交
306
{
S
Sean Barrett 已提交
307
   stbiw_uint32 zero = 0;
F
fahickman 已提交
308
   int i,j, j_end;
S
Sean Barrett 已提交
309 310 311 312

   if (y <= 0)
      return;

313
   if (vdir < 0)
S
Sean Barrett 已提交
314 315 316 317 318 319 320
      j_end = -1, j = y-1;
   else
      j_end =  y, j = 0;

   for (; j != j_end; j += vdir) {
      for (i=0; i < x; ++i) {
         unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
S
Sean Barrett 已提交
321
         stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
S
Sean Barrett 已提交
322
      }
323
      s->func(s->context, &zero, scanline_pad);
S
Sean Barrett 已提交
324 325 326
   }
}

S
Sean Barrett 已提交
327
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, ...)
S
Sean Barrett 已提交
328
{
329 330 331
   if (y < 0 || x < 0) {
      return 0;
   } else {
S
Sean Barrett 已提交
332 333
      va_list v;
      va_start(v, fmt);
S
Sean Barrett 已提交
334
      stbiw__writefv(s, fmt, v);
S
Sean Barrett 已提交
335
      va_end(v);
S
Sean Barrett 已提交
336
      stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono);
337
      return 1;
S
Sean Barrett 已提交
338 339 340
   }
}

S
Sean Barrett 已提交
341
static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
S
Sean Barrett 已提交
342 343
{
   int pad = (-x*3) & 3;
S
Sean Barrett 已提交
344
   return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
S
Sean Barrett 已提交
345 346 347 348 349
           "11 4 22 4" "4 44 22 444444",
           'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40,  // file header
            40, x,y, 1,24, 0,0,0,0,0,0);             // bitmap header
}

350
STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
351 352
{
   stbi__write_context s;
353 354
   stbi__start_write_callbacks(&s, func, context);
   return stbi_write_bmp_core(&s, x, y, comp, data);
355 356 357
}

#ifndef STBI_WRITE_NO_STDIO
358
STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
359 360
{
   stbi__write_context s;
S
Sean Barrett 已提交
361 362 363 364 365 366
   if (stbi__start_write_file(&s,filename)) {
      int r = stbi_write_bmp_core(&s, x, y, comp, data);
      stbi__end_write_file(&s);
      return r;
   } else
      return 0;
367 368 369
}
#endif //!STBI_WRITE_NO_STDIO

S
Sean Barrett 已提交
370
static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data)
S
Sean Barrett 已提交
371
{
S
Sean Barrett 已提交
372 373
   int has_alpha = (comp == 2 || comp == 4);
   int colorbytes = has_alpha ? comp-1 : comp;
374
   int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3
375 376 377

   if (y < 0 || x < 0)
      return 0;
F
fahickman 已提交
378

S
Sean Barrett 已提交
379
   if (!stbi_write_tga_with_rle) {
S
Sean Barrett 已提交
380
      return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0,
F
fahickman 已提交
381
         "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
382
   } else {
F
fahickman 已提交
383 384
      int i,j,k;

S
Sean Barrett 已提交
385
      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);
F
fahickman 已提交
386 387

      for (j = y - 1; j >= 0; --j) {
388
          unsigned char *row = (unsigned char *) data + j * x * comp;
F
fahickman 已提交
389
         int len;
F
fahickman 已提交
390

F
fahickman 已提交
391
         for (i = 0; i < x; i += len) {
392
            unsigned char *begin = row + i * comp;
F
fahickman 已提交
393
            int diff = 1;
F
fahickman 已提交
394
            len = 1;
F
fahickman 已提交
395 396

            if (i < x - 1) {
F
fahickman 已提交
397 398
               ++len;
               diff = memcmp(begin, row + (i + 1) * comp, comp);
F
fahickman 已提交
399
               if (diff) {
F
fahickman 已提交
400 401 402 403 404
                  const unsigned char *prev = begin;
                  for (k = i + 2; k < x && len < 128; ++k) {
                     if (memcmp(prev, row + k * comp, comp)) {
                        prev += comp;
                        ++len;
F
fahickman 已提交
405
                     } else {
F
fahickman 已提交
406
                        --len;
F
fahickman 已提交
407 408 409 410
                        break;
                     }
                  }
               } else {
F
fahickman 已提交
411 412 413
                  for (k = i + 2; k < x && len < 128; ++k) {
                     if (!memcmp(begin, row + k * comp, comp)) {
                        ++len;
F
fahickman 已提交
414 415 416 417 418 419 420 421
                     } else {
                        break;
                     }
                  }
               }
            }

            if (diff) {
F
fahickman 已提交
422
               unsigned char header = (unsigned char) (len - 1);
423
               s->func(s->context, &header, 1);
F
fahickman 已提交
424
               for (k = 0; k < len; ++k) {
S
Sean Barrett 已提交
425
                  stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
F
fahickman 已提交
426 427
               }
            } else {
F
fahickman 已提交
428
               unsigned char header = (unsigned char) (len - 129);
429
               s->func(s->context, &header, 1);
S
Sean Barrett 已提交
430
               stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
F
fahickman 已提交
431 432 433 434
            }
         }
      }
   }
435
   return 1;
S
Sean Barrett 已提交
436 437
}

438
int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
439 440
{
   stbi__write_context s;
441 442
   stbi__start_write_callbacks(&s, func, context);
   return stbi_write_tga_core(&s, x, y, comp, (void *) data);
443
}
F
fahickman 已提交
444

445
#ifndef STBI_WRITE_NO_STDIO
S
Sean Barrett 已提交
446
int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
447 448
{
   stbi__write_context s;
S
Sean Barrett 已提交
449 450 451 452 453 454
   if (stbi__start_write_file(&s,filename)) {
      int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
      stbi__end_write_file(&s);
      return r;
   } else
      return 0;
S
Sean Barrett 已提交
455
}
456
#endif
S
Sean Barrett 已提交
457

B
baldurk 已提交
458 459
// *************************************************************************************************
// Radiance RGBE HDR writer
460
// by Baldur Karlsson
461 462
#ifndef STBI_WRITE_NO_STDIO

B
baldurk 已提交
463 464 465 466 467 468 469 470 471 472
#define stbiw__max(a, b)  ((a) > (b) ? (a) : (b))

void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
{
   int exponent;
   float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));

   if (maxcomp < 1e-32) {
      rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
   } else {
473
      float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
B
baldurk 已提交
474

475 476 477
      rgbe[0] = (unsigned char)(linear[0] * normalize);
      rgbe[1] = (unsigned char)(linear[1] * normalize);
      rgbe[2] = (unsigned char)(linear[2] * normalize);
B
baldurk 已提交
478 479 480 481
      rgbe[3] = (unsigned char)(exponent + 128);
   }
}

482
void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
B
baldurk 已提交
483
{
S
Sean Barrett 已提交
484
   unsigned char lengthbyte = (unsigned char) (length+128);
485
   STBIW_ASSERT(length+128 <= 255);
486 487
   s->func(s->context, &lengthbyte, 1);
   s->func(s->context, &databyte, 1);
B
baldurk 已提交
488 489
}

490
void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
B
baldurk 已提交
491 492
{
   unsigned char lengthbyte = (unsigned char )(length & 0xff);
493
   STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
494 495
   s->func(s->context, &lengthbyte, 1);
   s->func(s->context, data, length);
B
baldurk 已提交
496 497
}

498
void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline)
B
baldurk 已提交
499 500 501 502 503 504 505 506 507 508 509 510
{
   unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
   unsigned char rgbe[4];
   float linear[3];
   int x;

   scanlineheader[2] = (width&0xff00)>>8;
   scanlineheader[3] = (width&0x00ff);

   /* skip RLE for images too small or large */
   if (width < 8 || width >= 32768) {
      for (x=0; x < width; x++) {
S
Sean Barrett 已提交
511
         switch (ncomp) {
B
baldurk 已提交
512
            case 4: /* fallthrough */
S
Sean Barrett 已提交
513 514 515
            case 3: linear[2] = scanline[x*ncomp + 2];
                    linear[1] = scanline[x*ncomp + 1];
                    linear[0] = scanline[x*ncomp + 0];
B
baldurk 已提交
516
                    break;
517
            default:
S
Sean Barrett 已提交
518
                    linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
B
baldurk 已提交
519 520 521
                    break;
         }
         stbiw__linear_to_rgbe(rgbe, linear);
522
         s->func(s->context, rgbe, 4);
B
baldurk 已提交
523 524
      }
   } else {
S
Sean Barrett 已提交
525
      int c,r;
B
baldurk 已提交
526 527
      /* encode into scratch buffer */
      for (x=0; x < width; x++) {
S
Sean Barrett 已提交
528
         switch(ncomp) {
B
baldurk 已提交
529
            case 4: /* fallthrough */
S
Sean Barrett 已提交
530 531 532
            case 3: linear[2] = scanline[x*ncomp + 2];
                    linear[1] = scanline[x*ncomp + 1];
                    linear[0] = scanline[x*ncomp + 0];
B
baldurk 已提交
533
                    break;
534
            default:
S
Sean Barrett 已提交
535
                    linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
B
baldurk 已提交
536 537 538 539 540 541 542 543 544
                    break;
         }
         stbiw__linear_to_rgbe(rgbe, linear);
         scratch[x + width*0] = rgbe[0];
         scratch[x + width*1] = rgbe[1];
         scratch[x + width*2] = rgbe[2];
         scratch[x + width*3] = rgbe[3];
      }

545
      s->func(s->context, scanlineheader, 4);
B
baldurk 已提交
546 547

      /* RLE each component separately */
S
Sean Barrett 已提交
548 549
      for (c=0; c < 4; c++) {
         unsigned char *comp = &scratch[width*c];
B
baldurk 已提交
550

S
Sean Barrett 已提交
551 552 553 554 555 556 557 558 559 560 561 562 563 564 565
         x = 0;
         while (x < width) {
            // find first run
            r = x;
            while (r+2 < width) {
               if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
                  break;
               ++r;
            }
            if (r+2 >= width)
               r = width;
            // dump up to first run
            while (x < r) {
               int len = r-x;
               if (len > 128) len = 128;
566
               stbiw__write_dump_data(s, len, &comp[x]);
S
Sean Barrett 已提交
567 568 569 570 571 572
               x += len;
            }
            // if there's a run, output it
            if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd
               // find next byte after run
               while (r < width && comp[r] == comp[x])
573
                  ++r;
S
Sean Barrett 已提交
574 575 576 577
               // output run up to r
               while (x < r) {
                  int len = r-x;
                  if (len > 127) len = 127;
578
                  stbiw__write_run_data(s, len, comp[x]);
S
Sean Barrett 已提交
579
                  x += len;
B
baldurk 已提交
580 581 582 583 584 585 586
               }
            }
         }
      }
   }
}

S
Sean Barrett 已提交
587
static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data)
B
baldurk 已提交
588
{
589 590 591 592
   if (y <= 0 || x <= 0 || data == NULL)
      return 0;
   else {
      // Each component is stored separately. Allocate scratch space for full output scanline.
593
      unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
594 595 596 597 598 599 600 601
      int i, len;
      char buffer[128];
      char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
      s->func(s->context, header, sizeof(header)-1);

      len = sprintf(buffer, "EXPOSURE=          1.0000000000000\n\n-Y %d +X %d\n", y, x);
      s->func(s->context, buffer, len);

602
      for(i=0; i < y; i++)
603
         stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x);
604
      STBIW_FREE(scratch);
605
      return 1;
B
baldurk 已提交
606 607 608
   }
}

609 610 611 612 613 614 615
int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
{
   stbi__write_context s;
   stbi__start_write_callbacks(&s, func, context);
   return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
}

S
Sean Barrett 已提交
616
int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
617 618
{
   stbi__write_context s;
S
Sean Barrett 已提交
619 620 621 622 623 624
   if (stbi__start_write_file(&s,filename)) {
      int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
      stbi__end_write_file(&s);
      return r;
   } else
      return 0;
625 626 627 628 629 630 631 632
}
#endif // STBI_WRITE_NO_STDIO


//////////////////////////////////////////////////////////////////////////////
//
// PNG writer
//
633

634 635 636 637
// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
#define stbiw__sbraw(a) ((int *) (a) - 2)
#define stbiw__sbm(a)   stbiw__sbraw(a)[0]
#define stbiw__sbn(a)   stbiw__sbraw(a)[1]
S
Sean Barrett 已提交
638

639 640 641
#define stbiw__sbneedgrow(a,n)  ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
#define stbiw__sbgrow(a,n)  stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
S
Sean Barrett 已提交
642

643 644
#define stbiw__sbpush(a, v)      (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
#define stbiw__sbcount(a)        ((a) ? stbiw__sbn(a) : 0)
645
#define stbiw__sbfree(a)         ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
S
Sean Barrett 已提交
646

647
static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
S
Sean Barrett 已提交
648
{
649
   int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
650 651
   void *p = STBIW_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2);
   STBIW_ASSERT(p);
S
Sean Barrett 已提交
652 653 654
   if (p) {
      if (!*arr) ((int *) p)[1] = 0;
      *arr = (void *) ((int *) p + 2);
655
      stbiw__sbm(*arr) = m;
S
Sean Barrett 已提交
656 657 658 659
   }
   return *arr;
}

660
static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
S
Sean Barrett 已提交
661 662
{
   while (*bitcount >= 8) {
663
      stbiw__sbpush(data, (unsigned char) *bitbuffer);
S
Sean Barrett 已提交
664 665 666 667 668 669
      *bitbuffer >>= 8;
      *bitcount -= 8;
   }
   return data;
}

670
static int stbiw__zlib_bitrev(int code, int codebits)
S
Sean Barrett 已提交
671 672 673 674 675 676 677 678 679
{
   int res=0;
   while (codebits--) {
      res = (res << 1) | (code & 1);
      code >>= 1;
   }
   return res;
}

680
static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit)
S
Sean Barrett 已提交
681 682 683 684 685 686 687
{
   int i;
   for (i=0; i < limit && i < 258; ++i)
      if (a[i] != b[i]) break;
   return i;
}

688
static unsigned int stbiw__zhash(unsigned char *data)
S
Sean Barrett 已提交
689 690 691 692 693 694 695 696 697 698 699
{
   stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
   hash ^= hash << 3;
   hash += hash >> 5;
   hash ^= hash << 4;
   hash += hash >> 17;
   hash ^= hash << 25;
   hash += hash >> 6;
   return hash;
}

700 701 702 703
#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
#define stbiw__zlib_add(code,codebits) \
      (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
#define stbiw__zlib_huffa(b,c)  stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
S
Sean Barrett 已提交
704
// default huffman tables
705 706 707 708 709 710
#define stbiw__zlib_huff1(n)  stbiw__zlib_huffa(0x30 + (n), 8)
#define stbiw__zlib_huff2(n)  stbiw__zlib_huffa(0x190 + (n)-144, 9)
#define stbiw__zlib_huff3(n)  stbiw__zlib_huffa(0 + (n)-256,7)
#define stbiw__zlib_huff4(n)  stbiw__zlib_huffa(0xc0 + (n)-280,8)
#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))
#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
S
Sean Barrett 已提交
711

712
#define stbiw__ZHASH   16384
S
Sean Barrett 已提交
713 714 715 716 717 718 719 720 721 722

unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
{
   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 };
   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 };
   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 };
   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 };
   unsigned int bitbuf=0;
   int i,j, bitcount=0;
   unsigned char *out = NULL;
723
   unsigned char **hash_table[stbiw__ZHASH]; // 64KB on the stack!
S
Sean Barrett 已提交
724 725
   if (quality < 5) quality = 5;

726 727 728 729
   stbiw__sbpush(out, 0x78);   // DEFLATE 32K window
   stbiw__sbpush(out, 0x5e);   // FLEVEL = 1
   stbiw__zlib_add(1,1);  // BFINAL = 1
   stbiw__zlib_add(1,2);  // BTYPE = 1 -- fixed huffman
S
Sean Barrett 已提交
730

731
   for (i=0; i < stbiw__ZHASH; ++i)
S
Sean Barrett 已提交
732 733 734 735
      hash_table[i] = NULL;

   i=0;
   while (i < data_len-3) {
736
      // hash next 3 bytes of data to be compressed
737
      int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
S
Sean Barrett 已提交
738 739
      unsigned char *bestloc = 0;
      unsigned char **hlist = hash_table[h];
740
      int n = stbiw__sbcount(hlist);
S
Sean Barrett 已提交
741 742
      for (j=0; j < n; ++j) {
         if (hlist[j]-data > i-32768) { // if entry lies within window
743
            int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
S
Sean Barrett 已提交
744 745 746 747
            if (d >= best) best=d,bestloc=hlist[j];
         }
      }
      // when hash table entry is too long, delete half the entries
748
      if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
749
         STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
750
         stbiw__sbn(hash_table[h]) = quality;
S
Sean Barrett 已提交
751
      }
752
      stbiw__sbpush(hash_table[h],data+i);
S
Sean Barrett 已提交
753 754 755

      if (bestloc) {
         // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal
756
         h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
S
Sean Barrett 已提交
757
         hlist = hash_table[h];
758
         n = stbiw__sbcount(hlist);
S
Sean Barrett 已提交
759 760
         for (j=0; j < n; ++j) {
            if (hlist[j]-data > i-32767) {
761
               int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
S
Sean Barrett 已提交
762 763 764 765 766 767 768 769 770
               if (e > best) { // if next match is better, bail on current match
                  bestloc = NULL;
                  break;
               }
            }
         }
      }

      if (bestloc) {
771
         int d = (int) (data+i - bestloc); // distance back
772
         STBIW_ASSERT(d <= 32767 && best <= 258);
S
Sean Barrett 已提交
773
         for (j=0; best > lengthc[j+1]-1; ++j);
774 775
         stbiw__zlib_huff(j+257);
         if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
S
Sean Barrett 已提交
776
         for (j=0; d > distc[j+1]-1; ++j);
777 778
         stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
         if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
S
Sean Barrett 已提交
779 780
         i += best;
      } else {
781
         stbiw__zlib_huffb(data[i]);
S
Sean Barrett 已提交
782 783 784 785 786
         ++i;
      }
   }
   // write out final bytes
   for (;i < data_len; ++i)
787 788
      stbiw__zlib_huffb(data[i]);
   stbiw__zlib_huff(256); // end of block
S
Sean Barrett 已提交
789 790
   // pad with 0 bits to byte boundary
   while (bitcount)
791
      stbiw__zlib_add(0,1);
S
Sean Barrett 已提交
792

793 794
   for (i=0; i < stbiw__ZHASH; ++i)
      (void) stbiw__sbfree(hash_table[i]);
S
Sean Barrett 已提交
795 796 797

   {
      // compute adler32 on input
S
Sean Barrett 已提交
798 799 800
      unsigned int k=0, s1=1, s2=0;
      int blocklen = (int) (data_len % 5552);
      j=0;
S
Sean Barrett 已提交
801 802 803 804 805 806
      while (j < data_len) {
         for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
         s1 %= 65521, s2 %= 65521;
         j += blocklen;
         blocklen = 5552;
      }
807 808 809 810
      stbiw__sbpush(out, (unsigned char) (s2 >> 8));
      stbiw__sbpush(out, (unsigned char) s2);
      stbiw__sbpush(out, (unsigned char) (s1 >> 8));
      stbiw__sbpush(out, (unsigned char) s1);
S
Sean Barrett 已提交
811
   }
812
   *out_len = stbiw__sbn(out);
S
Sean Barrett 已提交
813
   // make returned pointer freeable
814
   STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
815
   return (unsigned char *) stbiw__sbraw(out);
S
Sean Barrett 已提交
816 817
}

818
unsigned int stbiw__crc32(unsigned char *buffer, int len)
S
Sean Barrett 已提交
819 820 821 822 823 824 825 826 827 828 829 830 831
{
   static unsigned int crc_table[256];
   unsigned int crc = ~0u;
   int i,j;
   if (crc_table[1] == 0)
      for(i=0; i < 256; i++)
         for (crc_table[i]=i, j=0; j < 8; ++j)
            crc_table[i] = (crc_table[i] >> 1) ^ (crc_table[i] & 1 ? 0xedb88320 : 0);
   for (i=0; i < len; ++i)
      crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
   return ~crc;
}

832 833 834
#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=(unsigned char)(a),(o)[1]=(unsigned char)(b),(o)[2]=(unsigned char)(c),(o)[3]=(unsigned char)(d),(o)+=4)
#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
S
Sean Barrett 已提交
835

836
static void stbiw__wpcrc(unsigned char **data, int len)
S
Sean Barrett 已提交
837
{
838 839
   unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
   stbiw__wp32(*data, crc);
S
Sean Barrett 已提交
840 841
}

842
static unsigned char stbiw__paeth(int a, int b, int c)
S
Sean Barrett 已提交
843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860
{
   int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
   if (pa <= pb && pa <= pc) return (unsigned char) a;
   if (pb <= pc) return (unsigned char) b;
   return (unsigned char) c;
}

unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
{
   int ctype[5] = { -1, 0, 4, 2, 6 };
   unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
   unsigned char *out,*o, *filt, *zlib;
   signed char *line_buffer;
   int i,j,k,p,zlen;

   if (stride_bytes == 0)
      stride_bytes = x * n;

861 862
   filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
   line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
S
Sean Barrett 已提交
863 864 865 866 867 868 869 870 871 872 873 874 875 876 877
   for (j=0; j < y; ++j) {
      static int mapping[] = { 0,1,2,3,4 };
      static int firstmap[] = { 0,1,0,5,6 };
      int *mymap = j ? mapping : firstmap;
      int best = 0, bestval = 0x7fffffff;
      for (p=0; p < 2; ++p) {
         for (k= p?best:0; k < 5; ++k) {
            int type = mymap[k],est=0;
            unsigned char *z = pixels + stride_bytes*j;
            for (i=0; i < n; ++i)
               switch (type) {
                  case 0: line_buffer[i] = z[i]; break;
                  case 1: line_buffer[i] = z[i]; break;
                  case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
                  case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break;
878
                  case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break;
S
Sean Barrett 已提交
879 880 881 882 883 884 885 886 887
                  case 5: line_buffer[i] = z[i]; break;
                  case 6: line_buffer[i] = z[i]; break;
               }
            for (i=n; i < x*n; ++i) {
               switch (type) {
                  case 0: line_buffer[i] = z[i]; break;
                  case 1: line_buffer[i] = z[i] - z[i-n]; break;
                  case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
                  case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break;
888
                  case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break;
S
Sean Barrett 已提交
889
                  case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break;
890
                  case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
S
Sean Barrett 已提交
891 892 893 894 895 896 897 898 899 900
               }
            }
            if (p) break;
            for (i=0; i < x*n; ++i)
               est += abs((signed char) line_buffer[i]);
            if (est < bestval) { bestval = est; best = k; }
         }
      }
      // when we get here, best contains the filter type, and line_buffer contains the data
      filt[j*(x*n+1)] = (unsigned char) best;
901
      STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
S
Sean Barrett 已提交
902
   }
903
   STBIW_FREE(line_buffer);
S
Sean Barrett 已提交
904
   zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory
905
   STBIW_FREE(filt);
S
Sean Barrett 已提交
906 907 908
   if (!zlib) return 0;

   // each tag requires 12 bytes of overhead
909
   out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
S
Sean Barrett 已提交
910 911 912 913
   if (!out) return 0;
   *out_len = 8 + 12+13 + 12+zlen + 12;

   o=out;
914
   STBIW_MEMMOVE(o,sig,8); o+= 8;
915 916 917 918
   stbiw__wp32(o, 13); // header length
   stbiw__wptag(o, "IHDR");
   stbiw__wp32(o, x);
   stbiw__wp32(o, y);
S
Sean Barrett 已提交
919 920 921 922 923
   *o++ = 8;
   *o++ = (unsigned char) ctype[n];
   *o++ = 0;
   *o++ = 0;
   *o++ = 0;
924
   stbiw__wpcrc(&o,13);
S
Sean Barrett 已提交
925

926 927
   stbiw__wp32(o, zlen);
   stbiw__wptag(o, "IDAT");
928 929 930
   STBIW_MEMMOVE(o, zlib, zlen);
   o += zlen;
   STBIW_FREE(zlib);
931
   stbiw__wpcrc(&o, zlen);
S
Sean Barrett 已提交
932

933 934 935
   stbiw__wp32(o,0);
   stbiw__wptag(o, "IEND");
   stbiw__wpcrc(&o,0);
S
Sean Barrett 已提交
936

937
   STBIW_ASSERT(o == out + *out_len);
S
Sean Barrett 已提交
938 939 940 941

   return out;
}

942
#ifndef STBI_WRITE_NO_STDIO
943
STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
S
Sean Barrett 已提交
944 945 946 947
{
   FILE *f;
   int len;
   unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
948
   if (png == NULL) return 0;
S
Sean Barrett 已提交
949
   f = fopen(filename, "wb");
950
   if (!f) { STBIW_FREE(png); return 0; }
S
Sean Barrett 已提交
951 952
   fwrite(png, 1, len, f);
   fclose(f);
953
   STBIW_FREE(png);
S
Sean Barrett 已提交
954 955
   return 1;
}
956
#endif
957

958
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)
959
{
960 961 962 963 964 965
   int len;
   unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
   if (png == NULL) return 0;
   func(context, png, len);
   STBIW_FREE(png);
   return 1;
966 967
}

S
Sean Barrett 已提交
968 969 970
#endif // STB_IMAGE_WRITE_IMPLEMENTATION

/* Revision history
S
Sean Barrett 已提交
971 972
      1.00 (2015-09-14)
             installable file IO function
S
credits  
Sean Barrett 已提交
973
      0.99 (2015-09-13)
S
Sean Barrett 已提交
974
             warning fixes; TGA rle support
975
      0.98 (2015-04-08)
976
             added STBIW_MALLOC, STBIW_ASSERT etc
S
Sean Barrett 已提交
977 978
      0.97 (2015-01-18)
             fixed HDR asserts, rewrote HDR rle logic
979 980 981
      0.96 (2015-01-17)
             add HDR output
             fix monochrome BMP
S
Sean Barrett 已提交
982 983
      0.95 (2014-08-17)
		       add monochrome TGA output
S
Sean Barrett 已提交
984 985
      0.94 (2014-05-31)
             rename private functions to avoid conflicts with stb_image.h
986 987
      0.93 (2014-05-27)
             warning fixes
S
Sean Barrett 已提交
988 989 990 991 992 993
      0.92 (2010-08-01)
             casts to unsigned char to fix warnings
      0.91 (2010-07-17)
             first public release
      0.90   first internal release
*/