gosu 0.10.9.pre1 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/Gosu/Audio.hpp +35 -66
  3. data/Gosu/AutoLink.hpp +14 -16
  4. data/Gosu/Bitmap.hpp +50 -37
  5. data/Gosu/Buttons.hpp +246 -265
  6. data/Gosu/Color.hpp +32 -76
  7. data/Gosu/Directories.hpp +14 -17
  8. data/Gosu/Font.hpp +28 -34
  9. data/Gosu/Fwd.hpp +27 -31
  10. data/Gosu/Gosu.hpp +2 -5
  11. data/Gosu/Graphics.hpp +31 -48
  12. data/Gosu/GraphicsBase.hpp +27 -58
  13. data/Gosu/IO.hpp +44 -56
  14. data/Gosu/Image.hpp +29 -73
  15. data/Gosu/ImageData.hpp +13 -17
  16. data/Gosu/Input.hpp +42 -57
  17. data/Gosu/Inspection.hpp +2 -6
  18. data/Gosu/Math.hpp +32 -38
  19. data/Gosu/Platform.hpp +10 -29
  20. data/Gosu/Text.hpp +30 -39
  21. data/Gosu/TextInput.hpp +29 -36
  22. data/Gosu/Timing.hpp +14 -16
  23. data/Gosu/Utility.hpp +10 -15
  24. data/Gosu/Version.hpp +13 -14
  25. data/Gosu/Window.hpp +53 -68
  26. data/README.md +23 -11
  27. data/ext/gosu/extconf.rb +31 -81
  28. data/lib/gosu/patches.rb +35 -19
  29. data/lib/gosu/run.rb +13 -4
  30. data/rdoc/gosu.rb +24 -20
  31. data/src/ALChannelManagement.hpp +119 -0
  32. data/src/{Audio/Audio.cpp → Audio.cpp} +177 -211
  33. data/src/AudioFile.hpp +57 -0
  34. data/src/AudioToolboxFile.hpp +214 -0
  35. data/src/Bitmap.cpp +159 -0
  36. data/src/BitmapIO.cpp +141 -0
  37. data/src/BlockAllocator.cpp +133 -0
  38. data/src/{Graphics/BlockAllocator.hpp → BlockAllocator.hpp} +34 -35
  39. data/src/ClipRectStack.hpp +87 -0
  40. data/src/{Graphics/Color.cpp → Color.cpp} +30 -28
  41. data/src/DirectoriesApple.cpp +68 -0
  42. data/src/DirectoriesUnix.cpp +20 -18
  43. data/src/DirectoriesWin.cpp +40 -41
  44. data/src/DrawOp.hpp +168 -0
  45. data/src/DrawOpQueue.hpp +190 -0
  46. data/src/FileUnix.cpp +40 -46
  47. data/src/FileWin.cpp +42 -38
  48. data/src/Font.cpp +165 -0
  49. data/src/{Text/FormattedString.hpp → FormattedString.hpp} +114 -114
  50. data/src/GosuAppDelegate.cpp +30 -0
  51. data/src/{UIKit/GosuAppDelegate.h → GosuAppDelegate.h} +0 -0
  52. data/src/{UIKit/GosuGLView.mm → GosuGLView.cpp} +22 -17
  53. data/src/{UIKit/GosuGLView.h → GosuGLView.h} +0 -0
  54. data/src/GosuViewController.cpp +231 -0
  55. data/src/{UIKit/GosuViewController.h → GosuViewController.h} +0 -0
  56. data/src/Graphics.cpp +464 -0
  57. data/src/{Graphics/Common.hpp → GraphicsImpl.hpp} +29 -32
  58. data/src/IO.cpp +17 -16
  59. data/src/Iconv.hpp +13 -22
  60. data/src/Image.cpp +142 -0
  61. data/src/Input.cpp +459 -0
  62. data/src/InputUIKit.cpp +197 -0
  63. data/src/Inspection.cpp +4 -5
  64. data/src/LargeImageData.cpp +151 -0
  65. data/src/LargeImageData.hpp +43 -0
  66. data/src/{Graphics/Macro.cpp → Macro.cpp} +77 -78
  67. data/src/Macro.hpp +30 -0
  68. data/src/Math.cpp +17 -29
  69. data/src/{Audio/OggFile.hpp → OggFile.hpp} +19 -24
  70. data/src/RenderState.hpp +205 -0
  71. data/src/Resolution.cpp +86 -0
  72. data/src/ResolutionApple.cpp +25 -0
  73. data/{ext/gosu/gosu_wrap.cxx → src/RubyGosu.cxx} +2256 -1707
  74. data/{ext/gosu/gosu_wrap.h → src/RubyGosu.h} +9 -9
  75. data/src/{Audio/SndFile.hpp → SndFile.hpp} +54 -43
  76. data/src/TexChunk.cpp +117 -0
  77. data/src/{Graphics/TexChunk.hpp → TexChunk.hpp} +13 -18
  78. data/src/Text.cpp +371 -0
  79. data/src/TextApple.cpp +209 -0
  80. data/src/TextInput.cpp +278 -0
  81. data/src/TextTTFWin.cpp +251 -0
  82. data/src/{Text/TextUnix.cpp → TextUnix.cpp} +96 -92
  83. data/src/TextWin.cpp +194 -0
  84. data/src/{Graphics/Texture.cpp → Texture.cpp} +35 -38
  85. data/src/{Graphics/Texture.hpp → Texture.hpp} +9 -13
  86. data/src/TimingApple.cpp +11 -7
  87. data/src/TimingUnix.cpp +13 -7
  88. data/src/TimingWin.cpp +6 -1
  89. data/src/{Graphics/Transform.cpp → Transform.cpp} +17 -12
  90. data/src/{Graphics/TransformStack.hpp → TransformStack.hpp} +24 -25
  91. data/src/Utility.cpp +29 -70
  92. data/src/UtilityApple.cpp +52 -0
  93. data/src/UtilityWin.cpp +7 -4
  94. data/src/Version.cpp +22 -0
  95. data/src/WinMain.cpp +30 -33
  96. data/src/WinUtility.cpp +24 -22
  97. data/src/WinUtility.hpp +11 -20
  98. data/src/Window.cpp +142 -112
  99. data/src/WindowUIKit.cpp +155 -0
  100. data/src/stb_image.h +384 -173
  101. data/src/stb_vorbis.c +20 -18
  102. metadata +60 -62
  103. data/Gosu/TR1.hpp +0 -56
  104. data/src/AppleUtility.hpp +0 -66
  105. data/src/Audio/ALChannelManagement.hpp +0 -114
  106. data/src/Audio/Audio.mm +0 -1
  107. data/src/Audio/AudioFile.hpp +0 -53
  108. data/src/Audio/AudioToolboxFile.hpp +0 -207
  109. data/src/Bitmap/Bitmap.cpp +0 -183
  110. data/src/Bitmap/BitmapIO.cpp +0 -176
  111. data/src/DirectoriesApple.mm +0 -71
  112. data/src/Graphics/BlockAllocator.cpp +0 -142
  113. data/src/Graphics/ClipRectStack.hpp +0 -93
  114. data/src/Graphics/DrawOp.hpp +0 -175
  115. data/src/Graphics/DrawOpQueue.hpp +0 -188
  116. data/src/Graphics/Graphics.cpp +0 -478
  117. data/src/Graphics/Image.cpp +0 -193
  118. data/src/Graphics/LargeImageData.cpp +0 -133
  119. data/src/Graphics/LargeImageData.hpp +0 -46
  120. data/src/Graphics/Macro.hpp +0 -36
  121. data/src/Graphics/RenderState.hpp +0 -211
  122. data/src/Graphics/Resolution.cpp +0 -91
  123. data/src/Graphics/ResolutionApple.mm +0 -19
  124. data/src/Graphics/TexChunk.cpp +0 -112
  125. data/src/Input/Input.cpp +0 -463
  126. data/src/Input/InputUIKit.mm +0 -190
  127. data/src/Input/TextInput.cpp +0 -261
  128. data/src/Text/Font.cpp +0 -175
  129. data/src/Text/Text.cpp +0 -391
  130. data/src/Text/TextApple.mm +0 -227
  131. data/src/Text/TextTTFWin.cpp +0 -249
  132. data/src/Text/TextWin.cpp +0 -186
  133. data/src/UIKit/GosuAppDelegate.mm +0 -24
  134. data/src/UIKit/GosuViewController.mm +0 -211
  135. data/src/UtilityApple.mm +0 -63
  136. data/src/WindowUIKit.mm +0 -139
