OpenRaider  0.1.4-dev
Open Source Tomb Raider Game Engine implementation
stb_image_write.h
Go to the documentation of this file.
1 /* stb_image_write - v0.95 - public domain - http://nothings.org/stb/stb_image_write.h
2  writes out PNG/BMP/TGA images to C stdio - Sean Barrett 2010
3  no warranty implied; use at your own risk
4 
5 
6 Before including,
7 
8  #define STB_IMAGE_WRITE_IMPLEMENTATION
9 
10 in the file that you want to have the implementation.
11 
12 Will probably not work correctly with strict-aliasing optimizations.
13 
14 
15 ABOUT:
16 
17  This header file is a library for writing images to C stdio. It could be
18  adapted to write to memory or a general streaming interface; let me know.
19 
20  The PNG output is not optimal; it is 20-50% larger than the file
21  written by a decent optimizing implementation. This library is designed
22  for source code compactness and simplicitly, not optimal image file size
23  or run-time performance.
24 
25 USAGE:
26 
27  There are three functions, one for each image file format:
28 
29  int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
30  int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
31  int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
32 
33  Each function returns 0 on failure and non-0 on success.
34 
35  The functions create an image file defined by the parameters. The image
36  is a rectangle of pixels stored from left-to-right, top-to-bottom.
37  Each pixel contains 'comp' channels of data stored interleaved with 8-bits
38  per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is
39  monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall.
40  The *data pointer points to the first byte of the top-left-most pixel.
41  For PNG, "stride_in_bytes" is the distance in bytes from the first byte of
42  a row of pixels to the first byte of the next row of pixels.
43 
44  PNG creates output files with the same number of components as the input.
45  The BMP format expands Y to RGB in the file format and does not
46  output alpha.
47 
48  PNG supports writing rectangles of data even when the bytes storing rows of
49  data are not consecutive in memory (e.g. sub-rectangles of a larger image),
50  by supplying the stride between the beginning of adjacent rows. The other
51  formats do not. (Thus you cannot write a native-format BMP through the BMP
52  writer, both because it is in BGR order and because it may have padding
53  at the end of the line.)
54 */
55 
56 #ifndef INCLUDE_STB_IMAGE_WRITE_H
57 #define INCLUDE_STB_IMAGE_WRITE_H
58 
59 #ifdef __cplusplus
60 extern "C" {
61 #endif
62 
63 extern int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
64 extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
65 extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
66 
67 #ifdef __cplusplus
68 }
69 #endif
70 
71 #endif//INCLUDE_STB_IMAGE_WRITE_H
72 
73 #ifdef STB_IMAGE_WRITE_IMPLEMENTATION
74 
75 #include <stdarg.h>
76 #include <stdlib.h>
77 #include <stdio.h>
78 #include <string.h>
79 
80 #ifndef STBI_ASSERT
81 #include <assert.h>
82 #define STBI_ASSERT(x) assert(x)
83 #endif
84 
85 typedef unsigned int stbiw_uint32;
86 typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
87 
88 static void writefv(FILE *f, const char *fmt, va_list v)
89 {
90  while (*fmt) {
91  switch (*fmt++) {
92  case ' ': break;
93  case '1': { unsigned char x = (unsigned char) va_arg(v, int); fputc(x,f); break; }
94  case '2': { int x = va_arg(v,int); unsigned char b[2];
95  b[0] = (unsigned char) x; b[1] = (unsigned char) (x>>8);
96  fwrite(b,2,1,f); break; }
97  case '4': { stbiw_uint32 x = va_arg(v,int); unsigned char b[4];
98  b[0]=(unsigned char)x; b[1]=(unsigned char)(x>>8);
99  b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24);
100  fwrite(b,4,1,f); break; }
101  default:
102  STBI_ASSERT(0);
103  return;
104  }
105  }
106 }
107 
108 static void write3(FILE *f, unsigned char a, unsigned char b, unsigned char c)
109 {
110  unsigned char arr[3];
111  arr[0] = a, arr[1] = b, arr[2] = c;
112  fwrite(arr, 3, 1, f);
113 }
114 
115 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)
116 {
117  unsigned char bg[3] = { 255, 0, 255}, px[3];
118  stbiw_uint32 zero = 0;
119  int i,j,k, j_end;
120 
121  if (y <= 0)
122  return;
123 
124  if (vdir < 0)
125  j_end = -1, j = y-1;
126  else
127  j_end = y, j = 0;
128 
129  for (; j != j_end; j += vdir) {
130  for (i=0; i < x; ++i) {
131  unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
132  if (write_alpha < 0)
133  fwrite(&d[comp-1], 1, 1, f);
134  switch (comp) {
135  case 1:
136  case 2: fwrite(d, 1, 1, f);
137  break;
138  case 4:
139  if (!write_alpha) {
140  // composite against pink background
141  for (k=0; k < 3; ++k)
142  px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255;
143  write3(f, px[1-rgb_dir],px[1],px[1+rgb_dir]);
144  break;
145  }
146  /* FALLTHROUGH */
147  case 3:
148  write3(f, d[1-rgb_dir],d[1],d[1+rgb_dir]);
149  break;
150  }
151  if (write_alpha > 0)
152  fwrite(&d[comp-1], 1, 1, f);
153  }
154  fwrite(&zero,scanline_pad,1,f);
155  }
156 }
157 
158 static int outfile(char const *filename, int rgb_dir, int vdir, int x, int y, int comp, void *data, int alpha, int pad, const char *fmt, ...)
159 {
160  FILE *f;
161  if (y < 0 || x < 0) return 0;
162  f = fopen(filename, "wb");
163  if (f) {
164  va_list v;
165  va_start(v, fmt);
166  writefv(f, fmt, v);
167  va_end(v);
168  write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad);
169  fclose(f);
170  }
171  return f != NULL;
172 }
173 
174 int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
175 {
176  int pad = (-x*3) & 3;
177  return outfile(filename,-1,-1,x,y,comp,(void *) data,0,pad,
178  "11 4 22 4" "4 44 22 444444",
179  'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
180  40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
181 }
182 
183 int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
184 {
185  int has_alpha = (comp == 2 || comp == 4);
186  int colorbytes = has_alpha ? comp-1 : comp;
187  int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3
188  return outfile(filename, -1,-1, x, y, comp, (void *) data, has_alpha, 0,
189  "111 221 2222 11", 0,0,format, 0,0,0, 0,0,x,y, (colorbytes+has_alpha)*8, has_alpha*8);
190 }
191 
192 // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
193 #define stbiw__sbraw(a) ((int *) (a) - 2)
194 #define stbiw__sbm(a) stbiw__sbraw(a)[0]
195 #define stbiw__sbn(a) stbiw__sbraw(a)[1]
196 
197 #define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
198 #define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
199 #define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
200 
201 #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
202 #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
203 #define stbiw__sbfree(a) ((a) ? free(stbiw__sbraw(a)),0 : 0)
204 
205 static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
206 {
207  int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
208  void *p = realloc(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2);
209  STBI_ASSERT(p);
210  if (p) {
211  if (!*arr) ((int *) p)[1] = 0;
212  *arr = (void *) ((int *) p + 2);
213  stbiw__sbm(*arr) = m;
214  }
215  return *arr;
216 }
217 
218 static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
219 {
220  while (*bitcount >= 8) {
221  stbiw__sbpush(data, (unsigned char) *bitbuffer);
222  *bitbuffer >>= 8;
223  *bitcount -= 8;
224  }
225  return data;
226 }
227 
228 static int stbiw__zlib_bitrev(int code, int codebits)
229 {
230  int res=0;
231  while (codebits--) {
232  res = (res << 1) | (code & 1);
233  code >>= 1;
234  }
235  return res;
236 }
237 
238 static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit)
239 {
240  int i;
241  for (i=0; i < limit && i < 258; ++i)
242  if (a[i] != b[i]) break;
243  return i;
244 }
245 
246 static unsigned int stbiw__zhash(unsigned char *data)
247 {
248  stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
249  hash ^= hash << 3;
250  hash += hash >> 5;
251  hash ^= hash << 4;
252  hash += hash >> 17;
253  hash ^= hash << 25;
254  hash += hash >> 6;
255  return hash;
256 }
257 
258 #define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
259 #define stbiw__zlib_add(code,codebits) \
260  (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
261 #define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
262 // default huffman tables
263 #define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8)
264 #define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9)
265 #define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7)
266 #define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8)
267 #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))
268 #define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
269 
270 #define stbiw__ZHASH 16384
271 
272 unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
273 {
274  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 };
275  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 };
276  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 };
277  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 };
278  unsigned int bitbuf=0;
279  int i,j, bitcount=0;
280  unsigned char *out = NULL;
281  unsigned char **hash_table[stbiw__ZHASH]; // 64KB on the stack!
282  if (quality < 5) quality = 5;
283 
284  stbiw__sbpush(out, 0x78); // DEFLATE 32K window
285  stbiw__sbpush(out, 0x5e); // FLEVEL = 1
286  stbiw__zlib_add(1,1); // BFINAL = 1
287  stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman
288 
289  for (i=0; i < stbiw__ZHASH; ++i)
290  hash_table[i] = NULL;
291 
292  i=0;
293  while (i < data_len-3) {
294  // hash next 3 bytes of data to be compressed
295  int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
296  unsigned char *bestloc = 0;
297  unsigned char **hlist = hash_table[h];
298  int n = stbiw__sbcount(hlist);
299  for (j=0; j < n; ++j) {
300  if (hlist[j]-data > i-32768) { // if entry lies within window
301  int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
302  if (d >= best) best=d,bestloc=hlist[j];
303  }
304  }
305  // when hash table entry is too long, delete half the entries
306  if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
307  memcpy(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
308  stbiw__sbn(hash_table[h]) = quality;
309  }
310  stbiw__sbpush(hash_table[h],data+i);
311 
312  if (bestloc) {
313  // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal
314  h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
315  hlist = hash_table[h];
316  n = stbiw__sbcount(hlist);
317  for (j=0; j < n; ++j) {
318  if (hlist[j]-data > i-32767) {
319  int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
320  if (e > best) { // if next match is better, bail on current match
321  bestloc = NULL;
322  break;
323  }
324  }
325  }
326  }
327 
328  if (bestloc) {
329  int d = (int) (data+i - bestloc); // distance back
330  STBI_ASSERT(d <= 32767 && best <= 258);
331  for (j=0; best > lengthc[j+1]-1; ++j);
332  stbiw__zlib_huff(j+257);
333  if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
334  for (j=0; d > distc[j+1]-1; ++j);
335  stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
336  if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
337  i += best;
338  } else {
339  stbiw__zlib_huffb(data[i]);
340  ++i;
341  }
342  }
343  // write out final bytes
344  for (;i < data_len; ++i)
345  stbiw__zlib_huffb(data[i]);
346  stbiw__zlib_huff(256); // end of block
347  // pad with 0 bits to byte boundary
348  while (bitcount)
349  stbiw__zlib_add(0,1);
350 
351  for (i=0; i < stbiw__ZHASH; ++i)
352  (void) stbiw__sbfree(hash_table[i]);
353 
354  {
355  // compute adler32 on input
356  unsigned int i=0, s1=1, s2=0, blocklen = data_len % 5552;
357  int j=0;
358  while (j < data_len) {
359  for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
360  s1 %= 65521, s2 %= 65521;
361  j += blocklen;
362  blocklen = 5552;
363  }
364  stbiw__sbpush(out, (unsigned char) (s2 >> 8));
365  stbiw__sbpush(out, (unsigned char) s2);
366  stbiw__sbpush(out, (unsigned char) (s1 >> 8));
367  stbiw__sbpush(out, (unsigned char) s1);
368  }
369  *out_len = stbiw__sbn(out);
370  // make returned pointer freeable
371  memmove(stbiw__sbraw(out), out, *out_len);
372  return (unsigned char *) stbiw__sbraw(out);
373 }
374 
375 unsigned int stbiw__crc32(unsigned char *buffer, int len)
376 {
377  static unsigned int crc_table[256];
378  unsigned int crc = ~0u;
379  int i,j;
380  if (crc_table[1] == 0)
381  for(i=0; i < 256; i++)
382  for (crc_table[i]=i, j=0; j < 8; ++j)
383  crc_table[i] = (crc_table[i] >> 1) ^ (crc_table[i] & 1 ? 0xedb88320 : 0);
384  for (i=0; i < len; ++i)
385  crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
386  return ~crc;
387 }
388 
389 #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)
390 #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
391 #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
392 
393 static void stbiw__wpcrc(unsigned char **data, int len)
394 {
395  unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
396  stbiw__wp32(*data, crc);
397 }
398 
399 static unsigned char stbiw__paeth(int a, int b, int c)
400 {
401  int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
402  if (pa <= pb && pa <= pc) return (unsigned char) a;
403  if (pb <= pc) return (unsigned char) b;
404  return (unsigned char) c;
405 }
406 
407 unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
408 {
409  int ctype[5] = { -1, 0, 4, 2, 6 };
410  unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
411  unsigned char *out,*o, *filt, *zlib;
412  signed char *line_buffer;
413  int i,j,k,p,zlen;
414 
415  if (stride_bytes == 0)
416  stride_bytes = x * n;
417 
418  filt = (unsigned char *) malloc((x*n+1) * y); if (!filt) return 0;
419  line_buffer = (signed char *) malloc(x * n); if (!line_buffer) { free(filt); return 0; }
420  for (j=0; j < y; ++j) {
421  static int mapping[] = { 0,1,2,3,4 };
422  static int firstmap[] = { 0,1,0,5,6 };
423  int *mymap = j ? mapping : firstmap;
424  int best = 0, bestval = 0x7fffffff;
425  for (p=0; p < 2; ++p) {
426  for (k= p?best:0; k < 5; ++k) {
427  int type = mymap[k],est=0;
428  unsigned char *z = pixels + stride_bytes*j;
429  for (i=0; i < n; ++i)
430  switch (type) {
431  case 0: line_buffer[i] = z[i]; break;
432  case 1: line_buffer[i] = z[i]; break;
433  case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
434  case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break;
435  case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break;
436  case 5: line_buffer[i] = z[i]; break;
437  case 6: line_buffer[i] = z[i]; break;
438  }
439  for (i=n; i < x*n; ++i) {
440  switch (type) {
441  case 0: line_buffer[i] = z[i]; break;
442  case 1: line_buffer[i] = z[i] - z[i-n]; break;
443  case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
444  case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break;
445  case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break;
446  case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break;
447  case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
448  }
449  }
450  if (p) break;
451  for (i=0; i < x*n; ++i)
452  est += abs((signed char) line_buffer[i]);
453  if (est < bestval) { bestval = est; best = k; }
454  }
455  }
456  // when we get here, best contains the filter type, and line_buffer contains the data
457  filt[j*(x*n+1)] = (unsigned char) best;
458  memcpy(filt+j*(x*n+1)+1, line_buffer, x*n);
459  }
460  free(line_buffer);
461  zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory
462  free(filt);
463  if (!zlib) return 0;
464 
465  // each tag requires 12 bytes of overhead
466  out = (unsigned char *) malloc(8 + 12+13 + 12+zlen + 12);
467  if (!out) return 0;
468  *out_len = 8 + 12+13 + 12+zlen + 12;
469 
470  o=out;
471  memcpy(o,sig,8); o+= 8;
472  stbiw__wp32(o, 13); // header length
473  stbiw__wptag(o, "IHDR");
474  stbiw__wp32(o, x);
475  stbiw__wp32(o, y);
476  *o++ = 8;
477  *o++ = (unsigned char) ctype[n];
478  *o++ = 0;
479  *o++ = 0;
480  *o++ = 0;
481  stbiw__wpcrc(&o,13);
482 
483  stbiw__wp32(o, zlen);
484  stbiw__wptag(o, "IDAT");
485  memcpy(o, zlib, zlen); o += zlen; free(zlib);
486  stbiw__wpcrc(&o, zlen);
487 
488  stbiw__wp32(o,0);
489  stbiw__wptag(o, "IEND");
490  stbiw__wpcrc(&o,0);
491 
492  STBI_ASSERT(o == out + *out_len);
493 
494  return out;
495 }
496 
497 int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
498 {
499  FILE *f;
500  int len;
501  unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
502  if (!png) return 0;
503  f = fopen(filename, "wb");
504  if (!f) { free(png); return 0; }
505  fwrite(png, 1, len, f);
506  fclose(f);
507  free(png);
508  return 1;
509 }
510 #endif // STB_IMAGE_WRITE_IMPLEMENTATION
511 
512 /* Revision history
513 
514  0.95 (2014-08-17)
515  add monochrome TGA output
516  0.94 (2014-05-31)
517  rename private functions to avoid conflicts with stb_image.h
518  0.93 (2014-05-27)
519  warning fixes
520  0.92 (2010-08-01)
521  casts to unsigned char to fix warnings
522  0.91 (2010-07-17)
523  first public release
524  0.90 first internal release
525 */
int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data)
int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes)
#define STBI_ASSERT(x)
Definition: stb.cpp:11
int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data)