gosu 0.10.6 → 0.10.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/COPYING +1 -1
- data/Gosu/Gosu.hpp +1 -1
- data/Gosu/Version.hpp +3 -3
- data/README.md +4 -0
- data/ext/gosu/extconf.rb +8 -8
- data/ext/gosu/gosu_wrap.cxx +12 -7
- data/src/AppleUtility.hpp +19 -62
- data/src/Audio/Audio.cpp +31 -23
- data/src/Audio/AudioToolboxFile.hpp +19 -18
- data/src/Bitmap/BitmapIO.cpp +32 -17
- data/src/DirectoriesApple.mm +36 -41
- data/src/Input/Input.cpp +22 -6
- data/src/Input/InputUIKit.mm +37 -29
- data/src/Text/Font.cpp +1 -1
- data/src/Text/TextApple.mm +50 -41
- data/src/UIKit/GosuAppDelegate.mm +1 -1
- data/src/UIKit/GosuGLView.mm +0 -2
- data/src/UIKit/GosuViewController.mm +7 -10
- data/src/UtilityApple.mm +26 -19
- data/src/WindowUIKit.mm +22 -12
- data/src/stb_image.h +499 -253
- data/src/stb_image_write.h +98 -43
- data/src/stb_vorbis.c +188 -232
- metadata +4 -4
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
8
8
|
{
|
9
|
-
self.window = (UIWindow *)windowInstance().UIWindow();
|
9
|
+
self.window = (__bridge UIWindow *)windowInstance().UIWindow();
|
10
10
|
[self.window makeKeyAndVisible];
|
11
11
|
|
12
12
|
return YES;
|
data/src/UIKit/GosuGLView.mm
CHANGED
@@ -42,7 +42,7 @@ static void handleAudioInterruption(void *unused, UInt32 inInterruptionState)
|
|
42
42
|
|
43
43
|
- (void)loadView
|
44
44
|
{
|
45
|
-
self.view = [[
|
45
|
+
self.view = [[GosuGLView alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
46
46
|
}
|
47
47
|
|
48
48
|
- (BOOL)prefersStatusBarHidden
|
@@ -95,8 +95,6 @@ static void handleAudioInterruption(void *unused, UInt32 inInterruptionState)
|
|
95
95
|
- (void)dealloc
|
96
96
|
{
|
97
97
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
98
|
-
|
99
|
-
[super dealloc];
|
100
98
|
}
|
101
99
|
|
102
100
|
- (void)applicationDidBecomeActive:(NSNotification *)notification
|
@@ -128,7 +126,6 @@ static void handleAudioInterruption(void *unused, UInt32 inInterruptionState)
|
|
128
126
|
- (void)applicationDidEnterBackground:(NSNotification *)notification
|
129
127
|
{
|
130
128
|
[_timerOrDisplayLink invalidate];
|
131
|
-
[_timerOrDisplayLink release];
|
132
129
|
_timerOrDisplayLink = nil;
|
133
130
|
}
|
134
131
|
|
@@ -154,14 +151,14 @@ static void handleAudioInterruption(void *unused, UInt32 inInterruptionState)
|
|
154
151
|
NSTimeInterval interval = self.gosuWindowReference.updateInterval() / 1000.0;
|
155
152
|
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(updateAndDraw:) userInfo:nil repeats:YES];
|
156
153
|
|
157
|
-
_timerOrDisplayLink =
|
154
|
+
_timerOrDisplayLink = timer;
|
158
155
|
}
|
159
156
|
else {
|
160
157
|
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateAndDraw:)];
|
161
158
|
displayLink.frameInterval = 60 / targetFPS;
|
162
159
|
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
|
163
160
|
|
164
|
-
_timerOrDisplayLink =
|
161
|
+
_timerOrDisplayLink = displayLink;
|
165
162
|
}
|
166
163
|
}
|
167
164
|
|
@@ -193,22 +190,22 @@ static void handleAudioInterruption(void *unused, UInt32 inInterruptionState)
|
|
193
190
|
|
194
191
|
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
|
195
192
|
{
|
196
|
-
self.gosuWindowReference.input().feedTouchEvent(0, touches);
|
193
|
+
self.gosuWindowReference.input().feedTouchEvent(0, (__bridge void *)touches);
|
197
194
|
}
|
198
195
|
|
199
196
|
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
|
200
197
|
{
|
201
|
-
self.gosuWindowReference.input().feedTouchEvent(1, touches);
|
198
|
+
self.gosuWindowReference.input().feedTouchEvent(1, (__bridge void *)touches);
|
202
199
|
}
|
203
200
|
|
204
201
|
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
|
205
202
|
{
|
206
|
-
self.gosuWindowReference.input().feedTouchEvent(2, touches);
|
203
|
+
self.gosuWindowReference.input().feedTouchEvent(2, (__bridge void *)touches);
|
207
204
|
}
|
208
205
|
|
209
206
|
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
|
210
207
|
{
|
211
|
-
self.gosuWindowReference.input().feedTouchEvent(3, touches);
|
208
|
+
self.gosuWindowReference.input().feedTouchEvent(3, (__bridge void *)touches);
|
212
209
|
}
|
213
210
|
|
214
211
|
@end
|
data/src/UtilityApple.mm
CHANGED
@@ -9,38 +9,44 @@ using namespace std;
|
|
9
9
|
#ifdef GOSU_IS_IPHONE // (but could also be used for OS X)
|
10
10
|
wstring Gosu::utf8ToWstring(const string& s)
|
11
11
|
{
|
12
|
-
if (s.empty())
|
12
|
+
if (s.empty()) {
|
13
13
|
return wstring();
|
14
|
+
}
|
14
15
|
|
15
|
-
|
16
|
+
NSString *str = [NSString stringWithUTF8String:s.c_str()];
|
16
17
|
vector<wchar_t> buffer(s.size());
|
17
18
|
NSUInteger usedBufferCount;
|
18
|
-
if (![str
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
if (![str getBytes:&buffer[0]
|
20
|
+
maxLength:buffer.size() * sizeof(wchar_t)
|
21
|
+
usedLength:&usedBufferCount
|
22
|
+
encoding:NSUTF32LittleEndianStringEncoding
|
23
|
+
options:0
|
24
|
+
range:NSMakeRange(0, str.length)
|
25
|
+
remainingRange:NULL]) {
|
25
26
|
throw std::runtime_error("String " + s + " could not be converted to Unicode");
|
27
|
+
}
|
26
28
|
return wstring(&buffer[0], &buffer[0] + usedBufferCount / sizeof(wchar_t));
|
27
29
|
}
|
30
|
+
|
28
31
|
string Gosu::wstringToUTF8(const std::wstring& ws)
|
29
32
|
{
|
30
|
-
if (ws.empty())
|
33
|
+
if (ws.empty()) {
|
31
34
|
return string();
|
35
|
+
}
|
32
36
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
37
|
+
@autoreleasepool {
|
38
|
+
NSString *str = [[NSString alloc] initWithBytes:ws.data()
|
39
|
+
length:ws.size() * sizeof(wchar_t)
|
40
|
+
encoding:NSUTF32LittleEndianStringEncoding];
|
41
|
+
return str.UTF8String ?: string();
|
42
|
+
}
|
39
43
|
}
|
44
|
+
|
40
45
|
wstring Gosu::widen(const string& s)
|
41
46
|
{
|
42
47
|
return utf8ToWstring(s);
|
43
48
|
}
|
49
|
+
|
44
50
|
string Gosu::narrow(const std::wstring& ws)
|
45
51
|
{
|
46
52
|
return wstringToUTF8(ws);
|
@@ -49,7 +55,8 @@ string Gosu::narrow(const std::wstring& ws)
|
|
49
55
|
|
50
56
|
string Gosu::language()
|
51
57
|
{
|
52
|
-
|
53
|
-
|
54
|
-
|
58
|
+
@autoreleasepool {
|
59
|
+
NSString *language = [[NSLocale preferredLanguages] firstObject];
|
60
|
+
return [language UTF8String] ?: "en";
|
61
|
+
}
|
55
62
|
}
|
data/src/WindowUIKit.mm
CHANGED
@@ -17,16 +17,26 @@ namespace Gosu
|
|
17
17
|
static CGFloat width = MAX(screenSize.width, screenSize.height);
|
18
18
|
return width;
|
19
19
|
}
|
20
|
+
|
21
|
+
unsigned availableWidth()
|
22
|
+
{
|
23
|
+
return screenWidth();
|
24
|
+
}
|
25
|
+
|
26
|
+
unsigned availableHeight()
|
27
|
+
{
|
28
|
+
return screenHeight();
|
29
|
+
}
|
20
30
|
}
|
21
31
|
|
22
32
|
class Gosu::Audio {};
|
23
33
|
|
24
34
|
struct Gosu::Window::Impl
|
25
35
|
{
|
26
|
-
|
27
|
-
|
28
|
-
std::
|
29
|
-
std::
|
36
|
+
::UIWindow *window;
|
37
|
+
GosuViewController *controller;
|
38
|
+
std::unique_ptr<Graphics> graphics;
|
39
|
+
std::unique_ptr<Input> input;
|
30
40
|
double interval;
|
31
41
|
std::wstring caption;
|
32
42
|
};
|
@@ -35,18 +45,18 @@ Gosu::Window::Window(unsigned width, unsigned height,
|
|
35
45
|
bool fullscreen, double updateInterval)
|
36
46
|
: pimpl(new Impl)
|
37
47
|
{
|
38
|
-
pimpl->window
|
39
|
-
pimpl->controller
|
40
|
-
pimpl->controller.
|
41
|
-
pimpl->window.
|
48
|
+
pimpl->window = [[::UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
|
49
|
+
pimpl->controller = [GosuViewController new];
|
50
|
+
pimpl->controller.gosuWindow = this;
|
51
|
+
pimpl->window.rootViewController = pimpl->controller;
|
42
52
|
|
43
53
|
// It is important to load the view before creating the Graphics instance.
|
44
|
-
[pimpl->controller
|
54
|
+
[pimpl->controller loadView];
|
45
55
|
|
46
56
|
pimpl->graphics.reset(new Graphics(screenHeight(), screenWidth(), false));
|
47
57
|
pimpl->graphics->setResolution(width, height);
|
48
58
|
|
49
|
-
pimpl->input.reset(new Input(pimpl->controller.
|
59
|
+
pimpl->input.reset(new Input((__bridge void *)pimpl->controller.view, updateInterval));
|
50
60
|
pimpl->input->setMouseFactors(1.0 * width / screenHeight(), 1.0 * height / screenWidth());
|
51
61
|
|
52
62
|
using namespace std::tr1::placeholders;
|
@@ -123,7 +133,7 @@ void Gosu::Window::close()
|
|
123
133
|
throw std::logic_error("Cannot close windows manually on iOS");
|
124
134
|
}
|
125
135
|
|
126
|
-
void*
|
136
|
+
void *Gosu::Window::UIWindow() const
|
127
137
|
{
|
128
|
-
return pimpl->window
|
138
|
+
return (__bridge void *)pimpl->window;
|
129
139
|
}
|
data/src/stb_image.h
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
/* stb_image - v2.
|
1
|
+
/* stb_image - v2.12 - 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,13 @@
|
|
146
146
|
|
147
147
|
|
148
148
|
Latest revision history:
|
149
|
+
2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
|
150
|
+
2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64
|
151
|
+
RGB-format JPEG; remove white matting in PSD;
|
152
|
+
allocate large structures on the stack;
|
153
|
+
correct channel count for PNG & BMP
|
154
|
+
2.10 (2016-01-22) avoid warning introduced in 2.09
|
155
|
+
2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED
|
149
156
|
2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA
|
150
157
|
2.07 (2015-09-13) partial animated GIF support
|
151
158
|
limited 16-bit PSD support
|
@@ -165,60 +172,47 @@
|
|
165
172
|
STBI_MALLOC,STBI_REALLOC,STBI_FREE
|
166
173
|
STBI_NO_*, STBI_ONLY_*
|
167
174
|
GIF bugfix
|
168
|
-
1.48 (2014-12-14) fix incorrectly-named assert()
|
169
|
-
1.47 (2014-12-14) 1/2/4-bit PNG support (both grayscale and paletted)
|
170
|
-
optimize PNG
|
171
|
-
fix bug in interlaced PNG with user-specified channel count
|
172
175
|
|
173
176
|
See end of file for full revision history.
|
174
177
|
|
175
178
|
|
176
179
|
============================ Contributors =========================
|
177
180
|
|
178
|
-
Image formats
|
179
|
-
Sean Barrett (jpeg, png, bmp)
|
180
|
-
Nicolas Schulz (hdr, psd)
|
181
|
-
Jonathan Dummer (tga)
|
182
|
-
Jean-Marc Lienher (gif)
|
183
|
-
Tom Seddon (pic)
|
184
|
-
Thatcher Ulrich (psd)
|
185
|
-
Ken Miller (pgm, ppm)
|
186
|
-
urraka@github (animated gif)
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
Arseny Kapoulkine Sergio Gonzalez
|
208
|
-
Cass Everitt
|
209
|
-
Engin Manap
|
210
|
-
If your name should be here but Martins Mozeiko
|
211
|
-
isn't, let Sean know. Joseph Thomson
|
212
|
-
Phil Jordan
|
213
|
-
Nathan Reed
|
214
|
-
Michaelangel007@github
|
215
|
-
Nick Verigakis
|
181
|
+
Image formats Extensions, features
|
182
|
+
Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info)
|
183
|
+
Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info)
|
184
|
+
Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG)
|
185
|
+
Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks)
|
186
|
+
Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG)
|
187
|
+
Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip)
|
188
|
+
Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD)
|
189
|
+
urraka@github (animated gif) Junggon Kim (PNM comments)
|
190
|
+
Daniel Gibson (16-bit TGA)
|
191
|
+
|
192
|
+
Optimizations & bugfixes
|
193
|
+
Fabian "ryg" Giesen
|
194
|
+
Arseny Kapoulkine
|
195
|
+
|
196
|
+
Bug & warning fixes
|
197
|
+
Marc LeBlanc David Woo Guillaume George Martins Mozeiko
|
198
|
+
Christpher Lloyd Martin Golini Jerry Jansson Joseph Thomson
|
199
|
+
Dave Moore Roy Eltham Hayaki Saito Phil Jordan
|
200
|
+
Won Chun Luke Graham Johan Duparc Nathan Reed
|
201
|
+
the Horde3D community Thomas Ruf Ronny Chevalier Nick Verigakis
|
202
|
+
Janez Zemva John Bartholomew Michal Cichon svdijk@github
|
203
|
+
Jonathan Blow Ken Hamada Tero Hanninen Baldur Karlsson
|
204
|
+
Laurent Gomila Cort Stratton Sergio Gonzalez romigrou@github
|
205
|
+
Aruelien Pocheville Thibault Reuille Cass Everitt Matthew Gregan
|
206
|
+
Ryamond Barbiero Paul Du Bois Engin Manap snagar@github
|
207
|
+
Michaelangel007@github Oriol Ferrer Mesia socks-the-fox
|
208
|
+
Blazej Dariusz Roszkowski
|
209
|
+
|
216
210
|
|
217
211
|
LICENSE
|
218
212
|
|
219
|
-
This software is
|
220
|
-
|
221
|
-
|
213
|
+
This software is dual-licensed to the public domain and under the following
|
214
|
+
license: you are granted a perpetual, irrevocable license to copy, modify,
|
215
|
+
publish, and distribute this file as you see fit.
|
222
216
|
|
223
217
|
*/
|
224
218
|
|
@@ -461,12 +455,12 @@ STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y,
|
|
461
455
|
#ifndef STBI_NO_HDR
|
462
456
|
STBIDEF void stbi_hdr_to_ldr_gamma(float gamma);
|
463
457
|
STBIDEF void stbi_hdr_to_ldr_scale(float scale);
|
464
|
-
#endif
|
458
|
+
#endif // STBI_NO_HDR
|
465
459
|
|
466
460
|
#ifndef STBI_NO_LINEAR
|
467
461
|
STBIDEF void stbi_ldr_to_hdr_gamma(float gamma);
|
468
462
|
STBIDEF void stbi_ldr_to_hdr_scale(float scale);
|
469
|
-
#endif //
|
463
|
+
#endif // STBI_NO_LINEAR
|
470
464
|
|
471
465
|
// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR
|
472
466
|
STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user);
|
@@ -630,18 +624,22 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
|
|
630
624
|
#define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y))))
|
631
625
|
#endif
|
632
626
|
|
633
|
-
#if defined(STBI_MALLOC) && defined(STBI_FREE) && defined(STBI_REALLOC)
|
627
|
+
#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED))
|
634
628
|
// ok
|
635
|
-
#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC)
|
629
|
+
#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED)
|
636
630
|
// ok
|
637
631
|
#else
|
638
|
-
#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC."
|
632
|
+
#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)."
|
639
633
|
#endif
|
640
634
|
|
641
635
|
#ifndef STBI_MALLOC
|
642
|
-
#define STBI_MALLOC(sz)
|
643
|
-
#define STBI_REALLOC(p,
|
644
|
-
#define STBI_FREE(p)
|
636
|
+
#define STBI_MALLOC(sz) malloc(sz)
|
637
|
+
#define STBI_REALLOC(p,newsz) realloc(p,newsz)
|
638
|
+
#define STBI_FREE(p) free(p)
|
639
|
+
#endif
|
640
|
+
|
641
|
+
#ifndef STBI_REALLOC_SIZED
|
642
|
+
#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz)
|
645
643
|
#endif
|
646
644
|
|
647
645
|
// x86/x64 detection
|
@@ -675,7 +673,7 @@ typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1];
|
|
675
673
|
#define STBI_NO_SIMD
|
676
674
|
#endif
|
677
675
|
|
678
|
-
#if !defined(STBI_NO_SIMD) && defined(STBI__X86_TARGET)
|
676
|
+
#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET))
|
679
677
|
#define STBI_SSE2
|
680
678
|
#include <emmintrin.h>
|
681
679
|
|
@@ -1186,14 +1184,15 @@ STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void
|
|
1186
1184
|
#endif
|
1187
1185
|
}
|
1188
1186
|
|
1189
|
-
|
1187
|
+
#ifndef STBI_NO_LINEAR
|
1190
1188
|
static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f;
|
1191
1189
|
|
1192
|
-
#ifndef STBI_NO_LINEAR
|
1193
1190
|
STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; }
|
1194
1191
|
STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; }
|
1195
1192
|
#endif
|
1196
1193
|
|
1194
|
+
static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f;
|
1195
|
+
|
1197
1196
|
STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; }
|
1198
1197
|
STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; }
|
1199
1198
|
|
@@ -1508,6 +1507,7 @@ typedef struct
|
|
1508
1507
|
int succ_high;
|
1509
1508
|
int succ_low;
|
1510
1509
|
int eob_run;
|
1510
|
+
int rgb;
|
1511
1511
|
|
1512
1512
|
int scan_n, order[4];
|
1513
1513
|
int restart_interval, todo;
|
@@ -2719,11 +2719,17 @@ static int stbi__process_frame_header(stbi__jpeg *z, int scan)
|
|
2719
2719
|
|
2720
2720
|
if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG");
|
2721
2721
|
|
2722
|
+
z->rgb = 0;
|
2722
2723
|
for (i=0; i < s->img_n; ++i) {
|
2724
|
+
static unsigned char rgb[3] = { 'R', 'G', 'B' };
|
2723
2725
|
z->img_comp[i].id = stbi__get8(s);
|
2724
2726
|
if (z->img_comp[i].id != i+1) // JFIF requires
|
2725
|
-
if (z->img_comp[i].id != i) // some version of jpegtran outputs non-JFIF-compliant files!
|
2726
|
-
|
2727
|
+
if (z->img_comp[i].id != i) { // some version of jpegtran outputs non-JFIF-compliant files!
|
2728
|
+
// somethings output this (see http://fileformats.archiveteam.org/wiki/JPEG#Color_format)
|
2729
|
+
if (z->img_comp[i].id != rgb[i])
|
2730
|
+
return stbi__err("bad component ID","Corrupt JPEG");
|
2731
|
+
++z->rgb;
|
2732
|
+
}
|
2727
2733
|
q = stbi__get8(s);
|
2728
2734
|
z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG");
|
2729
2735
|
z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG");
|
@@ -3385,7 +3391,17 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
|
|
3385
3391
|
if (n >= 3) {
|
3386
3392
|
stbi_uc *y = coutput[0];
|
3387
3393
|
if (z->s->img_n == 3) {
|
3388
|
-
z->
|
3394
|
+
if (z->rgb == 3) {
|
3395
|
+
for (i=0; i < z->s->img_x; ++i) {
|
3396
|
+
out[0] = y[i];
|
3397
|
+
out[1] = coutput[1][i];
|
3398
|
+
out[2] = coutput[2][i];
|
3399
|
+
out[3] = 255;
|
3400
|
+
out += n;
|
3401
|
+
}
|
3402
|
+
} else {
|
3403
|
+
z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
|
3404
|
+
}
|
3389
3405
|
} else
|
3390
3406
|
for (i=0; i < z->s->img_x; ++i) {
|
3391
3407
|
out[0] = out[1] = out[2] = y[i];
|
@@ -3410,10 +3426,13 @@ static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp
|
|
3410
3426
|
|
3411
3427
|
static unsigned char *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
3412
3428
|
{
|
3413
|
-
|
3414
|
-
j
|
3415
|
-
|
3416
|
-
|
3429
|
+
unsigned char* result;
|
3430
|
+
stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));
|
3431
|
+
j->s = s;
|
3432
|
+
stbi__setup_jpeg(j);
|
3433
|
+
result = load_jpeg_image(j, x,y,comp,req_comp);
|
3434
|
+
STBI_FREE(j);
|
3435
|
+
return result;
|
3417
3436
|
}
|
3418
3437
|
|
3419
3438
|
static int stbi__jpeg_test(stbi__context *s)
|
@@ -3441,9 +3460,12 @@ static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp)
|
|
3441
3460
|
|
3442
3461
|
static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)
|
3443
3462
|
{
|
3444
|
-
|
3445
|
-
j
|
3446
|
-
|
3463
|
+
int result;
|
3464
|
+
stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));
|
3465
|
+
j->s = s;
|
3466
|
+
result = stbi__jpeg_info_raw(j, x, y, comp);
|
3467
|
+
STBI_FREE(j);
|
3468
|
+
return result;
|
3447
3469
|
}
|
3448
3470
|
#endif
|
3449
3471
|
|
@@ -3616,14 +3638,15 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
|
|
3616
3638
|
static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes
|
3617
3639
|
{
|
3618
3640
|
char *q;
|
3619
|
-
int cur, limit;
|
3641
|
+
int cur, limit, old_limit;
|
3620
3642
|
z->zout = zout;
|
3621
3643
|
if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG");
|
3622
3644
|
cur = (int) (z->zout - z->zout_start);
|
3623
|
-
limit = (int) (z->zout_end - z->zout_start);
|
3645
|
+
limit = old_limit = (int) (z->zout_end - z->zout_start);
|
3624
3646
|
while (cur + n > limit)
|
3625
3647
|
limit *= 2;
|
3626
|
-
q = (char *)
|
3648
|
+
q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit);
|
3649
|
+
STBI_NOTUSED(old_limit);
|
3627
3650
|
if (q == NULL) return stbi__err("outofmem", "Out of memory");
|
3628
3651
|
z->zout_start = q;
|
3629
3652
|
z->zout = q + cur;
|
@@ -3733,7 +3756,7 @@ static int stbi__compute_huffman_codes(stbi__zbuf *a)
|
|
3733
3756
|
return 1;
|
3734
3757
|
}
|
3735
3758
|
|
3736
|
-
static int
|
3759
|
+
static int stbi__parse_uncompressed_block(stbi__zbuf *a)
|
3737
3760
|
{
|
3738
3761
|
stbi_uc header[4];
|
3739
3762
|
int len,nlen,k;
|
@@ -3799,7 +3822,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header)
|
|
3799
3822
|
final = stbi__zreceive(a,1);
|
3800
3823
|
type = stbi__zreceive(a,2);
|
3801
3824
|
if (type == 0) {
|
3802
|
-
if (!
|
3825
|
+
if (!stbi__parse_uncompressed_block(a)) return 0;
|
3803
3826
|
} else if (type == 3) {
|
3804
3827
|
return 0;
|
3805
3828
|
} else {
|
@@ -3941,6 +3964,7 @@ typedef struct
|
|
3941
3964
|
{
|
3942
3965
|
stbi__context *s;
|
3943
3966
|
stbi_uc *idata, *expanded, *out;
|
3967
|
+
int depth;
|
3944
3968
|
} stbi__png;
|
3945
3969
|
|
3946
3970
|
|
@@ -3980,14 +4004,19 @@ static stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x0
|
|
3980
4004
|
// create the png data from post-deflated data
|
3981
4005
|
static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
|
3982
4006
|
{
|
4007
|
+
int bytes = (depth == 16? 2 : 1);
|
3983
4008
|
stbi__context *s = a->s;
|
3984
|
-
stbi__uint32 i,j,stride = x*out_n;
|
4009
|
+
stbi__uint32 i,j,stride = x*out_n*bytes;
|
3985
4010
|
stbi__uint32 img_len, img_width_bytes;
|
3986
4011
|
int k;
|
3987
4012
|
int img_n = s->img_n; // copy it into a local for later
|
3988
4013
|
|
4014
|
+
int output_bytes = out_n*bytes;
|
4015
|
+
int filter_bytes = img_n*bytes;
|
4016
|
+
int width = x;
|
4017
|
+
|
3989
4018
|
STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1);
|
3990
|
-
a->out = (stbi_uc *) stbi__malloc(x * y *
|
4019
|
+
a->out = (stbi_uc *) stbi__malloc(x * y * output_bytes); // extra bytes to write off the end into
|
3991
4020
|
if (!a->out) return stbi__err("outofmem", "Out of memory");
|
3992
4021
|
|
3993
4022
|
img_width_bytes = (((img_n * x * depth) + 7) >> 3);
|
@@ -4002,8 +4031,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
|
|
4002
4031
|
stbi_uc *cur = a->out + stride*j;
|
4003
4032
|
stbi_uc *prior = cur - stride;
|
4004
4033
|
int filter = *raw++;
|
4005
|
-
|
4006
|
-
int width = x;
|
4034
|
+
|
4007
4035
|
if (filter > 4)
|
4008
4036
|
return stbi__err("invalid filter","Corrupt PNG");
|
4009
4037
|
|
@@ -4036,6 +4064,14 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
|
|
4036
4064
|
raw += img_n;
|
4037
4065
|
cur += out_n;
|
4038
4066
|
prior += out_n;
|
4067
|
+
} else if (depth == 16) {
|
4068
|
+
if (img_n != out_n) {
|
4069
|
+
cur[filter_bytes] = 255; // first pixel top byte
|
4070
|
+
cur[filter_bytes+1] = 255; // first pixel bottom byte
|
4071
|
+
}
|
4072
|
+
raw += filter_bytes;
|
4073
|
+
cur += output_bytes;
|
4074
|
+
prior += output_bytes;
|
4039
4075
|
} else {
|
4040
4076
|
raw += 1;
|
4041
4077
|
cur += 1;
|
@@ -4044,7 +4080,7 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
|
|
4044
4080
|
|
4045
4081
|
// this is a little gross, so that we don't switch per-pixel or per-component
|
4046
4082
|
if (depth < 8 || img_n == out_n) {
|
4047
|
-
int nk = (width - 1)*
|
4083
|
+
int nk = (width - 1)*filter_bytes;
|
4048
4084
|
#define CASE(f) \
|
4049
4085
|
case f: \
|
4050
4086
|
for (k=0; k < nk; ++k)
|
@@ -4064,18 +4100,27 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
|
|
4064
4100
|
STBI_ASSERT(img_n+1 == out_n);
|
4065
4101
|
#define CASE(f) \
|
4066
4102
|
case f: \
|
4067
|
-
for (i=x-1; i >= 1; --i, cur[
|
4068
|
-
for (k=0; k <
|
4103
|
+
for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \
|
4104
|
+
for (k=0; k < filter_bytes; ++k)
|
4069
4105
|
switch (filter) {
|
4070
4106
|
CASE(STBI__F_none) cur[k] = raw[k]; break;
|
4071
|
-
CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-
|
4107
|
+
CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); break;
|
4072
4108
|
CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
|
4073
|
-
CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-
|
4074
|
-
CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-
|
4075
|
-
CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-
|
4076
|
-
CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-
|
4109
|
+
CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); break;
|
4110
|
+
CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); break;
|
4111
|
+
CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); break;
|
4112
|
+
CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); break;
|
4077
4113
|
}
|
4078
4114
|
#undef CASE
|
4115
|
+
|
4116
|
+
// the loop above sets the high byte of the pixels' alpha, but for
|
4117
|
+
// 16 bit png files we also need the low byte set. we'll do that here.
|
4118
|
+
if (depth == 16) {
|
4119
|
+
cur = a->out + stride*j; // start at the beginning of the row again
|
4120
|
+
for (i=0; i < x; ++i,cur+=output_bytes) {
|
4121
|
+
cur[filter_bytes+1] = 255;
|
4122
|
+
}
|
4123
|
+
}
|
4079
4124
|
}
|
4080
4125
|
}
|
4081
4126
|
|
@@ -4151,6 +4196,17 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
|
|
4151
4196
|
}
|
4152
4197
|
}
|
4153
4198
|
}
|
4199
|
+
} else if (depth == 16) {
|
4200
|
+
// force the image data from big-endian to platform-native.
|
4201
|
+
// this is done in a separate pass due to the decoding relying
|
4202
|
+
// on the data being untouched, but could probably be done
|
4203
|
+
// per-line during decode if care is taken.
|
4204
|
+
stbi_uc *cur = a->out;
|
4205
|
+
stbi__uint16 *cur16 = (stbi__uint16*)cur;
|
4206
|
+
|
4207
|
+
for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) {
|
4208
|
+
*cur16 = (cur[0] << 8) | cur[1];
|
4209
|
+
}
|
4154
4210
|
}
|
4155
4211
|
|
4156
4212
|
return 1;
|
@@ -4223,6 +4279,31 @@ static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n)
|
|
4223
4279
|
return 1;
|
4224
4280
|
}
|
4225
4281
|
|
4282
|
+
static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n)
|
4283
|
+
{
|
4284
|
+
stbi__context *s = z->s;
|
4285
|
+
stbi__uint32 i, pixel_count = s->img_x * s->img_y;
|
4286
|
+
stbi__uint16 *p = (stbi__uint16*) z->out;
|
4287
|
+
|
4288
|
+
// compute color-based transparency, assuming we've
|
4289
|
+
// already got 65535 as the alpha value in the output
|
4290
|
+
STBI_ASSERT(out_n == 2 || out_n == 4);
|
4291
|
+
|
4292
|
+
if (out_n == 2) {
|
4293
|
+
for (i = 0; i < pixel_count; ++i) {
|
4294
|
+
p[1] = (p[0] == tc[0] ? 0 : 65535);
|
4295
|
+
p += 2;
|
4296
|
+
}
|
4297
|
+
} else {
|
4298
|
+
for (i = 0; i < pixel_count; ++i) {
|
4299
|
+
if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2])
|
4300
|
+
p[3] = 0;
|
4301
|
+
p += 4;
|
4302
|
+
}
|
4303
|
+
}
|
4304
|
+
return 1;
|
4305
|
+
}
|
4306
|
+
|
4226
4307
|
static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n)
|
4227
4308
|
{
|
4228
4309
|
stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y;
|
@@ -4260,6 +4341,26 @@ static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int
|
|
4260
4341
|
return 1;
|
4261
4342
|
}
|
4262
4343
|
|
4344
|
+
static int stbi__reduce_png(stbi__png *p)
|
4345
|
+
{
|
4346
|
+
int i;
|
4347
|
+
int img_len = p->s->img_x * p->s->img_y * p->s->img_out_n;
|
4348
|
+
stbi_uc *reduced;
|
4349
|
+
stbi__uint16 *orig = (stbi__uint16*)p->out;
|
4350
|
+
|
4351
|
+
if (p->depth != 16) return 1; // don't need to do anything if not 16-bit data
|
4352
|
+
|
4353
|
+
reduced = (stbi_uc *)stbi__malloc(img_len);
|
4354
|
+
if (p == NULL) return stbi__err("outofmem", "Out of memory");
|
4355
|
+
|
4356
|
+
for (i = 0; i < img_len; ++i) reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is a decent approx of 16->8 bit scaling
|
4357
|
+
|
4358
|
+
p->out = reduced;
|
4359
|
+
STBI_FREE(orig);
|
4360
|
+
|
4361
|
+
return 1;
|
4362
|
+
}
|
4363
|
+
|
4263
4364
|
static int stbi__unpremultiply_on_load = 0;
|
4264
4365
|
static int stbi__de_iphone_flag = 0;
|
4265
4366
|
|
@@ -4321,8 +4422,9 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|
4321
4422
|
{
|
4322
4423
|
stbi_uc palette[1024], pal_img_n=0;
|
4323
4424
|
stbi_uc has_trans=0, tc[3];
|
4425
|
+
stbi__uint16 tc16[3];
|
4324
4426
|
stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;
|
4325
|
-
int first=1,k,interlace=0, color=0,
|
4427
|
+
int first=1,k,interlace=0, color=0, is_iphone=0;
|
4326
4428
|
stbi__context *s = z->s;
|
4327
4429
|
|
4328
4430
|
z->expanded = NULL;
|
@@ -4347,8 +4449,9 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|
4347
4449
|
if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG");
|
4348
4450
|
s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
|
4349
4451
|
s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)");
|
4350
|
-
depth = stbi__get8(s); if (depth != 1 && depth != 2 && depth != 4 && depth != 8) return stbi__err("1/2/4/8-bit only","PNG not supported: 1/2/4/8-bit only");
|
4452
|
+
z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only");
|
4351
4453
|
color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG");
|
4454
|
+
if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG");
|
4352
4455
|
if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG");
|
4353
4456
|
comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG");
|
4354
4457
|
filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG");
|
@@ -4396,8 +4499,11 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|
4396
4499
|
if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG");
|
4397
4500
|
if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG");
|
4398
4501
|
has_trans = 1;
|
4399
|
-
|
4400
|
-
|
4502
|
+
if (z->depth == 16) {
|
4503
|
+
for (k = 0; k < s->img_n; ++k) tc16[k] = stbi__get16be(s); // copy the values as-is
|
4504
|
+
} else {
|
4505
|
+
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
|
4506
|
+
}
|
4401
4507
|
}
|
4402
4508
|
break;
|
4403
4509
|
}
|
@@ -4408,11 +4514,13 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|
4408
4514
|
if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; }
|
4409
4515
|
if ((int)(ioff + c.length) < (int)ioff) return 0;
|
4410
4516
|
if (ioff + c.length > idata_limit) {
|
4517
|
+
stbi__uint32 idata_limit_old = idata_limit;
|
4411
4518
|
stbi_uc *p;
|
4412
4519
|
if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096;
|
4413
4520
|
while (ioff + c.length > idata_limit)
|
4414
4521
|
idata_limit *= 2;
|
4415
|
-
|
4522
|
+
STBI_NOTUSED(idata_limit_old);
|
4523
|
+
p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory");
|
4416
4524
|
z->idata = p;
|
4417
4525
|
}
|
4418
4526
|
if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG");
|
@@ -4426,7 +4534,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|
4426
4534
|
if (scan != STBI__SCAN_load) return 1;
|
4427
4535
|
if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG");
|
4428
4536
|
// initial guess for decoded data size to avoid unnecessary reallocs
|
4429
|
-
bpl = (s->img_x * depth + 7) / 8; // bytes per line, per component
|
4537
|
+
bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component
|
4430
4538
|
raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */;
|
4431
4539
|
z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone);
|
4432
4540
|
if (z->expanded == NULL) return 0; // zlib should set error
|
@@ -4435,9 +4543,14 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
|
|
4435
4543
|
s->img_out_n = s->img_n+1;
|
4436
4544
|
else
|
4437
4545
|
s->img_out_n = s->img_n;
|
4438
|
-
if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, depth, color, interlace)) return 0;
|
4439
|
-
if (has_trans)
|
4440
|
-
if (
|
4546
|
+
if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0;
|
4547
|
+
if (has_trans) {
|
4548
|
+
if (z->depth == 16) {
|
4549
|
+
if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0;
|
4550
|
+
} else {
|
4551
|
+
if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0;
|
4552
|
+
}
|
4553
|
+
}
|
4441
4554
|
if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2)
|
4442
4555
|
stbi__de_iphone(z);
|
4443
4556
|
if (pal_img_n) {
|
@@ -4479,6 +4592,11 @@ static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req
|
|
4479
4592
|
unsigned char *result=NULL;
|
4480
4593
|
if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error");
|
4481
4594
|
if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) {
|
4595
|
+
if (p->depth == 16) {
|
4596
|
+
if (!stbi__reduce_png(p)) {
|
4597
|
+
return result;
|
4598
|
+
}
|
4599
|
+
}
|
4482
4600
|
result = p->out;
|
4483
4601
|
p->out = NULL;
|
4484
4602
|
if (req_comp && req_comp != p->s->img_out_n) {
|
@@ -4488,7 +4606,7 @@ static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req
|
|
4488
4606
|
}
|
4489
4607
|
*x = p->s->img_x;
|
4490
4608
|
*y = p->s->img_y;
|
4491
|
-
if (n) *n = p->s->
|
4609
|
+
if (n) *n = p->s->img_n;
|
4492
4610
|
}
|
4493
4611
|
STBI_FREE(p->out); p->out = NULL;
|
4494
4612
|
STBI_FREE(p->expanded); p->expanded = NULL;
|
@@ -4598,19 +4716,23 @@ static int stbi__shiftsigned(int v, int shift, int bits)
|
|
4598
4716
|
return result;
|
4599
4717
|
}
|
4600
4718
|
|
4601
|
-
|
4719
|
+
typedef struct
|
4602
4720
|
{
|
4603
|
-
|
4604
|
-
unsigned int mr
|
4605
|
-
|
4606
|
-
|
4607
|
-
|
4721
|
+
int bpp, offset, hsz;
|
4722
|
+
unsigned int mr,mg,mb,ma, all_a;
|
4723
|
+
} stbi__bmp_data;
|
4724
|
+
|
4725
|
+
static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info)
|
4726
|
+
{
|
4727
|
+
int hsz;
|
4608
4728
|
if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP");
|
4609
4729
|
stbi__get32le(s); // discard filesize
|
4610
4730
|
stbi__get16le(s); // discard reserved
|
4611
4731
|
stbi__get16le(s); // discard reserved
|
4612
|
-
offset = stbi__get32le(s);
|
4613
|
-
hsz = stbi__get32le(s);
|
4732
|
+
info->offset = stbi__get32le(s);
|
4733
|
+
info->hsz = hsz = stbi__get32le(s);
|
4734
|
+
info->mr = info->mg = info->mb = info->ma = 0;
|
4735
|
+
|
4614
4736
|
if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown");
|
4615
4737
|
if (hsz == 12) {
|
4616
4738
|
s->img_x = stbi__get16le(s);
|
@@ -4620,15 +4742,10 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|
4620
4742
|
s->img_y = stbi__get32le(s);
|
4621
4743
|
}
|
4622
4744
|
if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP");
|
4623
|
-
bpp = stbi__get16le(s);
|
4624
|
-
if (bpp == 1) return stbi__errpuc("monochrome", "BMP type not supported: 1-bit");
|
4625
|
-
|
4626
|
-
|
4627
|
-
if (hsz == 12) {
|
4628
|
-
if (bpp < 24)
|
4629
|
-
psize = (offset - 14 - 24) / 3;
|
4630
|
-
} else {
|
4631
|
-
compress = stbi__get32le(s);
|
4745
|
+
info->bpp = stbi__get16le(s);
|
4746
|
+
if (info->bpp == 1) return stbi__errpuc("monochrome", "BMP type not supported: 1-bit");
|
4747
|
+
if (hsz != 12) {
|
4748
|
+
int compress = stbi__get32le(s);
|
4632
4749
|
if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE");
|
4633
4750
|
stbi__get32le(s); // discard sizeof
|
4634
4751
|
stbi__get32le(s); // discard hres
|
@@ -4642,26 +4759,25 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|
4642
4759
|
stbi__get32le(s);
|
4643
4760
|
stbi__get32le(s);
|
4644
4761
|
}
|
4645
|
-
if (bpp == 16 || bpp == 32) {
|
4646
|
-
mr = mg = mb = 0;
|
4762
|
+
if (info->bpp == 16 || info->bpp == 32) {
|
4647
4763
|
if (compress == 0) {
|
4648
|
-
if (bpp == 32) {
|
4649
|
-
mr = 0xffu << 16;
|
4650
|
-
mg = 0xffu << 8;
|
4651
|
-
mb = 0xffu << 0;
|
4652
|
-
ma = 0xffu << 24;
|
4653
|
-
all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0
|
4764
|
+
if (info->bpp == 32) {
|
4765
|
+
info->mr = 0xffu << 16;
|
4766
|
+
info->mg = 0xffu << 8;
|
4767
|
+
info->mb = 0xffu << 0;
|
4768
|
+
info->ma = 0xffu << 24;
|
4769
|
+
info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0
|
4654
4770
|
} else {
|
4655
|
-
mr = 31u << 10;
|
4656
|
-
mg = 31u << 5;
|
4657
|
-
mb = 31u << 0;
|
4771
|
+
info->mr = 31u << 10;
|
4772
|
+
info->mg = 31u << 5;
|
4773
|
+
info->mb = 31u << 0;
|
4658
4774
|
}
|
4659
4775
|
} else if (compress == 3) {
|
4660
|
-
mr = stbi__get32le(s);
|
4661
|
-
mg = stbi__get32le(s);
|
4662
|
-
mb = stbi__get32le(s);
|
4776
|
+
info->mr = stbi__get32le(s);
|
4777
|
+
info->mg = stbi__get32le(s);
|
4778
|
+
info->mb = stbi__get32le(s);
|
4663
4779
|
// not documented, but generated by photoshop and handled by mspaint
|
4664
|
-
if (mr == mg && mg == mb) {
|
4780
|
+
if (info->mr == info->mg && info->mg == info->mb) {
|
4665
4781
|
// ?!?!?
|
4666
4782
|
return stbi__errpuc("bad BMP", "bad BMP");
|
4667
4783
|
}
|
@@ -4669,11 +4785,13 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|
4669
4785
|
return stbi__errpuc("bad BMP", "bad BMP");
|
4670
4786
|
}
|
4671
4787
|
} else {
|
4672
|
-
|
4673
|
-
|
4674
|
-
|
4675
|
-
|
4676
|
-
|
4788
|
+
int i;
|
4789
|
+
if (hsz != 108 && hsz != 124)
|
4790
|
+
return stbi__errpuc("bad BMP", "bad BMP");
|
4791
|
+
info->mr = stbi__get32le(s);
|
4792
|
+
info->mg = stbi__get32le(s);
|
4793
|
+
info->mb = stbi__get32le(s);
|
4794
|
+
info->ma = stbi__get32le(s);
|
4677
4795
|
stbi__get32le(s); // discard color space
|
4678
4796
|
for (i=0; i < 12; ++i)
|
4679
4797
|
stbi__get32le(s); // discard color space parameters
|
@@ -4684,35 +4802,68 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|
4684
4802
|
stbi__get32le(s); // discard reserved
|
4685
4803
|
}
|
4686
4804
|
}
|
4687
|
-
if (bpp < 16)
|
4688
|
-
psize = (offset - 14 - hsz) >> 2;
|
4689
4805
|
}
|
4806
|
+
return (void *) 1;
|
4807
|
+
}
|
4808
|
+
|
4809
|
+
|
4810
|
+
static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
4811
|
+
{
|
4812
|
+
stbi_uc *out;
|
4813
|
+
unsigned int mr=0,mg=0,mb=0,ma=0, all_a;
|
4814
|
+
stbi_uc pal[256][4];
|
4815
|
+
int psize=0,i,j,width;
|
4816
|
+
int flip_vertically, pad, target;
|
4817
|
+
stbi__bmp_data info;
|
4818
|
+
|
4819
|
+
info.all_a = 255;
|
4820
|
+
if (stbi__bmp_parse_header(s, &info) == NULL)
|
4821
|
+
return NULL; // error code already set
|
4822
|
+
|
4823
|
+
flip_vertically = ((int) s->img_y) > 0;
|
4824
|
+
s->img_y = abs((int) s->img_y);
|
4825
|
+
|
4826
|
+
mr = info.mr;
|
4827
|
+
mg = info.mg;
|
4828
|
+
mb = info.mb;
|
4829
|
+
ma = info.ma;
|
4830
|
+
all_a = info.all_a;
|
4831
|
+
|
4832
|
+
if (info.hsz == 12) {
|
4833
|
+
if (info.bpp < 24)
|
4834
|
+
psize = (info.offset - 14 - 24) / 3;
|
4835
|
+
} else {
|
4836
|
+
if (info.bpp < 16)
|
4837
|
+
psize = (info.offset - 14 - info.hsz) >> 2;
|
4838
|
+
}
|
4839
|
+
|
4690
4840
|
s->img_n = ma ? 4 : 3;
|
4691
4841
|
if (req_comp && req_comp >= 3) // we can directly decode 3 or 4
|
4692
4842
|
target = req_comp;
|
4693
4843
|
else
|
4694
4844
|
target = s->img_n; // if they want monochrome, we'll post-convert
|
4845
|
+
|
4695
4846
|
out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y);
|
4696
4847
|
if (!out) return stbi__errpuc("outofmem", "Out of memory");
|
4697
|
-
if (bpp < 16) {
|
4848
|
+
if (info.bpp < 16) {
|
4698
4849
|
int z=0;
|
4699
4850
|
if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); }
|
4700
4851
|
for (i=0; i < psize; ++i) {
|
4701
4852
|
pal[i][2] = stbi__get8(s);
|
4702
4853
|
pal[i][1] = stbi__get8(s);
|
4703
4854
|
pal[i][0] = stbi__get8(s);
|
4704
|
-
if (hsz != 12) stbi__get8(s);
|
4855
|
+
if (info.hsz != 12) stbi__get8(s);
|
4705
4856
|
pal[i][3] = 255;
|
4706
4857
|
}
|
4707
|
-
stbi__skip(s, offset - 14 - hsz - psize * (hsz == 12 ? 3 : 4));
|
4708
|
-
if (bpp == 4) width = (s->img_x + 1) >> 1;
|
4709
|
-
else if (bpp == 8) width = s->img_x;
|
4858
|
+
stbi__skip(s, info.offset - 14 - info.hsz - psize * (info.hsz == 12 ? 3 : 4));
|
4859
|
+
if (info.bpp == 4) width = (s->img_x + 1) >> 1;
|
4860
|
+
else if (info.bpp == 8) width = s->img_x;
|
4710
4861
|
else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); }
|
4711
4862
|
pad = (-width)&3;
|
4712
4863
|
for (j=0; j < (int) s->img_y; ++j) {
|
4713
4864
|
for (i=0; i < (int) s->img_x; i += 2) {
|
4714
4865
|
int v=stbi__get8(s),v2=0;
|
4715
|
-
if (bpp == 4) {
|
4866
|
+
if (info.bpp == 4) {
|
4716
4867
|
v2 = v & 15;
|
4717
4868
|
v >>= 4;
|
4718
4869
|
}
|
@@ -4721,7 +4872,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|
4721
4872
|
out[z++] = pal[v][2];
|
4722
4873
|
if (target == 4) out[z++] = 255;
|
4723
4874
|
if (i+1 == (int) s->img_x) break;
|
4724
|
-
v = (bpp == 8) ? stbi__get8(s) : v2;
|
4875
|
+
v = (info.bpp == 8) ? stbi__get8(s) : v2;
|
4725
4876
|
out[z++] = pal[v][0];
|
4726
4877
|
out[z++] = pal[v][1];
|
4727
4878
|
out[z++] = pal[v][2];
|
@@ -4733,14 +4884,14 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|
4733
4884
|
int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0;
|
4734
4885
|
int z = 0;
|
4735
4886
|
int easy=0;
|
4736
|
-
stbi__skip(s, offset - 14 - hsz);
|
4737
|
-
if (bpp == 24) width = 3 * s->img_x;
|
4738
|
-
else if (bpp == 16) width = 2*s->img_x;
|
4887
|
+
stbi__skip(s, info.offset - 14 - info.hsz);
|
4888
|
+
if (info.bpp == 24) width = 3 * s->img_x;
|
4889
|
+
else if (info.bpp == 16) width = 2*s->img_x;
|
4739
4890
|
else /* bpp = 32 and pad = 0 */ width=0;
|
4740
4891
|
pad = (-width) & 3;
|
4741
|
-
if (bpp == 24) {
|
4892
|
+
if (info.bpp == 24) {
|
4742
4893
|
easy = 1;
|
4743
|
-
} else if (bpp == 32) {
|
4894
|
+
} else if (info.bpp == 32) {
|
4744
4895
|
if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000)
|
4745
4896
|
easy = 2;
|
4746
4897
|
}
|
@@ -4765,6 +4916,7 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|
4765
4916
|
if (target == 4) out[z++] = a;
|
4766
4917
|
}
|
4767
4918
|
} else {
|
4919
|
+
int bpp = info.bpp;
|
4768
4920
|
for (i=0; i < (int) s->img_x; ++i) {
|
4769
4921
|
stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s));
|
4770
4922
|
int a;
|
@@ -4811,20 +4963,55 @@ static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int
|
|
4811
4963
|
// Targa Truevision - TGA
|
4812
4964
|
// by Jonathan Dummer
|
4813
4965
|
#ifndef STBI_NO_TGA
|
4966
|
+
// returns STBI_rgb or whatever, 0 on error
|
4967
|
+
static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16)
|
4968
|
+
{
|
4969
|
+
// only RGB or RGBA (incl. 16bit) or grey allowed
|
4970
|
+
if(is_rgb16) *is_rgb16 = 0;
|
4971
|
+
switch(bits_per_pixel) {
|
4972
|
+
case 8: return STBI_grey;
|
4973
|
+
case 16: if(is_grey) return STBI_grey_alpha;
|
4974
|
+
// else: fall-through
|
4975
|
+
case 15: if(is_rgb16) *is_rgb16 = 1;
|
4976
|
+
return STBI_rgb;
|
4977
|
+
case 24: // fall-through
|
4978
|
+
case 32: return bits_per_pixel/8;
|
4979
|
+
default: return 0;
|
4980
|
+
}
|
4981
|
+
}
|
4982
|
+
|
4814
4983
|
static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
|
4815
4984
|
{
|
4816
|
-
int tga_w, tga_h, tga_comp;
|
4817
|
-
int sz;
|
4985
|
+
int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp;
|
4986
|
+
int sz, tga_colormap_type;
|
4818
4987
|
stbi__get8(s); // discard Offset
|
4819
|
-
|
4820
|
-
if(
|
4988
|
+
tga_colormap_type = stbi__get8(s); // colormap type
|
4989
|
+
if( tga_colormap_type > 1 ) {
|
4821
4990
|
stbi__rewind(s);
|
4822
4991
|
return 0; // only RGB or indexed allowed
|
4823
4992
|
}
|
4824
|
-
|
4825
|
-
|
4826
|
-
|
4827
|
-
|
4993
|
+
tga_image_type = stbi__get8(s); // image type
|
4994
|
+
if ( tga_colormap_type == 1 ) { // colormapped (paletted) image
|
4995
|
+
if (tga_image_type != 1 && tga_image_type != 9) {
|
4996
|
+
stbi__rewind(s);
|
4997
|
+
return 0;
|
4998
|
+
}
|
4999
|
+
stbi__skip(s,4); // skip index of first colormap entry and number of entries
|
5000
|
+
sz = stbi__get8(s); // check bits per palette color entry
|
5001
|
+
if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) {
|
5002
|
+
stbi__rewind(s);
|
5003
|
+
return 0;
|
5004
|
+
}
|
5005
|
+
stbi__skip(s,4); // skip image x and y origin
|
5006
|
+
tga_colormap_bpp = sz;
|
5007
|
+
} else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE
|
5008
|
+
if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) {
|
5009
|
+
stbi__rewind(s);
|
5010
|
+
return 0; // only RGB or grey allowed, +/- RLE
|
5011
|
+
}
|
5012
|
+
stbi__skip(s,9); // skip colormap specification and image x/y origin
|
5013
|
+
tga_colormap_bpp = 0;
|
5014
|
+
}
|
4828
5015
|
tga_w = stbi__get16le(s);
|
4829
5016
|
if( tga_w < 1 ) {
|
4830
5017
|
stbi__rewind(s);
|
@@ -4835,44 +5022,80 @@ static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp)
|
|
4835
5022
|
stbi__rewind(s);
|
4836
5023
|
return 0; // test height
|
4837
5024
|
}
|
4838
|
-
|
4839
|
-
//
|
4840
|
-
if (
|
4841
|
-
|
4842
|
-
|
5025
|
+
tga_bits_per_pixel = stbi__get8(s); // bits per pixel
|
5026
|
+
stbi__get8(s); // ignore alpha bits
|
5027
|
+
if (tga_colormap_bpp != 0) {
|
5028
|
+
if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) {
|
5029
|
+
// when using a colormap, tga_bits_per_pixel is the size of the indexes
|
5030
|
+
// I don't think anything but 8 or 16bit indexes makes sense
|
5031
|
+
stbi__rewind(s);
|
5032
|
+
return 0;
|
5033
|
+
}
|
5034
|
+
tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL);
|
5035
|
+
} else {
|
5036
|
+
tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL);
|
5037
|
+
}
|
5038
|
+
if(!tga_comp) {
|
5039
|
+
stbi__rewind(s);
|
5040
|
+
return 0;
|
4843
5041
|
}
|
4844
|
-
tga_comp = sz;
|
4845
5042
|
if (x) *x = tga_w;
|
4846
5043
|
if (y) *y = tga_h;
|
4847
|
-
if (comp) *comp = tga_comp
|
5044
|
+
if (comp) *comp = tga_comp;
|
4848
5045
|
return 1; // seems to have passed everything
|
4849
5046
|
}
|
4850
5047
|
|
4851
5048
|
static int stbi__tga_test(stbi__context *s)
|
4852
5049
|
{
|
4853
|
-
int res;
|
4854
|
-
int sz;
|
5050
|
+
int res = 0;
|
5051
|
+
int sz, tga_color_type;
|
4855
5052
|
stbi__get8(s); // discard Offset
|
4856
|
-
|
4857
|
-
if (
|
5053
|
+
tga_color_type = stbi__get8(s); // color type
|
5054
|
+
if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed
|
4858
5055
|
sz = stbi__get8(s); // image type
|
4859
|
-
if (
|
4860
|
-
|
4861
|
-
|
4862
|
-
|
4863
|
-
|
4864
|
-
|
4865
|
-
|
4866
|
-
|
5056
|
+
if ( tga_color_type == 1 ) { // colormapped (paletted) image
|
5057
|
+
if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9
|
5058
|
+
stbi__skip(s,4); // skip index of first colormap entry and number of entries
|
5059
|
+
sz = stbi__get8(s); // check bits per palette color entry
|
5060
|
+
if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
|
5061
|
+
stbi__skip(s,4); // skip image x and y origin
|
5062
|
+
} else { // "normal" image w/o colormap
|
5063
|
+
if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE
|
5064
|
+
stbi__skip(s,9); // skip colormap specification and image x/y origin
|
5065
|
+
}
|
5066
|
+
if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width
|
5067
|
+
if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height
|
4867
5068
|
sz = stbi__get8(s); // bits per pixel
|
4868
|
-
if ( (
|
4869
|
-
|
4870
|
-
|
4871
|
-
|
5069
|
+
if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index
|
5070
|
+
if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd;
|
5071
|
+
|
5072
|
+
res = 1; // if we got this far, everything's good and we can return 1 instead of 0
|
5073
|
+
|
5074
|
+
errorEnd:
|
4872
5075
|
stbi__rewind(s);
|
4873
5076
|
return res;
|
4874
5077
|
}
|
4875
5078
|
|
5079
|
+
// read 16bit value and convert to 24bit RGB
|
5080
|
+
void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out)
|
5081
|
+
{
|
5082
|
+
stbi__uint16 px = stbi__get16le(s);
|
5083
|
+
stbi__uint16 fiveBitMask = 31;
|
5084
|
+
// we have 3 channels with 5bits each
|
5085
|
+
int r = (px >> 10) & fiveBitMask;
|
5086
|
+
int g = (px >> 5) & fiveBitMask;
|
5087
|
+
int b = px & fiveBitMask;
|
5088
|
+
// Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later
|
5089
|
+
out[0] = (r * 255)/31;
|
5090
|
+
out[1] = (g * 255)/31;
|
5091
|
+
out[2] = (b * 255)/31;
|
5092
|
+
|
5093
|
+
// some people claim that the most significant bit might be used for alpha
|
5094
|
+
// (possibly if an alpha-bit is set in the "image descriptor byte")
|
5095
|
+
// but that only made 16bit test images completely translucent..
|
5096
|
+
// so let's treat all 15 and 16bit TGAs as RGB with no alpha.
|
5097
|
+
}
|
5098
|
+
|
4876
5099
|
static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
4877
5100
|
{
|
4878
5101
|
// read in the TGA header stuff
|
@@ -4888,8 +5111,9 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|
4888
5111
|
int tga_width = stbi__get16le(s);
|
4889
5112
|
int tga_height = stbi__get16le(s);
|
4890
5113
|
int tga_bits_per_pixel = stbi__get8(s);
|
4891
|
-
int tga_comp =
|
5114
|
+
int tga_comp, tga_rgb16=0;
|
4892
5115
|
int tga_inverted = stbi__get8(s);
|
5116
|
+
// int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?)
|
4893
5117
|
// image data
|
4894
5118
|
unsigned char *tga_data;
|
4895
5119
|
unsigned char *tga_palette = NULL;
|
@@ -4905,25 +5129,14 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|
4905
5129
|
tga_image_type -= 8;
|
4906
5130
|
tga_is_RLE = 1;
|
4907
5131
|
}
|
4908
|
-
/* int tga_alpha_bits = tga_inverted & 15; */
|
4909
5132
|
tga_inverted = 1 - ((tga_inverted >> 5) & 1);
|
4910
5133
|
|
4911
|
-
// error check
|
4912
|
-
if ( //(tga_indexed) ||
|
4913
|
-
(tga_width < 1) || (tga_height < 1) ||
|
4914
|
-
(tga_image_type < 1) || (tga_image_type > 3) ||
|
4915
|
-
((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16) &&
|
4916
|
-
(tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32))
|
4917
|
-
)
|
4918
|
-
{
|
4919
|
-
return NULL; // we don't report this as a bad TGA because we don't even know if it's TGA
|
4920
|
-
}
|
4921
|
-
|
4922
5134
|
// If I'm paletted, then I'll use the number of bits from the palette
|
4923
|
-
if ( tga_indexed )
|
4924
|
-
|
4925
|
-
|
4926
|
-
|
5135
|
+
if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16);
|
5136
|
+
else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16);
|
5137
|
+
|
5138
|
+
if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency
|
5139
|
+
return stbi__errpuc("bad format", "Can't find out TGA pixelformat");
|
4927
5140
|
|
4928
5141
|
// tga info
|
4929
5142
|
*x = tga_width;
|
@@ -4936,7 +5149,7 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|
4936
5149
|
// skip to the data's starting position (offset usually = 0)
|
4937
5150
|
stbi__skip(s, tga_offset );
|
4938
5151
|
|
4939
|
-
if ( !tga_indexed && !tga_is_RLE) {
|
5152
|
+
if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) {
|
4940
5153
|
for (i=0; i < tga_height; ++i) {
|
4941
5154
|
int row = tga_inverted ? tga_height -i - 1 : i;
|
4942
5155
|
stbi_uc *tga_row = tga_data + row*tga_width*tga_comp;
|
@@ -4949,15 +5162,22 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|
4949
5162
|
// any data to skip? (offset usually = 0)
|
4950
5163
|
stbi__skip(s, tga_palette_start );
|
4951
5164
|
// load the palette
|
4952
|
-
tga_palette = (unsigned char*)stbi__malloc( tga_palette_len *
|
5165
|
+
tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_comp );
|
4953
5166
|
if (!tga_palette) {
|
4954
5167
|
STBI_FREE(tga_data);
|
4955
5168
|
return stbi__errpuc("outofmem", "Out of memory");
|
4956
5169
|
}
|
4957
|
-
if (
|
4958
|
-
|
4959
|
-
|
4960
|
-
|
5170
|
+
if (tga_rgb16) {
|
5171
|
+
stbi_uc *pal_entry = tga_palette;
|
5172
|
+
STBI_ASSERT(tga_comp == STBI_rgb);
|
5173
|
+
for (i=0; i < tga_palette_len; ++i) {
|
5174
|
+
stbi__tga_read_rgb16(s, pal_entry);
|
5175
|
+
pal_entry += tga_comp;
|
5176
|
+
}
|
5177
|
+
} else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) {
|
5178
|
+
STBI_FREE(tga_data);
|
5179
|
+
STBI_FREE(tga_palette);
|
5180
|
+
return stbi__errpuc("bad palette", "Corrupt TGA");
|
4961
5181
|
}
|
4962
5182
|
}
|
4963
5183
|
// load the data
|
@@ -4987,23 +5207,22 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|
4987
5207
|
// load however much data we did have
|
4988
5208
|
if ( tga_indexed )
|
4989
5209
|
{
|
4990
|
-
//
|
4991
|
-
int pal_idx = stbi__get8(s);
|
4992
|
-
if ( pal_idx >= tga_palette_len )
|
4993
|
-
|
4994
|
-
// invalid index
|
5210
|
+
// read in index, then perform the lookup
|
5211
|
+
int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s);
|
5212
|
+
if ( pal_idx >= tga_palette_len ) {
|
5213
|
+
// invalid index
|
4995
5214
|
pal_idx = 0;
|
4996
5215
|
}
|
4997
|
-
pal_idx *=
|
4998
|
-
for (j = 0; j
|
4999
|
-
{
|
5216
|
+
pal_idx *= tga_comp;
|
5217
|
+
for (j = 0; j < tga_comp; ++j) {
|
5000
5218
|
raw_data[j] = tga_palette[pal_idx+j];
|
5001
5219
|
}
|
5002
|
-
} else
|
5003
|
-
|
5220
|
+
} else if(tga_rgb16) {
|
5221
|
+
STBI_ASSERT(tga_comp == STBI_rgb);
|
5222
|
+
stbi__tga_read_rgb16(s, raw_data);
|
5223
|
+
} else {
|
5004
5224
|
// read in the data raw
|
5005
|
-
for (j = 0; j
|
5006
|
-
{
|
5225
|
+
for (j = 0; j < tga_comp; ++j) {
|
5007
5226
|
raw_data[j] = stbi__get8(s);
|
5008
5227
|
}
|
5009
5228
|
}
|
@@ -5042,8 +5261,8 @@ static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int
|
|
5042
5261
|
}
|
5043
5262
|
}
|
5044
5263
|
|
5045
|
-
// swap RGB
|
5046
|
-
if (tga_comp >= 3)
|
5264
|
+
// swap RGB - if the source data was RGB16, it already is in the right order
|
5265
|
+
if (tga_comp >= 3 && !tga_rgb16)
|
5047
5266
|
{
|
5048
5267
|
unsigned char* tga_pixel = tga_data;
|
5049
5268
|
for (i=0; i < tga_width * tga_height; ++i)
|
@@ -5235,6 +5454,21 @@ static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int
|
|
5235
5454
|
}
|
5236
5455
|
}
|
5237
5456
|
|
5457
|
+
if (channelCount >= 4) {
|
5458
|
+
for (i=0; i < w*h; ++i) {
|
5459
|
+
unsigned char *pixel = out + 4*i;
|
5460
|
+
if (pixel[3] != 0 && pixel[3] != 255) {
|
5461
|
+
// remove weird white matte from PSD
|
5462
|
+
float a = pixel[3] / 255.0f;
|
5463
|
+
float ra = 1.0f / a;
|
5464
|
+
float inv_a = 255.0f * (1 - ra);
|
5465
|
+
pixel[0] = (unsigned char) (pixel[0]*ra + inv_a);
|
5466
|
+
pixel[1] = (unsigned char) (pixel[1]*ra + inv_a);
|
5467
|
+
pixel[2] = (unsigned char) (pixel[2]*ra + inv_a);
|
5468
|
+
}
|
5469
|
+
}
|
5470
|
+
}
|
5471
|
+
|
5238
5472
|
if (req_comp && req_comp != 4) {
|
5239
5473
|
out = stbi__convert_format(out, 4, req_comp, w, h);
|
5240
5474
|
if (out == NULL) return out; // stbi__convert_format frees input on failure
|
@@ -5547,13 +5781,15 @@ static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_in
|
|
5547
5781
|
|
5548
5782
|
static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp)
|
5549
5783
|
{
|
5550
|
-
stbi__gif g;
|
5551
|
-
if (!stbi__gif_header(s,
|
5784
|
+
stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
|
5785
|
+
if (!stbi__gif_header(s, g, comp, 1)) {
|
5786
|
+
STBI_FREE(g);
|
5552
5787
|
stbi__rewind( s );
|
5553
5788
|
return 0;
|
5554
5789
|
}
|
5555
|
-
if (x) *x = g
|
5556
|
-
if (y) *y = g
|
5790
|
+
if (x) *x = g->w;
|
5791
|
+
if (y) *y = g->h;
|
5792
|
+
STBI_FREE(g);
|
5557
5793
|
return 1;
|
5558
5794
|
}
|
5559
5795
|
|
@@ -5806,20 +6042,20 @@ static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, i
|
|
5806
6042
|
static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp)
|
5807
6043
|
{
|
5808
6044
|
stbi_uc *u = 0;
|
5809
|
-
stbi__gif g;
|
5810
|
-
memset(
|
6045
|
+
stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif));
|
6046
|
+
memset(g, 0, sizeof(*g));
|
5811
6047
|
|
5812
|
-
u = stbi__gif_load_next(s,
|
6048
|
+
u = stbi__gif_load_next(s, g, comp, req_comp);
|
5813
6049
|
if (u == (stbi_uc *) s) u = 0; // end of animated gif marker
|
5814
6050
|
if (u) {
|
5815
|
-
*x = g
|
5816
|
-
*y = g
|
6051
|
+
*x = g->w;
|
6052
|
+
*y = g->h;
|
5817
6053
|
if (req_comp && req_comp != 4)
|
5818
|
-
u = stbi__convert_format(u, 4, req_comp, g
|
6054
|
+
u = stbi__convert_format(u, 4, req_comp, g->w, g->h);
|
5819
6055
|
}
|
5820
|
-
else if (g
|
5821
|
-
STBI_FREE(g
|
5822
|
-
|
6056
|
+
else if (g->out)
|
6057
|
+
STBI_FREE(g->out);
|
6058
|
+
STBI_FREE(g);
|
5823
6059
|
return u;
|
5824
6060
|
}
|
5825
6061
|
|
@@ -6017,7 +6253,7 @@ static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp)
|
|
6017
6253
|
char *token;
|
6018
6254
|
int valid = 0;
|
6019
6255
|
|
6020
|
-
if (
|
6256
|
+
if (stbi__hdr_test(s) == 0) {
|
6021
6257
|
stbi__rewind( s );
|
6022
6258
|
return 0;
|
6023
6259
|
}
|
@@ -6054,29 +6290,17 @@ static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp)
|
|
6054
6290
|
#ifndef STBI_NO_BMP
|
6055
6291
|
static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp)
|
6056
6292
|
{
|
6057
|
-
|
6058
|
-
|
6059
|
-
|
6060
|
-
|
6061
|
-
|
6062
|
-
|
6063
|
-
|
6064
|
-
|
6065
|
-
|
6066
|
-
|
6067
|
-
|
6068
|
-
if (hsz == 12) {
|
6069
|
-
*x = stbi__get16le(s);
|
6070
|
-
*y = stbi__get16le(s);
|
6071
|
-
} else {
|
6072
|
-
*x = stbi__get32le(s);
|
6073
|
-
*y = stbi__get32le(s);
|
6074
|
-
}
|
6075
|
-
if (stbi__get16le(s) != 1) {
|
6076
|
-
stbi__rewind( s );
|
6077
|
-
return 0;
|
6078
|
-
}
|
6079
|
-
*comp = stbi__get16le(s) / 8;
|
6293
|
+
void *p;
|
6294
|
+
stbi__bmp_data info;
|
6295
|
+
|
6296
|
+
info.all_a = 255;
|
6297
|
+
p = stbi__bmp_parse_header(s, &info);
|
6298
|
+
stbi__rewind( s );
|
6299
|
+
if (p == NULL)
|
6300
|
+
return 0;
|
6301
|
+
*x = s->img_x;
|
6302
|
+
*y = s->img_y;
|
6303
|
+
*comp = info.ma ? 4 : 3;
|
6080
6304
|
return 1;
|
6081
6305
|
}
|
6082
6306
|
#endif
|
@@ -6222,8 +6446,16 @@ static int stbi__pnm_isspace(char c)
|
|
6222
6446
|
|
6223
6447
|
static void stbi__pnm_skip_whitespace(stbi__context *s, char *c)
|
6224
6448
|
{
|
6225
|
-
|
6226
|
-
|
6449
|
+
for (;;) {
|
6450
|
+
while (!stbi__at_eof(s) && stbi__pnm_isspace(*c))
|
6451
|
+
*c = (char) stbi__get8(s);
|
6452
|
+
|
6453
|
+
if (stbi__at_eof(s) || *c != '#')
|
6454
|
+
break;
|
6455
|
+
|
6456
|
+
while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' )
|
6457
|
+
*c = (char) stbi__get8(s);
|
6458
|
+
}
|
6227
6459
|
}
|
6228
6460
|
|
6229
6461
|
static int stbi__pnm_isdigit(char c)
|
@@ -6361,10 +6593,24 @@ STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int
|
|
6361
6593
|
|
6362
6594
|
/*
|
6363
6595
|
revision history:
|
6596
|
+
2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes
|
6597
|
+
2.11 (2016-04-02) allocate large structures on the stack
|
6598
|
+
remove white matting for transparent PSD
|
6599
|
+
fix reported channel count for PNG & BMP
|
6600
|
+
re-enable SSE2 in non-gcc 64-bit
|
6601
|
+
support RGB-formatted JPEG
|
6602
|
+
read 16-bit PNGs (only as 8-bit)
|
6603
|
+
2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED
|
6604
|
+
2.09 (2016-01-16) allow comments in PNM files
|
6605
|
+
16-bit-per-pixel TGA (not bit-per-component)
|
6606
|
+
info() for TGA could break due to .hdr handling
|
6607
|
+
info() for BMP to shares code instead of sloppy parse
|
6608
|
+
can use STBI_REALLOC_SIZED if allocator doesn't support realloc
|
6609
|
+
code cleanup
|
6364
6610
|
2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA
|
6365
6611
|
2.07 (2015-09-13) fix compiler warnings
|
6366
6612
|
partial animated GIF support
|
6367
|
-
limited 16-
|
6613
|
+
limited 16-bpc PSD support
|
6368
6614
|
#ifdef unused functions
|
6369
6615
|
bug with < 92 byte PIC,PNM,HDR,TGA
|
6370
6616
|
2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value
|