Path: blob/master/SLICK_HOME/src/org/newdawn/slick/opengl/ImageIOImageData.java
1461 views
package org.newdawn.slick.opengl;12import java.awt.Color;3import java.awt.Graphics2D;4import java.awt.color.ColorSpace;5import java.awt.image.BufferedImage;6import java.awt.image.ColorModel;7import java.awt.image.ComponentColorModel;8import java.awt.image.DataBuffer;9import java.awt.image.DataBufferByte;10import java.awt.image.Raster;11import java.awt.image.WritableRaster;12import java.io.IOException;13import java.io.InputStream;14import java.nio.ByteBuffer;15import java.nio.ByteOrder;16import java.util.Hashtable;1718import javax.imageio.ImageIO;1920/**21* An image data provider that uses ImageIO to retrieve image data in a format22* suitable for creating OpenGL textures. This implementation is used when23* formats not natively supported by the library are required.24*25* @author kevin26*/27public class ImageIOImageData implements LoadableImageData {28/** The colour model including alpha for the GL image */29private static final ColorModel glAlphaColorModel =30new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),31new int[] {8,8,8,8},32true,33false,34ComponentColorModel.TRANSLUCENT,35DataBuffer.TYPE_BYTE);3637/** The colour model for the GL image */38private static final ColorModel glColorModel =39new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB),40new int[] {8,8,8,0},41false,42false,43ComponentColorModel.OPAQUE,44DataBuffer.TYPE_BYTE);4546/** The bit depth of the image */47private int depth;48/** The height of the image */49private int height;50/** The width of the image */51private int width;52/** The width of the texture that should be created for the image */53private int texWidth;54/** The height of the texture that should be created for the image */55private int texHeight;56/** True if we should edge */57private boolean edging = true;5859/**60* @see org.newdawn.slick.opengl.ImageData#getDepth()61*/62public int getDepth() {63return depth;64}6566/**67* @see org.newdawn.slick.opengl.ImageData#getHeight()68*/69public int getHeight() {70return height;71}7273/**74* @see org.newdawn.slick.opengl.ImageData#getTexHeight()75*/76public int getTexHeight() {77return texHeight;78}7980/**81* @see org.newdawn.slick.opengl.ImageData#getTexWidth()82*/83public int getTexWidth() {84return texWidth;85}8687/**88* @see org.newdawn.slick.opengl.ImageData#getWidth()89*/90public int getWidth() {91return width;92}9394/**95* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream)96*/97public ByteBuffer loadImage(InputStream fis) throws IOException {98return loadImage(fis, true, null);99}100101/**102* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, int[])103*/104public ByteBuffer loadImage(InputStream fis, boolean flipped, int[] transparent) throws IOException {105return loadImage(fis, flipped, false, transparent);106}107108/**109* @see org.newdawn.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, boolean, int[])110*/111public ByteBuffer loadImage(InputStream fis, boolean flipped, boolean forceAlpha, int[] transparent) throws IOException {112if (transparent != null) {113forceAlpha = true;114}115116BufferedImage bufferedImage = ImageIO.read(fis);117return imageToByteBuffer(bufferedImage, flipped, forceAlpha, transparent);118}119120public ByteBuffer imageToByteBuffer(BufferedImage image, boolean flipped, boolean forceAlpha, int[] transparent) {121ByteBuffer imageBuffer = null;122WritableRaster raster;123BufferedImage texImage;124125int texWidth = 2;126int texHeight = 2;127128// find the closest power of 2 for the width and height129// of the produced texture130131while (texWidth < image.getWidth()) {132texWidth *= 2;133}134while (texHeight < image.getHeight()) {135texHeight *= 2;136}137138this.width = image.getWidth();139this.height = image.getHeight();140this.texHeight = texHeight;141this.texWidth = texWidth;142143// create a raster that can be used by OpenGL as a source144// for a texture145boolean useAlpha = image.getColorModel().hasAlpha() || forceAlpha;146147if (useAlpha) {148depth = 32;149raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,texWidth,texHeight,4,null);150texImage = new BufferedImage(glAlphaColorModel,raster,false,new Hashtable());151} else {152depth = 24;153raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,texWidth,texHeight,3,null);154texImage = new BufferedImage(glColorModel,raster,false,new Hashtable());155}156157// copy the source image into the produced image158Graphics2D g = (Graphics2D) texImage.getGraphics();159160// only need to blank the image for mac compatibility if we're using alpha161if (useAlpha) {162g.setColor(new Color(0f,0f,0f,0f));163g.fillRect(0,0,texWidth,texHeight);164}165166if (flipped) {167g.scale(1,-1);168g.drawImage(image,0,-height,null);169} else {170g.drawImage(image,0,0,null);171}172173if (edging) {174if (height < texHeight - 1) {175copyArea(texImage, 0, 0, width, 1, 0, texHeight-1);176copyArea(texImage, 0, height-1, width, 1, 0, 1);177}178if (width < texWidth - 1) {179copyArea(texImage, 0,0,1,height,texWidth-1,0);180copyArea(texImage, width-1,0,1,height,1,0);181}182}183184// build a byte buffer from the temporary image185// that be used by OpenGL to produce a texture.186byte[] data = ((DataBufferByte) texImage.getRaster().getDataBuffer()).getData();187188if (transparent != null) {189for (int i=0;i<data.length;i+=4) {190boolean match = true;191for (int c=0;c<3;c++) {192int value = data[i+c] < 0 ? 256 + data[i+c] : data[i+c];193if (value != transparent[c]) {194match = false;195}196}197198if (match) {199data[i+3] = 0;200}201}202}203204imageBuffer = ByteBuffer.allocateDirect(data.length);205imageBuffer.order(ByteOrder.nativeOrder());206imageBuffer.put(data, 0, data.length);207imageBuffer.flip();208g.dispose();209210return imageBuffer;211}212213/**214* @see org.newdawn.slick.opengl.ImageData#getImageBufferData()215*/216public ByteBuffer getImageBufferData() {217throw new RuntimeException("ImageIOImageData doesn't store it's image.");218}219220/**221* Implement of transform copy area for 1.4222*223* @param image The image to copy224* @param x The x position to copy to225* @param y The y position to copy to226* @param width The width of the image227* @param height The height of the image228* @param dx The transform on the x axis229* @param dy The transform on the y axis230*/231private void copyArea(BufferedImage image, int x, int y, int width, int height, int dx, int dy) {232Graphics2D g = (Graphics2D) image.getGraphics();233234g.drawImage(image.getSubimage(x, y, width, height),x+dx,y+dy,null);235}236237/**238* @see org.newdawn.slick.opengl.LoadableImageData#configureEdging(boolean)239*/240public void configureEdging(boolean edging) {241this.edging = edging;242}243}244245246