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

com.github.mathiewz.slick.opengl.TGAImageData 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.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

import org.lwjgl.BufferUtils;

import com.github.mathiewz.slick.SlickException;

/**
 * A utility to load TGAs. Note: NOT THREAD SAFE
 *
 * Fresh cut of code but largely influeneced by the TGA loading class
 * provided as part of the Java Monkey Engine (JME). Why not check out
 * what they're doing over at http://www.jmonkeyengine.com. kudos to
 * Mark Powell.
 *
 * @author Kevin Glass
 */
public class TGAImageData implements LoadableImageData {
    /** The width of the texture that needs to be generated */
    private int texWidth;
    /** The height of the texture that needs to be generated */
    private int texHeight;
    /** The width of the TGA image */
    private int width;
    /** The height of the TGA image */
    private int height;
    /** The bit depth of the image */
    private short pixelDepth;

    /**
     * Create a new TGA Loader
     */
    public TGAImageData() {
    }

    /**
     * Flip the endian-ness of the short
     *
     * @param signedShort
     *            The short to flip
     * @return The flipped short
     */
    private short flipEndian(short signedShort) {
        int input = signedShort & 0xFFFF;
        return (short) (input << 8 | (input & 0xFF00) >>> 8);
    }

    /**
     * @see com.github.mathiewz.slick.opengl.ImageData#getDepth()
     */
    @Override
    public int getDepth() {
        return pixelDepth;
    }

    /**
     * @see com.github.mathiewz.slick.opengl.ImageData#getWidth()
     */
    @Override
    public int getWidth() {
        return width;
    }

    /**
     * @see com.github.mathiewz.slick.opengl.ImageData#getHeight()
     */
    @Override
    public int getHeight() {
        return height;
    }

    /**
     * @see com.github.mathiewz.slick.opengl.ImageData#getTexWidth()
     */
    @Override
    public int getTexWidth() {
        return texWidth;
    }

    /**
     * @see com.github.mathiewz.slick.opengl.ImageData#getTexHeight()
     */
    @Override
    public int getTexHeight() {
        return texHeight;
    }

