/[projet1]/public/pc/shared_libraries/nanosvg/example/stb_image_write.h
Defence Force logotype

Contents of /public/pc/shared_libraries/nanosvg/example/stb_image_write.h

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26