Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
epoxy
GitHub Repository: epoxy/proj11
Path: blob/master/SLICK_HOME/src/org/newdawn/slick/opengl/ImageIOImageData.java
1461 views
1
package org.newdawn.slick.opengl;
2
3
import java.awt.Color;
4
import java.awt.Graphics2D;
5
import java.awt.color.ColorSpace;
6
import java.awt.image.BufferedImage;
7
import java.awt.image.ColorModel;
8
import java.awt.image.ComponentColorModel;
9
import java.awt.image.DataBuffer;
10
import java.awt.image.DataBufferByte;
11
import java.awt.image.Raster;
12
import java.awt.image.WritableRaster;
13
import java.io.IOException;
14
import java.io.InputStream;
15
import java.nio.ByteBuffer;
16
import java.nio.ByteOrder;
17
import java.util.Hashtable;
18
19
import javax.imageio.ImageIO;
20
21
/**
22
* An image data provider that uses ImageIO to retrieve image data in a format
23
* suitable for creating OpenGL textures. This implementation is used when
24
* formats not natively supported by the library are required.
25
*
26
* @author kevin
27
*/
28
public class ImageIOImageData implements LoadableImageData {
29
/** The colour model including alpha for the GL image */
30
private static final ColorModel glAlphaColorModel =
31
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
32
new int[] {8,8,8,8},
33
true,
34
false,
35
ComponentColorModel.TRANSLUCENT,
36
DataBuffer.TYPE_BYTE);
37
38
/** The colour model for the GL image */
39
private static final ColorModel glColorModel =
40
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
41
new int[] {8,8,8,0},
42
false,
43
false,
44
ComponentColorModel.OPAQUE,
45
DataBuffer.TYPE_BYTE);
46
47
/** The bit depth of the image */
48
private int depth;
49
/** The height of the image */
50
private int height;
51
/** The width of the image */
52
private int width;
53
/** The width of the texture that should be created for the image */
54
private int texWidth;
55
/** The height of the texture that should be created for the image */
56
private int texHeight;
57
/** True if we should edge */
58
private boolean edging = true;
59
60
/**
61
* @see org.newdawn.slick.opengl.ImageData#getDepth()
62
*/
63
public int getDepth() {
64
return depth;
65
}
66
67
/**
68
* @see org.newdawn.slick.opengl.ImageData#getHeight()
69
*/
70
public int getHeight() {
71
return height;
72
}
73
74
/**
75
* @see org.newdawn.slick.opengl.ImageData#getTexHeight()
76
*/
77
public int getTexHeight() {
78
return texHeight;
79
}
80
81
/**
82
* @see org.newdawn.slick.opengl.ImageData#getTexWidth()
83
*/
84
public int getTexWidth() {
85
return texWidth;
86
}
87
88
/**
89
* @see org.newdawn.slick.opengl.ImageData#getWidth()
90
*/
91
public int getWidth() {
92
return width;
93
}
94
95
/**
96
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream)
97
*/
98
public ByteBuffer loadImage(InputStream fis) throws IOException {
99
return loadImage(fis, true, null);
100
}
101
102
/**
103
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, int[])
104
*/
105
public ByteBuffer loadImage(InputStream fis, boolean flipped, int[] transparent) throws IOException {
106
return loadImage(fis, flipped, false, transparent);
107
}
108
109
/**
110
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, boolean, int[])
111
*/
112
public ByteBuffer loadImage(InputStream fis, boolean flipped, boolean forceAlpha, int[] transparent) throws IOException {
113
if (transparent != null) {
114
forceAlpha = true;
115
}
116
117
BufferedImage bufferedImage = ImageIO.read(fis);
118
return imageToByteBuffer(bufferedImage, flipped, forceAlpha, transparent);
119
}
120
121
public ByteBuffer imageToByteBuffer(BufferedImage image, boolean flipped, boolean forceAlpha, int[] transparent) {
122
ByteBuffer imageBuffer = null;
123
WritableRaster raster;
124
BufferedImage texImage;
125
126
int texWidth = 2;
127
int texHeight = 2;
128
129
// find the closest power of 2 for the width and height
130
// of the produced texture
131
132
while (texWidth < image.getWidth()) {
133
texWidth *= 2;
134
}
135
while (texHeight < image.getHeight()) {
136
texHeight *= 2;
137
}
138
139
this.width = image.getWidth();
140
this.height = image.getHeight();
141
this.texHeight = texHeight;
142
this.texWidth = texWidth;
143
144
// create a raster that can be used by OpenGL as a source
145
// for a texture
146
boolean useAlpha = image.getColorModel().hasAlpha() || forceAlpha;
147
148
if (useAlpha) {
149
depth = 32;
150
raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,texWidth,texHeight,4,null);
151
texImage = new BufferedImage(glAlphaColorModel,raster,false,new Hashtable());
152
} else {
153
depth = 24;
154
raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,texWidth,texHeight,3,null);
155
texImage = new BufferedImage(glColorModel,raster,false,new Hashtable());
156
}
157
158
// copy the source image into the produced image
159
Graphics2D g = (Graphics2D) texImage.getGraphics();
160
161
// only need to blank the image for mac compatibility if we're using alpha
162
if (useAlpha) {
163
g.setColor(new Color(0f,0f,0f,0f));
164
g.fillRect(0,0,texWidth,texHeight);
165
}
166
167
if (flipped) {
168
g.scale(1,-1);
169
g.drawImage(image,0,-height,null);
170
} else {
171
g.drawImage(image,0,0,null);
172
}
173
174
if (edging) {
175
if (height < texHeight - 1) {
176
copyArea(texImage, 0, 0, width, 1, 0, texHeight-1);
177
copyArea(texImage, 0, height-1, width, 1, 0, 1);
178
}
179
if (width < texWidth - 1) {
180
copyArea(texImage, 0,0,1,height,texWidth-1,0);
181
copyArea(texImage, width-1,0,1,height,1,0);
182
}
183
}
184
185
// build a byte buffer from the temporary image
186
// that be used by OpenGL to produce a texture.
187
byte[] data = ((DataBufferByte) texImage.getRaster().getDataBuffer()).getData();
188
189
if (transparent != null) {
190
for (int i=0;i<data.length;i+=4) {
191
boolean match = true;
192
for (int c=0;c<3;c++) {
193
int value = data[i+c] < 0 ? 256 + data[i+c] : data[i+c];
194
if (value != transparent[c]) {
195
match = false;
196
}
197
}
198
199
if (match) {
200
data[i+3] = 0;
201
}
202
}
203
}
204
205
imageBuffer = ByteBuffer.allocateDirect(data.length);
206
imageBuffer.order(ByteOrder.nativeOrder());
207
imageBuffer.put(data, 0, data.length);
208
imageBuffer.flip();
209
g.dispose();
210
211
return imageBuffer;
212
}
213
214
/**
215
* @see org.newdawn.slick.opengl.ImageData#getImageBufferData()
216
*/
217
public ByteBuffer getImageBufferData() {
218
throw new RuntimeException("ImageIOImageData doesn't store it's image.");
219
}
220
221
/**
222
* Implement of transform copy area for 1.4
223
*
224
* @param image The image to copy
225
* @param x The x position to copy to
226
* @param y The y position to copy to
227
* @param width The width of the image
228
* @param height The height of the image
229
* @param dx The transform on the x axis
230
* @param dy The transform on the y axis
231
*/
232
private void copyArea(BufferedImage image, int x, int y, int width, int height, int dx, int dy) {
233
Graphics2D g = (Graphics2D) image.getGraphics();
234
235
g.drawImage(image.getSubimage(x, y, width, height),x+dx,y+dy,null);
236
}
237
238
/**
239
* @see org.newdawn.slick.opengl.LoadableImageData#configureEdging(boolean)
240
*/
241
public void configureEdging(boolean edging) {
242
this.edging = edging;
243
}
244
}
245
246