    /**
     * @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;
        }
        byte red = 0;
        byte green = 0;
        byte blue = 0;
        byte alpha = 0;

        BufferedInputStream bis = new BufferedInputStream(fis, 100000);
        DataInputStream dis = new DataInputStream(bis);

        // Read in the Header
        short idLength = (short) dis.read();
        short imageType = (short) dis.read();
        if (imageType != 2) {
            throw new IOException("Slick only supports uncompressed RGB(A) TGA images");
        }

        width = flipEndian(dis.readShort());
        height = flipEndian(dis.readShort());
        pixelDepth = (short) dis.read();
        if (pixelDepth == 32) {
            forceAlpha = false;
        }

        texWidth = get2Fold(width);
        texHeight = get2Fold(height);

        short imageDescriptor = (short) dis.read();
        if ((imageDescriptor & 0x0020) == 0) {
            flipped = !flipped;
        }

        // Skip image ID
        if (idLength > 0) {
            bis.skip(idLength);
        }

        byte[] rawData = null;
        if (pixelDepth == 32 || forceAlpha) {
            pixelDepth = 32;
            rawData = new byte[texWidth * texHeight * 4];
        } else if (pixelDepth == 24) {
            rawData = new byte[texWidth * texHeight * 3];
        } else {
            throw new SlickException("Only 24 and 32 bit TGAs are supported");
        }

        if (pixelDepth == 24) {
            if (flipped) {
                for (int i = height - 1; i >= 0; i--) {
                    for (int j = 0; j < width; j++) {
                        blue = dis.readByte();
                        green = dis.readByte();
                        red = dis.readByte();

                        int ofs = (j + i * texWidth) * 3;
                        rawData[ofs] = red;
                        rawData[ofs + 1] = green;
                        rawData[ofs + 2] = blue;
                    }
                }
            } else {
                for (int i = 0; i < height; i++) {
                    for (int j = 0; j < width; j++) {
                        blue = dis.readByte();
                        green = dis.readByte();
                        red = dis.readByte();

                        int ofs = (j + i * texWidth) * 3;
                        rawData[ofs] = red;
                        rawData[ofs + 1] = green;
                        rawData[ofs + 2] = blue;
                    }
                }
            }
        } else if (pixelDepth == 32) {
            if (flipped) {
                for (int i = height - 1; i >= 0; i--) {
                    for (int j = 0; j < width; j++) {
                        blue = dis.readByte();
                        green = dis.readByte();
                        red = dis.readByte();
                        if (forceAlpha) {
                            alpha = (byte) 255;
                        } else {
                            alpha = dis.readByte();
                        }

                        int ofs = (j + i * texWidth) * 4;

                        rawData[ofs] = red;
                        rawData[ofs + 1] = green;
                        rawData[ofs + 2] = blue;
                        rawData[ofs + 3] = alpha;

                        if (alpha == 0) {
                            rawData[ofs + 2] = (byte) 0;
                            rawData[ofs + 1] = (byte) 0;
                            rawData[ofs] = (byte) 0;
                        }
                    }
                }
            } else {
                for (int i = 0; i < height; i++) {
                    for (int j = 0; j < width; j++) {
                        blue = dis.readByte();
                        green = dis.readByte();
                        red = dis.readByte();
                        if (forceAlpha) {
                            alpha = (byte) 255;
                        } else {
                            alpha = dis.readByte();
                        }

                        int ofs = (j + i * texWidth) * 4;

                        if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
                            rawData[ofs] = red;
                            rawData[ofs + 1] = green;
                            rawData[ofs + 2] = blue;
                            rawData[ofs + 3] = alpha;
                        } else {
                            rawData[ofs] = red;
                            rawData[ofs + 1] = green;
                            rawData[ofs + 2] = blue;
                            rawData[ofs + 3] = alpha;
                        }

                        if (alpha == 0) {
                            rawData[ofs + 2] = 0;
                            rawData[ofs + 1] = 0;
                            rawData[ofs] = 0;
                        }
                    }
                }
            }
        }
        fis.close();

        if (transparent != null) {
            for (int i = 0; i < rawData.length; i += 4) {
                boolean match = true;
                for (int c = 0; c < 3; c++) {
                    if (rawData[i + c] != transparent[c]) {
                        match = false;
                    }
                }

                if (match) {
                    rawData[i + 3] = 0;
                }
            }
        }

        // Get a pointer to the image memory
        ByteBuffer scratch = BufferUtils.createByteBuffer(rawData.length);
        scratch.put(rawData);

        int perPixel = pixelDepth / 8;
        if (height < texHeight - 1) {
            int topOffset = (texHeight - 1) * texWidth * perPixel;
            int bottomOffset = (height - 1) * texWidth * perPixel;
            for (int x = 0; x < texWidth * perPixel; x++) {
                scratch.put(topOffset + x, scratch.get(x));
                scratch.put(bottomOffset + texWidth * perPixel + x, scratch.get(texWidth * perPixel + x));
            }
        }
        if (width < texWidth - 1) {
            for (int y = 0; y < texHeight; y++) {
                for (int i = 0; i < perPixel; i++) {
                    scratch.put((y + 1) * texWidth * perPixel - perPixel + i, scratch.get(y * texWidth * perPixel + i));
                    scratch.put(y * texWidth * perPixel + width * perPixel + i, scratch.get(y * texWidth * perPixel + (width - 1) * perPixel + i));
                }
            }
        }

        scratch.flip();

        return scratch;
    }

    /**
     * Get the closest greater power of 2 to the fold number
     *
     * @param fold
     *            The target number
     * @return The power of 2
     */
    private int get2Fold(int fold) {
        int ret = 2;
        while (ret < fold) {
            ret *= 2;
        }
        return ret;
    }

    /**
     * @see com.github.mathiewz.slick.opengl.ImageData#getImageBufferData()
     */
    @Override
    public ByteBuffer getImageBufferData() {
        throw new SlickException("TGAImageData doesn't store it's image.");
    }

    /**
     * @see com.github.mathiewz.slick.opengl.LoadableImageData#configureEdging(boolean)
     */
    @Override
    public void configureEdging(boolean edging) {
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy