All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.mathiewz.slick.opengl.ImageIOImageData Maven / Gradle / Ivy

Go to download

The main purpose of this libraryis to modernize and maintain the slick2D library.

The newest version!
package com.github.mathiewz.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;

import com.github.mathiewz.slick.SlickException;

/**
 * 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 com.github.mathiewz.slick.opengl.ImageData#getDepth()
     */
    @Override
    public int getDepth() {
        return depth;
    }
    
    /**
     * @see com.github.mathiewz.slick.opengl.ImageData#getHeight()
     */
    @Override
    public int getHeight() {
        return height;
    }
    
    /**
     * @see com.github.mathiewz.slick.opengl.ImageData#getTexHeight()
     */
    @Override
    public int getTexHeight() {
        return texHeight;
    }
    
    /**
     * @see com.github.mathiewz.slick.opengl.ImageData#getTexWidth()
     */
    @Override
    public int getTexWidth() {
        return texWidth;
    }
    
    /**
     * @see com.github.mathiewz.slick.opengl.ImageData#getWidth()
     */
    @Override
    public int getWidth() {
        return width;
    }
    
    /**
     * @see com.github.mathiewz.slick.opengl.LoadableImageData#loadImage(java.io.InputStream)
     */
    @Override
    public ByteBuffer loadImage(InputStream fis) throws IOException {
        return loadImage(fis, true, null);
    }
    
    /**
     * @see com.github.mathiewz.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, int[])
     */
    @Override
    public ByteBuffer loadImage(InputStream fis, boolean flipped, int[] transparent) throws IOException {
        return loadImage(fis, flipped, false, transparent);
    }
    
    /**
     * @see com.github.mathiewz.slick.opengl.LoadableImageData#loadImage(java.io.InputStream, boolean, boolean, int[])
     */
    @Override
    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;
        }
        
        width = image.getWidth();
        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 com.github.mathiewz.slick.opengl.ImageData#getImageBufferData()
     */
    @Override
    public ByteBuffer getImageBufferData() {
        throw new SlickException("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 com.github.mathiewz.slick.opengl.LoadableImageData#configureEdging(boolean)
     */
    @Override
    public void configureEdging(boolean edging) {
        this.edging = edging;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy