stb_image_write.h
Go to the documentation of this file.
00001 /* stb_image_write - v1.01 - public domain - http://nothings.org/stb/stb_image_write.h
00002    writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010-2015
00003                                      no warranty implied; use at your own risk
00004 
00005    Before #including,
00006 
00007        #define STB_IMAGE_WRITE_IMPLEMENTATION
00008 
00009    in the file that you want to have the implementation.
00010 
00011    Will probably not work correctly with strict-aliasing optimizations.
00012 
00013 ABOUT:
00014 
00015    This header file is a library for writing images to C stdio. It could be
00016    adapted to write to memory or a general streaming interface; let me know.
00017 
00018    The PNG output is not optimal; it is 20-50% larger than the file
00019    written by a decent optimizing implementation. This library is designed
00020    for source code compactness and simplicity, not optimal image file size
00021    or run-time performance.
00022 
00023 BUILDING:
00024 
00025    You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h.
00026    You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace
00027    malloc,realloc,free.
00028    You can define STBIW_MEMMOVE() to replace memmove()
00029 
00030 USAGE:
00031 
00032    There are four functions, one for each image file format:
00033 
00034      int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
00035      int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
00036      int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
00037      int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
00038 
00039    There are also four equivalent functions that use an arbitrary write function. You are
00040    expected to open/close your file-equivalent before and after calling these:
00041 
00042      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);
00043      int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
00044      int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
00045      int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
00046 
00047    where the callback is:
00048       void stbi_write_func(void *context, void *data, int size);
00049 
00050    You can define STBI_WRITE_NO_STDIO to disable the file variant of these
00051    functions, so the library will not use stdio.h at all. However, this will
00052    also disable HDR writing, because it requires stdio for formatted output.
00053 
00054    Each function returns 0 on failure and non-0 on success.
00055 
00056    The functions create an image file defined by the parameters. The image
00057    is a rectangle of pixels stored from left-to-right, top-to-bottom.
00058    Each pixel contains 'comp' channels of data stored interleaved with 8-bits
00059    per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is
00060    monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall.
00061    The *data pointer points to the first byte of the top-left-most pixel.
00062    For PNG, "stride_in_bytes" is the distance in bytes from the first byte of
00063    a row of pixels to the first byte of the next row of pixels.
00064 
00065    PNG creates output files with the same number of components as the input.
00066    The BMP format expands Y to RGB in the file format and does not
00067    output alpha.
00068 
00069    PNG supports writing rectangles of data even when the bytes storing rows of
00070    data are not consecutive in memory (e.g. sub-rectangles of a larger image),
00071    by supplying the stride between the beginning of adjacent rows. The other
00072    formats do not. (Thus you cannot write a native-format BMP through the BMP
00073    writer, both because it is in BGR order and because it may have padding
00074    at the end of the line.)
00075 
00076    HDR expects linear float data. Since the format is always 32-bit rgb(e)
00077    data, alpha (if provided) is discarded, and for monochrome data it is
00078    replicated across all three channels.
00079 
00080    TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed
00081    data, set the global variable 'stbi_write_tga_with_rle' to 0.
00082 
00083 CREDITS:
00084 
00085    PNG/BMP/TGA
00086       Sean Barrett
00087    HDR
00088       Baldur Karlsson
00089    TGA monochrome:
00090       Jean-Sebastien Guay
00091    misc enhancements:
00092       Tim Kelsey
00093    TGA RLE
00094       Alan Hickman
00095    initial file IO callback implementation
00096       Emmanuel Julien
00097    bugfixes:
00098       github:Chribba
00099       Guillaume Chereau
00100       github:jry2
00101       github:romigrou
00102       Sergio Gonzalez
00103       Jonas Karlsson
00104       Filip Wasil
00105       
00106 LICENSE
00107 
00108 This software is in the public domain. Where that dedication is not
00109 recognized, you are granted a perpetual, irrevocable license to copy,
00110 distribute, and modify this file as you see fit.
00111 
00112 */
00113 
00114 #ifndef INCLUDE_STB_IMAGE_WRITE_H
00115 #define INCLUDE_STB_IMAGE_WRITE_H
00116 
00117 #ifdef __cplusplus
00118 extern "C" {
00119 #endif
00120 
00121 #ifdef STB_IMAGE_WRITE_STATIC
00122 #define STBIWDEF static
00123 #else
00124 #define STBIWDEF extern
00125 extern int stbi_write_tga_with_rle;
00126 #endif
00127 
00128 #ifndef STBI_WRITE_NO_STDIO
00129 STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void  *data, int stride_in_bytes);
00130 STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void  *data);
00131 STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void  *data);
00132 STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
00133 #endif
00134 
00135 typedef void stbi_write_func(void *context, void *data, int size);
00136 
00137 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);
00138 STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
00139 STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void  *data);
00140 STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data);
00141 
00142 #ifdef __cplusplus
00143 }
00144 #endif
00145 
00146 #endif//INCLUDE_STB_IMAGE_WRITE_H
00147 
00148 #ifdef STB_IMAGE_WRITE_IMPLEMENTATION
00149 
00150 #ifdef _WIN32
00151    #ifndef _CRT_SECURE_NO_WARNINGS
00152    #define _CRT_SECURE_NO_WARNINGS
00153    #endif
00154    #ifndef _CRT_NONSTDC_NO_DEPRECATE
00155    #define _CRT_NONSTDC_NO_DEPRECATE
00156    #endif
00157 #endif
00158 
00159 #ifndef STBI_WRITE_NO_STDIO
00160 #include <stdio.h>
00161 #endif // STBI_WRITE_NO_STDIO
00162 
00163 #include <stdarg.h>
00164 #include <stdlib.h>
00165 #include <string.h>
00166 #include <math.h>
00167 
00168 #if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED))
00169 // ok
00170 #elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED)
00171 // ok
00172 #else
00173 #error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)."
00174 #endif
00175 
00176 #ifndef STBIW_MALLOC
00177 #define STBIW_MALLOC(sz)        malloc(sz)
00178 #define STBIW_REALLOC(p,newsz)  realloc(p,newsz)
00179 #define STBIW_FREE(p)           free(p)
00180 #endif
00181 
00182 #ifndef STBIW_REALLOC_SIZED
00183 #define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz)
00184 #endif
00185 
00186 
00187 #ifndef STBIW_MEMMOVE
00188 #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
00189 #endif
00190 
00191 
00192 #ifndef STBIW_ASSERT
00193 #include <assert.h>
00194 #define STBIW_ASSERT(x) assert(x)
00195 #endif
00196 
00197 #define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff)
00198 
00199 typedef struct
00200 {
00201    stbi_write_func *func;
00202    void *context;
00203 } stbi__write_context;
00204 
00205 // initialize a callback-based context
00206 static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context)
00207 {
00208    s->func    = c;
00209    s->context = context;
00210 }
00211 
00212 #ifndef STBI_WRITE_NO_STDIO
00213 
00214 static void stbi__stdio_write(void *context, void *data, int size)
00215 {
00216    fwrite(data,1,size,(FILE*) context);
00217 }
00218 
00219 static int stbi__start_write_file(stbi__write_context *s, const char *filename)
00220 {
00221    FILE *f = fopen(filename, "wb");
00222    stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f);
00223    return f != NULL;
00224 }
00225 
00226 static void stbi__end_write_file(stbi__write_context *s)
00227 {
00228    fclose((FILE *)s->context);
00229 }
00230 
00231 #endif // !STBI_WRITE_NO_STDIO
00232 
00233 typedef unsigned int stbiw_uint32;
00234 typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
00235 
00236 #ifdef STB_IMAGE_WRITE_STATIC
00237 static int stbi_write_tga_with_rle = 1;
00238 #else
00239 int stbi_write_tga_with_rle = 1;
00240 #endif
00241 
00242 static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v)
00243 {
00244    while (*fmt) {
00245       switch (*fmt++) {
00246          case ' ': break;
00247          case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int));
00248                      s->func(s->context,&x,1);
00249                      break; }
00250          case '2': { int x = va_arg(v,int);
00251                      unsigned char b[2];
00252                      b[0] = STBIW_UCHAR(x);
00253                      b[1] = STBIW_UCHAR(x>>8);
00254                      s->func(s->context,b,2);
00255                      break; }
00256          case '4': { stbiw_uint32 x = va_arg(v,int);
00257                      unsigned char b[4];
00258                      b[0]=STBIW_UCHAR(x);
00259                      b[1]=STBIW_UCHAR(x>>8);
00260                      b[2]=STBIW_UCHAR(x>>16);
00261                      b[3]=STBIW_UCHAR(x>>24);
00262                      s->func(s->context,b,4);
00263                      break; }
00264          default:
00265             STBIW_ASSERT(0);
00266             return;
00267       }
00268    }
00269 }
00270 
00271 static void stbiw__writef(stbi__write_context *s, const char *fmt, ...)
00272 {
00273    va_list v;
00274    va_start(v, fmt);
00275    stbiw__writefv(s, fmt, v);
00276    va_end(v);
00277 }
00278 
00279 static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c)
00280 {
00281    unsigned char arr[3];
00282    arr[0] = a, arr[1] = b, arr[2] = c;
00283    s->func(s->context, arr, 3);
00284 }
00285 
00286 static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d)
00287 {
00288    unsigned char bg[3] = { 255, 0, 255}, px[3];
00289    int k;
00290 
00291    if (write_alpha < 0)
00292       s->func(s->context, &d[comp - 1], 1);
00293 
00294    switch (comp) {
00295       case 1:
00296          s->func(s->context,d,1);
00297          break;
00298       case 2:
00299          if (expand_mono)
00300             stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp
00301          else
00302             s->func(s->context, d, 1);  // monochrome TGA
00303          break;
00304       case 4:
00305          if (!write_alpha) {
00306             // composite against pink background
00307             for (k = 0; k < 3; ++k)
00308                px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255;
00309             stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]);
00310             break;
00311          }
00312          /* FALLTHROUGH */
00313       case 3:
00314          stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]);
00315          break;
00316    }
00317    if (write_alpha > 0)
00318       s->func(s->context, &d[comp - 1], 1);
00319 }
00320 
00321 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)
00322 {
00323    stbiw_uint32 zero = 0;
00324    int i,j, j_end;
00325 
00326    if (y <= 0)
00327       return;
00328 
00329    if (vdir < 0)
00330       j_end = -1, j = y-1;
00331    else
00332       j_end =  y, j = 0;
00333 
00334    for (; j != j_end; j += vdir) {
00335       for (i=0; i < x; ++i) {
00336          unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
00337          stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d);
00338       }
00339       s->func(s->context, &zero, scanline_pad);
00340    }
00341 }
00342 
00343 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, ...)
00344 {
00345    if (y < 0 || x < 0) {
00346       return 0;
00347    } else {
00348       va_list v;
00349       va_start(v, fmt);
00350       stbiw__writefv(s, fmt, v);
00351       va_end(v);
00352       stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono);
00353       return 1;
00354    }
00355 }
00356 
00357 static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data)
00358 {
00359    int pad = (-x*3) & 3;
00360    return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad,
00361            "11 4 22 4" "4 44 22 444444",
00362            'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40,  // file header
00363             40, x,y, 1,24, 0,0,0,0,0,0);             // bitmap header
00364 }
00365 
00366 STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
00367 {
00368    stbi__write_context s;
00369    stbi__start_write_callbacks(&s, func, context);
00370    return stbi_write_bmp_core(&s, x, y, comp, data);
00371 }
00372 
00373 #ifndef STBI_WRITE_NO_STDIO
00374 STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
00375 {
00376    stbi__write_context s;
00377    if (stbi__start_write_file(&s,filename)) {
00378       int r = stbi_write_bmp_core(&s, x, y, comp, data);
00379       stbi__end_write_file(&s);
00380       return r;
00381    } else
00382       return 0;
00383 }
00384 #endif //!STBI_WRITE_NO_STDIO
00385 
00386 static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data)
00387 {
00388    int has_alpha = (comp == 2 || comp == 4);
00389    int colorbytes = has_alpha ? comp-1 : comp;
00390    int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3
00391 
00392    if (y < 0 || x < 0)
00393       return 0;
00394 
00395    if (!stbi_write_tga_with_rle) {
00396       return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0,
00397          "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8);
00398    } else {
00399       int i,j,k;
00400 
00401       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);
00402 
00403       for (j = y - 1; j >= 0; --j) {
00404           unsigned char *row = (unsigned char *) data + j * x * comp;
00405          int len;
00406 
00407          for (i = 0; i < x; i += len) {
00408             unsigned char *begin = row + i * comp;
00409             int diff = 1;
00410             len = 1;
00411 
00412             if (i < x - 1) {
00413                ++len;
00414                diff = memcmp(begin, row + (i + 1) * comp, comp);
00415                if (diff) {
00416                   const unsigned char *prev = begin;
00417                   for (k = i + 2; k < x && len < 128; ++k) {
00418                      if (memcmp(prev, row + k * comp, comp)) {
00419                         prev += comp;
00420                         ++len;
00421                      } else {
00422                         --len;
00423                         break;
00424                      }
00425                   }
00426                } else {
00427                   for (k = i + 2; k < x && len < 128; ++k) {
00428                      if (!memcmp(begin, row + k * comp, comp)) {
00429                         ++len;
00430                      } else {
00431                         break;
00432                      }
00433                   }
00434                }
00435             }
00436 
00437             if (diff) {
00438                unsigned char header = STBIW_UCHAR(len - 1);
00439                s->func(s->context, &header, 1);
00440                for (k = 0; k < len; ++k) {
00441                   stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp);
00442                }
00443             } else {
00444                unsigned char header = STBIW_UCHAR(len - 129);
00445                s->func(s->context, &header, 1);
00446                stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin);
00447             }
00448          }
00449       }
00450    }
00451    return 1;
00452 }
00453 
00454 int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data)
00455 {
00456    stbi__write_context s;
00457    stbi__start_write_callbacks(&s, func, context);
00458    return stbi_write_tga_core(&s, x, y, comp, (void *) data);
00459 }
00460 
00461 #ifndef STBI_WRITE_NO_STDIO
00462 int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
00463 {
00464    stbi__write_context s;
00465    if (stbi__start_write_file(&s,filename)) {
00466       int r = stbi_write_tga_core(&s, x, y, comp, (void *) data);
00467       stbi__end_write_file(&s);
00468       return r;
00469    } else
00470       return 0;
00471 }
00472 #endif
00473 
00474 // *************************************************************************************************
00475 // Radiance RGBE HDR writer
00476 // by Baldur Karlsson
00477 #ifndef STBI_WRITE_NO_STDIO
00478 
00479 #define stbiw__max(a, b)  ((a) > (b) ? (a) : (b))
00480 
00481 void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
00482 {
00483    int exponent;
00484    float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
00485 
00486    if (maxcomp < 1e-32f) {
00487       rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
00488    } else {
00489       float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
00490 
00491       rgbe[0] = (unsigned char)(linear[0] * normalize);
00492       rgbe[1] = (unsigned char)(linear[1] * normalize);
00493       rgbe[2] = (unsigned char)(linear[2] * normalize);
00494       rgbe[3] = (unsigned char)(exponent + 128);
00495    }
00496 }
00497 
00498 void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte)
00499 {
00500    unsigned char lengthbyte = STBIW_UCHAR(length+128);
00501    STBIW_ASSERT(length+128 <= 255);
00502    s->func(s->context, &lengthbyte, 1);
00503    s->func(s->context, &databyte, 1);
00504 }
00505 
00506 void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data)
00507 {
00508    unsigned char lengthbyte = STBIW_UCHAR(length);
00509    STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
00510    s->func(s->context, &lengthbyte, 1);
00511    s->func(s->context, data, length);
00512 }
00513 
00514 void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline)
00515 {
00516    unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
00517    unsigned char rgbe[4];
00518    float linear[3];
00519    int x;
00520 
00521    scanlineheader[2] = (width&0xff00)>>8;
00522    scanlineheader[3] = (width&0x00ff);
00523 
00524    /* skip RLE for images too small or large */
00525    if (width < 8 || width >= 32768) {
00526       for (x=0; x < width; x++) {
00527          switch (ncomp) {
00528             case 4: /* fallthrough */
00529             case 3: linear[2] = scanline[x*ncomp + 2];
00530                     linear[1] = scanline[x*ncomp + 1];
00531                     linear[0] = scanline[x*ncomp + 0];
00532                     break;
00533             default:
00534                     linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
00535                     break;
00536          }
00537          stbiw__linear_to_rgbe(rgbe, linear);
00538          s->func(s->context, rgbe, 4);
00539       }
00540    } else {
00541       int c,r;
00542       /* encode into scratch buffer */
00543       for (x=0; x < width; x++) {
00544          switch(ncomp) {
00545             case 4: /* fallthrough */
00546             case 3: linear[2] = scanline[x*ncomp + 2];
00547                     linear[1] = scanline[x*ncomp + 1];
00548                     linear[0] = scanline[x*ncomp + 0];
00549                     break;
00550             default:
00551                     linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0];
00552                     break;
00553          }
00554          stbiw__linear_to_rgbe(rgbe, linear);
00555          scratch[x + width*0] = rgbe[0];
00556          scratch[x + width*1] = rgbe[1];
00557          scratch[x + width*2] = rgbe[2];
00558          scratch[x + width*3] = rgbe[3];
00559       }
00560 
00561       s->func(s->context, scanlineheader, 4);
00562 
00563       /* RLE each component separately */
00564       for (c=0; c < 4; c++) {
00565          unsigned char *comp = &scratch[width*c];
00566 
00567          x = 0;
00568          while (x < width) {
00569             // find first run
00570             r = x;
00571             while (r+2 < width) {
00572                if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
00573                   break;
00574                ++r;
00575             }
00576             if (r+2 >= width)
00577                r = width;
00578             // dump up to first run
00579             while (x < r) {
00580                int len = r-x;
00581                if (len > 128) len = 128;
00582                stbiw__write_dump_data(s, len, &comp[x]);
00583                x += len;
00584             }
00585             // if there's a run, output it
00586             if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd
00587                // find next byte after run
00588                while (r < width && comp[r] == comp[x])
00589                   ++r;
00590                // output run up to r
00591                while (x < r) {
00592                   int len = r-x;
00593                   if (len > 127) len = 127;
00594                   stbiw__write_run_data(s, len, comp[x]);
00595                   x += len;
00596                }
00597             }
00598          }
00599       }
00600    }
00601 }
00602 
00603 static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data)
00604 {
00605    if (y <= 0 || x <= 0 || data == NULL)
00606       return 0;
00607    else {
00608       // Each component is stored separately. Allocate scratch space for full output scanline.
00609       unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
00610       int i, len;
00611       char buffer[128];
00612       char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n";
00613       s->func(s->context, header, sizeof(header)-1);
00614 
00615       len = sprintf(buffer, "EXPOSURE=          1.0000000000000\n\n-Y %d +X %d\n", y, x);
00616       s->func(s->context, buffer, len);
00617 
00618       for(i=0; i < y; i++)
00619          stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*i*x);
00620       STBIW_FREE(scratch);
00621       return 1;
00622    }
00623 }
00624 
00625 int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data)
00626 {
00627    stbi__write_context s;
00628    stbi__start_write_callbacks(&s, func, context);
00629    return stbi_write_hdr_core(&s, x, y, comp, (float *) data);
00630 }
00631 
00632 int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
00633 {
00634    stbi__write_context s;
00635    if (stbi__start_write_file(&s,filename)) {
00636       int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data);
00637       stbi__end_write_file(&s);
00638       return r;
00639    } else
00640       return 0;
00641 }
00642 #endif // STBI_WRITE_NO_STDIO
00643 
00644 
00646 //
00647 // PNG writer
00648 //
00649 
00650 // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
00651 #define stbiw__sbraw(a) ((int *) (a) - 2)
00652 #define stbiw__sbm(a)   stbiw__sbraw(a)[0]
00653 #define stbiw__sbn(a)   stbiw__sbraw(a)[1]
00654 
00655 #define stbiw__sbneedgrow(a,n)  ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
00656 #define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
00657 #define stbiw__sbgrow(a,n)  stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
00658 
00659 #define stbiw__sbpush(a, v)      (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
00660 #define stbiw__sbcount(a)        ((a) ? stbiw__sbn(a) : 0)
00661 #define stbiw__sbfree(a)         ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
00662 
00663 static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
00664 {
00665    int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
00666    void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2);
00667    STBIW_ASSERT(p);
00668    if (p) {
00669       if (!*arr) ((int *) p)[1] = 0;
00670       *arr = (void *) ((int *) p + 2);
00671       stbiw__sbm(*arr) = m;
00672    }
00673    return *arr;
00674 }
00675 
00676 static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
00677 {
00678    while (*bitcount >= 8) {
00679       stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer));
00680       *bitbuffer >>= 8;
00681       *bitcount -= 8;
00682    }
00683    return data;
00684 }
00685 
00686 static int stbiw__zlib_bitrev(int code, int codebits)
00687 {
00688    int res=0;
00689    while (codebits--) {
00690       res = (res << 1) | (code & 1);
00691       code >>= 1;
00692    }
00693    return res;
00694 }
00695 
00696 static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit)
00697 {
00698    int i;
00699    for (i=0; i < limit && i < 258; ++i)
00700       if (a[i] != b[i]) break;
00701    return i;
00702 }
00703 
00704 static unsigned int stbiw__zhash(unsigned char *data)
00705 {
00706    stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
00707    hash ^= hash << 3;
00708    hash += hash >> 5;
00709    hash ^= hash << 4;
00710    hash += hash >> 17;
00711    hash ^= hash << 25;
00712    hash += hash >> 6;
00713    return hash;
00714 }
00715 
00716 #define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
00717 #define stbiw__zlib_add(code,codebits) \
00718       (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
00719 #define stbiw__zlib_huffa(b,c)  stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
00720 // default huffman tables
00721 #define stbiw__zlib_huff1(n)  stbiw__zlib_huffa(0x30 + (n), 8)
00722 #define stbiw__zlib_huff2(n)  stbiw__zlib_huffa(0x190 + (n)-144, 9)
00723 #define stbiw__zlib_huff3(n)  stbiw__zlib_huffa(0 + (n)-256,7)
00724 #define stbiw__zlib_huff4(n)  stbiw__zlib_huffa(0xc0 + (n)-280,8)
00725 #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))
00726 #define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
00727 
00728 #define stbiw__ZHASH   16384
00729 
00730 unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
00731 {
00732    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 };
00733    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 };
00734    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 };
00735    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 };
00736    unsigned int bitbuf=0;
00737    int i,j, bitcount=0;
00738    unsigned char *out = NULL;
00739    unsigned char **hash_table[stbiw__ZHASH]; // 64KB on the stack!
00740    if (quality < 5) quality = 5;
00741 
00742    stbiw__sbpush(out, 0x78);   // DEFLATE 32K window
00743    stbiw__sbpush(out, 0x5e);   // FLEVEL = 1
00744    stbiw__zlib_add(1,1);  // BFINAL = 1
00745    stbiw__zlib_add(1,2);  // BTYPE = 1 -- fixed huffman
00746 
00747    for (i=0; i < stbiw__ZHASH; ++i)
00748       hash_table[i] = NULL;
00749 
00750    i=0;
00751    while (i < data_len-3) {
00752       // hash next 3 bytes of data to be compressed
00753       int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
00754       unsigned char *bestloc = 0;
00755       unsigned char **hlist = hash_table[h];
00756       int n = stbiw__sbcount(hlist);
00757       for (j=0; j < n; ++j) {
00758          if (hlist[j]-data > i-32768) { // if entry lies within window
00759             int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
00760             if (d >= best) best=d,bestloc=hlist[j];
00761          }
00762       }
00763       // when hash table entry is too long, delete half the entries
00764       if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
00765          STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
00766          stbiw__sbn(hash_table[h]) = quality;
00767       }
00768       stbiw__sbpush(hash_table[h],data+i);
00769 
00770       if (bestloc) {
00771          // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal
00772          h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
00773          hlist = hash_table[h];
00774          n = stbiw__sbcount(hlist);
00775          for (j=0; j < n; ++j) {
00776             if (hlist[j]-data > i-32767) {
00777                int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
00778                if (e > best) { // if next match is better, bail on current match
00779                   bestloc = NULL;
00780                   break;
00781                }
00782             }
00783          }
00784       }
00785 
00786       if (bestloc) {
00787          int d = (int) (data+i - bestloc); // distance back
00788          STBIW_ASSERT(d <= 32767 && best <= 258);
00789          for (j=0; best > lengthc[j+1]-1; ++j);
00790          stbiw__zlib_huff(j+257);
00791          if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
00792          for (j=0; d > distc[j+1]-1; ++j);
00793          stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
00794          if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
00795          i += best;
00796       } else {
00797          stbiw__zlib_huffb(data[i]);
00798          ++i;
00799       }
00800    }
00801    // write out final bytes
00802    for (;i < data_len; ++i)
00803       stbiw__zlib_huffb(data[i]);
00804    stbiw__zlib_huff(256); // end of block
00805    // pad with 0 bits to byte boundary
00806    while (bitcount)
00807       stbiw__zlib_add(0,1);
00808 
00809    for (i=0; i < stbiw__ZHASH; ++i)
00810       (void) stbiw__sbfree(hash_table[i]);
00811 
00812    {
00813       // compute adler32 on input
00814       unsigned int s1=1, s2=0;
00815       int blocklen = (int) (data_len % 5552);
00816       j=0;
00817       while (j < data_len) {
00818          for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
00819          s1 %= 65521, s2 %= 65521;
00820          j += blocklen;
00821          blocklen = 5552;
00822       }
00823       stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8));
00824       stbiw__sbpush(out, STBIW_UCHAR(s2));
00825       stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8));
00826       stbiw__sbpush(out, STBIW_UCHAR(s1));
00827    }
00828    *out_len = stbiw__sbn(out);
00829    // make returned pointer freeable
00830    STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
00831    return (unsigned char *) stbiw__sbraw(out);
00832 }
00833 
00834 static unsigned int stbiw__crc32(unsigned char *buffer, int len)
00835 {
00836    static unsigned int crc_table[256] =
00837    {
00838       0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
00839       0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
00840       0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
00841       0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
00842       0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
00843       0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
00844       0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
00845       0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
00846       0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
00847       0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
00848       0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
00849       0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
00850       0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
00851       0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
00852       0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
00853       0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
00854       0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
00855       0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
00856       0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
00857       0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
00858       0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
00859       0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
00860       0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
00861       0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
00862       0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
00863       0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
00864       0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
00865       0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
00866       0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
00867       0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
00868       0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
00869       0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
00870    };
00871 
00872    unsigned int crc = ~0u;
00873    int i;
00874    for (i=0; i < len; ++i)
00875       crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
00876    return ~crc;
00877 }
00878 
00879 #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)
00880 #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
00881 #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
00882 
00883 static void stbiw__wpcrc(unsigned char **data, int len)
00884 {
00885    unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
00886    stbiw__wp32(*data, crc);
00887 }
00888 
00889 static unsigned char stbiw__paeth(int a, int b, int c)
00890 {
00891    int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
00892    if (pa <= pb && pa <= pc) return STBIW_UCHAR(a);
00893    if (pb <= pc) return STBIW_UCHAR(b);
00894    return STBIW_UCHAR(c);
00895 }
00896 
00897 unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
00898 {
00899    int ctype[5] = { -1, 0, 4, 2, 6 };
00900    unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
00901    unsigned char *out,*o, *filt, *zlib;
00902    signed char *line_buffer;
00903    int i,j,k,p,zlen;
00904 
00905    if (stride_bytes == 0)
00906       stride_bytes = x * n;
00907 
00908    filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
00909    line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
00910    for (j=0; j < y; ++j) {
00911       static int mapping[] = { 0,1,2,3,4 };
00912       static int firstmap[] = { 0,1,0,5,6 };
00913       int *mymap = j ? mapping : firstmap;
00914       int best = 0, bestval = 0x7fffffff;
00915       for (p=0; p < 2; ++p) {
00916          for (k= p?best:0; k < 5; ++k) {
00917             int type = mymap[k],est=0;
00918             unsigned char *z = pixels + stride_bytes*j;
00919             for (i=0; i < n; ++i)
00920                switch (type) {
00921                   case 0: line_buffer[i] = z[i]; break;
00922                   case 1: line_buffer[i] = z[i]; break;
00923                   case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
00924                   case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break;
00925                   case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break;
00926                   case 5: line_buffer[i] = z[i]; break;
00927                   case 6: line_buffer[i] = z[i]; break;
00928                }
00929             for (i=n; i < x*n; ++i) {
00930                switch (type) {
00931                   case 0: line_buffer[i] = z[i]; break;
00932                   case 1: line_buffer[i] = z[i] - z[i-n]; break;
00933                   case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
00934                   case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break;
00935                   case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break;
00936                   case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break;
00937                   case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
00938                }
00939             }
00940             if (p) break;
00941             for (i=0; i < x*n; ++i)
00942                est += abs((signed char) line_buffer[i]);
00943             if (est < bestval) { bestval = est; best = k; }
00944          }
00945       }
00946       // when we get here, best contains the filter type, and line_buffer contains the data
00947       filt[j*(x*n+1)] = (unsigned char) best;
00948       STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
00949    }
00950    STBIW_FREE(line_buffer);
00951    zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory
00952    STBIW_FREE(filt);
00953    if (!zlib) return 0;
00954 
00955    // each tag requires 12 bytes of overhead
00956    out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
00957    if (!out) return 0;
00958    *out_len = 8 + 12+13 + 12+zlen + 12;
00959 
00960    o=out;
00961    STBIW_MEMMOVE(o,sig,8); o+= 8;
00962    stbiw__wp32(o, 13); // header length
00963    stbiw__wptag(o, "IHDR");
00964    stbiw__wp32(o, x);
00965    stbiw__wp32(o, y);
00966    *o++ = 8;
00967    *o++ = STBIW_UCHAR(ctype[n]);
00968    *o++ = 0;
00969    *o++ = 0;
00970    *o++ = 0;
00971    stbiw__wpcrc(&o,13);
00972 
00973    stbiw__wp32(o, zlen);
00974    stbiw__wptag(o, "IDAT");
00975    STBIW_MEMMOVE(o, zlib, zlen);
00976    o += zlen;
00977    STBIW_FREE(zlib);
00978    stbiw__wpcrc(&o, zlen);
00979 
00980    stbiw__wp32(o,0);
00981    stbiw__wptag(o, "IEND");
00982    stbiw__wpcrc(&o,0);
00983 
00984    STBIW_ASSERT(o == out + *out_len);
00985 
00986    return out;
00987 }
00988 
00989 #ifndef STBI_WRITE_NO_STDIO
00990 STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
00991 {
00992    FILE *f;
00993    int len;
00994    unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
00995    if (png == NULL) return 0;
00996    f = fopen(filename, "wb");
00997    if (!f) { STBIW_FREE(png); return 0; }
00998    fwrite(png, 1, len, f);
00999    fclose(f);
01000    STBIW_FREE(png);
01001    return 1;
01002 }
01003 #endif
01004 
01005 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)
01006 {
01007    int len;
01008    unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
01009    if (png == NULL) return 0;
01010    func(context, png, len);
01011    STBIW_FREE(png);
01012    return 1;
01013 }
01014 
01015 #endif // STB_IMAGE_WRITE_IMPLEMENTATION
01016 
01017 /* Revision history
01018       1.01 (2016-01-16)
01019              STBIW_REALLOC_SIZED: support allocators with no realloc support
01020              avoid race-condition in crc initialization
01021              minor compile issues
01022       1.00 (2015-09-14)
01023              installable file IO function
01024       0.99 (2015-09-13)
01025              warning fixes; TGA rle support
01026       0.98 (2015-04-08)
01027              added STBIW_MALLOC, STBIW_ASSERT etc
01028       0.97 (2015-01-18)
01029              fixed HDR asserts, rewrote HDR rle logic
01030       0.96 (2015-01-17)
01031              add HDR output
01032              fix monochrome BMP
01033       0.95 (2014-08-17)
01034                        add monochrome TGA output
01035       0.94 (2014-05-31)
01036              rename private functions to avoid conflicts with stb_image.h
01037       0.93 (2014-05-27)
01038              warning fixes
01039       0.92 (2010-08-01)
01040              casts to unsigned char to fix warnings
01041       0.91 (2010-07-17)
01042              first public release
01043       0.90   first internal release
01044 */


librealsense
Author(s): Sergey Dorodnicov , Mark Horn , Reagan Lopez
autogenerated on Tue Jun 25 2019 19:54:39