Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epoxy
GitHub Repository: epoxy/proj11
Path: blob/master/SLICK_HOME/src/org/newdawn/slick/opengl/TGAImageData.java
1461 views
1
package org.newdawn.slick.opengl;
2
3
import java.io.BufferedInputStream;
4
import java.io.DataInputStream;
5
import java.io.IOException;
6
import java.io.InputStream;
7
import java.nio.ByteBuffer;
8
import java.nio.ByteOrder;
9
10
import org.lwjgl.BufferUtils;
11
12
/**
13
* A utility to load TGAs. Note: NOT THREAD SAFE
14
*
15
* Fresh cut of code but largely influeneced by the TGA loading class
16
* provided as part of the Java Monkey Engine (JME). Why not check out
17
* what they're doing over at http://www.jmonkeyengine.com. kudos to
18
* Mark Powell.
19
*
20
* @author Kevin Glass
21
*/
22
public class TGAImageData implements LoadableImageData {
23
/** The width of the texture that needs to be generated */
24
private int texWidth;
25
/** The height of the texture that needs to be generated */
26
private int texHeight;
27
/** The width of the TGA image */
28
private int width;
29
/** The height of the TGA image */
30
private int height;
31
/** The bit depth of the image */
32
private short pixelDepth;
33
34
/**
35
* Create a new TGA Loader
36
*/
37
public TGAImageData() {
38
}
39
40
/**
41
* Flip the endian-ness of the short
42
*
43
* @param signedShort The short to flip
44
* @return The flipped short
45
*/
46
private short flipEndian(short signedShort) {
47
int input = signedShort & 0xFFFF;
48
return (short) (input << 8 | (input & 0xFF00) >>> 8);
49
}
50
51
/**
52
* @see org.newdawn.slick.opengl.ImageData#getDepth()
53
*/
54
public int getDepth() {
55
return pixelDepth;
56
}
57
58
/**
59
* @see org.newdawn.slick.opengl.ImageData#getWidth()
60
*/
61
public int getWidth() {
62
return width;
63
}
64
65
/**
66
* @see org.newdawn.slick.opengl.ImageData#getHeight()
67
*/
68
public int getHeight() {
69
return height;
70
}
71
72
/**
73
* @see org.newdawn.slick.opengl.ImageData#getTexWidth()
74
*/
75
public int getTexWidth() {
76
return texWidth;
77
}
78
79
/**
80
* @see org.newdawn.slick.opengl.ImageData#getTexHeight()
81
*/
82
public int getTexHeight() {
83
return texHeight;
84
}
85
86
/**
87
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream)
88
*/
89
public ByteBuffer loadImage(InputStream fis) throws IOException {
90
return loadImage(fis,true, null);
91
}
92
93
/**
94
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, int[])
95
*/
96
public ByteBuffer loadImage(InputStream fis, boolean flipped, int[] transparent) throws IOException {
97
return loadImage(fis, flipped, false, transparent);
98
}
99
100
/**
101
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, boolean, int[])
102
*/
103
public ByteBuffer loadImage(InputStream fis, boolean flipped, boolean forceAlpha, int[] transparent) throws IOException {
104
if (transparent != null) {
105
forceAlpha = true;
106
}
107
byte red = 0;
108
byte green = 0;
109
byte blue = 0;
110
byte alpha = 0;
111
112
BufferedInputStream bis = new BufferedInputStream(fis, 100000);
113
DataInputStream dis = new DataInputStream(bis);
114
115
// Read in the Header
116
short idLength = (short) dis.read();
117
short colorMapType = (short) dis.read();
118
short imageType = (short) dis.read();
119
short cMapStart = flipEndian(dis.readShort());
120
short cMapLength = flipEndian(dis.readShort());
121
short cMapDepth = (short) dis.read();
122
short xOffset = flipEndian(dis.readShort());
123
short yOffset = flipEndian(dis.readShort());
124
125
width = flipEndian(dis.readShort());
126
height = flipEndian(dis.readShort());
127
pixelDepth = (short) dis.read();
128
if (pixelDepth == 32) {
129
forceAlpha = false;
130
}
131
132
texWidth = get2Fold(width);
133
texHeight = get2Fold(height);
134
135
short imageDescriptor = (short) dis.read();
136
if ((imageDescriptor & 0x0020) == 0) {
137
flipped = !flipped;
138
}
139
140
// Skip image ID
141
if (idLength > 0) {
142
bis.skip(idLength);
143
}
144
145
byte[] rawData = null;
146
if ((pixelDepth == 32) || (forceAlpha)) {
147
pixelDepth = 32;
148
rawData = new byte[texWidth * texHeight * 4];
149
} else if (pixelDepth == 24) {
150
rawData = new byte[texWidth * texHeight * 3];
151
} else {
152
throw new RuntimeException("Only 24 and 32 bit TGAs are supported");
153
}
154
155
if (pixelDepth == 24) {
156
if (flipped) {
157
for (int i = height-1; i >= 0; i--) {
158
for (int j = 0; j < width; j++) {
159
blue = dis.readByte();
160
green = dis.readByte();
161
red = dis.readByte();
162
163
int ofs = ((j + (i * texWidth)) * 3);
164
rawData[ofs] = red;
165
rawData[ofs + 1] = green;
166
rawData[ofs + 2] = blue;
167
}
168
}
169
} else {
170
for (int i = 0; i < height; i++) {
171
for (int j = 0; j < width; j++) {
172
blue = dis.readByte();
173
green = dis.readByte();
174
red = dis.readByte();
175
176
int ofs = ((j + (i * texWidth)) * 3);
177
rawData[ofs] = red;
178
rawData[ofs + 1] = green;
179
rawData[ofs + 2] = blue;
180
}
181
}
182
}
183
} else if (pixelDepth == 32) {
184
if (flipped) {
185
for (int i = height-1; i >= 0; i--) {
186
for (int j = 0; j < width; j++) {
187
blue = dis.readByte();
188
green = dis.readByte();
189
red = dis.readByte();
190
if (forceAlpha) {
191
alpha = (byte) 255;
192
} else {
193
alpha = dis.readByte();
194
}
195
196
int ofs = ((j + (i * texWidth)) * 4);
197
198
rawData[ofs] = red;
199
rawData[ofs + 1] = green;
200
rawData[ofs + 2] = blue;
201
rawData[ofs + 3] = alpha;
202
203
if (alpha == 0) {
204
rawData[ofs + 2] = (byte) 0;
205
rawData[ofs + 1] = (byte) 0;
206
rawData[ofs] = (byte) 0;
207
}
208
}
209
}
210
} else {
211
for (int i = 0; i < height; i++) {
212
for (int j = 0; j < width; j++) {
213
blue = dis.readByte();
214
green = dis.readByte();
215
red = dis.readByte();
216
if (forceAlpha) {
217
alpha = (byte) 255;
218
} else {
219
alpha = dis.readByte();
220
}
221
222
int ofs = ((j + (i * texWidth)) * 4);
223
224
if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
225
rawData[ofs] = red;
226
rawData[ofs + 1] = green;
227
rawData[ofs + 2] = blue;
228
rawData[ofs + 3] = alpha;
229
} else {
230
rawData[ofs] = red;
231
rawData[ofs + 1] = green;
232
rawData[ofs + 2] = blue;
233
rawData[ofs + 3] = alpha;
234
}
235
236
if (alpha == 0) {
237
rawData[ofs + 2] = 0;
238
rawData[ofs + 1] = 0;
239
rawData[ofs] = 0;
240
}
241
}
242
}
243
}
244
}
245
fis.close();
246
247
if (transparent != null) {
248
for (int i=0;i<rawData.length;i+=4) {
249
boolean match = true;
250
for (int c=0;c<3;c++) {
251
if (rawData[i+c] != transparent[c]) {
252
match = false;
253
}
254
}
255
256
if (match) {
257
rawData[i+3] = 0;
258
}
259
}
260
}
261
262
// Get a pointer to the image memory
263
ByteBuffer scratch = BufferUtils.createByteBuffer(rawData.length);
264
scratch.put(rawData);
265
266
int perPixel = pixelDepth / 8;
267
if (height < texHeight-1) {
268
int topOffset = (texHeight-1) * (texWidth*perPixel);
269
int bottomOffset = (height-1) * (texWidth*perPixel);
270
for (int x=0;x<texWidth*perPixel;x++) {
271
scratch.put(topOffset+x, scratch.get(x));
272
scratch.put(bottomOffset+(texWidth*perPixel)+x, scratch.get((texWidth*perPixel)+x));
273
}
274
}
275
if (width < texWidth-1) {
276
for (int y=0;y<texHeight;y++) {
277
for (int i=0;i<perPixel;i++) {
278
scratch.put(((y+1)*(texWidth*perPixel))-perPixel+i, scratch.get(y*(texWidth*perPixel)+i));
279
scratch.put((y*(texWidth*perPixel))+(width*perPixel)+i, scratch.get((y*(texWidth*perPixel))+((width-1)*perPixel)+i));
280
}
281
}
282
}
283
284
scratch.flip();
285
286
return scratch;
287
}
288
289
/**
290
* Get the closest greater power of 2 to the fold number
291
*
292
* @param fold The target number
293
* @return The power of 2
294
*/
295
private int get2Fold(int fold) {
296
int ret = 2;
297
while (ret < fold) {
298
ret *= 2;
299
}
300
return ret;
301
}
302
303
/**
304
* @see org.newdawn.slick.opengl.ImageData#getImageBufferData()
305
*/
306
public ByteBuffer getImageBufferData() {
307
throw new RuntimeException("TGAImageData doesn't store it's image.");
308
}
309
310
/**
311
* @see org.newdawn.slick.opengl.LoadableImageData#configureEdging(boolean)
312
*/
313
public void configureEdging(boolean edging) {
314
}
315
}
316
317