mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-10 13:51:53 +09:00
Former-commit-id: 1647fa32ef6894bd7db44f741f07c2f4dcdf9054 Former-commit-id: 0e5810dcfbe1fd59b13e7cabe9f1e93c5542da2d
245 lines
7.4 KiB
Java
245 lines
7.4 KiB
Java
package org.newdawn.slick.opengl;
|
|
|
|
import java.awt.Color;
|
|
import java.awt.Graphics2D;
|
|
import java.awt.color.ColorSpace;
|
|
import java.awt.image.BufferedImage;
|
|
import java.awt.image.ColorModel;
|
|
import java.awt.image.ComponentColorModel;
|
|
import java.awt.image.DataBuffer;
|
|
import java.awt.image.DataBufferByte;
|
|
import java.awt.image.Raster;
|
|
import java.awt.image.WritableRaster;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.ByteOrder;
|
|
import java.util.Hashtable;
|
|
|
|
import javax.imageio.ImageIO;
|
|
|
|
/**
|
|
* An image data provider that uses ImageIO to retrieve image data in a format
|
|
* suitable for creating OpenGL textures. This implementation is used when
|
|
* formats not natively supported by the library are required.
|
|
*
|
|
* @author kevin
|
|
*/
|
|
public class ImageIOImageData implements LoadableImageData {
|
|
/** The colour model including alpha for the GL image */
|
|
private static final ColorModel glAlphaColorModel =
|
|
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
|
|
new int[] {8,8,8,8},
|
|
true,
|
|
false,
|
|
ComponentColorModel.TRANSLUCENT,
|
|
DataBuffer.TYPE_BYTE);
|
|
|
|
/** The colour model for the GL image */
|
|
private static final ColorModel glColorModel =
|
|
new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),
|
|
new int[] {8,8,8,0},
|
|
false,
|
|
false,
|
|
ComponentColorModel.OPAQUE,
|
|
DataBuffer.TYPE_BYTE);
|
|
|
|
/** The bit depth of the image */
|
|
private int depth;
|
|
/** The height of the image */
|
|
private int height;
|
|
/** The width of the image */
|
|
private int width;
|
|
/** The width of the texture that should be created for the image */
|
|
private int texWidth;
|
|
/** The height of the texture that should be created for the image */
|
|
private int texHeight;
|
|
/** True if we should edge */
|
|
private boolean edging = true;
|
|
|
|
/**
|
|
* @see org.newdawn.slick.opengl.ImageData#getDepth()
|
|
*/
|
|
public int getDepth() {
|
|
return depth;
|
|
}
|
|
|
|
/**
|
|
* @see org.newdawn.slick.opengl.ImageData#getHeight()
|
|
*/
|
|
public int getHeight() {
|
|
return height;
|
|
}
|
|
|
|
/**
|
|
* @see org.newdawn.slick.opengl.ImageData#getTexHeight()
|
|
*/
|
|
public int getTexHeight() {
|
|
return texHeight;
|
|
}
|
|
|
|
/**
|
|
* @see org.newdawn.slick.opengl.ImageData#getTexWidth()
|
|
*/
|
|
public int getTexWidth() {
|
|
return texWidth;
|
|
}
|
|
|
|
/**
|
|
* @see org.newdawn.slick.opengl.ImageData#getWidth()
|
|
*/
|
|
public int getWidth() {
|
|
return width;
|
|
}
|
|
|
|
/**
|
|
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream)
|
|
*/
|
|
public ByteBuffer loadImage(InputStream fis) throws IOException {
|
|
return loadImage(fis, true, null);
|
|
}
|
|
|
|
/**
|
|
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, int[])
|
|
*/
|
|
public ByteBuffer loadImage(InputStream fis, boolean flipped, int[] transparent) throws IOException {
|
|
return loadImage(fis, flipped, false, transparent);
|
|
}
|
|
|
|
/**
|
|
* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, boolean, int[])
|
|
*/
|
|
public ByteBuffer loadImage(InputStream fis, boolean flipped, boolean forceAlpha, int[] transparent) throws IOException {
|
|
if (transparent != null) {
|
|
forceAlpha = true;
|
|
}
|
|
|
|
BufferedImage bufferedImage = ImageIO.read(fis);
|
|
return imageToByteBuffer(bufferedImage, flipped, forceAlpha, transparent);
|
|
}
|
|
|
|
public ByteBuffer imageToByteBuffer(BufferedImage image, boolean flipped, boolean forceAlpha, int[] transparent) {
|
|
ByteBuffer imageBuffer = null;
|
|
WritableRaster raster;
|
|
BufferedImage texImage;
|
|
|
|
int texWidth = 2;
|
|
int texHeight = 2;
|
|
|
|
// find the closest power of 2 for the width and height
|
|
// of the produced texture
|
|
|
|
while (texWidth < image.getWidth()) {
|
|
texWidth *= 2;
|
|
}
|
|
while (texHeight < image.getHeight()) {
|
|
texHeight *= 2;
|
|
}
|
|
|
|
this.width = image.getWidth();
|
|
this.height = image.getHeight();
|
|
this.texHeight = texHeight;
|
|
this.texWidth = texWidth;
|
|
|
|
// create a raster that can be used by OpenGL as a source
|
|
// for a texture
|
|
boolean useAlpha = image.getColorModel().hasAlpha() || forceAlpha;
|
|
|
|
if (useAlpha) {
|
|
depth = 32;
|
|
raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,texWidth,texHeight,4,null);
|
|
texImage = new BufferedImage(glAlphaColorModel,raster,false,new Hashtable());
|
|
} else {
|
|
depth = 24;
|
|
raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,texWidth,texHeight,3,null);
|
|
texImage = new BufferedImage(glColorModel,raster,false,new Hashtable());
|
|
}
|
|
|
|
// copy the source image into the produced image
|
|
Graphics2D g = (Graphics2D) texImage.getGraphics();
|
|
|
|
// only need to blank the image for mac compatibility if we're using alpha
|
|
if (useAlpha) {
|
|
g.setColor(new Color(0f,0f,0f,0f));
|
|
g.fillRect(0,0,texWidth,texHeight);
|
|
}
|
|
|
|
if (flipped) {
|
|
g.scale(1,-1);
|
|
g.drawImage(image,0,-height,null);
|
|
} else {
|
|
g.drawImage(image,0,0,null);
|
|
}
|
|
|
|
if (edging) {
|
|
if (height < texHeight - 1) {
|
|
copyArea(texImage, 0, 0, width, 1, 0, texHeight-1);
|
|
copyArea(texImage, 0, height-1, width, 1, 0, 1);
|
|
}
|
|
if (width < texWidth - 1) {
|
|
copyArea(texImage, 0,0,1,height,texWidth-1,0);
|
|
copyArea(texImage, width-1,0,1,height,1,0);
|
|
}
|
|
}
|
|
|
|
// build a byte buffer from the temporary image
|
|
// that be used by OpenGL to produce a texture.
|
|
byte[] data = ((DataBufferByte) texImage.getRaster().getDataBuffer()).getData();
|
|
|
|
if (transparent != null) {
|
|
for (int i=0;i<data.length;i+=4) {
|
|
boolean match = true;
|
|
for (int c=0;c<3;c++) {
|
|
int value = data[i+c] < 0 ? 256 + data[i+c] : data[i+c];
|
|
if (value != transparent[c]) {
|
|
match = false;
|
|
}
|
|
}
|
|
|
|
if (match) {
|
|
data[i+3] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
imageBuffer = ByteBuffer.allocateDirect(data.length);
|
|
imageBuffer.order(ByteOrder.nativeOrder());
|
|
imageBuffer.put(data, 0, data.length);
|
|
imageBuffer.flip();
|
|
g.dispose();
|
|
|
|
return imageBuffer;
|
|
}
|
|
|
|
/**
|
|
* @see org.newdawn.slick.opengl.ImageData#getImageBufferData()
|
|
*/
|
|
public ByteBuffer getImageBufferData() {
|
|
throw new RuntimeException("ImageIOImageData doesn't store it's image.");
|
|
}
|
|
|
|
/**
|
|
* Implement of transform copy area for 1.4
|
|
*
|
|
* @param image The image to copy
|
|
* @param x The x position to copy to
|
|
* @param y The y position to copy to
|
|
* @param width The width of the image
|
|
* @param height The height of the image
|
|
* @param dx The transform on the x axis
|
|
* @param dy The transform on the y axis
|
|
*/
|
|
private void copyArea(BufferedImage image, int x, int y, int width, int height, int dx, int dy) {
|
|
Graphics2D g = (Graphics2D) image.getGraphics();
|
|
|
|
g.drawImage(image.getSubimage(x, y, width, height),x+dx,y+dy,null);
|
|
}
|
|
|
|
/**
|
|
* @see org.newdawn.slick.opengl.LoadableImageData#configureEdging(boolean)
|
|
*/
|
|
public void configureEdging(boolean edging) {
|
|
this.edging = edging;
|
|
}
|
|
}
|