@@ -0,0 +1,155 @@
1
+ #include <Gosu/Platform.hpp>
2
+ #if defined(GOSU_IS_IPHONE)
3
+
4
+ #include "GosuViewController.h"
5
+ #include <Gosu/Gosu.hpp>
6
+
7
+ namespace Gosu
8
+ {
9
+ unsigned screen_width()
10
+ {
11
+ static CGSize screen_size = [UIScreen mainScreen].bounds.size;
12
+ static CGFloat width = MIN(screen_size.width, screen_size.height);
13
+ return width;
14
+ }
15
+
16
+ unsigned screen_height()
17
+ {
18
+ static CGSize screen_size = [UIScreen mainScreen].bounds.size;
19
+ static CGFloat width = MAX(screen_size.width, screen_size.height);
20
+ return width;
21
+ }
22
+
23
+ unsigned available_width()
24
+ {
25
+ return screen_width();
26
+ }
27
+
28
+ unsigned available_height()
29
+ {
30
+ return screen_height();
31
+ }
32
+ }
33
+
34
+ struct Gosu::Window::Impl
35
+ {
36
+ ::UIWindow* window;
37
+ GosuViewController* controller;
38
+ std::unique_ptr<Graphics> graphics;
39
+ std::unique_ptr<Input> input;
40
+
41
+ bool fullscreen;
42
+ double update_interval;
43
+ std::string caption;
44
+ };
45
+
46
+ Gosu::Window::Window(unsigned width, unsigned height, bool fullscreen, double update_interval)
47
+ : pimpl(new Impl)
48
+ {
49
+ pimpl->window = [[::UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
50
+ pimpl->controller = [GosuViewController new];
51
+ pimpl->controller.gosuWindow = this;
52
+ pimpl->window.rootViewController = pimpl->controller;
53
+
54
+ // It is important to load the view before creating the Graphics instance.
55
+ [pimpl->controller loadView];
56
+
57
+ pimpl->graphics.reset(new Graphics(screen_height(), screen_width()));
58
+ pimpl->graphics->set_resolution(width, height);
59
+
60
+ pimpl->input.reset(new Input((__bridge void*) pimpl->controller.view, update_interval));
61
+ pimpl->input->set_mouse_factors(1.0 * width / screen_height(), 1.0 * height / screen_width());
62
+
63
+ pimpl->input->on_touch_began = [this](Gosu::Touch touch) { touch_began(touch); };
64
+ pimpl->input->on_touch_moved = [this](Gosu::Touch touch) { touch_moved(touch); };
65
+ pimpl->input->on_touch_ended = [this](Gosu::Touch touch) { touch_ended(touch); };
66
+ pimpl->input->on_touch_cancelled = [this](Gosu::Touch touch) { touch_cancelled(touch); };
67
+
68
+ pimpl->fullscreen = fullscreen;
69
+ pimpl->update_interval = update_interval;
70
+ }
71
+
72
+ Gosu::Window::~Window()
73
+ {
74
+ }
75
+
76
+ unsigned Gosu::Window::width() const
77
+ {
78
+ return graphics().width();
79
+ }
80
+
81
+ unsigned Gosu::Window::height() const
82
+ {
83
+ return graphics().height();
84
+ }
85
+
86
+ bool Gosu::Window::fullscreen() const
87
+ {
88
+ return pimpl->fullscreen;
89
+ }
90
+
91
+ void Gosu::Window::resize(unsigned width, unsigned height, bool fullscreen)
92
+ {
93
+ throw std::logic_error("Cannot resize windows on iOS");
94
+ }
95
+
96
+ double Gosu::Window::update_interval() const
97
+ {
98
+ return pimpl->update_interval;
99
+ }
100
+
101
+ void Gosu::Window::set_update_interval(double update_interval)
102
+ {
103
+ throw std::logic_error("Cannot change the update interval on iOS");
104
+ }
105
+
106
+ std::string Gosu::Window::caption() const
107
+ {
108
+ return pimpl->caption;
109
+ }
110
+
111
+ void Gosu::Window::set_caption(const std::string& caption)
112
+ {
113
+ pimpl->caption = caption;
114
+ }
115
+
116
+ const Gosu::Graphics& Gosu::Window::graphics() const
117
+ {
118
+ return *pimpl->graphics;
119
+ }
120
+
121
+ Gosu::Graphics& Gosu::Window::graphics()
122
+ {
123
+ return *pimpl->graphics;
124
+ }
125
+
126
+ const Gosu::Input& Gosu::Window::input() const
127
+ {
128
+ return *pimpl->input;
129
+ }
130
+
131
+ Gosu::Input& Gosu::Window::input()
132
+ {
133
+ return *pimpl->input;
134
+ }
135
+
136
+ void Gosu::Window::show()
137
+ {
138
+ }
139
+
140
+ bool Gosu::Window::tick()
141
+ {
142
+ return true;
143
+ }
144
+
145
+ void Gosu::Window::close()
146
+ {
147
+ throw std::logic_error("Cannot close windows manually on iOS");
148
+ }
149
+
150
+ void* Gosu::Window::UIWindow() const
151
+ {
152
+ return (__bridge void*) pimpl->window;
153
+ }
154
+
155
+ #endif
@@ -1,4 +1,4 @@
1
- /* stb_image - v2.12 with fixes from https://github.com/nothings/stb/pull/343 - public domain image loader - http://nothings.org/stb_image.h
1
+ /* stb_image - v2.13 - public domain image loader - http://nothings.org/stb_image.h
2
2
  no warranty implied; use at your own risk
3
3
 
4
4
  Do this:
@@ -146,6 +146,7 @@
146
146
 
147
147
 
148
148
  Latest revision history:
149
+ 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes
149
150
  2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
150
151
  2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64
151
152
  RGB-format JPEG; remove white matting in PSD;
@@ -157,21 +158,6 @@
157
158
  2.07 (2015-09-13) partial animated GIF support
158
159
  limited 16-bit PSD support
159
160
  minor bugs, code cleanup, and compiler warnings
160
- 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value
161
- 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning
162
- 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit
163
- 2.03 (2015-04-12) additional corruption checking
164
- stbi_set_flip_vertically_on_load
165
- fix NEON support; fix mingw support
166
- 2.02 (2015-01-19) fix incorrect assert, fix warning
167
- 2.01 (2015-01-17) fix various warnings
168
- 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG
169
- 2.00 (2014-12-25) optimize JPEG, including x86 SSE2 & ARM NEON SIMD
170
- progressive JPEG
171
- PGM/PPM support
172
- STBI_MALLOC,STBI_REALLOC,STBI_FREE
173
- STBI_NO_*, STBI_ONLY_*
174
- GIF bugfix
175
161
 
176
162
  See end of file for full revision history.
177
163
 
@@ -204,8 +190,9 @@
204
190
  Laurent Gomila Cort Stratton Sergio Gonzalez romigrou@github
205
191
  Aruelien Pocheville Thibault Reuille Cass Everitt Matthew Gregan
206
192
  Ryamond Barbiero Paul Du Bois Engin Manap snagar@github
207
- Michaelangel007@github Oriol Ferrer Mesia socks-the-fox
208
- Blazej Dariusz Roszkowski
193
+ Michaelangel007@github Oriol Ferrer Mesia socks-the-fox Zelex@github
194
+ Philipp Wiesemann Josh Tobin rlyeh@github grim210@github
195
+ Blazej Dariusz Roszkowski
209
196
 
210
197
 
211
198
  LICENSE
@@ -238,10 +225,10 @@ publish, and distribute this file as you see fit.
238
225
  // stbi_image_free(data)
239
226
  //
240
227
  // Standard parameters:
241
- // int *x -- outputs image width in pixels
242
- // int *y -- outputs image height in pixels
243
- // int *comp -- outputs # of image components in image file
244
- // int req_comp -- if non-zero, # of image components requested in result
228
+ // int *x -- outputs image width in pixels
229
+ // int *y -- outputs image height in pixels
230
+ // int *channels_in_file -- outputs # of image components in image file
231
+ // int desired_channels -- if non-zero, # of image components requested in result
245
232
  //
246
233
  // The return value from an image loader is an 'unsigned char *' which points
247
234
  // to the pixel data, or NULL on an allocation failure or if the image is
@@ -406,6 +393,7 @@ enum
406
393
  };
407
394
 
408
395
  typedef unsigned char stbi_uc;
396
+ typedef unsigned short stbi_us;
409
397
 
410
398
  #ifdef __cplusplus
411
399
  extern "C" {
@@ -433,22 +421,42 @@ typedef struct
433
421
  int (*eof) (void *user); // returns nonzero if we are at end of file/data
434
422
  } stbi_io_callbacks;
435
423
 
436
- STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp);
437
- STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *comp, int req_comp);
438
- STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *comp, int req_comp);
424
+ ////////////////////////////////////
425
+ //
426
+ // 8-bits-per-channel interface
427
+ //
428
+
429
+ STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
430
+ STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels);
431
+ STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels);
439
432
 
440
433
  #ifndef STBI_NO_STDIO
441
- STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
434
+ STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
442
435
  // for stbi_load_from_file, file pointer is left pointing immediately after image
443
436
  #endif
444
437
 
438
+ ////////////////////////////////////
439
+ //
440
+ // 16-bits-per-channel interface
441
+ //
442
+
443
+ STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
444
+ #ifndef STBI_NO_STDIO
445
+ STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
446
+ #endif
447
+ // @TODO the other variants
448
+
449
+ ////////////////////////////////////
450
+ //
451
+ // float-per-channel interface
452
+ //
445
453
  #ifndef STBI_NO_LINEAR
446
- STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp);
447
- STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp);
448
- STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp);
454
+ STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels);
455
+ STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels);
456
+ STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels);
449
457
 
450
458
  #ifndef STBI_NO_STDIO
451
- STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp);
459
+ STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels);
452
460
  #endif
453
461
  #endif
454
462
 
@@ -828,57 +836,70 @@ static void stbi__rewind(stbi__context *s)
828
836
  s->img_buffer_end = s->img_buffer_original_end;
829
837
  }
830
838
 
839
+ enum
840
+ {
841
+ STBI_ORDER_RGB,
842
+ STBI_ORDER_BGR
843
+ };
844
+
845
+ typedef struct
846
+ {
847
+ int bits_per_channel;
848
+ int num_channels;
849
+ int channel_order;
850
+ } stbi__result_info;
851
+
831
852
  #ifndef STBI_NO_JPEG
832
853
  static int stbi__jpeg_test(stbi__context *s);
833
- static stbi_uc *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
854
+ static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
834
855
  static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp);
835
856
  #endif
836
857
 
837
858
  #ifndef STBI_NO_PNG
838
859
  static int stbi__png_test(stbi__context *s);
839
- static stbi_uc *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
860
+ static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
840
861
  static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp);
841
862
  #endif
842
863
 
843
864
  #ifndef STBI_NO_BMP
844
865
  static int stbi__bmp_test(stbi__context *s);
845
- static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
866
+ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
846
867
  static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp);
847
868
  #endif
848
869
 
849
870
  #ifndef STBI_NO_TGA
850
871
  static int stbi__tga_test(stbi__context *s);
851
- static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
872
+ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
852
873
  static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp);
853
874
  #endif
854
875
 
855
876
  #ifndef STBI_NO_PSD
856
877
  static int stbi__psd_test(stbi__context *s);
857
- static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
878
+ static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc);
858
879
  static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp);
859
880
  #endif
860
881
 
861
882
  #ifndef STBI_NO_HDR
862
883
  static int stbi__hdr_test(stbi__context *s);
863
- static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
884
+ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
864
885
  static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp);
865
886
  #endif
866
887
 
867
888
  #ifndef STBI_NO_PIC
868
889
  static int stbi__pic_test(stbi__context *s);
869
- static stbi_uc *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
890
+ static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
870
891
  static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp);
871
892
  #endif
872
893
 
873
894
  #ifndef STBI_NO_GIF
874
895
  static int stbi__gif_test(stbi__context *s);
875
- static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
896
+ static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
876
897
  static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp);
877
898
  #endif
878
899
 
879
900
  #ifndef STBI_NO_PNM
880
901
  static int stbi__pnm_test(stbi__context *s);
881
- static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp);
902
+ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri);
882
903
  static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp);
883
904
  #endif
884
905
 
@@ -1007,33 +1028,38 @@ STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip)
1007
1028
  stbi__vertically_flip_on_load = flag_true_if_should_flip;
1008
1029
  }
1009
1030
 
1010
- static unsigned char *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp)
1031
+ static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
1011
1032
  {
1033
+ memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields
1034
+ ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed
1035
+ ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order
1036
+ ri->num_channels = 0;
1037
+
1012
1038
  #ifndef STBI_NO_JPEG
1013
- if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp);
1039
+ if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri);
1014
1040
  #endif
1015
1041
  #ifndef STBI_NO_PNG
1016
- if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp);
1042
+ if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri);
1017
1043
  #endif
1018
1044
  #ifndef STBI_NO_BMP
1019
- if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp);
1045
+ if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri);
1020
1046
  #endif
1021
1047
  #ifndef STBI_NO_GIF
1022
- if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp);
1048
+ if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri);
1023
1049
  #endif
1024
1050
  #ifndef STBI_NO_PSD
1025
- if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp);
1051
+ if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc);
1026
1052
  #endif
1027
1053
  #ifndef STBI_NO_PIC
1028
- if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp);
1054
+ if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri);
1029
1055
  #endif
1030
1056
  #ifndef STBI_NO_PNM
1031
- if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp);
1057
+ if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri);
1032
1058
  #endif
1033
1059
 
1034
1060
  #ifndef STBI_NO_HDR
1035
1061
  if (stbi__hdr_test(s)) {
1036
- float *hdr = stbi__hdr_load(s, x,y,comp,req_comp);
1062
+ float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri);
1037
1063
  return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp);
1038
1064
  }
1039
1065
  #endif
@@ -1041,35 +1067,117 @@ static unsigned char *stbi__load_main(stbi__context *s, int *x, int *y, int *com
1041
1067
  #ifndef STBI_NO_TGA
1042
1068
  // test tga last because it's a crappy test!
1043
1069
  if (stbi__tga_test(s))
1044
- return stbi__tga_load(s,x,y,comp,req_comp);
1070
+ return stbi__tga_load(s,x,y,comp,req_comp, ri);
1045
1071
  #endif
1046
1072
 
1047
1073
  return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt");
1048
1074
  }
1049
1075
 
1050
- static unsigned char *stbi__load_flip(stbi__context *s, int *x, int *y, int *comp, int req_comp)
1076
+ static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels)
1051
1077
  {
1052
- unsigned char *result = stbi__load_main(s, x, y, comp, req_comp);
1078
+ int i;
1079
+ int img_len = w * h * channels;
1080
+ stbi_uc *reduced;
1053
1081
 
1054
- if (stbi__vertically_flip_on_load && result != NULL) {
1082
+ reduced = (stbi_uc *) stbi__malloc(img_len);
1083
+ if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory");
1084
+
1085
+ for (i = 0; i < img_len; ++i)
1086
+ reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling
1087
+
1088
+ STBI_FREE(orig);
1089
+ return reduced;
1090
+ }
1091
+
1092
+ static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels)
1093
+ {
1094
+ int i;
1095
+ int img_len = w * h * channels;
1096
+ stbi__uint16 *enlarged;
1097
+
1098
+ enlarged = (stbi__uint16 *) stbi__malloc(img_len*2);
1099
+ if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");
1100
+
1101
+ for (i = 0; i < img_len; ++i)
1102
+ enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff
1103
+
1104
+ STBI_FREE(orig);
1105
+ return enlarged;
1106
+ }
1107
+
1108
+ static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
1109
+ {
1110
+ stbi__result_info ri;
1111
+ void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8);
1112
+
1113
+ if (result == NULL)
1114
+ return NULL;
1115
+
1116
+ if (ri.bits_per_channel != 8) {
1117
+ STBI_ASSERT(ri.bits_per_channel == 16);
1118
+ result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
1119
+ ri.bits_per_channel = 8;
1120
+ }
1121
+
1122
+ // @TODO: move stbi__convert_format to here
1123
+
1124
+ if (stbi__vertically_flip_on_load) {
1055
1125
  int w = *x, h = *y;
1056
- int depth = req_comp ? req_comp : *comp;
1126
+ int channels = req_comp ? req_comp : *comp;
1057
1127
  int row,col,z;
1058
- stbi_uc temp;
1128
+ stbi_uc *image = (stbi_uc *) result;
1059
1129
 
1060
1130
  // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once
1061
1131
  for (row = 0; row < (h>>1); row++) {
1062
1132
  for (col = 0; col < w; col++) {
1063
- for (z = 0; z < depth; z++) {
1064
- temp = result[(row * w + col) * depth + z];
1065
- result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z];
1066
- result[((h - row - 1) * w + col) * depth + z] = temp;
1133
+ for (z = 0; z < channels; z++) {
1134
+ stbi_uc temp = image[(row * w + col) * channels + z];
1135
+ image[(row * w + col) * channels + z] = image[((h - row - 1) * w + col) * channels + z];
1136
+ image[((h - row - 1) * w + col) * channels + z] = temp;
1067
1137
  }
1068
1138
  }
1069
1139
  }
1070
1140
  }
1071
1141
 
1072
- return result;
1142
+ return (unsigned char *) result;
1143
+ }
1144
+
1145
+ static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp)
1146
+ {
1147
+ stbi__result_info ri;
1148
+ void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16);
1149
+
1150
+ if (result == NULL)
1151
+ return NULL;
1152
+
1153
+ if (ri.bits_per_channel != 16) {
1154
+ STBI_ASSERT(ri.bits_per_channel == 8);
1155
+ result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp);
1156
+ ri.bits_per_channel = 16;
1157
+ }
1158
+
1159
+ // @TODO: move stbi__convert_format16 to here
1160
+ // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision
1161
+
1162
+ if (stbi__vertically_flip_on_load) {
1163
+ int w = *x, h = *y;
1164
+ int channels = req_comp ? req_comp : *comp;
1165
+ int row,col,z;
1166
+ stbi__uint16 *image = (stbi__uint16 *) result;
1167
+
1168
+ // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once
1169
+ for (row = 0; row < (h>>1); row++) {
1170
+ for (col = 0; col < w; col++) {
1171
+ for (z = 0; z < channels; z++) {
1172
+ stbi__uint16 temp = image[(row * w + col) * channels + z];
1173
+ image[(row * w + col) * channels + z] = image[((h - row - 1) * w + col) * channels + z];
1174
+ image[((h - row - 1) * w + col) * channels + z] = temp;
1175
+ }
1176
+ }
1177
+ }
1178
+ }
1179
+
1180
+ return (stbi__uint16 *) result;
1073
1181
  }
1074
1182
 
1075
1183
  #ifndef STBI_NO_HDR
@@ -1125,27 +1233,52 @@ STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req
1125
1233
  unsigned char *result;
1126
1234
  stbi__context s;
1127
1235
  stbi__start_file(&s,f);
1128
- result = stbi__load_flip(&s,x,y,comp,req_comp);
1236
+ result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
1237
+ if (result) {
1238
+ // need to 'unget' all the characters in the IO buffer
1239
+ fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
1240
+ }
1241
+ return result;
1242
+ }
1243
+
1244
+ STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp)
1245
+ {
1246
+ stbi__uint16 *result;
1247
+ stbi__context s;
1248
+ stbi__start_file(&s,f);
1249
+ result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp);
1129
1250
  if (result) {
1130
1251
  // need to 'unget' all the characters in the IO buffer
1131
1252
  fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR);
1132
1253
  }
1133
1254
  return result;
1134
1255
  }
1256
+
1257
+ STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp)
1258
+ {
1259
+ FILE *f = stbi__fopen(filename, "rb");
1260
+ stbi__uint16 *result;
1261
+ if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file");
1262
+ result = stbi_load_from_file_16(f,x,y,comp,req_comp);
1263
+ fclose(f);
1264
+ return result;
1265
+ }
1266
+
1267
+
1135
1268
  #endif //!STBI_NO_STDIO
1136
1269
 
1137
1270
  STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp)
1138
1271
  {
1139
1272
  stbi__context s;
1140
1273
  stbi__start_mem(&s,buffer,len);
1141
- return stbi__load_flip(&s,x,y,comp,req_comp);
1274
+ return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
1142
1275
  }
1143
1276
 
1144
1277
  STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp)
1145
1278
  {
1146
1279
  stbi__context s;
1147
1280
  stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user);
1148
- return stbi__load_flip(&s,x,y,comp,req_comp);
1281
+ return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp);
1149
1282
  }
1150
1283
 
1151
1284
  #ifndef STBI_NO_LINEAR
@@ -1154,13 +1287,14 @@ static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int
1154
1287
  unsigned char *data;
1155
1288
  #ifndef STBI_NO_HDR
1156
1289
  if (stbi__hdr_test(s)) {
1157
- float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp);
1290
+ stbi__result_info ri;
1291
+ float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri);
1158
1292
  if (hdr_data)
1159
1293
  stbi__float_postprocess(hdr_data,x,y,comp,req_comp);
1160
1294
  return hdr_data;
1161
1295
  }
1162
1296
  #endif
1163
- data = stbi__load_flip(s, x, y, comp, req_comp);
1297
+ data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp);
1164
1298
  if (data)
1165
1299
  return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp);
1166
1300
  return stbi__errpf("unknown image type", "Image not of any known type, or corrupt");
@@ -1428,26 +1562,75 @@ static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int r
1428
1562
  unsigned char *src = data + j * x * img_n ;
1429
1563
  unsigned char *dest = good + j * x * req_comp;
1430
1564
 
1431
- #define COMBO(a,b) ((a)*8+(b))
1432
- #define CASE(a,b) case COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
1565
+ #define STBI__COMBO(a,b) ((a)*8+(b))
1566
+ #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
1567
+ // convert source image with img_n components to one with req_comp components;
1568
+ // avoid switch per pixel, so use switch per scanline and massive macros
1569
+ switch (STBI__COMBO(img_n, req_comp)) {
1570
+ STBI__CASE(1,2) { dest[0]=src[0], dest[1]=255; } break;
1571
+ STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;
1572
+ STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; } break;
1573
+ STBI__CASE(2,1) { dest[0]=src[0]; } break;
1574
+ STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;
1575
+ STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break;
1576
+ STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; } break;
1577
+ STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break;
1578
+ STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; } break;
1579
+ STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break;
1580
+ STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; } break;
1581
+ STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break;
1582
+ default: STBI_ASSERT(0);
1583
+ }
1584
+ #undef STBI__CASE
1585
+ }
1586
+
1587
+ STBI_FREE(data);
1588
+ return good;
1589
+ }
1590
+
1591
+ static stbi__uint16 stbi__compute_y_16(int r, int g, int b)
1592
+ {
1593
+ return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8);
1594
+ }
1595
+
1596
+ static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y)
1597
+ {
1598
+ int i,j;
1599
+ stbi__uint16 *good;
1600
+
1601
+ if (req_comp == img_n) return data;
1602
+ STBI_ASSERT(req_comp >= 1 && req_comp <= 4);
1603
+
1604
+ good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2);
1605
+ if (good == NULL) {
1606
+ STBI_FREE(data);
1607
+ return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory");
1608
+ }
1609
+
1610
+ for (j=0; j < (int) y; ++j) {
1611
+ stbi__uint16 *src = data + j * x * img_n ;
1612
+ stbi__uint16 *dest = good + j * x * req_comp;
1613
+
1614
+ #define STBI__COMBO(a,b) ((a)*8+(b))
1615
+ #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b)
1433
1616
  // convert source image with img_n components to one with req_comp components;
1434
1617
  // avoid switch per pixel, so use switch per scanline and massive macros
1435
- switch (COMBO(img_n, req_comp)) {
1436
- CASE(1,2) dest[0]=src[0], dest[1]=255; break;
1437
- CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break;
1438
- CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break;
1439
- CASE(2,1) dest[0]=src[0]; break;
1440
- CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break;
1441
- CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break;
1442
- CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break;
1443
- CASE(3,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break;
1444
- CASE(3,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; break;
1445
- CASE(4,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break;
1446
- CASE(4,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break;
1447
- CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break;
1618
+ switch (STBI__COMBO(img_n, req_comp)) {
1619
+ STBI__CASE(1,2) { dest[0]=src[0], dest[1]=0xffff; } break;
1620
+ STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;
1621
+ STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=0xffff; } break;
1622
+ STBI__CASE(2,1) { dest[0]=src[0]; } break;
1623
+ STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break;
1624
+ STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; } break;
1625
+ STBI__CASE(3,4) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=0xffff; } break;
1626
+ STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break;
1627
+ STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = 0xffff; } break;
1628
+ STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break;
1629
+ STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]), dest[1] = src[3]; } break;
1630
+ STBI__CASE(4,3) { dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; } break;
1448
1631
  default: STBI_ASSERT(0);
1449
1632
  }
1450
- #undef CASE
1633
+ #undef STBI__CASE
1451
1634
  }
1452
1635
 
1453
1636
  STBI_FREE(data);
@@ -3506,7 +3689,7 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
3506
3689
  }
3507
3690
  }
3508
3691
 
3509
- static unsigned char *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
3692
+ static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
3510
3693
  {
3511
3694
  unsigned char* result;
3512
3695
  stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));
@@ -4166,37 +4349,37 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
4166
4349
  // this is a little gross, so that we don't switch per-pixel or per-component
4167
4350
  if (depth < 8 || img_n == out_n) {
4168
4351
  int nk = (width - 1)*filter_bytes;
4169
- #define CASE(f) \
4352
+ #define STBI__CASE(f) \
4170
4353
  case f: \
4171
4354
  for (k=0; k < nk; ++k)
4172
4355
  switch (filter) {
4173
4356
  // "none" filter turns into a memcpy here; make that explicit.
4174
4357
  case STBI__F_none: memcpy(cur, raw, nk); break;
4175
- CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); break;
4176
- CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
4177
- CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); break;
4178
- CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); break;
4179
- CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); break;
4180
- CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); break;
4358
+ STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break;
4359
+ STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
4360
+ STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break;
4361
+ STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break;
4362
+ STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break;
4363
+ STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break;
4181
4364
  }
4182
- #undef CASE
4365
+ #undef STBI__CASE
4183
4366
  raw += nk;
4184
4367
  } else {
4185
4368
  STBI_ASSERT(img_n+1 == out_n);
4186
- #define CASE(f) \
4369
+ #define STBI__CASE(f) \
4187
4370
  case f: \
4188
4371
  for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \
4189
4372
  for (k=0; k < filter_bytes; ++k)
4190
4373
  switch (filter) {
4191
- CASE(STBI__F_none) cur[k] = raw[k]; break;
4192
- CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); break;
4193
- CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
4194
- CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); break;
4195
- CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); break;
4196
- CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); break;
4197
- CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); break;
4374
+ STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break;
4375
+ STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break;
4376
+ STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
4377
+ STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break;
4378
+ STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break;
4379
+ STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break;
4380
+ STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break;
4198
4381
  }
4199
- #undef CASE
4382
+ #undef STBI__CASE
4200
4383
 
4201
4384
  // the loop above sets the high byte of the pixels' alpha, but for
4202
4385
  // 16 bit png files we also need the low byte set. we'll do that here.
@@ -4428,27 +4611,6 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int
4428
4611
  return 1;
4429
4612
  }
4430
4613
 
4431
- static int stbi__reduce_png(stbi__png *p)
4432
- {
4433
- int i;
4434
- int img_len = p->s->img_x * p->s->img_y * p->s->img_out_n;
4435
- stbi_uc *reduced;
4436
- stbi__uint16 *orig = (stbi__uint16*)p->out;
4437
-
4438
- if (p->depth != 16) return 1; // don't need to do anything if not 16-bit data
4439
-
4440
- reduced = (stbi_uc *)stbi__malloc(img_len);
4441
- if (reduced == NULL) return stbi__err("outofmem", "Out of memory");
4442
-
4443
- for (i = 0; i < img_len; ++i)
4444
- reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is a decent approx of 16->8 bit scaling
4445
-
4446
- p->out = reduced;
4447
- STBI_FREE(orig);
4448
-
4449
- return 1;
4450
- }
4451
-
4452
4614
  static int stbi__unpremultiply_on_load = 0;
4453
4615
  static int stbi__de_iphone_flag = 0;
4454
4616
 
@@ -4588,7 +4750,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
4588
4750
  if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG");
4589
4751
  has_trans = 1;
4590
4752
  if (z->depth == 16) {
4591
- for (k = 0; k < s->img_n; ++k) tc16[k] = stbi__get16be(s); // copy the values as-is
4753
+ for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
4592
4754
  } else {
4593
4755
  for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger
4594
4756
  }
@@ -4675,20 +4837,19 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
4675
4837
  }
4676
4838
  }
4677
4839
 
4678
- static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp)
4840
+ static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri)
4679
4841
  {
4680
- unsigned char *result=NULL;
4842
+ void *result=NULL;
4681
4843
  if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
4682
4844
  if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
4683
- if (p->depth == 16) {
4684
- if (!stbi__reduce_png(p)) {
4685
- return result;
4686
- }
4687
- }
4845
+ ri->bits_per_channel = p->depth;
4688
4846
  result = p->out;
4689
4847
  p->out = NULL;
4690
4848
  if (req_comp && req_comp != p->s->img_out_n) {
4691
- result = stbi__convert_format(result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
4849
+ if (ri->bits_per_channel == 8)
4850
+ result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
4851
+ else
4852
+ result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y);
4692
4853
  p->s->img_out_n = req_comp;
4693
4854
  if (result == NULL) return result;
4694
4855
  }
@@ -4703,11 +4864,11 @@ static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req
4703
4864
  return result;
4704
4865
  }
4705
4866
 
4706
- static unsigned char *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
4867
+ static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
4707
4868
  {
4708
4869
  stbi__png p;
4709
4870
  p.s = s;
4710
- return stbi__do_png(&p, x,y,comp,req_comp);
4871
+ return stbi__do_png(&p, x,y,comp,req_comp, ri);
4711
4872
  }
4712
4873
 
4713
4874
  static int stbi__png_test(stbi__context *s)
@@ -4895,7 +5056,7 @@ static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
4895
5056
  }
4896
5057
 
4897
5058
 
4898
- static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
5059
+ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
4899
5060
  {
4900
5061
  stbi_uc *out;
4901
5062
  unsigned int mr=0,mg=0,mb=0,ma=0, all_a;
@@ -4903,6 +5064,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
4903
5064
  int psize=0,i,j,width;
4904
5065
  int flip_vertically, pad, target;
4905
5066
  stbi__bmp_data info;
5067
+ STBI_NOTUSED(ri);
4906
5068
 
4907
5069
  info.all_a = 255;
4908
5070
  if (stbi__bmp_parse_header(s, &info) == NULL)
@@ -5169,18 +5331,18 @@ errorEnd:
5169
5331
  }
5170
5332
 
5171
5333
  // read 16bit value and convert to 24bit RGB
5172
- void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out)
5334
+ static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out)
5173
5335
  {
5174
- stbi__uint16 px = stbi__get16le(s);
5336
+ stbi__uint16 px = (stbi__uint16)stbi__get16le(s);
5175
5337
  stbi__uint16 fiveBitMask = 31;
5176
5338
  // we have 3 channels with 5bits each
5177
5339
  int r = (px >> 10) & fiveBitMask;
5178
5340
  int g = (px >> 5) & fiveBitMask;
5179
5341
  int b = px & fiveBitMask;
5180
5342
  // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later
5181
- out[0] = (r * 255)/31;
5182
- out[1] = (g * 255)/31;
5183
- out[2] = (b * 255)/31;
5343
+ out[0] = (stbi_uc)((r * 255)/31);
5344
+ out[1] = (stbi_uc)((g * 255)/31);
5345
+ out[2] = (stbi_uc)((b * 255)/31);
5184
5346
 
5185
5347
  // some people claim that the most significant bit might be used for alpha
5186
5348
  // (possibly if an alpha-bit is set in the "image descriptor byte")
@@ -5188,7 +5350,7 @@ void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out)
5188
5350
  // so let's treat all 15 and 16bit TGAs as RGB with no alpha.
5189
5351
  }
5190
5352
 
5191
- static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
5353
+ static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
5192
5354
  {
5193
5355
  // read in the TGA header stuff
5194
5356
  int tga_offset = stbi__get8(s);
@@ -5214,6 +5376,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
5214
5376
  int RLE_count = 0;
5215
5377
  int RLE_repeating = 0;
5216
5378
  int read_next_pixel = 1;
5379
+ STBI_NOTUSED(ri);
5217
5380
 
5218
5381
  // do a tiny bit of precessing
5219
5382
  if ( tga_image_type >= 8 )
@@ -5431,7 +5594,7 @@ static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount)
5431
5594
  return 1;
5432
5595
  }
5433
5596
 
5434
- static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
5597
+ static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc)
5435
5598
  {
5436
5599
  int pixelCount;
5437
5600
  int channelCount, compression;
@@ -5439,6 +5602,7 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
5439
5602
  int bitdepth;
5440
5603
  int w,h;
5441
5604
  stbi_uc *out;
5605
+ STBI_NOTUSED(ri);
5442
5606
 
5443
5607
  // Check identifier
5444
5608
  if (stbi__get32be(s) != 0x38425053) // "8BPS"
@@ -5500,7 +5664,13 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
5500
5664
  return stbi__errpuc("too large", "Corrupt PSD");
5501
5665
 
5502
5666
  // Create the destination image.
5503
- out = (stbi_uc *) stbi__malloc_mad3(4, w, h, 0);
5667
+
5668
+ if (!compression && bitdepth == 16 && bpc == 16) {
5669
+ out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0);
5670
+ ri->bits_per_channel = 16;
5671
+ } else
5672
+ out = (stbi_uc *) stbi__malloc(4 * w*h);
5673
+
5504
5674
  if (!out) return stbi__errpuc("outofmem", "Out of memory");
5505
5675
  pixelCount = w*h;
5506
5676
 
@@ -5541,48 +5711,77 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
5541
5711
 
5542
5712
  } else {
5543
5713
  // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...)
5544
- // where each channel consists of an 8-bit value for each pixel in the image.
5714
+ // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image.
5545
5715
 
5546
5716
  // Read the data by channel.
5547
5717
  for (channel = 0; channel < 4; channel++) {
5548
- stbi_uc *p;
5549
-
5550
- p = out + channel;
5551
5718
  if (channel >= channelCount) {
5552
5719
  // Fill this channel with default data.
5553
- stbi_uc val = channel == 3 ? 255 : 0;
5554
- for (i = 0; i < pixelCount; i++, p += 4)
5555
- *p = val;
5556
- } else {
5557
- // Read the data.
5558
- if (bitdepth == 16) {
5559
- for (i = 0; i < pixelCount; i++, p += 4)
5560
- *p = (stbi_uc) (stbi__get16be(s) >> 8);
5720
+ if (bitdepth == 16 && bpc == 16) {
5721
+ stbi__uint16 *q = ((stbi__uint16 *) out) + channel;
5722
+ stbi_uc val = channel == 3 ? 65535 : 0;
5723
+ for (i = 0; i < pixelCount; i++, q += 4)
5724
+ *q = val;
5561
5725
  } else {
5726
+ stbi_uc *p = out+channel;
5727
+ stbi_uc val = channel == 3 ? 255 : 0;
5562
5728
  for (i = 0; i < pixelCount; i++, p += 4)
5563
- *p = stbi__get8(s);
5729
+ *p = val;
5730
+ }
5731
+ } else {
5732
+ if (ri->bits_per_channel == 16) { // output bpc
5733
+ stbi__uint16 *q = ((stbi__uint16 *) out) + channel;
5734
+ for (i = 0; i < pixelCount; i++, q += 4)
5735
+ *q = (stbi__uint16) stbi__get16be(s);
5736
+ } else {
5737
+ stbi_uc *p = out+channel;
5738
+ if (bitdepth == 16) { // input bpc
5739
+ for (i = 0; i < pixelCount; i++, p += 4)
5740
+ *p = (stbi_uc) (stbi__get16be(s) >> 8);
5741
+ } else {
5742
+ for (i = 0; i < pixelCount; i++, p += 4)
5743
+ *p = stbi__get8(s);
5744
+ }
5564
5745
  }
5565
5746
  }
5566
5747
  }
5567
5748
  }
5568
5749
 
5750
+ // remove weird white matte from PSD
5569
5751
  if (channelCount >= 4) {
5570
- for (i=0; i < w*h; ++i) {
5571
- unsigned char *pixel = out + 4*i;
5572
- if (pixel[3] != 0 && pixel[3] != 255) {
5573
- // remove weird white matte from PSD
5574
- float a = pixel[3] / 255.0f;
5575
- float ra = 1.0f / a;
5576
- float inv_a = 255.0f * (1 - ra);
5577
- pixel[0] = (unsigned char) (pixel[0]*ra + inv_a);
5578
- pixel[1] = (unsigned char) (pixel[1]*ra + inv_a);
5579
- pixel[2] = (unsigned char) (pixel[2]*ra + inv_a);
5752
+ if (ri->bits_per_channel == 16) {
5753
+ for (i=0; i < w*h; ++i) {
5754
+ stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i;
5755
+ if (pixel[3] != 0 && pixel[3] != 65535) {
5756
+ float a = pixel[3] / 65535.0f;
5757
+ float ra = 1.0f / a;
5758
+ float inv_a = 65535.0f * (1 - ra);
5759
+ pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a);
5760
+ pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a);
5761
+ pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a);
5762
+ }
5763
+ }
5764
+ } else {
5765
+ for (i=0; i < w*h; ++i) {
5766
+ unsigned char *pixel = out + 4*i;
5767
+ if (pixel[3] != 0 && pixel[3] != 255) {
5768
+ float a = pixel[3] / 255.0f;
5769
+ float ra = 1.0f / a;
5770
+ float inv_a = 255.0f * (1 - ra);
5771
+ pixel[0] = (unsigned char) (pixel[0]*ra + inv_a);
5772
+ pixel[1] = (unsigned char) (pixel[1]*ra + inv_a);
5773
+ pixel[2] = (unsigned char) (pixel[2]*ra + inv_a);
5774
+ }
5580
5775
  }
5581
5776
  }
5582
5777
  }
5583
5778
 
5779
+ // convert to desired output format
5584
5780
  if (req_comp && req_comp != 4) {
5585
- out = stbi__convert_format(out, 4, req_comp, w, h);
5781
+ if (ri->bits_per_channel == 16)
5782
+ out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h);
5783
+ else
5784
+ out = stbi__convert_format(out, 4, req_comp, w, h);
5586
5785
  if (out == NULL) return out; // stbi__convert_format frees input on failure
5587
5786
  }
5588
5787
 
@@ -5766,10 +5965,11 @@ static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *c
5766
5965
  return result;
5767
5966
  }
5768
5967
 
5769
- static stbi_uc *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp)
5968
+ static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri)
5770
5969
  {
5771
5970
  stbi_uc *result;
5772
5971
  int i, x,y;
5972
+ STBI_NOTUSED(ri);
5773
5973
 
5774
5974
  for (i=0; i<92; ++i)
5775
5975
  stbi__get8(s);
@@ -6154,11 +6354,12 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
6154
6354
  STBI_NOTUSED(req_comp);
6155
6355
  }
6156
6356
 
6157
- static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
6357
+ static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
6158
6358
  {
6159
6359
  stbi_uc *u = 0;
6160
6360
  stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
6161
6361
  memset(g, 0, sizeof(*g));
6362
+ STBI_NOTUSED(ri);
6162
6363
 
6163
6364
  u = stbi__gif_load_next(s, g, comp, req_comp);
6164
6365
  if (u == (stbi_uc *) s) u = 0; // end of animated gif marker
@@ -6184,20 +6385,24 @@ static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp)
6184
6385
  // Radiance RGBE HDR loader
6185
6386
  // originally by Nicolas Schulz
6186
6387
  #ifndef STBI_NO_HDR
6187
- static int stbi__hdr_test_core(stbi__context *s)
6388
+ static int stbi__hdr_test_core(stbi__context *s, const char *signature)
6188
6389
  {
6189
- const char *signature = "#?RADIANCE\n";
6190
6390
  int i;
6191
6391
  for (i=0; signature[i]; ++i)
6192
6392
  if (stbi__get8(s) != signature[i])
6193
- return 0;
6393
+ return 0;
6394
+ stbi__rewind(s);
6194
6395
  return 1;
6195
6396
  }
6196
6397
 
6197
6398
  static int stbi__hdr_test(stbi__context* s)
6198
6399
  {
6199
- int r = stbi__hdr_test_core(s);
6400
+ int r = stbi__hdr_test_core(s, "#?RADIANCE\n");
6200
6401
  stbi__rewind(s);
6402
+ if(!r) {
6403
+ r = stbi__hdr_test_core(s, "#?RGBE\n");
6404
+ stbi__rewind(s);
6405
+ }
6201
6406
  return r;
6202
6407
  }
6203
6408
 
@@ -6251,7 +6456,7 @@ static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp)
6251
6456
  }
6252
6457
  }
6253
6458
 
6254
- static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
6459
+ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
6255
6460
  {
6256
6461
  char buffer[STBI__HDR_BUFLEN];
6257
6462
  char *token;
@@ -6262,10 +6467,12 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
6262
6467
  int len;
6263
6468
  unsigned char count, value;
6264
6469
  int i, j, k, c1,c2, z;
6265
-
6470
+ const char *headerToken;
6471
+ STBI_NOTUSED(ri);
6266
6472
 
6267
6473
  // Check identifier
6268
- if (strcmp(stbi__hdr_gettoken(s,buffer), "#?RADIANCE") != 0)
6474
+ headerToken = stbi__hdr_gettoken(s,buffer);
6475
+ if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0)
6269
6476
  return stbi__errpf("not HDR", "Corrupt HDR image");
6270
6477
 
6271
6478
  // Parse header
@@ -6549,11 +6756,14 @@ static int stbi__pnm_test(stbi__context *s)
6549
6756
  return 1;
6550
6757
  }
6551
6758
 
6552
- static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
6759
+ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri)
6553
6760
  {
6554
6761
  stbi_uc *out;
6762
+ STBI_NOTUSED(ri);
6763
+
6555
6764
  if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n))
6556
6765
  return 0;
6766
+
6557
6767
  *x = s->img_x;
6558
6768
  *y = s->img_y;
6559
6769
  *comp = s->img_n;
@@ -6726,6 +6936,7 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
6726
6936
 
6727
6937
  /*
6728
6938
  revision history:
6939
+ 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now
6729
6940
  2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
6730
6941
  2.11 (2016-04-02) allocate large structures on the stack
6731
6942
  remove white matting for transparent PSD