📄 tgaloader.java
字号:
package demos.nehe.lesson32;
import demos.common.ResourceRetriever;
import javax.media.opengl.GL;
import java.io.IOException;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.Channels;
import java.nio.ByteBuffer;
import com.sun.opengl.util.BufferUtil;
public class TGALoader {
private static final byte[] TGA_MAGIC_NUMBER = new byte[]{0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0};
public static TextureImage loadTGA(GL gl, String filename) throws IOException {
ReadableByteChannel file = Channels.newChannel(ResourceRetriever.getResourceAsStream("resources/" + filename));
try {
return loadTGA(gl, file);
} finally {
try {
file.close();
} catch (IOException n) {
// Ignored
}
}
}
private static TextureImage loadTGA(GL gl, ReadableByteChannel file) throws IOException {
// Loads A TGA File Into Memory
ByteBuffer magicNumber = BufferUtil.newByteBuffer(12); // Used To Compare TGA Header
ByteBuffer header = BufferUtil.newByteBuffer(6); // First 6 Useful Bytes From The Header
int type = GL.GL_RGBA; // Set The Default GL Mode To RBGA (32 BPP)
readBuffer(file, magicNumber);
readBuffer(file, header);
for (int i = 0; i < magicNumber.capacity(); i++) {
// Does The Header Match What We Want?
if (magicNumber.get(i) != TGA_MAGIC_NUMBER[i]) {
throw new IOException("Invalid TGA header");
}
}
int width = unsignedByteToInt(header.get(1)) * 256 + unsignedByteToInt(header.get(0)); // Determine The TGA Width(highbyte*256+lowbyte)
int height = unsignedByteToInt(header.get(3)) * 256 + unsignedByteToInt(header.get(2)); // Determine The TGA Height(highbyte*256+lowbyte)
if (width <= 0) {
// Is The Width Less Than Or Equal To Zero
throw new IOException("Image has negative width");
}
if (height <= 0) {
// Is The Height Less Than Or Equal To Zero
throw new IOException("Image has negative height");
}
if (header.get(4) != 24 && header.get(4) != 32) {
// Is The TGA 24 or 32 Bit?
throw new IOException("Image is not 24 or 32-bit");
}
int bpp = header.get(4); // Grab The TGA's Bits Per Pixel (24 or 32)
int bytesPerPixel = bpp / 8; // Divide By 8 To Get The Bytes Per Pixel
int imageSize = width * height * bytesPerPixel; // Calculate The Memory Required For The TGA Data
ByteBuffer imageData = BufferUtil.newByteBuffer(imageSize); // Reserve Memory To Hold The TGA Data
readBuffer(file, imageData);
for (int i = 0; i < imageSize; i += bytesPerPixel) {
// Loop Through The Image Data
// Swaps The 1st And 3rd Bytes ('R'ed and 'B'lue)
byte temp = imageData.get(i); // Temporarily Store The Value At Image Data 'i'
imageData.put(i, imageData.get(i + 2)); // Set The 1st Byte To The Value Of The 3rd Byte
imageData.put(i + 2, temp); // Set The 3rd Byte To The Value In 'temp' (1st Byte Value)
}
// Build A Texture From The Data
int[] texID = new int[1];
gl.glGenTextures(1, texID, 0); // Generate OpenGL texture IDs
int textureID = texID[0];
gl.glBindTexture(GL.GL_TEXTURE_2D, textureID); // Bind Our Texture
gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR); // Linear Filtered
gl.glTexParameterf(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR); // Linear Filtered
if (bpp == 24) {
// Was The TGA 24 Bits
type = GL.GL_RGB; // If So Set The 'type' To GL_RGB
}
gl.glTexImage2D(GL.GL_TEXTURE_2D, 0, type, width, height, 0, type, GL.GL_UNSIGNED_BYTE, imageData);
return new TextureImage(
textureID, width, height, bytesPerPixel, imageData
);
}
private static int unsignedByteToInt(byte b) {
return (int) b & 0xFF;
}
private static void readBuffer(ReadableByteChannel in, ByteBuffer buffer) throws IOException {
while (buffer.hasRemaining()) {
in.read(buffer);
}
buffer.flip();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -