gosu 0.9.2 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/Gosu/Bitmap.hpp +3 -3
  3. data/Gosu/Directories.hpp +6 -3
  4. data/Gosu/Gosu.hpp +0 -1
  5. data/Gosu/GraphicsBase.hpp +12 -8
  6. data/Gosu/Input.hpp +5 -16
  7. data/Gosu/Platform.hpp +1 -0
  8. data/Gosu/Version.hpp +3 -5
  9. data/Gosu/Window.hpp +7 -8
  10. data/README.txt +3 -3
  11. data/ext/gosu/extconf.rb +17 -16
  12. data/ext/gosu/gosu_wrap.cxx +59 -58
  13. data/ext/gosu/gosu_wrap.h +1 -1
  14. data/rdoc/gosu.rb +285 -283
  15. data/src/{MacUtility.hpp → AppleUtility.hpp} +24 -42
  16. data/src/Audio/ALChannelManagement.hpp +1 -1
  17. data/src/Audio/{AudioOpenAL.cpp → Audio.cpp} +6 -7
  18. data/src/Audio/Audio.mm +1 -0
  19. data/src/Audio/AudioFile.hpp +2 -2
  20. data/src/Audio/AudioToolboxFile.hpp +5 -20
  21. data/src/Audio/OggFile.hpp +44 -56
  22. data/src/Audio/SndFile.hpp +2 -2
  23. data/src/Bitmap/Bitmap.cpp +98 -2
  24. data/src/Bitmap/BitmapIO.cpp +156 -0
  25. data/src/DirectoriesApple.mm +76 -0
  26. data/src/DirectoriesUnix.cpp +5 -12
  27. data/src/DirectoriesWin.cpp +5 -0
  28. data/src/Graphics/BlockAllocator.hpp +2 -2
  29. data/src/Graphics/ClipRectStack.hpp +2 -2
  30. data/src/Graphics/Common.hpp +2 -2
  31. data/src/Graphics/DrawOp.hpp +2 -2
  32. data/src/Graphics/DrawOpQueue.hpp +2 -2
  33. data/src/Graphics/Graphics.cpp +7 -2
  34. data/src/Graphics/LargeImageData.cpp +6 -6
  35. data/src/Graphics/LargeImageData.hpp +3 -3
  36. data/src/Graphics/Macro.hpp +2 -2
  37. data/src/Graphics/RenderState.hpp +2 -2
  38. data/src/Graphics/Resolution.cpp +1 -1
  39. data/src/Graphics/TexChunk.hpp +2 -2
  40. data/src/Graphics/Texture.cpp +21 -16
  41. data/src/Graphics/Texture.hpp +7 -5
  42. data/src/Graphics/TransformStack.hpp +2 -2
  43. data/src/Iconv.hpp +2 -2
  44. data/src/Input/Input.cpp +3 -1
  45. data/src/Input/{InputTouch.mm → InputUIKit.mm} +32 -26
  46. data/src/Input/TextInput.cpp +1 -1
  47. data/src/Text/FormattedString.hpp +2 -2
  48. data/src/Text/TextApple.mm +8 -8
  49. data/src/Text/TextMac.cpp +1 -1
  50. data/src/Text/TextUnix.cpp +1 -1
  51. data/src/UIKit/GosuAppDelegate.h +8 -0
  52. data/src/UIKit/GosuAppDelegate.mm +24 -0
  53. data/src/UIKit/GosuGLView.h +8 -0
  54. data/src/UIKit/GosuGLView.mm +130 -0
  55. data/src/UIKit/GosuViewController.h +13 -0
  56. data/src/UIKit/GosuViewController.mm +214 -0
  57. data/src/UtilityApple.mm +5 -18
  58. data/src/Window.cpp +1 -3
  59. data/src/WindowUIKit.mm +124 -0
  60. data/src/stb_image.h +6437 -0
  61. data/src/stb_image_write.h +730 -0
  62. data/src/stb_vorbis.c +5459 -0
  63. metadata +18 -26
  64. data/Gosu/Sockets.hpp +0 -156
  65. data/src/Audio/AudioOpenAL.mm +0 -1
  66. data/src/Bitmap/BitmapApple.mm +0 -226
  67. data/src/Bitmap/BitmapBMP.cpp +0 -79
  68. data/src/Bitmap/BitmapColorKey.cpp +0 -50
  69. data/src/Bitmap/BitmapFreeImage.cpp +0 -174
  70. data/src/Bitmap/BitmapGDIplus.cpp +0 -212
  71. data/src/Bitmap/BitmapUtils.cpp +0 -76
  72. data/src/DirectoriesMac.mm +0 -38
  73. data/src/DirectoriesTouch.mm +0 -38
  74. data/src/GosuView.hpp +0 -15
  75. data/src/GosuView.mm +0 -208
  76. data/src/Input/AccelerometerReader.hpp +0 -10
  77. data/src/Input/AccelerometerReader.mm +0 -31
  78. data/src/Sockets/CommSocket.cpp +0 -305
  79. data/src/Sockets/ListenerSocket.cpp +0 -59
  80. data/src/Sockets/MessageSocket.cpp +0 -128
  81. data/src/Sockets/Socket.cpp +0 -145
  82. data/src/Sockets/Socket.hpp +0 -66
  83. data/src/WindowTouch.mm +0 -243
  84. data/src/X11vroot.h +0 -118
@@ -0,0 +1,730 @@
1
+ /* stb_image_write - v0.98 - 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
+ ABOUT:
15
+
16
+ This header file is a library for writing images to C stdio. It could be
17
+ adapted to write to memory or a general streaming interface; let me know.
18
+
19
+ The PNG output is not optimal; it is 20-50% larger than the file
20
+ written by a decent optimizing implementation. This library is designed
21
+ for source code compactness and simplicitly, not optimal image file size
22
+ or run-time performance.
23
+
24
+ BUILDING:
25
+
26
+ You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h.
27
+ You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace
28
+ malloc,realloc,free.
29
+ You can define STBIW_MEMMOVE() to replace memmove()
30
+
31
+ USAGE:
32
+
33
+ There are four functions, one for each image file format:
34
+
35
+ int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
36
+ int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
37
+ int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
38
+ int stbi_write_hdr(char const *filename, int w, int h, int comp, const void *data);
39
+
40
+ Each function returns 0 on failure and non-0 on success.
41
+
42
+ The functions create an image file defined by the parameters. The image
43
+ is a rectangle of pixels stored from left-to-right, top-to-bottom.
44
+ Each pixel contains 'comp' channels of data stored interleaved with 8-bits
45
+ per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is
46
+ monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall.
47
+ The *data pointer points to the first byte of the top-left-most pixel.
48
+ For PNG, "stride_in_bytes" is the distance in bytes from the first byte of
49
+ a row of pixels to the first byte of the next row of pixels.
50
+
51
+ PNG creates output files with the same number of components as the input.
52
+ The BMP format expands Y to RGB in the file format and does not
53
+ output alpha.
54
+
55
+ PNG supports writing rectangles of data even when the bytes storing rows of
56
+ data are not consecutive in memory (e.g. sub-rectangles of a larger image),
57
+ by supplying the stride between the beginning of adjacent rows. The other
58
+ formats do not. (Thus you cannot write a native-format BMP through the BMP
59
+ writer, both because it is in BGR order and because it may have padding
60
+ at the end of the line.)
61
+
62
+ HDR expects linear float data. Since the format is always 32-bit rgb(e)
63
+ data, alpha (if provided) is discarded, and for monochrome data it is
64
+ replicated across all three channels.
65
+
66
+ CREDITS:
67
+
68
+ PNG/BMP/TGA
69
+ Sean Barrett
70
+ HDR
71
+ Baldur Karlsson
72
+ TGA monochrome:
73
+ Jean-Sebastien Guay
74
+ misc enhancements:
75
+ Tim Kelsey
76
+ bugfixes:
77
+ github:Chribba
78
+ */
79
+
80
+ #ifndef INCLUDE_STB_IMAGE_WRITE_H
81
+ #define INCLUDE_STB_IMAGE_WRITE_H
82
+
83
+ #ifdef __cplusplus
84
+ extern "C" {
85
+ #endif
86
+
87
+ extern int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes);
88
+ extern int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
89
+ extern int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
90
+ extern int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data);
91
+
92
+ #ifdef __cplusplus
93
+ }
94
+ #endif
95
+
96
+ #endif//INCLUDE_STB_IMAGE_WRITE_H
97
+
98
+ #ifdef STB_IMAGE_WRITE_IMPLEMENTATION
99
+
100
+ #include <stdarg.h>
101
+ #include <stdlib.h>
102
+ #include <stdio.h>
103
+ #include <string.h>
104
+ #include <math.h>
105
+
106
+ #if defined(STBIW_MALLOC) && defined(STBIW_FREE) && defined(STBIW_REALLOC)
107
+ // ok
108
+ #elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC)
109
+ // ok
110
+ #else
111
+ #error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC."
112
+ #endif
113
+
114
+ #ifndef STBIW_MALLOC
115
+ #define STBIW_MALLOC(sz) malloc(sz)
116
+ #define STBIW_REALLOC(p,sz) realloc(p,sz)
117
+ #define STBIW_FREE(p) free(p)
118
+ #endif
119
+ #ifndef STBIW_MEMMOVE
120
+ #define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz)
121
+ #endif
122
+
123
+
124
+ #ifndef STBIW_ASSERT
125
+ #include <assert.h>
126
+ #define STBIW_ASSERT(x) assert(x)
127
+ #endif
128
+
129
+ typedef unsigned int stbiw_uint32;
130
+ typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1];
131
+
132
+ static void writefv(FILE *f, const char *fmt, va_list v)
133
+ {
134
+ while (*fmt) {
135
+ switch (*fmt++) {
136
+ case ' ': break;
137
+ case '1': { unsigned char x = (unsigned char) va_arg(v, int); fputc(x,f); break; }
138
+ case '2': { int x = va_arg(v,int); unsigned char b[2];
139
+ b[0] = (unsigned char) x; b[1] = (unsigned char) (x>>8);
140
+ fwrite(b,2,1,f); break; }
141
+ case '4': { stbiw_uint32 x = va_arg(v,int); unsigned char b[4];
142
+ b[0]=(unsigned char)x; b[1]=(unsigned char)(x>>8);
143
+ b[2]=(unsigned char)(x>>16); b[3]=(unsigned char)(x>>24);
144
+ fwrite(b,4,1,f); break; }
145
+ default:
146
+ STBIW_ASSERT(0);
147
+ return;
148
+ }
149
+ }
150
+ }
151
+
152
+ static void write3(FILE *f, unsigned char a, unsigned char b, unsigned char c)
153
+ {
154
+ unsigned char arr[3];
155
+ arr[0] = a, arr[1] = b, arr[2] = c;
156
+ fwrite(arr, 3, 1, f);
157
+ }
158
+
159
+ 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)
160
+ {
161
+ unsigned char bg[3] = { 255, 0, 255}, px[3];
162
+ stbiw_uint32 zero = 0;
163
+ int i,j,k, j_end;
164
+
165
+ if (y <= 0)
166
+ return;
167
+
168
+ if (vdir < 0)
169
+ j_end = -1, j = y-1;
170
+ else
171
+ j_end = y, j = 0;
172
+
173
+ for (; j != j_end; j += vdir) {
174
+ for (i=0; i < x; ++i) {
175
+ unsigned char *d = (unsigned char *) data + (j*x+i)*comp;
176
+ if (write_alpha < 0)
177
+ fwrite(&d[comp-1], 1, 1, f);
178
+ switch (comp) {
179
+ case 1: fwrite(d, 1, 1, f);
180
+ break;
181
+ case 2: if (expand_mono)
182
+ write3(f, d[0],d[0],d[0]); // monochrome bmp
183
+ else
184
+ fwrite(d, 1, 1, f); // monochrome TGA
185
+ break;
186
+ case 4:
187
+ if (!write_alpha) {
188
+ // composite against pink background
189
+ for (k=0; k < 3; ++k)
190
+ px[k] = bg[k] + ((d[k] - bg[k]) * d[3])/255;
191
+ write3(f, px[1-rgb_dir],px[1],px[1+rgb_dir]);
192
+ break;
193
+ }
194
+ /* FALLTHROUGH */
195
+ case 3:
196
+ write3(f, d[1-rgb_dir],d[1],d[1+rgb_dir]);
197
+ break;
198
+ }
199
+ if (write_alpha > 0)
200
+ fwrite(&d[comp-1], 1, 1, f);
201
+ }
202
+ fwrite(&zero,scanline_pad,1,f);
203
+ }
204
+ }
205
+
206
+ 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, ...)
207
+ {
208
+ FILE *f;
209
+ if (y < 0 || x < 0) return 0;
210
+ f = fopen(filename, "wb");
211
+ if (f) {
212
+ va_list v;
213
+ va_start(v, fmt);
214
+ writefv(f, fmt, v);
215
+ va_end(v);
216
+ write_pixels(f,rgb_dir,vdir,x,y,comp,data,alpha,pad,expand_mono);
217
+ fclose(f);
218
+ }
219
+ return f != NULL;
220
+ }
221
+
222
+ int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data)
223
+ {
224
+ int pad = (-x*3) & 3;
225
+ return outfile(filename,-1,-1,x,y,comp,1,(void *) data,0,pad,
226
+ "11 4 22 4" "4 44 22 444444",
227
+ 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header
228
+ 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header
229
+ }
230
+
231
+ int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data)
232
+ {
233
+ int has_alpha = (comp == 2 || comp == 4);
234
+ int colorbytes = has_alpha ? comp-1 : comp;
235
+ int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3
236
+ return outfile(filename, -1,-1, x, y, comp, 0, (void *) data, has_alpha, 0,
237
+ "111 221 2222 11", 0,0,format, 0,0,0, 0,0,x,y, (colorbytes+has_alpha)*8, has_alpha*8);
238
+ }
239
+
240
+ // *************************************************************************************************
241
+ // Radiance RGBE HDR writer
242
+ // by Baldur Karlsson
243
+ #define stbiw__max(a, b) ((a) > (b) ? (a) : (b))
244
+
245
+ void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear)
246
+ {
247
+ int exponent;
248
+ float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2]));
249
+
250
+ if (maxcomp < 1e-32) {
251
+ rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
252
+ } else {
253
+ float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp;
254
+
255
+ rgbe[0] = (unsigned char)(linear[0] * normalize);
256
+ rgbe[1] = (unsigned char)(linear[1] * normalize);
257
+ rgbe[2] = (unsigned char)(linear[2] * normalize);
258
+ rgbe[3] = (unsigned char)(exponent + 128);
259
+ }
260
+ }
261
+
262
+ void stbiw__write_run_data(FILE *f, int length, unsigned char databyte)
263
+ {
264
+ unsigned char lengthbyte = (unsigned char) (length+128);
265
+ STBIW_ASSERT(length+128 <= 255);
266
+ fwrite(&lengthbyte, 1, 1, f);
267
+ fwrite(&databyte, 1, 1, f);
268
+ }
269
+
270
+ void stbiw__write_dump_data(FILE *f, int length, unsigned char *data)
271
+ {
272
+ unsigned char lengthbyte = (unsigned char )(length & 0xff);
273
+ STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code
274
+ fwrite(&lengthbyte, 1, 1, f);
275
+ fwrite(data, length, 1, f);
276
+ }
277
+
278
+ void stbiw__write_hdr_scanline(FILE *f, int width, int comp, unsigned char *scratch, const float *scanline)
279
+ {
280
+ unsigned char scanlineheader[4] = { 2, 2, 0, 0 };
281
+ unsigned char rgbe[4];
282
+ float linear[3];
283
+ int x;
284
+
285
+ scanlineheader[2] = (width&0xff00)>>8;
286
+ scanlineheader[3] = (width&0x00ff);
287
+
288
+ /* skip RLE for images too small or large */
289
+ if (width < 8 || width >= 32768) {
290
+ for (x=0; x < width; x++) {
291
+ switch (comp) {
292
+ case 4: /* fallthrough */
293
+ case 3: linear[2] = scanline[x*comp + 2];
294
+ linear[1] = scanline[x*comp + 1];
295
+ linear[0] = scanline[x*comp + 0];
296
+ break;
297
+ case 2: /* fallthrough */
298
+ case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0];
299
+ break;
300
+ }
301
+ stbiw__linear_to_rgbe(rgbe, linear);
302
+ fwrite(rgbe, 4, 1, f);
303
+ }
304
+ } else {
305
+ int c,r;
306
+ /* encode into scratch buffer */
307
+ for (x=0; x < width; x++) {
308
+ switch(comp) {
309
+ case 4: /* fallthrough */
310
+ case 3: linear[2] = scanline[x*comp + 2];
311
+ linear[1] = scanline[x*comp + 1];
312
+ linear[0] = scanline[x*comp + 0];
313
+ break;
314
+ case 2: /* fallthrough */
315
+ case 1: linear[0] = linear[1] = linear[2] = scanline[x*comp + 0];
316
+ break;
317
+ }
318
+ stbiw__linear_to_rgbe(rgbe, linear);
319
+ scratch[x + width*0] = rgbe[0];
320
+ scratch[x + width*1] = rgbe[1];
321
+ scratch[x + width*2] = rgbe[2];
322
+ scratch[x + width*3] = rgbe[3];
323
+ }
324
+
325
+ fwrite(scanlineheader, 4, 1, f);
326
+
327
+ /* RLE each component separately */
328
+ for (c=0; c < 4; c++) {
329
+ unsigned char *comp = &scratch[width*c];
330
+
331
+ x = 0;
332
+ while (x < width) {
333
+ // find first run
334
+ r = x;
335
+ while (r+2 < width) {
336
+ if (comp[r] == comp[r+1] && comp[r] == comp[r+2])
337
+ break;
338
+ ++r;
339
+ }
340
+ if (r+2 >= width)
341
+ r = width;
342
+ // dump up to first run
343
+ while (x < r) {
344
+ int len = r-x;
345
+ if (len > 128) len = 128;
346
+ stbiw__write_dump_data(f, len, &comp[x]);
347
+ x += len;
348
+ }
349
+ // if there's a run, output it
350
+ if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd
351
+ // find next byte after run
352
+ while (r < width && comp[r] == comp[x])
353
+ ++r;
354
+ // output run up to r
355
+ while (x < r) {
356
+ int len = r-x;
357
+ if (len > 127) len = 127;
358
+ stbiw__write_run_data(f, len, comp[x]);
359
+ x += len;
360
+ }
361
+ }
362
+ }
363
+ }
364
+ }
365
+ }
366
+
367
+ int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data)
368
+ {
369
+ int i;
370
+ FILE *f;
371
+ if (y <= 0 || x <= 0 || data == NULL) return 0;
372
+ f = fopen(filename, "wb");
373
+ if (f) {
374
+ /* Each component is stored separately. Allocate scratch space for full output scanline. */
375
+ unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4);
376
+ fprintf(f, "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n" );
377
+ fprintf(f, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n" , y, x);
378
+ for(i=0; i < y; i++)
379
+ stbiw__write_hdr_scanline(f, x, comp, scratch, data + comp*i*x);
380
+ STBIW_FREE(scratch);
381
+ fclose(f);
382
+ }
383
+ return f != NULL;
384
+ }
385
+
386
+ /////////////////////////////////////////////////////////
387
+ // PNG
388
+
389
+ // stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size()
390
+ #define stbiw__sbraw(a) ((int *) (a) - 2)
391
+ #define stbiw__sbm(a) stbiw__sbraw(a)[0]
392
+ #define stbiw__sbn(a) stbiw__sbraw(a)[1]
393
+
394
+ #define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a))
395
+ #define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0)
396
+ #define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a)))
397
+
398
+ #define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v))
399
+ #define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0)
400
+ #define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0)
401
+
402
+ static void *stbiw__sbgrowf(void **arr, int increment, int itemsize)
403
+ {
404
+ int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1;
405
+ void *p = STBIW_REALLOC(*arr ? stbiw__sbraw(*arr) : 0, itemsize * m + sizeof(int)*2);
406
+ STBIW_ASSERT(p);
407
+ if (p) {
408
+ if (!*arr) ((int *) p)[1] = 0;
409
+ *arr = (void *) ((int *) p + 2);
410
+ stbiw__sbm(*arr) = m;
411
+ }
412
+ return *arr;
413
+ }
414
+
415
+ static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount)
416
+ {
417
+ while (*bitcount >= 8) {
418
+ stbiw__sbpush(data, (unsigned char) *bitbuffer);
419
+ *bitbuffer >>= 8;
420
+ *bitcount -= 8;
421
+ }
422
+ return data;
423
+ }
424
+
425
+ static int stbiw__zlib_bitrev(int code, int codebits)
426
+ {
427
+ int res=0;
428
+ while (codebits--) {
429
+ res = (res << 1) | (code & 1);
430
+ code >>= 1;
431
+ }
432
+ return res;
433
+ }
434
+
435
+ static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit)
436
+ {
437
+ int i;
438
+ for (i=0; i < limit && i < 258; ++i)
439
+ if (a[i] != b[i]) break;
440
+ return i;
441
+ }
442
+
443
+ static unsigned int stbiw__zhash(unsigned char *data)
444
+ {
445
+ stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16);
446
+ hash ^= hash << 3;
447
+ hash += hash >> 5;
448
+ hash ^= hash << 4;
449
+ hash += hash >> 17;
450
+ hash ^= hash << 25;
451
+ hash += hash >> 6;
452
+ return hash;
453
+ }
454
+
455
+ #define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount))
456
+ #define stbiw__zlib_add(code,codebits) \
457
+ (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush())
458
+ #define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c)
459
+ // default huffman tables
460
+ #define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8)
461
+ #define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9)
462
+ #define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7)
463
+ #define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8)
464
+ #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))
465
+ #define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n))
466
+
467
+ #define stbiw__ZHASH 16384
468
+
469
+ unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality)
470
+ {
471
+ 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 };
472
+ 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 };
473
+ 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 };
474
+ 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 };
475
+ unsigned int bitbuf=0;
476
+ int i,j, bitcount=0;
477
+ unsigned char *out = NULL;
478
+ unsigned char **hash_table[stbiw__ZHASH]; // 64KB on the stack!
479
+ if (quality < 5) quality = 5;
480
+
481
+ stbiw__sbpush(out, 0x78); // DEFLATE 32K window
482
+ stbiw__sbpush(out, 0x5e); // FLEVEL = 1
483
+ stbiw__zlib_add(1,1); // BFINAL = 1
484
+ stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman
485
+
486
+ for (i=0; i < stbiw__ZHASH; ++i)
487
+ hash_table[i] = NULL;
488
+
489
+ i=0;
490
+ while (i < data_len-3) {
491
+ // hash next 3 bytes of data to be compressed
492
+ int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3;
493
+ unsigned char *bestloc = 0;
494
+ unsigned char **hlist = hash_table[h];
495
+ int n = stbiw__sbcount(hlist);
496
+ for (j=0; j < n; ++j) {
497
+ if (hlist[j]-data > i-32768) { // if entry lies within window
498
+ int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i);
499
+ if (d >= best) best=d,bestloc=hlist[j];
500
+ }
501
+ }
502
+ // when hash table entry is too long, delete half the entries
503
+ if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) {
504
+ STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality);
505
+ stbiw__sbn(hash_table[h]) = quality;
506
+ }
507
+ stbiw__sbpush(hash_table[h],data+i);
508
+
509
+ if (bestloc) {
510
+ // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal
511
+ h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1);
512
+ hlist = hash_table[h];
513
+ n = stbiw__sbcount(hlist);
514
+ for (j=0; j < n; ++j) {
515
+ if (hlist[j]-data > i-32767) {
516
+ int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1);
517
+ if (e > best) { // if next match is better, bail on current match
518
+ bestloc = NULL;
519
+ break;
520
+ }
521
+ }
522
+ }
523
+ }
524
+
525
+ if (bestloc) {
526
+ int d = (int) (data+i - bestloc); // distance back
527
+ STBIW_ASSERT(d <= 32767 && best <= 258);
528
+ for (j=0; best > lengthc[j+1]-1; ++j);
529
+ stbiw__zlib_huff(j+257);
530
+ if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]);
531
+ for (j=0; d > distc[j+1]-1; ++j);
532
+ stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5);
533
+ if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]);
534
+ i += best;
535
+ } else {
536
+ stbiw__zlib_huffb(data[i]);
537
+ ++i;
538
+ }
539
+ }
540
+ // write out final bytes
541
+ for (;i < data_len; ++i)
542
+ stbiw__zlib_huffb(data[i]);
543
+ stbiw__zlib_huff(256); // end of block
544
+ // pad with 0 bits to byte boundary
545
+ while (bitcount)
546
+ stbiw__zlib_add(0,1);
547
+
548
+ for (i=0; i < stbiw__ZHASH; ++i)
549
+ (void) stbiw__sbfree(hash_table[i]);
550
+
551
+ {
552
+ // compute adler32 on input
553
+ unsigned int i=0, s1=1, s2=0, blocklen = data_len % 5552;
554
+ int j=0;
555
+ while (j < data_len) {
556
+ for (i=0; i < blocklen; ++i) s1 += data[j+i], s2 += s1;
557
+ s1 %= 65521, s2 %= 65521;
558
+ j += blocklen;
559
+ blocklen = 5552;
560
+ }
561
+ stbiw__sbpush(out, (unsigned char) (s2 >> 8));
562
+ stbiw__sbpush(out, (unsigned char) s2);
563
+ stbiw__sbpush(out, (unsigned char) (s1 >> 8));
564
+ stbiw__sbpush(out, (unsigned char) s1);
565
+ }
566
+ *out_len = stbiw__sbn(out);
567
+ // make returned pointer freeable
568
+ STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len);
569
+ return (unsigned char *) stbiw__sbraw(out);
570
+ }
571
+
572
+ unsigned int stbiw__crc32(unsigned char *buffer, int len)
573
+ {
574
+ static unsigned int crc_table[256];
575
+ unsigned int crc = ~0u;
576
+ int i,j;
577
+ if (crc_table[1] == 0)
578
+ for(i=0; i < 256; i++)
579
+ for (crc_table[i]=i, j=0; j < 8; ++j)
580
+ crc_table[i] = (crc_table[i] >> 1) ^ (crc_table[i] & 1 ? 0xedb88320 : 0);
581
+ for (i=0; i < len; ++i)
582
+ crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)];
583
+ return ~crc;
584
+ }
585
+
586
+ #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)
587
+ #define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v));
588
+ #define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3])
589
+
590
+ static void stbiw__wpcrc(unsigned char **data, int len)
591
+ {
592
+ unsigned int crc = stbiw__crc32(*data - len - 4, len+4);
593
+ stbiw__wp32(*data, crc);
594
+ }
595
+
596
+ static unsigned char stbiw__paeth(int a, int b, int c)
597
+ {
598
+ int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c);
599
+ if (pa <= pb && pa <= pc) return (unsigned char) a;
600
+ if (pb <= pc) return (unsigned char) b;
601
+ return (unsigned char) c;
602
+ }
603
+
604
+ unsigned char *stbi_write_png_to_mem(unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len)
605
+ {
606
+ int ctype[5] = { -1, 0, 4, 2, 6 };
607
+ unsigned char sig[8] = { 137,80,78,71,13,10,26,10 };
608
+ unsigned char *out,*o, *filt, *zlib;
609
+ signed char *line_buffer;
610
+ int i,j,k,p,zlen;
611
+
612
+ if (stride_bytes == 0)
613
+ stride_bytes = x * n;
614
+
615
+ filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0;
616
+ line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; }
617
+ for (j=0; j < y; ++j) {
618
+ static int mapping[] = { 0,1,2,3,4 };
619
+ static int firstmap[] = { 0,1,0,5,6 };
620
+ int *mymap = j ? mapping : firstmap;
621
+ int best = 0, bestval = 0x7fffffff;
622
+ for (p=0; p < 2; ++p) {
623
+ for (k= p?best:0; k < 5; ++k) {
624
+ int type = mymap[k],est=0;
625
+ unsigned char *z = pixels + stride_bytes*j;
626
+ for (i=0; i < n; ++i)
627
+ switch (type) {
628
+ case 0: line_buffer[i] = z[i]; break;
629
+ case 1: line_buffer[i] = z[i]; break;
630
+ case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
631
+ case 3: line_buffer[i] = z[i] - (z[i-stride_bytes]>>1); break;
632
+ case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-stride_bytes],0)); break;
633
+ case 5: line_buffer[i] = z[i]; break;
634
+ case 6: line_buffer[i] = z[i]; break;
635
+ }
636
+ for (i=n; i < x*n; ++i) {
637
+ switch (type) {
638
+ case 0: line_buffer[i] = z[i]; break;
639
+ case 1: line_buffer[i] = z[i] - z[i-n]; break;
640
+ case 2: line_buffer[i] = z[i] - z[i-stride_bytes]; break;
641
+ case 3: line_buffer[i] = z[i] - ((z[i-n] + z[i-stride_bytes])>>1); break;
642
+ case 4: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-stride_bytes], z[i-stride_bytes-n]); break;
643
+ case 5: line_buffer[i] = z[i] - (z[i-n]>>1); break;
644
+ case 6: line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break;
645
+ }
646
+ }
647
+ if (p) break;
648
+ for (i=0; i < x*n; ++i)
649
+ est += abs((signed char) line_buffer[i]);
650
+ if (est < bestval) { bestval = est; best = k; }
651
+ }
652
+ }
653
+ // when we get here, best contains the filter type, and line_buffer contains the data
654
+ filt[j*(x*n+1)] = (unsigned char) best;
655
+ STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n);
656
+ }
657
+ STBIW_FREE(line_buffer);
658
+ zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, 8); // increase 8 to get smaller but use more memory
659
+ STBIW_FREE(filt);
660
+ if (!zlib) return 0;
661
+
662
+ // each tag requires 12 bytes of overhead
663
+ out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12);
664
+ if (!out) return 0;
665
+ *out_len = 8 + 12+13 + 12+zlen + 12;
666
+
667
+ o=out;
668
+ STBIW_MEMMOVE(o,sig,8); o+= 8;
669
+ stbiw__wp32(o, 13); // header length
670
+ stbiw__wptag(o, "IHDR");
671
+ stbiw__wp32(o, x);
672
+ stbiw__wp32(o, y);
673
+ *o++ = 8;
674
+ *o++ = (unsigned char) ctype[n];
675
+ *o++ = 0;
676
+ *o++ = 0;
677
+ *o++ = 0;
678
+ stbiw__wpcrc(&o,13);
679
+
680
+ stbiw__wp32(o, zlen);
681
+ stbiw__wptag(o, "IDAT");
682
+ STBIW_MEMMOVE(o, zlib, zlen);
683
+ o += zlen;
684
+ STBIW_FREE(zlib);
685
+ stbiw__wpcrc(&o, zlen);
686
+
687
+ stbiw__wp32(o,0);
688
+ stbiw__wptag(o, "IEND");
689
+ stbiw__wpcrc(&o,0);
690
+
691
+ STBIW_ASSERT(o == out + *out_len);
692
+
693
+ return out;
694
+ }
695
+
696
+ int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
697
+ {
698
+ FILE *f;
699
+ int len;
700
+ unsigned char *png = stbi_write_png_to_mem((unsigned char *) data, stride_bytes, x, y, comp, &len);
701
+ if (!png) return 0;
702
+ f = fopen(filename, "wb");
703
+ if (!f) { STBIW_FREE(png); return 0; }
704
+ fwrite(png, 1, len, f);
705
+ fclose(f);
706
+ STBIW_FREE(png);
707
+ return 1;
708
+ }
709
+ #endif // STB_IMAGE_WRITE_IMPLEMENTATION
710
+
711
+ /* Revision history
712
+ 0.98 (2015-04-08)
713
+ added STBIW_MALLOC, STBIW_ASSERT etc
714
+ 0.97 (2015-01-18)
715
+ fixed HDR asserts, rewrote HDR rle logic
716
+ 0.96 (2015-01-17)
717
+ add HDR output
718
+ fix monochrome BMP
719
+ 0.95 (2014-08-17)
720
+ add monochrome TGA output
721
+ 0.94 (2014-05-31)
722
+ rename private functions to avoid conflicts with stb_image.h
723
+ 0.93 (2014-05-27)
724
+ warning fixes
725
+ 0.92 (2010-08-01)
726
+ casts to unsigned char to fix warnings
727
+ 0.91 (2010-07-17)
728
+ first public release
729
+ 0.90 first internal release
730
+ */