159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/* 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved. 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met: 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer. 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer in the 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * documentation and/or other materials provided with the distribution. 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * may be used to endorse or promote products derived from this software 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * without specific prior written permission. 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.texture.plugins; 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.asset.AssetInfo; 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.asset.AssetLoader; 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.asset.TextureKey; 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.FastMath; 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Image; 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.texture.Image.Format; 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.BufferUtils; 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.BufferedInputStream; 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.DataInputStream; 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.IOException; 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.io.InputStream; 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.ByteBuffer; 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/** 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>TextureManager</code> provides static methods for building a 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>Texture</code> object. Typically, the information supplied is the 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * filename and the texture properties. 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Mark Powell 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Joshua Slack - cleaned, commented, added ability to read 16bit true color and color-mapped TGAs. 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Kirill Vainer - ported to jME3 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @version $Id: TGALoader.java 4131 2009-03-19 20:15:28Z blaine.dev $ 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic final class TGALoader implements AssetLoader { 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // 0 - no image data in file 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public static final int TYPE_NO_IMAGE = 0; 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // 1 - uncompressed, color-mapped image 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public static final int TYPE_COLORMAPPED = 1; 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // 2 - uncompressed, true-color image 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public static final int TYPE_TRUECOLOR = 2; 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // 3 - uncompressed, black and white image 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public static final int TYPE_BLACKANDWHITE = 3; 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // 9 - run-length encoded, color-mapped image 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public static final int TYPE_COLORMAPPED_RLE = 9; 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // 10 - run-length encoded, true-color image 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public static final int TYPE_TRUECOLOR_RLE = 10; 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // 11 - run-length encoded, black and white image 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public static final int TYPE_BLACKANDWHITE_RLE = 11; 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Object load(AssetInfo info) throws IOException{ 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!(info.getKey() instanceof TextureKey)) 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalArgumentException("Texture assets must be loaded using a TextureKey"); 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean flip = ((TextureKey)info.getKey()).isFlipY(); 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta InputStream in = null; 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta in = info.openStream(); 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Image img = load(in, flip); 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return img; 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } finally { 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (in != null){ 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta in.close(); 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>loadImage</code> is a manual image loader which is entirely 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * independent of AWT. OUT: RGB888 or RGBA8888 Image object 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return <code>Image</code> object that contains the 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * image, either as a RGB888 or RGBA8888 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param flip 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Flip the image vertically 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param exp32 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Add a dummy Alpha channel to 24b RGB image. 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param fis 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * InputStream of an uncompressed 24b RGB or 32b RGBA TGA 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @throws java.io.IOException 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public static Image load(InputStream in, boolean flip) throws IOException { 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean flipH = false; 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // open a stream to the file 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta DataInputStream dis = new DataInputStream(new BufferedInputStream(in)); 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // ---------- Start Reading the TGA header ---------- // 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // length of the image id (1 byte) 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int idLength = dis.readUnsignedByte(); 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Type of color map (if any) included with the image 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // 0 - no color map data is included 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // 1 - a color map is included 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int colorMapType = dis.readUnsignedByte(); 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Type of image being read: 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int imageType = dis.readUnsignedByte(); 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Read Color Map Specification (5 bytes) 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Index of first color map entry (if we want to use it, uncomment and remove extra read.) 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// short cMapStart = flipEndian(dis.readShort()); 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta dis.readShort(); 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // number of entries in the color map 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta short cMapLength = flipEndian(dis.readShort()); 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // number of bits per color map entry 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int cMapDepth = dis.readUnsignedByte(); 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Read Image Specification (10 bytes) 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // horizontal coordinate of lower left corner of image. (if we want to use it, uncomment and remove extra read.) 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// int xOffset = flipEndian(dis.readShort()); 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta dis.readShort(); 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // vertical coordinate of lower left corner of image. (if we want to use it, uncomment and remove extra read.) 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// int yOffset = flipEndian(dis.readShort()); 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta dis.readShort(); 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // width of image - in pixels 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int width = flipEndian(dis.readShort()); 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // height of image - in pixels 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int height = flipEndian(dis.readShort()); 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // bits per pixel in image. 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int pixelDepth = dis.readUnsignedByte(); 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int imageDescriptor = dis.readUnsignedByte(); 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if ((imageDescriptor & 32) != 0) // bit 5 : if 1, flip top/bottom ordering 15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta flip = !flip; 15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if ((imageDescriptor & 16) != 0) // bit 4 : if 1, flip left/right ordering 15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta flipH = !flipH; 15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // ---------- Done Reading the TGA header ---------- // 15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Skip image ID 16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (idLength > 0) 16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta in.skip(idLength); 16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ColorMapEntry[] cMapEntries = null; 16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (colorMapType != 0) { 16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // read the color map. 16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int bytesInColorMap = (cMapDepth * cMapLength) >> 3; 16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int bitsPerColor = Math.min(cMapDepth/3 , 8); 16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte[] cMapData = new byte[bytesInColorMap]; 17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta in.read(cMapData); 17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Only go to the trouble of constructing the color map 17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // table if this is declared a color mapped image. 17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (imageType == TYPE_COLORMAPPED || imageType == TYPE_COLORMAPPED_RLE) { 17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta cMapEntries = new ColorMapEntry[cMapLength]; 17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int alphaSize = cMapDepth - (3*bitsPerColor); 17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float scalar = 255f / (FastMath.pow(2, bitsPerColor) - 1); 17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float alphaScalar = 255f / (FastMath.pow(2, alphaSize) - 1); 18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < cMapLength; i++) { 18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ColorMapEntry entry = new ColorMapEntry(); 18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int offset = cMapDepth * i; 18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta entry.red = (byte)(int)(getBitsAsByte(cMapData, offset, bitsPerColor) * scalar); 18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta entry.green = (byte)(int)(getBitsAsByte(cMapData, offset+bitsPerColor, bitsPerColor) * scalar); 18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta entry.blue = (byte)(int)(getBitsAsByte(cMapData, offset+(2*bitsPerColor), bitsPerColor) * scalar); 18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (alphaSize <= 0) 18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta entry.alpha = (byte)255; 18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta else 18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta entry.alpha = (byte)(int)(getBitsAsByte(cMapData, offset+(3*bitsPerColor), alphaSize) * alphaScalar); 19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta cMapEntries[i] = entry; 19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Allocate image data array 19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Format format; 19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte[] rawData = null; 20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int dl; 20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (pixelDepth == 32) { 20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData = new byte[width * height * 4]; 20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta dl = 4; 20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData = new byte[width * height * 3]; 20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta dl = 3; 20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int rawDataIndex = 0; 20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (imageType == TYPE_TRUECOLOR) { 21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte red = 0; 21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte green = 0; 21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte blue = 0; 21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte alpha = 0; 21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Faster than doing a 16-or-24-or-32 check on each individual pixel, 21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // just make a seperate loop for each. 21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (pixelDepth == 16) { 21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte[] data = new byte[2]; 22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float scalar = 255f/31f; 22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i <= (height - 1); i++) { 22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!flip) 22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawDataIndex = (height - 1 - i) * width * dl; 22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int j = 0; j < width; j++) { 22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta data[1] = dis.readByte(); 22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta data[0] = dis.readByte(); 22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = (byte)(int)(getBitsAsByte(data, 1, 5) * scalar); 22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = (byte)(int)(getBitsAsByte(data, 6, 5) * scalar); 22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = (byte)(int)(getBitsAsByte(data, 11, 5) * scalar); 23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (dl == 4) { 23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // create an alpha channel 23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alpha = getBitsAsByte(data, 0, 1); 23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (alpha == 1) alpha = (byte)255; 23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = alpha; 23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta format = dl == 4 ? Format.RGBA8 : Format.RGB8; 24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (pixelDepth == 24){ 24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int y = 0; y < height; y++) { 24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!flip) 24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawDataIndex = (height - 1 - y) * width * dl; 24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta else 24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawDataIndex = y * width * dl; 24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta dis.readFully(rawData, rawDataIndex, width * dl); 24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// for (int x = 0; x < width; x++) { 24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //read scanline 25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// blue = dis.readByte(); 25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// green = dis.readByte(); 25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// red = dis.readByte(); 25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// rawData[rawDataIndex++] = red; 25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// rawData[rawDataIndex++] = green; 25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// rawData[rawDataIndex++] = blue; 25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// } 25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta format = Format.BGR8; 25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (pixelDepth == 32){ 26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i <= (height - 1); i++) { 26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!flip) 26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawDataIndex = (height - 1 - i) * width * dl; 26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int j = 0; j < width; j++) { 26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta blue = dis.readByte(); 26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta green = dis.readByte(); 26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta red = dis.readByte(); 26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alpha = dis.readByte(); 26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = red; 27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = green; 27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = blue; 27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = alpha; 27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta format = Format.RGBA8; 27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IOException("Unsupported TGA true color depth: "+pixelDepth); 27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if( imageType == TYPE_TRUECOLOR_RLE ) { 28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte red = 0; 28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte green = 0; 28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte blue = 0; 28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte alpha = 0; 28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Faster than doing a 16-or-24-or-32 check on each individual pixel, 28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // just make a seperate loop for each. 28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if( pixelDepth == 32 ){ 28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for( int i = 0; i <= ( height - 1 ); ++i ){ 28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if( !flip ){ 28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawDataIndex = ( height - 1 - i ) * width * dl; 29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for( int j = 0; j < width; ++j ){ 29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Get the number of pixels the next chunk covers (either packed or unpacked) 29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int count = dis.readByte(); 29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if( ( count & 0x80 ) != 0 ){ 29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Its an RLE packed block - use the following 1 pixel for the next <count> pixels 29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta count &= 0x07f; 29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta j += count; 29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta blue = dis.readByte(); 30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta green = dis.readByte(); 30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta red = dis.readByte(); 30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alpha = dis.readByte(); 30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while( count-- >= 0 ){ 30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = red; 30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = green; 30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = blue; 30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = alpha; 30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else{ 31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Its not RLE packed, but the next <count> pixels are raw. 31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta j += count; 31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while( count-- >= 0 ){ 31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta blue = dis.readByte(); 31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta green = dis.readByte(); 31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta red = dis.readByte(); 31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alpha = dis.readByte(); 31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = red; 31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = green; 31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = blue; 32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = alpha; 32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta format = Format.RGBA8; 32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if( pixelDepth == 24 ){ 32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for( int i = 0; i <= ( height - 1 ); i++ ){ 32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if( !flip ){ 32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawDataIndex = ( height - 1 - i ) * width * dl; 33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for( int j = 0; j < width; ++j ){ 33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Get the number of pixels the next chunk covers (either packed or unpacked) 33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int count = dis.readByte(); 33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if( ( count & 0x80 ) != 0 ){ 33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Its an RLE packed block - use the following 1 pixel for the next <count> pixels 33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta count &= 0x07f; 33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta j += count; 33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta blue = dis.readByte(); 33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta green = dis.readByte(); 34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta red = dis.readByte(); 34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while( count-- >= 0 ){ 34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = red; 34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = green; 34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = blue; 34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else{ 34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Its not RLE packed, but the next <count> pixels are raw. 34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta j += count; 34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while( count-- >= 0 ){ 35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta blue = dis.readByte(); 35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta green = dis.readByte(); 35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta red = dis.readByte(); 35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = red; 35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = green; 35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = blue; 35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta format = Format.RGB8; 36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if( pixelDepth == 16 ){ 36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte[] data = new byte[ 2 ]; 36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta float scalar = 255f / 31f; 36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for( int i = 0; i <= ( height - 1 ); i++ ){ 36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if( !flip ){ 36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawDataIndex = ( height - 1 - i ) * width * dl; 36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for( int j = 0; j < width; j++ ){ 36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Get the number of pixels the next chunk covers (either packed or unpacked) 37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int count = dis.readByte(); 37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if( ( count & 0x80 ) != 0 ){ 37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Its an RLE packed block - use the following 1 pixel for the next <count> pixels 37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta count &= 0x07f; 37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta j += count; 37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta data[1] = dis.readByte(); 37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta data[0] = dis.readByte(); 37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta blue = (byte) (int) ( getBitsAsByte( data, 1, 5 ) * scalar ); 37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta green = (byte) (int) ( getBitsAsByte( data, 6, 5 ) * scalar ); 37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta red = (byte) (int) ( getBitsAsByte( data, 11, 5 ) * scalar ); 38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while( count-- >= 0 ){ 38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = red; 38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = green; 38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = blue; 38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else{ 38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Its not RLE packed, but the next <count> pixels are raw. 38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta j += count; 38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while( count-- >= 0 ){ 38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta data[1] = dis.readByte(); 39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta data[0] = dis.readByte(); 39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta blue = (byte) (int) ( getBitsAsByte( data, 1, 5 ) * scalar ); 39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta green = (byte) (int) ( getBitsAsByte( data, 6, 5 ) * scalar ); 39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta red = (byte) (int) ( getBitsAsByte( data, 11, 5 ) * scalar ); 39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = red; 39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = green; 39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = blue; 39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta format = Format.RGB8; 40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else{ 40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IOException( "Unsupported TGA true color depth: " + pixelDepth ); 40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if( imageType == TYPE_COLORMAPPED ){ 40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int bytesPerIndex = pixelDepth / 8; 40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (bytesPerIndex == 1) { 41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i <= (height - 1); i++) { 41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!flip) 41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawDataIndex = (height - 1 - i) * width * dl; 41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int j = 0; j < width; j++) { 41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int index = dis.readUnsignedByte(); 41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (index >= cMapEntries.length || index < 0) 41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IOException("TGA: Invalid color map entry referenced: "+index); 41759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 41859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ColorMapEntry entry = cMapEntries[index]; 41959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = entry.red; 42059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = entry.green; 42159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = entry.blue; 42259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (dl == 4) { 42359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = entry.alpha; 42459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 42559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 42659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 42759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 42859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else if (bytesPerIndex == 2) { 42959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i <= (height - 1); i++) { 43059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!flip) 43159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawDataIndex = (height - 1 - i) * width * dl; 43259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int j = 0; j < width; j++) { 43359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int index = flipEndian(dis.readShort()); 43459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (index >= cMapEntries.length || index < 0) 43559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IOException("TGA: Invalid color map entry referenced: "+index); 43659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 43759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ColorMapEntry entry = cMapEntries[index]; 43859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = entry.red; 43959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = entry.green; 44059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = entry.blue; 44159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (dl == 4) { 44259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rawData[rawDataIndex++] = entry.alpha; 44359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 44759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IOException("TGA: unknown colormap indexing size used: "+bytesPerIndex); 44859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 45059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta format = dl == 4 ? Format.RGBA8 : Format.RGB8; 45159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else { 45259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IOException("Grayscale TGA not supported"); 45359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 45459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 45559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 45659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta in.close(); 45759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Get a pointer to the image memory 45859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ByteBuffer scratch = BufferUtils.createByteBuffer(rawData.length); 45959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta scratch.clear(); 46059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta scratch.put(rawData); 46159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta scratch.rewind(); 46259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Create the Image object 46359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Image textureImage = new Image(); 46459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta textureImage.setFormat(format); 46559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta textureImage.setWidth(width); 46659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta textureImage.setHeight(height); 46759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta textureImage.setData(scratch); 46859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return textureImage; 46959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 47059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 47159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private static byte getBitsAsByte(byte[] data, int offset, int length) { 47259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int offsetBytes = offset / 8; 47359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int indexBits = offset % 8; 47459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int rVal = 0; 47559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 47659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // start at data[offsetBytes]... spill into next byte as needed. 47759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = length; --i >=0;) { 47859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte b = data[offsetBytes]; 47959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int test = indexBits == 7 ? 1 : 2 << (6-indexBits); 48059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if ((b & test) != 0) { 48159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (i == 0) 48259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rVal++; 48359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta else 48459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta rVal += (2 << i-1); 48559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 48659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexBits++; 48759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (indexBits == 8) { 48859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta indexBits = 0; 48959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta offsetBytes++; 49059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 49159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 49259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 49359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return (byte)rVal; 49459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 49559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 49659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 49759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * <code>flipEndian</code> is used to flip the endian bit of the header 49859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * file. 49959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 50059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param signedShort 50159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the bit to flip. 50259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the flipped bit. 50359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 50459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private static short flipEndian(short signedShort) { 50559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int input = signedShort & 0xFFFF; 50659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return (short) (input << 8 | (input & 0xFF00) >>> 8); 50759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 50859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 50959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta static class ColorMapEntry { 51059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta byte red, green, blue, alpha; 51159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 51259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 51359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public String toString() { 51459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return "entry: "+red+","+green+","+blue+","+alpha; 51559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 51659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 51759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 518