|
|
|
@ -1,5 +1,5 @@ |
|
|
|
|
/* |
|
|
|
|
* Copyright (c) 2009-2010 jMonkeyEngine |
|
|
|
|
* Copyright (c) 2009-2012 jMonkeyEngine |
|
|
|
|
* All rights reserved. |
|
|
|
|
* |
|
|
|
|
* Redistribution and use in source and binary forms, with or without |
|
|
|
@ -29,7 +29,6 @@ |
|
|
|
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
|
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
package com.jme3.texture.plugins; |
|
|
|
|
|
|
|
|
|
import com.jme3.asset.AssetInfo; |
|
|
|
@ -59,28 +58,23 @@ public final class TGALoader implements AssetLoader { |
|
|
|
|
|
|
|
|
|
// 0 - no image data in file
|
|
|
|
|
public static final int TYPE_NO_IMAGE = 0; |
|
|
|
|
|
|
|
|
|
// 1 - uncompressed, color-mapped image
|
|
|
|
|
public static final int TYPE_COLORMAPPED = 1; |
|
|
|
|
|
|
|
|
|
// 2 - uncompressed, true-color image
|
|
|
|
|
public static final int TYPE_TRUECOLOR = 2; |
|
|
|
|
|
|
|
|
|
// 3 - uncompressed, black and white image
|
|
|
|
|
public static final int TYPE_BLACKANDWHITE = 3; |
|
|
|
|
|
|
|
|
|
// 9 - run-length encoded, color-mapped image
|
|
|
|
|
public static final int TYPE_COLORMAPPED_RLE = 9; |
|
|
|
|
|
|
|
|
|
// 10 - run-length encoded, true-color image
|
|
|
|
|
public static final int TYPE_TRUECOLOR_RLE = 10; |
|
|
|
|
|
|
|
|
|
// 11 - run-length encoded, black and white image
|
|
|
|
|
public static final int TYPE_BLACKANDWHITE_RLE = 11; |
|
|
|
|
|
|
|
|
|
public Object load(AssetInfo info) throws IOException { |
|
|
|
|
if (!(info.getKey() instanceof TextureKey)) |
|
|
|
|
if (!(info.getKey() instanceof TextureKey)) { |
|
|
|
|
throw new IllegalArgumentException("Texture assets must be loaded using a TextureKey"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
boolean flip = ((TextureKey) info.getKey()).isFlipY(); |
|
|
|
|
InputStream in = null; |
|
|
|
@ -99,14 +93,14 @@ public final class TGALoader implements AssetLoader { |
|
|
|
|
* <code>loadImage</code> is a manual image loader which is entirely |
|
|
|
|
* independent of AWT. OUT: RGB888 or RGBA8888 Image object |
|
|
|
|
* |
|
|
|
|
* @return <code>Image</code> object that contains the |
|
|
|
|
* image, either as a RGB888 or RGBA8888 |
|
|
|
|
* |
|
|
|
|
|
|
|
|
|
* @param in |
|
|
|
|
* InputStream of an uncompressed 24b RGB or 32b RGBA TGA |
|
|
|
|
* @param flip |
|
|
|
|
* Flip the image vertically |
|
|
|
|
* @param exp32 |
|
|
|
|
* Add a dummy Alpha channel to 24b RGB image. |
|
|
|
|
* @param fis |
|
|
|
|
* InputStream of an uncompressed 24b RGB or 32b RGBA TGA |
|
|
|
|
* @return <code>Image</code> object that contains the |
|
|
|
|
* image, either as a RGB888 or RGBA8888 |
|
|
|
|
* @throws java.io.IOException |
|
|
|
|
*/ |
|
|
|
|
public static Image load(InputStream in, boolean flip) throws IOException { |
|
|
|
@ -151,15 +145,20 @@ public final class TGALoader implements AssetLoader { |
|
|
|
|
int pixelDepth = dis.readUnsignedByte(); |
|
|
|
|
int imageDescriptor = dis.readUnsignedByte(); |
|
|
|
|
if ((imageDescriptor & 32) != 0) // bit 5 : if 1, flip top/bottom ordering
|
|
|
|
|
{ |
|
|
|
|
flip = !flip; |
|
|
|
|
} |
|
|
|
|
if ((imageDescriptor & 16) != 0) // bit 4 : if 1, flip left/right ordering
|
|
|
|
|
{ |
|
|
|
|
flipH = !flipH; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// ---------- Done Reading the TGA header ---------- //
|
|
|
|
|
|
|
|
|
|
// Skip image ID
|
|
|
|
|
if (idLength > 0) |
|
|
|
|
if (idLength > 0) { |
|
|
|
|
in.skip(idLength); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ColorMapEntry[] cMapEntries = null; |
|
|
|
|
if (colorMapType != 0) { |
|
|
|
@ -183,10 +182,11 @@ public final class TGALoader implements AssetLoader { |
|
|
|
|
entry.red = (byte) (int) (getBitsAsByte(cMapData, offset, bitsPerColor) * scalar); |
|
|
|
|
entry.green = (byte) (int) (getBitsAsByte(cMapData, offset + bitsPerColor, bitsPerColor) * scalar); |
|
|
|
|
entry.blue = (byte) (int) (getBitsAsByte(cMapData, offset + (2 * bitsPerColor), bitsPerColor) * scalar); |
|
|
|
|
if (alphaSize <= 0) |
|
|
|
|
if (alphaSize <= 0) { |
|
|
|
|
entry.alpha = (byte) 255; |
|
|
|
|
else |
|
|
|
|
} else { |
|
|
|
|
entry.alpha = (byte) (int) (getBitsAsByte(cMapData, offset + (3 * bitsPerColor), alphaSize) * alphaScalar); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
cMapEntries[i] = entry; |
|
|
|
|
} |
|
|
|
@ -219,8 +219,9 @@ public final class TGALoader implements AssetLoader { |
|
|
|
|
byte[] data = new byte[2]; |
|
|
|
|
float scalar = 255f / 31f; |
|
|
|
|
for (int i = 0; i <= (height - 1); i++) { |
|
|
|
|
if (!flip) |
|
|
|
|
if (!flip) { |
|
|
|
|
rawDataIndex = (height - 1 - i) * width * dl; |
|
|
|
|
} |
|
|
|
|
for (int j = 0; j < width; j++) { |
|
|
|
|
data[1] = dis.readByte(); |
|
|
|
|
data[0] = dis.readByte(); |
|
|
|
@ -230,7 +231,9 @@ public final class TGALoader implements AssetLoader { |
|
|
|
|
if (dl == 4) { |
|
|
|
|
// create an alpha channel
|
|
|
|
|
alpha = getBitsAsByte(data, 0, 1); |
|
|
|
|
if (alpha == 1) alpha = (byte)255; |
|
|
|
|
if (alpha == 1) { |
|
|
|
|
alpha = (byte) 255; |
|
|
|
|
} |
|
|
|
|
rawData[rawDataIndex++] = alpha; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -239,10 +242,11 @@ public final class TGALoader implements AssetLoader { |
|
|
|
|
format = dl == 4 ? Format.RGBA8 : Format.RGB8; |
|
|
|
|
} else if (pixelDepth == 24) { |
|
|
|
|
for (int y = 0; y < height; y++) { |
|
|
|
|
if (!flip) |
|
|
|
|
if (!flip) { |
|
|
|
|
rawDataIndex = (height - 1 - y) * width * dl; |
|
|
|
|
else |
|
|
|
|
} else { |
|
|
|
|
rawDataIndex = y * width * dl; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
dis.readFully(rawData, rawDataIndex, width * dl); |
|
|
|
|
// for (int x = 0; x < width; x++) {
|
|
|
|
@ -258,8 +262,9 @@ public final class TGALoader implements AssetLoader { |
|
|
|
|
format = Format.BGR8; |
|
|
|
|
} else if (pixelDepth == 32) { |
|
|
|
|
for (int i = 0; i <= (height - 1); i++) { |
|
|
|
|
if (!flip) |
|
|
|
|
if (!flip) { |
|
|
|
|
rawDataIndex = (height - 1 - i) * width * dl; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (int j = 0; j < width; j++) { |
|
|
|
|
blue = dis.readByte(); |
|
|
|
@ -408,12 +413,14 @@ public final class TGALoader implements AssetLoader { |
|
|
|
|
|
|
|
|
|
if (bytesPerIndex == 1) { |
|
|
|
|
for (int i = 0; i <= (height - 1); i++) { |
|
|
|
|
if (!flip) |
|
|
|
|
if (!flip) { |
|
|
|
|
rawDataIndex = (height - 1 - i) * width * dl; |
|
|
|
|
} |
|
|
|
|
for (int j = 0; j < width; j++) { |
|
|
|
|
int index = dis.readUnsignedByte(); |
|
|
|
|
if (index >= cMapEntries.length || index < 0) |
|
|
|
|
if (index >= cMapEntries.length || index < 0) { |
|
|
|
|
throw new IOException("TGA: Invalid color map entry referenced: " + index); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ColorMapEntry entry = cMapEntries[index]; |
|
|
|
|
rawData[rawDataIndex++] = entry.red; |
|
|
|
@ -427,12 +434,14 @@ public final class TGALoader implements AssetLoader { |
|
|
|
|
} |
|
|
|
|
} else if (bytesPerIndex == 2) { |
|
|
|
|
for (int i = 0; i <= (height - 1); i++) { |
|
|
|
|
if (!flip) |
|
|
|
|
if (!flip) { |
|
|
|
|
rawDataIndex = (height - 1 - i) * width * dl; |
|
|
|
|
} |
|
|
|
|
for (int j = 0; j < width; j++) { |
|
|
|
|
int index = flipEndian(dis.readShort()); |
|
|
|
|
if (index >= cMapEntries.length || index < 0) |
|
|
|
|
if (index >= cMapEntries.length || index < 0) { |
|
|
|
|
throw new IOException("TGA: Invalid color map entry referenced: " + index); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ColorMapEntry entry = cMapEntries[index]; |
|
|
|
|
rawData[rawDataIndex++] = entry.red; |
|
|
|
@ -478,11 +487,12 @@ public final class TGALoader implements AssetLoader { |
|
|
|
|
byte b = data[offsetBytes]; |
|
|
|
|
int test = indexBits == 7 ? 1 : 2 << (6 - indexBits); |
|
|
|
|
if ((b & test) != 0) { |
|
|
|
|
if (i == 0) |
|
|
|
|
if (i == 0) { |
|
|
|
|
rVal++; |
|
|
|
|
else |
|
|
|
|
} else { |
|
|
|
|
rVal += (2 << i - 1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
indexBits++; |
|
|
|
|
if (indexBits == 8) { |
|
|
|
|
indexBits = 0; |
|
|
|
@ -507,6 +517,7 @@ public final class TGALoader implements AssetLoader { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static class ColorMapEntry { |
|
|
|
|
|
|
|
|
|
byte red, green, blue, alpha; |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|