stb_image_write.h
Go to the documentation of this file.
00001 /* stb_image_write - v0.98 - public domain - http://nothings.org/stb/stb_image_write.h
00002    writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010
00003                             no warranty implied; use at your own risk
00004 
00005 
00006    Before #including,
00007 
00008        #define STB_IMAGE_WRITE_IMPLEMENTATION
00009 
00010    in the file that you want to have the implementation.
00011 
00012    Will probably not work correctly with strict-aliasing optimizations.
00013 
00014 ABOUT:
00015 
00016    This header file is a library for writing images to C stdio. It could be
00017    adapted to write to memory or a general streaming interface; let me know.
00018 
00019    The PNG output is not optimal; it is 20-50% larger than the file
00020    written by a decent optimizing implementation. This library is designed
00021    for source code compactness and simplicitly, not optimal image file size
00022    or run-time performance.
00023 
00024 BUILDING:
00025 
00026    You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h.
00027    You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace
00028    malloc,realloc,free.
00029    You can define STBIW_MEMMOVE() to replace memmove()
00030 
00031 USAGE:
00032 
00033    There are four functions, one for each image file format:
00034 
00035      int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
00036      int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
00037      int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
00038      int stbi_write_hdr(char const *filename, int w, int h, int comp, const void *data);
00039 
00040    Each function returns 0 on failure and non-0 on success.
00041 
00042    The functions create an image file defined by the parameters. The image
00043    is a rectangle of pixels stored from left-to-right, top-to-bottom.
00044    Each pixel contains 'comp' channels of data stored interleaved with 8-bits
00045    per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is
00046    monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall.
00047    The *data pointer points to the first byte of the top-left-most pixel.
00048    For PNG, "stride_in_bytes" is the distance in bytes from the first byte of
00049    a row of pixels to the first byte of the next row of pixels.
00050 
00051    PNG creates output files with the same number of components as the input.
00052    The BMP format expands Y to RGB in the file format and does not
00053    output alpha.
00054 
00055    PNG supports writing rectangles of data even when the bytes storing rows of
00056    data are not consecutive in memory (e.g. sub-rectangles of a larger image),
00057    by supplying the stride between the beginning of adjacent rows. The other
00058    formats do not. (Thus you cannot write a native-format BMP through the BMP
00059    writer, both because it is in BGR order and because it may have padding
00060    at the end of the line.)
00061 
00062    HDR expects linear float data. Since the format is always 32-bit rgb(e)
00063    data, alpha (if provided) is discarded, and for monochrome data it is
00064    replicated across all three channels.
00065 
00066 CREDITS:
00067 
00068    PNG/BMP/TGA
00069       Sean Barrett
00070    HDR
00071       Baldur Karlsson
00072    TGA monochrome:
00073       Jean-Sebastien Guay
00074    misc enhancements:
00075       Tim Kelsey
00076    bugfixes:
00077       github:Chribba
00078 */
00079 
00080 #ifndef INCLUDE_STB_IMAGE_WRITE_H
00081 #define INCLUDE_STB_IMAGE_WRITE_H
00082 
00083 #ifdef __cplusplus
00084 extern "C" {
00085 #endif
00086 
00087 extern int stbi_write_png(char const *filename, int w, int h, int comp, const void  *data, int stride_in_bytes);
00088 extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void  *data);
00089 extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void  *data);
00090 extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
00091 
00092 #ifdef __cplusplus
00093 }
00094 #endif
00095 
00096 #endif//INCLUDE_STB_IMAGE_WRITE_H
00097 
00098 #ifdef STB_IMAGE_WRITE_IMPLEMENTATION
00099 
00100 #include <stdarg.h>
00101 #include <stdlib.h>
00102 #include <stdio.h>
00103 #include <string.h>
00104 #include <math.h>
00105 
00106 #if defined(STBIW_MALLOC) && defined(STBIW_FREE) && defined(STBIW_REALLOC)
00107 // ok
00108 #elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC)
00109 // ok
00110 #else
00111 #error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC."
00112 #endif
00113 
00114 #ifndef STBIW_MALLOC
00115 #define STBIW_MALLOC(sz)    malloc(sz)
00116 #define STBIW_REALLOC(p,sz) realloc(p,sz)
00117 #define STBIW_FREE(p)       free(p)
00118 #endif
00119 #ifndef STBIW_MEMMOVE
00120 #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
00121 #endif
00122 
00123 
00124 #ifndef STBIW_ASSERT
00125 #include <assert.h>
00126 #define STBIW_ASSERT(x) assert(x)
00127 #endif
00128 
00129 typedef unsigned int stbiw_uint32;
00130 typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
00131 
00132 static void writefv(FILE *f, const char *fmt, va_list v)
00133 {
00134    while (*fmt) {
00135       switch (*fmt++) {
00136          case ' ': break;
00137          case '1': { unsigned char x = (unsigned char) va_arg(v, int); fputc(x,f); break; }
00138          case '2': { int x = va_arg(v,int); unsigned char b[2];
00139                      b[0] = (unsigned char) x; b[1] = (unsigned char) (x>>8);
00140                      fwrite(b,2,1,f); break; }
00141          case '4': { stbiw_uint32 x = va_arg(v,int); unsigned char b[4];
00142                      b[0]=(unsigned char)x; b[1]=(unsigned char)(x>>8);
00143                      b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24);
00144                      fwrite(b,4,1,f); break; }
00145          default:
00146             STBIW_ASSERT(0);
00147             return;
00148       }
00149    }
00150 }
00151 
00152 static void write3(FILE *f, unsigned char a, unsigned char b, unsigned char c)
00153 {
00154    unsigned char arr[3];
00155    arr[0] = a, arr[1] = b, arr[2] = c;
00156    fwrite(arr, 3, 1, f);
00157 }
00158 
00159 static void write_pixels(FILE *f, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono)
00160 {
00161    unsigned char bg[3] = { 255, 0, 255}, px[3];
00162    stbiw_uint32 zero = 0;
00163    int i,j,k, j_end;
00164 
00165    if (y <= 0)
00166       return;
00167 
00168    if (vdir < 0)
00169       j_end = -1, j = y-1;
00170    else
00171       j_end =  y, j = 0;
00172 
00173    for (; j != j_end; j += vdir) {
00174       for (i=0; i < x; ++i) {
00175          unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
00176          if (write_alpha < 0)
00177             fwrite(&d[comp-1], 1, 1, f);
00178          switch (comp) {
00179             case 1: fwrite(d, 1, 1, f);
00180                     break;
00181             case 2: if (expand_mono)
00182                        write3(f, d[0],d[0],d[0]); // monochrome bmp
00183                     else
00184                        fwrite(d, 1, 1, f);  // monochrome TGA
00185                     break;
00186             case 4:
00187                if (!write_alpha) {
00188                   // composite against pink background
00189                   for (k=0; k < 3; ++k)
00190                      px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255;
00191                   write3(f, px[1-rgb_dir],px[1],px[1+rgb_dir]);
00192                   break;
00193                }
00194                /* FALLTHROUGH */
00195             case 3:
00196                write3(f, d[1-rgb_dir],d[1],d[1+rgb_dir]);
00197                break;
00198          }
00199          if (write_alpha > 0)
00200             fwrite(&d[comp-1], 1, 1, f);
00201       }
00202       fwrite(&zero,scanline_pad,1,f);
00203    }
00204 }
00205 
00206 static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...)
00207 {
00208    FILE *f;
00209    if (y < 0 || x < 0) return 0;
00210    f = fopen(filename, "wb");
00211    if (f) {
00212       va_list v;
00213       va_start(v, fmt);
00214       writefv(f, fmt, v);
00215       va_end(v);
00216       write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad,expand_mono);
00217       fclose(f);
00218    }
00219    return f != NULL;
00220 }
00221 
00222 int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
00223 {
00224    int pad = (-x*3) & 3;
00225    return outfile(filename,-1,-1,x,y,comp,1,(void *) data,0,pad,
00226            "11 4 22 4" "4 44 22 444444",
00227            'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40,  // file header
00228             40, x,y, 1,24, 0,0,0,0,0,0);             // bitmap header
00229 }
00230 
00231 int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
00232 {
00233    int has_alpha = (comp == 2 || comp == 4);
00234    int colorbytes = has_alpha ? comp-1 : comp;
00235    int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3
00236    return outfile(filename, -1,-1, x, y, comp, 0, (void *) data, has_alpha, 0,
00237                   "111 221 2222 11", 0,0,format, 0,0,0, 0,0,x,y, (colorbytes+has_alpha)*8, has_alpha*8);
00238 }
00239 
00240 // *************************************************************************************************
00241 // Radiance RGBE HDR writer
00242 // by Baldur Karlsson
00243 #define stbiw__max(a, b)  ((a) > (b) ? (a) : (b))
00244 
00245 void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
00246 {
00247    int exponent;
00248    float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
00249 
00250    if (maxcomp < 1e-32) {
00251       rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
00252    } else {
00253       float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
00254 
00255       rgbe[0] = (unsigned char)(linear[0] * normalize);
00256       rgbe[1] = (unsigned char)(linear[1] * normalize);
00257       rgbe[2] = (unsigned char)(linear[2] * normalize);
00258       rgbe[3] = (unsigned char)(exponent + 128);
00259    }
00260 }
00261 
00262 void stbiw__write_run_data(FILE *f, int length, unsigned char databyte)
00263 {
00264    unsigned char lengthbyte = (unsigned char) (length+128);
00265    STBIW_ASSERT(length+128 <= 255);
00266    fwrite(&lengthbyte, 1, 1, f);
00267    fwrite(&databyte, 1, 1, f);
00268 }
00269 
00270 void stbiw__write_dump_data(FILE *f, int length, unsigned char *data)
00271 {
00272    unsigned char lengthbyte = (unsigned char )(length & 0xff);
00273    STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
00274    fwrite(&lengthbyte, 1, 1, f);
00275    fwrite(data, length, 1, f);
00276 }
00277 
00278 void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scratch, const float *scanline)
00279 {
00280    unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
00281    unsigned char rgbe[4];
00282    float linear[3] = {0};
00283    int x;
00284 
00285    scanlineheader[2] = (width&0xff00)>>8;
00286    scanlineheader[3] = (width&0x00ff);
00287 
00288    /* skip RLE for images too small or large */
00289    if (width < 8 || width >= 32768) {
00290       for (x=0; x < width; x++) {
00291          switch (comp) {
00292             case 4: /* fallthrough */
00293             case 3: linear[2] = scanline[x*comp + 2];
00294                     linear[1] = scanline[x*comp + 1];
00295                     linear[0] = scanline[x*comp + 0];
00296                     break;
00297             case 2: /* fallthrough */
00298             case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0];
00299                     break;
00300          }
00301          stbiw__linear_to_rgbe(rgbe, linear);
00302          fwrite(rgbe, 4, 1, f);
00303       }
00304    } else {
00305       int c,r;
00306       /* encode into scratch buffer */
00307       for (x=0; x < width; x++) {
00308          switch(comp) {
00309             case 4: /* fallthrough */
00310             case 3: linear[2] = scanline[x*comp + 2];
00311                     linear[1] = scanline[x*comp + 1];
00312                     linear[0] = scanline[x*comp + 0];
00313                     break;
00314             case 2: /* fallthrough */
00315             case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0];
00316                     break;
00317          }
00318          stbiw__linear_to_rgbe(rgbe, linear);
00319          scratch[x + width*0] = rgbe[0];
00320          scratch[x + width*1] = rgbe[1];
00321          scratch[x + width*2] = rgbe[2];
00322          scratch[x + width*3] = rgbe[3];
00323       }
00324 
00325       fwrite(scanlineheader, 4, 1, f);
00326 
00327       /* RLE each component separately */
00328       for (c=0; c < 4; c++) {
00329          unsigned char *comp = &scratch[width*c];
00330 
00331          x = 0;
00332          while (x < width) {
00333             // find first run
00334             r = x;
00335             while (r+2 < width) {
00336                if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
00337                   break;
00338                ++r;
00339             }
00340             if (r+2 >= width)
00341                r = width;
00342             // dump up to first run
00343             while (x < r) {
00344                int len = r-x;
00345                if (len > 128) len = 128;
00346                stbiw__write_dump_data(f, len, &comp[x]);
00347                x += len;
00348             }
00349             // if there's a run, output it
00350             if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd
00351                // find next byte after run
00352                while (r < width && comp[r] == comp[x])
00353                   ++r;
00354                // output run up to r
00355                while (x < r) {
00356                   int len = r-x;
00357                   if (len > 127) len = 127;
00358                   stbiw__write_run_data(f, len, comp[x]);
00359                   x += len;
00360                }
00361             }
00362          }
00363       }
00364    }
00365 }
00366 
00367 int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
00368 {
00369    int i;
00370    FILE *f;
00371    if (y <= 0 || x <= 0 || data == NULL) return 0;
00372    f = fopen(filename, "wb");
00373    if (f) {
00374       /* Each component is stored separately. Allocate scratch space for full output scanline. */
00375       unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
00376       fprintf(f, "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"      );
00377       fprintf(f, "EXPOSURE=          1.0000000000000\n\n-Y %d +X %d\n"                 , y, x);
00378       for(i=0; i < y; i++)
00379          stbiw__write_hdr_scanline(f, x, comp, scratch, data + comp*i*x);
00380       STBIW_FREE(scratch);
00381       fclose(f);
00382    }
00383    return f != NULL;
00384 }
00385 
00387 // PNG
00388 
00389 // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
00390 #define stbiw__sbraw(a) ((int *) (a) - 2)
00391 #define stbiw__sbm(a)   stbiw__sbraw(a)[0]
00392 #define stbiw__sbn(a)   stbiw__sbraw(a)[1]
00393 
00394 #define stbiw__sbneedgrow(a,n)  ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
00395 #define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
00396 #define stbiw__sbgrow(a,n)  stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
00397 
00398 #define stbiw__sbpush(a, v)      (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
00399 #define stbiw__sbcount(a)        ((a) ? stbiw__sbn(a) : 0)
00400 #define stbiw__sbfree(a)         ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
00401 
00402 static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
00403 {
00404    int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
00405    void *p = STBIW_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2);
00406    STBIW_ASSERT(p);
00407    if (p) {
00408       if (!*arr) ((int *) p)[1] = 0;
00409       *arr = (void *) ((int *) p + 2);
00410       stbiw__sbm(*arr) = m;
00411    }
00412    return *arr;
00413 }
00414 
00415 static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
00416 {
00417    while (*bitcount >= 8) {
00418       stbiw__sbpush(data, (unsigned char) *bitbuffer);
00419       *bitbuffer >>= 8;
00420       *bitcount -= 8;
00421    }
00422    return data;
00423 }
00424 
00425 static int stbiw__zlib_bitrev(int code, int codebits)
00426 {
00427    int res=0;
00428    while (codebits--) {
00429       res = (res << 1) | (code & 1);
00430       code >>= 1;
00431    }
00432    return res;
00433 }
00434 
00435 static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit)
00436 {
00437    int i;
00438    for (i=0; i < limit && i < 258; ++i)
00439       if (a[i] != b[i]) break;
00440    return i;
00441 }
00442 
00443 static unsigned int stbiw__zhash(unsigned char *data)
00444 {
00445    stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
00446    hash ^= hash << 3;
00447    hash += hash >> 5;
00448    hash ^= hash << 4;
00449    hash += hash >> 17;
00450    hash ^= hash << 25;
00451    hash += hash >> 6;
00452    return hash;
00453 }
00454 
00455 #define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
00456 #define stbiw__zlib_add(code,codebits) \
00457       (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
00458 #define stbiw__zlib_huffa(b,c)  stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
00459 // default huffman tables
00460 #define stbiw__zlib_huff1(n)  stbiw__zlib_huffa(0x30 + (n), 8)
00461 #define stbiw__zlib_huff2(n)  stbiw__zlib_huffa(0x190 + (n)-144, 9)
00462 #define stbiw__zlib_huff3(n)  stbiw__zlib_huffa(0 + (n)-256,7)
00463 #define stbiw__zlib_huff4(n)  stbiw__zlib_huffa(0xc0 + (n)-280,8)
00464 #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))
00465 #define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
00466 
00467 #define stbiw__ZHASH   16384
00468 
00469 unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
00470 {
00471    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 };
00472    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 };
00473    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 };
00474    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 };
00475    unsigned int bitbuf=0;
00476    int i,j, bitcount=0;
00477    unsigned char *out = NULL;
00478    unsigned char **hash_table[stbiw__ZHASH]; // 64KB on the stack!
00479    if (quality < 5) quality = 5;
00480 
00481    stbiw__sbpush(out, 0x78);   // DEFLATE 32K window
00482    stbiw__sbpush(out, 0x5e);   // FLEVEL = 1
00483    stbiw__zlib_add(1,1);  // BFINAL = 1
00484    stbiw__zlib_add(1,2);  // BTYPE = 1 -- fixed huffman
00485 
00486    for (i=0; i < stbiw__ZHASH; ++i)
00487       hash_table[i] = NULL;
00488 
00489    i=0;
00490    while (i < data_len-3) {
00491       // hash next 3 bytes of data to be compressed
00492       int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
00493       unsigned char *bestloc = 0;
00494       unsigned char **hlist = hash_table[h];
00495       int n = stbiw__sbcount(hlist);
00496       for (j=0; j < n; ++j) {
00497          if (hlist[j]-data > i-32768) { // if entry lies within window
00498             int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
00499             if (d >= best) best=d,bestloc=hlist[j];
00500          }
00501       }
00502       // when hash table entry is too long, delete half the entries
00503       if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
00504          STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
00505          stbiw__sbn(hash_table[h]) = quality;
00506       }
00507       stbiw__sbpush(hash_table[h],data+i);
00508 
00509       if (bestloc) {
00510          // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal
00511          h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
00512          hlist = hash_table[h];
00513          n = stbiw__sbcount(hlist);
00514          for (j=0; j < n; ++j) {
00515             if (hlist[j]-data > i-32767) {
00516                int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
00517                if (e > best) { // if next match is better, bail on current match
00518                   bestloc = NULL;
00519                   break;
00520                }
00521             }
00522          }
00523       }
00524 
00525       if (bestloc) {
00526          int d = (int) (data+i - bestloc); // distance back
00527          STBIW_ASSERT(d <= 32767 && best <= 258);
00528          for (j=0; best > lengthc[j+1]-1; ++j);
00529          stbiw__zlib_huff(j+257);
00530          if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
00531          for (j=0; d > distc[j+1]-1; ++j);
00532          stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
00533          if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
00534          i += best;
00535       } else {
00536          stbiw__zlib_huffb(data[i]);
00537          ++i;
00538       }
00539    }
00540    // write out final bytes
00541    for (;i < data_len; ++i)
00542       stbiw__zlib_huffb(data[i]);
00543    stbiw__zlib_huff(256); // end of block
00544    // pad with 0 bits to byte boundary
00545    while (bitcount)
00546       stbiw__zlib_add(0,1);
00547 
00548    for (i=0; i < stbiw__ZHASH; ++i)
00549       (void) stbiw__sbfree(hash_table[i]);
00550 
00551    {
00552       // compute adler32 on input
00553       unsigned int i=0, s1=1, s2=0, blocklen = data_len % 5552;
00554       int j=0;
00555       while (j < data_len) {
00556          for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
00557          s1 %= 65521, s2 %= 65521;
00558          j += blocklen;
00559          blocklen = 5552;
00560       }
00561       stbiw__sbpush(out, (unsigned char) (s2 >> 8));
00562       stbiw__sbpush(out, (unsigned char) s2);
00563       stbiw__sbpush(out, (unsigned char) (s1 >> 8));
00564       stbiw__sbpush(out, (unsigned char) s1);
00565    }
00566    *out_len = stbiw__sbn(out);
00567    // make returned pointer freeable
00568    STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
00569    return (unsigned char *) stbiw__sbraw(out);
00570 }
00571 
00572 unsigned int stbiw__crc32(unsigned char *buffer, int len)
00573 {
00574    static unsigned int crc_table[256];
00575    unsigned int crc = ~0u;
00576    int i,j;
00577    if (crc_table[1] == 0)
00578       for(i=0; i < 256; i++)
00579          for (crc_table[i]=i, j=0; j < 8; ++j)
00580             crc_table[i] = (crc_table[i] >> 1) ^ (crc_table[i] & 1 ? 0xedb88320 : 0);
00581    for (i=0; i < len; ++i)
00582       crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
00583    return ~crc;
00584 }
00585 
00586 #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)
00587 #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
00588 #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
00589 
00590 static void stbiw__wpcrc(unsigned char **data, int len)
00591 {
00592    unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
00593    stbiw__wp32(*data, crc);
00594 }
00595 
00596 static unsigned char stbiw__paeth(int a, int b, int c)
00597 {
00598    int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
00599    if (pa <= pb && pa <= pc) return (unsigned char) a;
00600    if (pb <= pc) return (unsigned char) b;
00601    return (unsigned char) c;
00602 }
00603 
00604 unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
00605 {
00606    int ctype[5] = { -1, 0, 4, 2, 6 };
00607    unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
00608    unsigned char *out,*o, *filt, *zlib;
00609    signed char *line_buffer;
00610    int i,j,k,p,zlen;
00611 
00612    if (stride_bytes == 0)
00613       stride_bytes = x * n;
00614 
00615    filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
00616    line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
00617    for (j=0; j < y; ++j) {
00618       static int mapping[] = { 0,1,2,3,4 };
00619       static int firstmap[] = { 0,1,0,5,6 };
00620       int *mymap = j ? mapping : firstmap;
00621       int best = 0, bestval = 0x7fffffff;
00622       for (p=0; p < 2; ++p) {
00623          for (k= p?best:0; k < 5; ++k) {
00624             int type = mymap[k],est=0;
00625             unsigned char *z = pixels + stride_bytes*j;
00626             for (i=0; i < n; ++i)
00627                switch (type) {
00628                   case 0: line_buffer[i] = z[i]; break;
00629                   case 1: line_buffer[i] = z[i]; break;
00630                   case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
00631                   case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break;
00632                   case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break;
00633                   case 5: line_buffer[i] = z[i]; break;
00634                   case 6: line_buffer[i] = z[i]; break;
00635                }
00636             for (i=n; i < x*n; ++i) {
00637                switch (type) {
00638                   case 0: line_buffer[i] = z[i]; break;
00639                   case 1: line_buffer[i] = z[i] - z[i-n]; break;
00640                   case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
00641                   case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break;
00642                   case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break;
00643                   case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break;
00644                   case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
00645                }
00646             }
00647             if (p) break;
00648             for (i=0; i < x*n; ++i)
00649                est += abs((signed char) line_buffer[i]);
00650             if (est < bestval) { bestval = est; best = k; }
00651          }
00652       }
00653       // when we get here, best contains the filter type, and line_buffer contains the data
00654       filt[j*(x*n+1)] = (unsigned char) best;
00655       STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
00656    }
00657    STBIW_FREE(line_buffer);
00658    zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory
00659    STBIW_FREE(filt);
00660    if (!zlib) return 0;
00661 
00662    // each tag requires 12 bytes of overhead
00663    out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
00664    if (!out) return 0;
00665    *out_len = 8 + 12+13 + 12+zlen + 12;
00666 
00667    o=out;
00668    STBIW_MEMMOVE(o,sig,8); o+= 8;
00669    stbiw__wp32(o, 13); // header length
00670    stbiw__wptag(o, "IHDR");
00671    stbiw__wp32(o, x);
00672    stbiw__wp32(o, y);
00673    *o++ = 8;
00674    *o++ = (unsigned char) ctype[n];
00675    *o++ = 0;
00676    *o++ = 0;
00677    *o++ = 0;
00678    stbiw__wpcrc(&o,13);
00679 
00680    stbiw__wp32(o, zlen);
00681    stbiw__wptag(o, "IDAT");
00682    STBIW_MEMMOVE(o, zlib, zlen);
00683    o += zlen;
00684    STBIW_FREE(zlib);
00685    stbiw__wpcrc(&o, zlen);
00686 
00687    stbiw__wp32(o,0);
00688    stbiw__wptag(o, "IEND");
00689    stbiw__wpcrc(&o,0);
00690 
00691    STBIW_ASSERT(o == out + *out_len);
00692 
00693    return out;
00694 }
00695 
00696 int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
00697 {
00698    FILE *f;
00699    int len;
00700    unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
00701    if (!png) return 0;
00702    f = fopen(filename, "wb");
00703    if (!f) { STBIW_FREE(png); return 0; }
00704    fwrite(png, 1, len, f);
00705    fclose(f);
00706    STBIW_FREE(png);
00707    return 1;
00708 }
00709 #endif // STB_IMAGE_WRITE_IMPLEMENTATION
00710 
00711 /* Revision history
00712       0.98 (2015-04-08)
00713              added STBIW_MALLOC, STBIW_ASSERT etc
00714       0.97 (2015-01-18)
00715              fixed HDR asserts, rewrote HDR rle logic
00716       0.96 (2015-01-17)
00717              add HDR output
00718              fix monochrome BMP
00719       0.95 (2014-08-17)
00720                        add monochrome TGA output
00721       0.94 (2014-05-31)
00722              rename private functions to avoid conflicts with stb_image.h
00723       0.93 (2014-05-27)
00724              warning fixes
00725       0.92 (2010-08-01)
00726              casts to unsigned char to fix warnings
00727       0.91 (2010-07-17)
00728              first public release
00729       0.90   first internal release
00730 */


rail_object_detector
Author(s):
autogenerated on Sat Jun 8 2019 20:26:31