From 2895f4be6d17a064c9e991c3a5ad39f5da63086e Mon Sep 17 00:00:00 2001 From: Song Minjae Date: Wed, 19 Apr 2017 20:53:03 +0900 Subject: [PATCH] Proper tga.gz loading using own imagedata --- .../torvald/slick/opengl/TGAGzImageData.java | 328 ++++++++++++++++++ .../torvald/terrarum/mapdrawer/TilesDrawer.kt | 32 +- .../slick/opengl/ImageDataFactory.java | 87 +++++ 3 files changed, 416 insertions(+), 31 deletions(-) create mode 100644 src/net/torvald/slick/opengl/TGAGzImageData.java create mode 100644 src/org/newdawn/slick/opengl/ImageDataFactory.java diff --git a/src/net/torvald/slick/opengl/TGAGzImageData.java b/src/net/torvald/slick/opengl/TGAGzImageData.java new file mode 100644 index 000000000..0065cacf8 --- /dev/null +++ b/src/net/torvald/slick/opengl/TGAGzImageData.java @@ -0,0 +1,328 @@ +package net.torvald.slick.opengl; + +/* + * A utility to load .tga.gz + * + * Created by SKYHi14 on 2017-04-19. + */ + + +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 java.util.zip.GZIPInputStream; + +import org.lwjgl.BufferUtils; +import org.newdawn.slick.opengl.LoadableImageData; + +/** + * 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 TGAGzImageData 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 TGAGzImageData() { + } + + /** + * 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 org.newdawn.slick.opengl.ImageData#getDepth() + */ + public int getDepth() { + return pixelDepth; + } + + /** + * @see org.newdawn.slick.opengl.ImageData#getWidth() + */ + public int getWidth() { + return width; + } + + /** + * @see org.newdawn.slick.opengl.ImageData#getHeight() + */ + public int getHeight() { + return height; + } + + /** + * @see org.newdawn.slick.opengl.ImageData#getTexWidth() + */ + public int getTexWidth() { + return texWidth; + } + + /** + * @see org.newdawn.slick.opengl.ImageData#getTexHeight() + */ + public int getTexHeight() { + return texHeight; + } + + /** + * @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; + } + byte red = 0; + byte green = 0; + byte blue = 0; + byte alpha = 0; + + BufferedInputStream bis = new BufferedInputStream(new GZIPInputStream(fis, 8192), 16384); + DataInputStream dis = new DataInputStream(bis); + + // Read in the Header + short idLength = (short) dis.read(); + short colorMapType = (short) dis.read(); + short imageType = (short) dis.read(); + short cMapStart = flipEndian(dis.readShort()); + short cMapLength = flipEndian(dis.readShort()); + short cMapDepth = (short) dis.read(); + short xOffset = flipEndian(dis.readShort()); + short yOffset = flipEndian(dis.readShort()); + + 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 RuntimeException("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