Updated Release Archive

Updated Release Archive.  Fixed Mage-killer prereqs.  Removed old LETO & ConvoCC related files.  Added organized spell scroll store.  Fixed Gloura spellbook. Various TLK fixes.  Reorganized Repo.  Removed invalid user folders. Added DocGen back in.
This commit is contained in:
Jaysyn904
2023-08-22 10:00:21 -04:00
parent 3acda03f30
commit 5914ed2ab5
22853 changed files with 57524 additions and 47307 deletions

View File

@@ -0,0 +1,88 @@
package com.realityinteractive.imageio.tga;
/*
* TGAConstants.java
* Copyright (c) 2003 Reality Interactive, Inc.
* See bottom of file for license and warranty information.
* Created on Sep 26, 2003
*/
/**
* <p>Various header and such constants for the TGA image format.</p>
*
* @author Rob Grzywinski <a href="mailto:rgrzywinski@realityinteractive.com">rgrzywinski@realityinteractive.com</a>
* @version $Id: TGAConstants.java,v 1.1 2005/04/12 11:23:53 ornedan Exp $
* @since 1.0
*/
public interface TGAConstants
{
// =========================================================================
// image types
/**
* <p>An image type indicating no image data.</p>
*/
int NO_IMAGE = 0;
/**
* <p>An image type indicating an uncompressed color mapped (indexed) image.</p>
*/
int COLOR_MAP = 1;
/**
* <p>An image type indicating an uncompressed true-color image.</p>
*/
int TRUE_COLOR = 2;
/**
* <p>An image type indicating a black and white (monochrome) image.</p>
*/
int MONO = 3;
/**
* <p>An image type indicating an RLE (run-length encoded) color-mapped
* (indexed) image.</p>
*/
int RLE_COLOR_MAP = 9;
/**
* <p>An image type indicating an RLE (run-length encoded) true-color
* image.</p>
*/
int RLE_TRUE_COLOR = 10;
/**
* <p>An image type indicating an RLE (run-length encoded) black and white
* (monochrome) image.</p>
*/
int RLE_MONO = 11;
// =========================================================================
// Image descriptor bit
/**
* <p>The bit of the image descriptor field (5.5) indicating that the first
* pixel should be at the left or the right.</p>
*/
int LEFT_RIGHT_BIT = 0x10;
/**
* <p>The bit of the image descriptor field (5.5) indicating that the first
* pixel should be at the bottom or the top.</p>
*/
int BOTTOM_TOP_BIT = 0x20;
}
// =============================================================================
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -0,0 +1,479 @@
package com.realityinteractive.imageio.tga;
/*
* TGAHeader.java
* Copyright (c) 2003 Reality Interactive, Inc.
* See bottom of file for license and warranty information.
* Created on Sep 26, 2003
*/
import java.io.IOException;
import javax.imageio.stream.ImageInputStream;
/**
* <p>The header to a TGA image file.</p>
*
* <p>See <a href="http://organicbit.com/closecombat/formats/tga.html">format</a>,
* <a href="http://www.opennet.ru/docs/formats/targa.pdf">format</a> or
* <a href="http://netghost.narod.ru/gff/graphics/summary/tga.htm">format</a>
* for header information.</p>
*
* @author Rob Grzywinski <a href="mailto:rgrzywinski@realityinteractive.com">rgrzywinski@realityinteractive.com</a>
* @version $Id: TGAHeader.java,v 1.1 2005/04/12 11:23:53 ornedan Exp $
* @since 1.0
*/
public class TGAHeader
{
/**
* <p>The length of the TGA identifier. This is a <code>byte</code> in
* length.</p>
*/
private int idLength;
/**
* <p>The image identifier with length <code>idLength</code>.</p>
*/
private byte[] id;
/**
* <p>Does this TGA have an associated color map? <code>1</code> indicates
* that there is a color map. <code>0</code> indicates no color map.</p>
*/
private boolean hasColorMap;
/**
* <p>The type of image. See the image type constants in {@link com.realityinteractive.imageio.tga.TGAConstants}
* for allowed values.</p>
*/
private int imageType;
/**
* <p>An image is compressed if its image type is {@link TGAConstants#RLE_COLOR_MAP},
* {@link TGAConstants#RLE_TRUE_COLOR}, or {@link TGAConstants#RLE_MONO}.</p>
*/
private boolean isCompressed;
/**
* <p>The index of the first color map entry.</p>
*/
private int firstColorMapEntryIndex;
/**
* <p>The total number of color map entries.</p>
*/
private int numberColorMapEntries;
/**
* <p>The number of bits per color map entry.</p>
*/
private int bitsPerColorMapEntry;
/**
* <p>The computed size of a color map entry in <code>byte</code>s.</p>
*/
private int colorMapEntrySize;
/**
* <p>The computed size of the color map field in <code>byte</code>s. This
* is determined from the <code>numberColorMapEntries</code> and
* <code>colorMapEntrySize</code>.</p>
*/
private int colorMapSize;
/**
* <p>The horizontal coordinate for the lower-left corner of the image.</p>
*/
private int xOrigin;
/**
* <p>The vertical coordinate for the lower-left corner of the image.</p>
*/
private int yOrigin;
/**
* <p>The width of the image in pixels.</p>
*/
private int width;
/**
* <p>The height of the image in pixels.</p>
*/
private int height;
/**
* <p>The number of bits per pixel.</p>
*/
private int bitsPerPixel;
/**
* <p>The number of attribute bits per pixel.</p>
*/
private int imageDescriptor;
/**
* <p>The horizontal ordering of the pixels as determined from the image
* descriptor. By default the order is left to right.</p>
*/
// NOTE: true -> left-to-right; false -> right-to-left
private boolean leftToRight;
/**
* <p>The horizontal ordering of the pixels as determined from the image
* descriptor. By default the order is left to right.</p>
*/
// NOTE: true -> bottom-to-top; false -> top-to-bottom
private boolean bottomToTop;
/**
* <p>The offset to the color map data. This value is not defined if there
* is no color map (see <code>hasColorMap</code>).</p>
*/
private int colorMapDataOffset;
/**
* <p>The offset to the pixel data.</p>
*/
private int pixelDataOffset;
// =========================================================================
/**
* <p>Constructs a TGA header that will be populated by setters or directly
* (via a static "factory" method).</p>
*/
public TGAHeader() {}
/**
* <p>Constructs and populates a TGA header from the specified {@link javax.imageio.stream.ImageInputStream}.</p>
*
* @param inputStream the <code>ImageInputStream</code> from which the
* header data is read
* @throws IOException if there was an I/O error while reading the header
* data
*/
public TGAHeader(final ImageInputStream inputStream)
throws IOException
{
// read the data
readHeader(inputStream);
}
/**
* <p>Reads and populates the header from the specifed {@link javax.imageio.stream.ImageInputStream}.
* Any existing values will be over written.</p>
*
* <p>The <code>ImageInputStream</code> will be changed as a result of this
* operation (the offset will be moved).</p>
*
* @param inputStream the <code>ImageInputStream</code> from which the
* header data is read
* @throws IOException if there was an I/O error while reading the header
* data
*/
public void readHeader(final ImageInputStream inputStream)
throws IOException
{
// read in the header as per the spec
idLength = inputStream.readUnsignedByte();
hasColorMap = (inputStream.readUnsignedByte() == 1); // 1 == true, 0 == false
imageType = inputStream.readUnsignedByte();
firstColorMapEntryIndex = inputStream.readUnsignedShort();
numberColorMapEntries = inputStream.readUnsignedShort();
bitsPerColorMapEntry = inputStream.readByte();
xOrigin = inputStream.readUnsignedShort();
yOrigin = inputStream.readUnsignedShort();
width = inputStream.readUnsignedShort();
height = inputStream.readUnsignedShort();
bitsPerPixel = inputStream.readByte();
imageDescriptor = inputStream.readByte();
// determine if the image is compressed
isCompressed = ( (imageType == TGAConstants.RLE_COLOR_MAP) ||
(imageType == TGAConstants.RLE_TRUE_COLOR) ||
(imageType == TGAConstants.RLE_MONO) );
// compute the size of the color map field in bytes
switch(bitsPerColorMapEntry)
{
case 8:
default:
colorMapEntrySize = 1;
break;
case 15:
case 16:
colorMapEntrySize = 2;
break;
case 24:
case 32:
colorMapEntrySize = 3;
break;
}
colorMapSize = colorMapEntrySize * numberColorMapEntries; // in bytes
// set the pixel ordering from the imageDescriptor bit mask
// (bit set indicates false)
leftToRight = ((imageDescriptor & TGAConstants.LEFT_RIGHT_BIT) == 0);
bottomToTop = ((imageDescriptor & TGAConstants.BOTTOM_TOP_BIT) == 0);
// read the image id based whose length is idLength
if(idLength > 0)
{
// allocate the space for the id
id = new byte[idLength];
// read the id
inputStream.read(id, 0, idLength);
} /* else -- the idLength was not positive */
// compute the color map and pixel data offsets. The color map data
// offset is the current offset.
// NOTE: the conversion to int is OK since the maximum size of the
// color map data is 65536 bytes.
final long currentOffset = inputStream.getStreamPosition();
colorMapDataOffset = (int)currentOffset;
if(hasColorMap)
{
// there is a color map so the pixel data offset is the current
// offset + the size of the color map data
pixelDataOffset = colorMapDataOffset + colorMapSize;
} else /* there is no color map */
{
// there is no color map so the pixel data offset is the current
// offset
pixelDataOffset = (int)currentOffset;
}
}
/**
* <p>The length of the TGA identifier. This is a <code>byte</code> in
* length.</p>
*/
public int getIdLength()
{
return idLength;
}
/**
* <p>Does this TGA have an associated color map?</p>
*/
public boolean hasColorMap()
{
return hasColorMap;
}
/**
* <p>Retrieves the type of image. See the image type constants in {@link com.realityinteractive.imageio.tga.TGAConstants}
* for allowed values.</p>
*/
public int getImageType()
{
return imageType;
}
/**
* <p>Retrieves a string that represents the image type.</p>
*/
public String getImageTypeString()
{
switch(imageType)
{
case TGAConstants.NO_IMAGE:
return "NO IMAGE";
case TGAConstants.COLOR_MAP:
return "COLOR MAP";
case TGAConstants.TRUE_COLOR:
return "TRUE COLOR";
case TGAConstants.MONO:
return "MONOCHROME";
case TGAConstants.RLE_COLOR_MAP:
return "RLE COMPRESSED COLOR MAP";
case TGAConstants.RLE_TRUE_COLOR:
return "RLE COMPRESSED TRUE COLOR";
case TGAConstants.RLE_MONO:
return "RLE COMPRESSED MONOCHROME";
default:
return "UNKNOWN";
}
}
/**
* <p>Retrieves if this image is compressed. If the image type is
* {@link TGAConstants#RLE_COLOR_MAP}, {@link TGAConstants#RLE_TRUE_COLOR},
* or {@link TGAConstants#RLE_MONO} then the image is compressed.</p>
*/
public boolean isCompressed()
{
return isCompressed;
}
/**
* <p>Retrieves the index of the first color map entry.</p>
*/
public int getFirstColorMapEntryIndex()
{
return firstColorMapEntryIndex;
}
/**
* <p>Retrieves ttotal number of color map entries.</p>
*/
public int getColorMapLength()
{
return numberColorMapEntries;
}
/**
* <p>Retrieves the number of bits per color map entry.</p>
*/
public int getBitsPerColorMapEntry()
{
return bitsPerColorMapEntry;
}
/**
* <p>Retrieves the horizontal coordinate for the lower-left corner of the
* image.</p>
*/
public int getXOrigin()
{
return xOrigin;
}
/**
* <p>Retrieves the vertical coordinate for the lower-left corner of the image.</p>
*/
public int getYOrigin()
{
return yOrigin;
}
/**
* <p>Retrieves the width of the image in pixels.</p>
*/
public int getWidth()
{
return width;
}
/**
* <p>Retrieves the height of the image in pixels.</p>
*/
public int getHeight()
{
return height;
}
/**
* <p>Retrieves the number of bits per pixel.</p>
*/
public int getBitsPerPixel()
{
return bitsPerPixel;
}
/**
* <p>Retrieves the number of samples per pixel.</p>
*/
public int getSamplesPerPixel()
{
// FIXME: this is overly simplistic but it is accurate
return (bitsPerPixel == 32) ? 4 : 3;
}
/**
* <p>Retrieves the number of attribute bits per pixel.</p>
*/
public int getImageDescriptor()
{
return imageDescriptor;
}
/**
* <p>Returns if this image is left-to-right (<code>true</code>) or right-
* to-left (<code>false</code>).</p>
*/
public boolean isLeftToRight()
{
return leftToRight;
}
/**
* <p>Returns if this image is bottom-to-top (<code>true</code>) or top-to-
* bottom (<code>false</code>).</p>
*/
public boolean isBottomToTop()
{
return bottomToTop;
}
/**
* <p>Retrieves the offset to the color map data. If there is no color
* map ({@link #hasColorMap()} returns <code>false</code>) then this is
* undefined.</p>
*/
public int getColorMapDataOffset()
{
return colorMapDataOffset;
}
/**
* <p>Retrieves the offset to the pixel data.</p>
*/
public int getPixelDataOffset()
{
return pixelDataOffset;
}
// =========================================================================
/**
* <p>Retrieves a string useful for debugging.</p>
*
* @return a string useful for debugging
*/
public String debugString()
{
return "TGAHeader[" +
"type=" + getImageTypeString() + ", " +
(hasColorMap ?
("firstColorMapEntryIndex=" + firstColorMapEntryIndex + ", " +
"numberColorMapEntries=" + numberColorMapEntries + ", " +
"bitsPerColorMapEntry=" + bitsPerColorMapEntry + ", " +
"totalColorMapEntrySize=" + colorMapSize + ", " ) :
"") +
"isCompressed=" + isCompressed + ", " +
"xOrigin=" + xOrigin + ", " +
"yOrigin=" + yOrigin + ", " +
"width=" + width + ", " +
"height=" + height + ", " +
"bitsPerPixel=" + bitsPerPixel + ", " +
"samplesPerPixel=" + getSamplesPerPixel() +
"]";
}
}
// =============================================================================
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -0,0 +1,131 @@
package com.realityinteractive.imageio.tga;
/*
* TGAImageMetadata.java
* Copyright (c) 2003 Reality Interactive, Inc.
* See bottom of file for license and warranty information.
* Created on Sep 27, 2003
*/
import javax.imageio.metadata.IIOInvalidTreeException;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.metadata.IIOMetadataFormat;
import javax.imageio.metadata.IIOMetadataNode;
import org.w3c.dom.Node;
/**
* <p>The image metadata for a TGA image type. At this time there are no
* elements in the format (i.e. {@link javax.imageio.metadata.IIOMetadataFormat#canNodeAppear(java.lang.String, javax.imageio.ImageTypeSpecifier)}
* always returns <code>false</code>).</p>
*
* @author Rob Grzywinski <a href="mailto:rgrzywinski@realityinteractive.com">rgrzywinski@realityinteractive.com</a>
* @version $Id: TGAImageMetadata.java,v 1.1 2005/04/12 11:23:53 ornedan Exp $
* @since 1.0
*/
// NOTE: this is currently unused
public class TGAImageMetadata extends IIOMetadata
{
// =========================================================================
/**
* @see javax.imageio.metadata.IIOMetadata#IIOMetadata()
*/
public TGAImageMetadata()
{
super(TGAImageReaderSpi.SUPPORTS_STANDARD_IMAGE_METADATA_FORMAT,
TGAImageReaderSpi.NATIVE_IMAGE_METADATA_FORMAT_NAME,
TGAImageReaderSpi.NATIVE_IMAGE_METADATA_FORMAT_CLASSNAME,
TGAImageReaderSpi.EXTRA_IMAGE_METADATA_FORMAT_NAMES,
TGAImageReaderSpi.EXTRA_IMAGE_METADATA_FORMAT_CLASSNAMES);
}
/**
* <p>Ensure that the specified format name is supported by this metadata.
* If the format is not supported {@link java.lang.IllegalArgumentException}
* is thrown.</p>
*
* @param formatName the name of the metadata format that is to be validated
*/
private void checkFormatName(final String formatName)
{
// if the format name is not known, throw an exception
if(!TGAImageReaderSpi.NATIVE_IMAGE_METADATA_FORMAT_NAME.equals(formatName))
{
throw new IllegalArgumentException("Unknown image metadata format name \"" + formatName + "\"."); // FIXME: localize
} /* else -- the format name is valid */
}
/**
* @see javax.imageio.metadata.IIOMetadata#getAsTree(java.lang.String)
*/
public Node getAsTree(final String formatName)
{
// validate the format name (this will throw if invalid)
checkFormatName(formatName);
// create and return a root node
// NOTE: there are no children at this time
final IIOMetadataNode root = new IIOMetadataNode(TGAImageReaderSpi.NATIVE_IMAGE_METADATA_FORMAT_NAME);
return root;
}
/**
* @see javax.imageio.metadata.IIOMetadata#getMetadataFormat(java.lang.String)
*/
public IIOMetadataFormat getMetadataFormat(final String formatName)
{
// validate the format name (this will throw if invalid)
checkFormatName(formatName);
// return the metadata format
return TGAImageMetadataFormat.getInstance();
}
/**
* <p>This is read-only metadata.</p>
*
* @see javax.imageio.metadata.IIOMetadata#isReadOnly()
*/
public boolean isReadOnly()
{
// see javadoc
return true;
}
/**
* @see javax.imageio.metadata.IIOMetadata#mergeTree(java.lang.String, org.w3c.dom.Node)
*/
public void mergeTree(final String formatName, final Node root)
throws IIOInvalidTreeException
{
// validate the format name (this will throw if invalid)
checkFormatName(formatName);
// since there are no elements in the tree, there is nothing to merge
}
/**
* @see javax.imageio.metadata.IIOMetadata#reset()
*/
public void reset()
{
// NOTE: nothing to do since there are no elements
}
}
// =============================================================================
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -0,0 +1,88 @@
package com.realityinteractive.imageio.tga;
/*
* TGAImageMetadataFormat.java
* Copyright (c) 2003 Reality Interactive, Inc.
* See bottom of file for license and warranty information.
* Created on Sep 27, 2003
*/
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadataFormatImpl;
/**
* <p>The image metadata format for a TGA image type. At this time there are
* no elements in the format (i.e. {@link javax.imageio.metadata.IIOMetadataFormat#canNodeAppear(java.lang.String, javax.imageio.ImageTypeSpecifier)}
* always returns <code>false</code>).</p>
*
* @author Rob Grzywinski <a href="mailto:rgrzywinski@realityinteractive.com">rgrzywinski@realityinteractive.com</a>
* @version $Id: TGAImageMetadataFormat.java,v 1.1 2005/04/12 11:23:53 ornedan Exp $
* @since 1.0
*/
// NOTE: this is currently unused
public class TGAImageMetadataFormat extends IIOMetadataFormatImpl
{
/**
* <p>The singleton instance of this {@linkjavax.imageio.metadata.IIOMetadataFormat}.
* It is created lazily.</p>
*/
private static TGAImageMetadataFormat instance;
// =========================================================================
/**
* <p>A private constructor to enforce the singleton pattern.</p>
*/
private TGAImageMetadataFormat()
{
// set the name of the root document node. The child elements may
// repeat
super(TGAImageReaderSpi.NATIVE_IMAGE_METADATA_FORMAT_NAME,
CHILD_POLICY_REPEAT);
// TODO: add the full metadata
}
/**
* <p>Retrieves the singleton instance of <code>TGAMetadataformat</code>.
* The instance is created lazily.</p>
*
* @return the singleton instnace
*/
public static synchronized TGAImageMetadataFormat getInstance()
{
// if the instance doesn't already exist then create it
if(instance == null)
{
instance = new TGAImageMetadataFormat();
} /* else -- there is a singleton instance */
return instance;
}
// =========================================================================
/**
* @see javax.imageio.metadata.IIOMetadataFormat#canNodeAppear(java.lang.String, javax.imageio.ImageTypeSpecifier)
*/
public boolean canNodeAppear(final String elementName,
final ImageTypeSpecifier imageType)
{
// NOTE: since there are no elements, none are allowed
return false;
}
}
// =============================================================================
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -0,0 +1,648 @@
package com.realityinteractive.imageio.tga;
/*
* TGAImageReader.java
* Copyright (c) 2003 Reality Interactive, Inc.
* See bottom of file for license and warranty information.
* Created on Sep 26, 2003
*/
import java.awt.Rectangle;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferInt;
import java.awt.image.WritableRaster;
import java.io.IOException;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.ImageTypeSpecifier;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
/**
* <p>The {@link javax.imageio.ImageReader} that exposes the TGA image reading.
* 8, 15, 16, 24 and 32 bit true color or color mapped (RLE compressed or
* uncompressed) are supported. Monochrome images are not supported.</p>
*
* <p>Great care should be employed with {@link javax.imageio.ImageReadParam}s.
* Little to no effort has been made to correctly handle sub-sampling or
* specified bands.</p>
*
* <p>{@link javax.imageio.ImageIO#setUseCache(boolean)} should be set to <code>false</code>
* when using this reader. Also, {@link javax.imageio.ImageIO#read(java.io.InputStream)}
* is the preferred read method if used against a buffered array (for performance
* reasons).</p>
*
* @author Rob Grzywinski <a href="mailto:rgrzywinski@realityinteractive.com">rgrzywinski@realityinteractive.com</a>
* @version $Id: TGAImageReader.java,v 1.1 2005/04/12 11:23:53 ornedan Exp $
* @since 1.0
*/
// TODO: incorporate the x and y origins
public class TGAImageReader extends ImageReader
{
/**
* <p>The {@link javax.imageio.stream.ImageInputStream} from which the TGA
* is read. This may be <code>null</code> if {@link javax.imageio.ImageReader#setInput(java.lang.Object)}
* (or the other forms of <code>setInput()</code>) has not been called. The
* stream will be set litle-endian when it is set.</p>
*/
private ImageInputStream inputStream;
/**
* <p>The {@link com.realityinteractive.imageio.tga.TGAHeader}. If <code>null</code>
* then the header has not been read since <code>inputStream</code> was
* last set. This is created lazily.</p>
*/
private TGAHeader header;
// =========================================================================
/**
* @see javax.imageio.ImageReader#ImageReader(javax.imageio.spi.ImageReaderSpi)
*/
public TGAImageReader(final ImageReaderSpi originatingProvider)
{
super(originatingProvider);
}
/**
* <p>Store the input if it is an {@link javax.imageio.stream.ImageInputStream}.
* Otherwise {@link java.lang.IllegalArgumentException} is thrown. The
* stream is set to little-endian byte ordering.</p>
*
* @see javax.imageio.ImageReader#setInput(java.lang.Object, boolean, boolean)
*/
// NOTE: can't read the header in here as there would be no place for
// exceptions to go. It must be read lazily.
public void setInput(final Object input, final boolean seekForwardOnly,
final boolean ignoreMetadata)
{
// delegate to the partent
super.setInput(input, seekForwardOnly, ignoreMetadata);
// if the input is null clear the inputStream and header
if(input == null)
{
inputStream = null;
header = null;
} /* else -- the input is non-null */
// only ImageInputStream are allowed. If other throw IllegalArgumentException
if(input instanceof ImageInputStream)
{
// set the inputStream
inputStream = (ImageInputStream)input;
// put the ImageInputStream into little-endian ("Intel byte ordering")
// byte ordering
inputStream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
} else /* input is not an instance of ImageInputStream */
{
throw new IllegalArgumentException("Only ImageInputStreams are accepted."); // FIXME: localize
}
}
/**
* <p>Create and read the {@link com.realityinteractive.imageio.tga.TGAHeader}
* only if there is not one already.</p>
*
* @return the <code>TGAHeader</code> (for convenience)
* @throws IOException if there is an I/O error while reading the header
*/
private synchronized TGAHeader getHeader()
throws IOException
{
// if there is already a header (non-null) then there is nothing to be
// done
if(header != null)
return header;
/* else -- there is no header */
// ensure that there is an ImageInputStream from which the header is
// read
if(inputStream == null)
throw new IllegalStateException("There is no ImageInputStream from which the header can be read."); // FIXME: localize
/* else -- there is an input stream */
header = new TGAHeader(inputStream);
return header;
}
/**
* <p>Only a single image can be read by this reader. Validate the
* specified image index and if not <code>0</code> then {@link java.lang.IndexOutOfBoundsException}
* is thrown.</p>
*
* @param imageIndex the index of the image to validate
* @throws IndexOutOfBoundsException if the <code>imageIndex</code> is not
* <code>0</code>
*/
private void checkImageIndex(final int imageIndex)
{
// if the imageIndex is not 0 then throw an exception
if(imageIndex != 0)
throw new IndexOutOfBoundsException("Image index out of bounds (" + imageIndex + " != 0)."); // FIXME: localize
/* else -- the index is in bounds */
}
// =========================================================================
// Required ImageReader methods
/**
* @see javax.imageio.ImageReader#getImageTypes(int)
*/
public Iterator/*<ImageTypeSpecifier>*/ getImageTypes(final int imageIndex)
throws IOException
{
// validate the imageIndex (this will throw if invalid)
checkImageIndex(imageIndex);
// read / get the header
final TGAHeader header = getHeader();
// get the ImageTypeSpecifier for the image type
// FIXME: finish
final ImageTypeSpecifier imageTypeSpecifier;
switch(header.getImageType())
{
case TGAConstants.COLOR_MAP:
case TGAConstants.RLE_COLOR_MAP:
case TGAConstants.TRUE_COLOR:
case TGAConstants.RLE_TRUE_COLOR:
{
// determine if there is an alpha mask based on the number of
// samples per pixel
final int alphaMask;
if(header.getSamplesPerPixel() == 4)
alphaMask = 0xFF000000;
else /* no alpha channel (less than 32 bits or 4 samples) */
alphaMask = 0;
// packed RGB(A) pixel data (more specifically (A)BGR)
// TODO: split on 16, 24, and 32 bit images otherwise there
// will be wasted space
final ColorSpace rgb = ColorSpace.getInstance(ColorSpace.CS_sRGB);
imageTypeSpecifier = ImageTypeSpecifier.createPacked(rgb,
0x000000FF,
0x0000FF00,
0x00FF0000,
alphaMask,
DataBuffer.TYPE_INT,
false /*not pre-multiplied by an alpha*/);
break;
}
case TGAConstants.MONO:
case TGAConstants.RLE_MONO:
throw new IllegalArgumentException("Monochrome image type not supported.");
case TGAConstants.NO_IMAGE:
default:
throw new IllegalArgumentException("The image type is not known."); // FIXME: localize
}
// create a list and add the ImageTypeSpecifier to it
final List/*<ImageTypeSpecifier>*/ imageSpecifiers = new ArrayList/*<ImageTypeSpecifier>*/();
imageSpecifiers.add(imageTypeSpecifier);
return imageSpecifiers.iterator();
}
/**
* <p>Only a single image is supported.</p>
*
* @see javax.imageio.ImageReader#getNumImages(boolean)
*/
public int getNumImages(final boolean allowSearch)
throws IOException
{
// see javadoc
// NOTE: 1 is returned regardless if a search is allowed or not
return 1;
}
/**
* <p>There is no stream metadata (i.e. <code>null</code> is returned).</p>
*
* @see javax.imageio.ImageReader#getStreamMetadata()
*/
public IIOMetadata getStreamMetadata()
throws IOException
{
// see javadoc
return null;
}
/**
* <p>There is no image metadata (i.e. <code>null</code> is returned).</p>
*
* @see javax.imageio.ImageReader#getImageMetadata(int)
*/
public IIOMetadata getImageMetadata(final int imageIndex)
throws IOException
{
// see javadoc
return null;
}
/**
* @see javax.imageio.ImageReader#getHeight(int)
*/
public int getHeight(final int imageIndex)
throws IOException
{
// validate the imageIndex (this will throw if invalid)
checkImageIndex(imageIndex);
// get the header and return the height
return getHeader().getHeight();
}
/**
* @see javax.imageio.ImageReader#getWidth(int)
*/
public int getWidth(final int imageIndex)
throws IOException
{
// validate the imageIndex (this will throw if invalid)
checkImageIndex(imageIndex);
// get the header and return the width
return getHeader().getHeight();
}
/**
* @see javax.imageio.ImageReader#read(int, javax.imageio.ImageReadParam)
*/
public BufferedImage read(final int imageIndex, final ImageReadParam param)
throws IOException
{
// ensure that the image is of a supported type
// NOTE: this will implicitly ensure that the imageIndex is valid
final Iterator imageTypes = getImageTypes(imageIndex);
if(!imageTypes.hasNext())
{
throw new IOException("Unsupported Image Type");
}
// read and get the header
final TGAHeader header = getHeader();
// ensure that the ImageReadParam hasn't been set to other than the
// defaults (this will throw if not acceptible)
checkImageReadParam(param, header);
// get the height and width from the header for convenience
final int width = header.getWidth();
final int height = header.getHeight();
// read the color map data. If the image does not contain a color map
// then null will be returned.
final int[] colorMap = readColorMap(header);
// seek to the pixel data offset
// TODO: read the color map
inputStream.seek(header.getPixelDataOffset());
// get the destination image and WritableRaster for the image type and
// size
final BufferedImage image = getDestination(param, imageTypes,
width, height);
final WritableRaster imageRaster = image.getRaster();
// get and validate the number of image bands
final int numberOfImageBands = image.getSampleModel().getNumBands();
checkReadParamBandSettings(param, header.getSamplesPerPixel(),
numberOfImageBands);
// get the destination bands
final int[] destinationBands;
if(param != null)
{
// there is an ImageReadParam -- use its destination bands
destinationBands = param.getDestinationBands();
} else
{
// there are no destination bands
destinationBands = null;
}
// create the destination WritableRaster
final WritableRaster raster = imageRaster.createWritableChild(0, 0,
width,
height,
0, 0,
destinationBands);
// set up to read the data
final int[] intData = ((DataBufferInt)raster.getDataBuffer()).getData(); // CHECK: is this valid / acceptible?
int index = 0; // the index in the intData array
int runLength = 0; // the number of pixels in a run length
boolean readPixel = true; // if true then a raw pixel is read. Used by the RLE.
boolean isRaw = false; // if true then the next pixels should be read. Used by the RLE.
int pixel = 0; // the current pixel data
// TODO: break out the case of 32 bit non-RLE as it can be read
// directly and 24 bit non-RLE as it can be read simply. If
// subsampling and ROI's are implemented then selection must be
// done per pixel for RLE otherwise it's possible to miss the
// repetition count field.
// TODO: account for TGAHeader.firstColorMapEntryIndex
// loop over the rows
// TODO: this should be destinationROI.height (right?)
for(int y=0; y<height; y++)
{
// if the image is flipped top-to-bottom then set the index in
// intData appropriately
if(header.isBottomToTop())
//index = y;
index = (height - y) - 1;
else /* is top-to-bottom */
index = y;
//index = (height - y) - 1;
// account for the width
// TODO: this doesn't take into account the destination size or bands
index *= width;
// loop over the columns
// TODO: this should be destinationROI.width (right?)
// NOTE: *if* destinations are used the RLE will break as this will
// cause the repetition count field to be missed.
for(int x=0; x<width; x++)
{
// if the image is compressed (run length encoded) then determine
// if a pixel should be read or if the current one should be
// used (using the current one is part of the RLE'ing).
if(header.isCompressed())
{
// if there is a non-zero run length then there are still
// compressed pixels
if(runLength > 0)
{
// decrement the run length and flag that a pixel should
// not be read
// NOTE: a pixel is only read from the input if the
// packet was raw. If it was a run length packet
// then the previous (current) pixel is used.
runLength--;
readPixel = isRaw;
} else /* non-positive run length */
{
// read the repetition count field
runLength = inputStream.readByte() & 0xFF; // unsigned
// determine which packet type: raw or runlength
isRaw = ( (runLength & 0x80) == 0); // bit 7 == 0 -> raw; bit 7 == 1 -> runlength
// if a run length packet then shift to get the number
if(!isRaw)
runLength -= 0x80;
/* else -- is raw so there's no need to shift */
// the next field is always read (it's the pixel data)
readPixel = true;
}
}
// read the next pixel
// NOTE: only don't read when in a run length packet
if(readPixel)
{
// NOTE: the alpha must hav a default value since it is
// not guaranteed to be present for each pixel read
int red = 0, green = 0, blue = 0, alpha = 0xFF;
// read based on the number of bits per pixel
switch(header.getBitsPerPixel())
{
// grey scale (R = G = B)
case 8:
default:
{
// read the data -- it is either the color map index
// or the color for each pixel
final int data = inputStream.readByte() & 0xFF; // unsigned
// if the image is a color mapped image then the
// resulting pixel is pulled from the color map,
// otherwise each pixel gets the data
if(header.hasColorMap())
{
// the pixel is pulled from the color map
// CHECK: do sanity bounds check?
pixel = colorMap[data];
} else /* no color map */
{
// each color component is set to the color
red = green = blue = data;
// combine each component into the result
pixel = (red << 0) | (green << 8) | (blue << 16);
}
break;
}
// 5-5-5 (RGB)
case 15:
case 16:
{
// read the two bytes
final int data = inputStream.readShort() & 0xFFFF; // unsigned
// get each color component -- each is 5 bits
red = ((data >> 10) & 0x1F) << 3;
green = ((data >> 5) & 0x1F) << 3;
blue = (data & 0x1F) << 3;
// combine each component into the result
pixel = (red << 0) | (green << 8) | (blue << 16);
break;
}
// true color RGB(A) (8 bits per pixel)
case 24:
case 32:
// read each color component -- the alpha is only
// read if there are 32 bits per pixel
blue = inputStream.readByte() & 0xFF; // unsigned
green = inputStream.readByte() & 0xFF; // unsigned
red = inputStream.readByte() & 0xFF; // unsigned
if(header.getBitsPerPixel() == 32)
alpha = (inputStream.readByte() & 0xFF); // unsigned
/* else -- 24 bits per pixel (i.e. no alpha) */
// combine each component into the result
pixel = (red << 0) | (green << 8) | (blue << 16) | (alpha << 24);
break;
}
}
// put the pixel in the data array
intData[index] = pixel;
// advance to the next pixel
// TODO: the right-to-left switch
index++;
}
}
return image;
}
/**
* <p>Reads and returns an array of color mapped values. If the image does
* not contain a color map <code>null</code> will be returned</p>
*
* @param header the <code>TGAHeader</code> for the image
* @return the array of <code>int</code> color map values or <code>null</code>
* if the image does not contain a color map
* @throws IOException if there is an I/O error while reading the color map
*/
private int[] readColorMap(final TGAHeader header)
throws IOException
{
// determine if the image contains a color map. If not, return null
if(!header.hasColorMap())
return null;
/* else -- there is a color map */
// seek to the start of the color map in the input stream
inputStream.seek(header.getColorMapDataOffset());
// get the number of colros in the color map and the number of bits
// per color map entry
final int numberOfColors = header.getColorMapLength();
final int bitsPerEntry = header.getBitsPerColorMapEntry();
// create the array that will contain the color map data
// CHECK: why is tge explicit +1 needed here ?!?
final int[] colorMap = new int[numberOfColors + 1];
// read each color map entry
for(int i=0; i<numberOfColors; i++)
{
int red = 0, green = 0, blue = 0;
// read based on the number of bits per color map entry
switch(bitsPerEntry)
{
// grey scale (R = G = B)
case 8:
default:
{
final int data = inputStream.readByte() & 0xFF; // unsigned
red = green = blue = data;
break;
}
// 5-5-5 (RGB)
case 15:
case 16:
{
// read the two bytes
final int data = inputStream.readShort() & 0xFFFF; // unsigned
// get each color component -- each is 5 bits
red = ((data >> 10) & 0x1F) << 3;
green = ((data >> 5) & 0x1F) << 3;
blue = (data & 0x1F) << 3;
break;
}
// true color RGB(A) (8 bits per pixel)
case 24:
case 32:
// read each color component
// CHECK: is there an alpha?!?
blue = inputStream.readByte() & 0xFF; // unsigned
green = inputStream.readByte() & 0xFF; // unsigned
red = inputStream.readByte() & 0xFF; // unsigned
break;
}
// combine each component into the result
colorMap[i] = (red << 0) | (green << 8) | (blue << 16);
}
return colorMap;
}
/**
* <p>Validate that the specified {@link javax.imageio.ImageReadParam}
* contains only the default values. If non-default values are present,
* {@link java.io.IOException} is thrown.</p>
*
* @param param the <code>ImageReadParam</code> to be validated
* @param head the <code>TGAHeader</code> that contains information about
* the source image
* @throws IOException if the <code>ImageReadParam</code> contains non-default
* values
*/
private void checkImageReadParam(final ImageReadParam param,
final TGAHeader header)
throws IOException
{
if(param != null)
{
// get the image height and width from the header for convenience
final int width = header.getWidth();
final int height = header.getHeight();
// ensure that the param contains only the defaults
final Rectangle sourceROI = param.getSourceRegion();
if( (sourceROI != null) &&
( (sourceROI.x != 0) || (sourceROI.y != 0) ||
(sourceROI.width != width) || (sourceROI.height != height) ) )
{
throw new IOException("The source region of interest is not the default."); // FIXME: localize
} /* else -- the source ROI is the default */
final Rectangle destinationROI = param.getSourceRegion();
if( (destinationROI != null) &&
( (destinationROI.x != 0) || (destinationROI.y != 0) ||
(destinationROI.width != width) || (destinationROI.height != height) ) )
{
throw new IOException("The destination region of interest is not the default."); // FIXME: localize
} /* else -- the destination ROI is the default */
if( (param.getSourceXSubsampling() != 1) ||
(param.getSourceYSubsampling() != 1) )
{
throw new IOException("Source sub-sampling is not supported."); // FIXME: localize
} /* else -- sub-sampling is the default */
} /* else -- the ImageReadParam is null so the defaults *are* used */
}
}
// =============================================================================
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/

View File

@@ -0,0 +1,227 @@
package com.realityinteractive.imageio.tga;
/*
* TGAImageReaderSpi.java
* Copyright (c) 2003 Reality Interactive, Inc.
* See bottom of file for license and warranty information.
* Created on Sep 26, 2003
*/
import java.io.IOException;
import java.util.Locale;
import javax.imageio.ImageReader;
import javax.imageio.spi.ImageReaderSpi;
import javax.imageio.stream.ImageInputStream;
/**
* <p>A service provider for reading TGA images. Only {@link javax.imageio.stream.ImageInputStream}
* input types are allowed. See {@link com.realityinteractive.imageio.tga.TGAImageReader}
* for supported features.</p>
*
* @author Rob Grzywinski <a href="mailto:rgrzywinski@realityinteractive.com">rgrzywinski@realityinteractive.com</a>
* @version $Id: TGAImageReaderSpi.java,v 1.1 2005/04/12 11:23:53 ornedan Exp $
* @since 1.0
*/
public class TGAImageReaderSpi extends ImageReaderSpi
{
// =========================================================================
// NOTE: these should be package (default protected) as it is used
// frequently elsewhere
/**
* <p>The vendor name: Reality Interactive, Inc.</p>
*/
static final String VENDOR_NAME = "Reality Interactive, Inc.";
/**
* <p>The plugin version number.</p>
*/
static final String VERSION = "1.00";
/**
* <p>The class name for the TGA image reader.</p>
*/
static final String READER_CLASSNAME =
"com.realityinteractive.imageio.tga.TGAImageReader";
/**
* <p>The format names.</p>
*/
static final String[] FORMAT_NAMES = { "tga", "targa" };
/**
* <p>The canonical suffix names.</p>
*/
static final String[] SUFFIXES = { "tga", "targa" };
/**
* <p>The supported mime types.</p>
*/
static final String[] MIME_TYPES =
{ "application/tga", "application/x-tga", "application/x-targa",
"image/tga", "image/x-tga", "image/targa", "image/x-targa" };
/**
* <p>This is a read-only TGA plugin.</p>
*/
static final String[] WRITER_SPI_CLASSNAMES = null;
/**
* <p>The standard stream metadata format is not supported.</p>
*/
static final boolean SUPPORTS_STANDARD_STREAM_METADATA_FORMAT = false;
/**
* <p>There is no "native" stream metadata formats supported by the TGA
* plugin.</p>
*/
static final String NATIVE_STREAM_METADATA_FORMAT_NAME = null;
/**
* <p>There is no "native" stream metadata formats supported by the TGA
* plugin.</p>
*/
static final String NATIVE_STREAM_METADATA_FORMAT_CLASSNAME = null;
/**
* <p>There are no stream metadata formats other than the standard.</p>
*/
static final String[] EXTRA_STREAM_METADATA_FORMAT_NAMES = null;
/**
* <p>There are no stream metadata formats other than the standard.</p>
*/
static final String[] EXTRA_STREAM_METADATA_FORMAT_CLASSNAMES = null;
/**
* <p>The standard image metadata format is not supported.</p>
*/
static final boolean SUPPORTS_STANDARD_IMAGE_METADATA_FORMAT = false;
/**
* <p>There are no "native" image metadata formats supported by the TGA
* plugin.</p>
*/
static final String NATIVE_IMAGE_METADATA_FORMAT_NAME = null;
/**
* <p>There are no "native" image metadata formats supported by the TGA
* plugin.</p>
*/
static final String NATIVE_IMAGE_METADATA_FORMAT_CLASSNAME = null;
/**
* <p>There are no image metadata formats supported other than the standard.</p>
*/
static final String[] EXTRA_IMAGE_METADATA_FORMAT_NAMES = null;
/**
* <p>There are no image metadata formats supported other than the standard.</p>
*/
static final String[] EXTRA_IMAGE_METADATA_FORMAT_CLASSNAMES = null;
// =========================================================================
/**
* <p>Constructs an {@link javax.imageio.spi.ImageReaderSpi} that accepts
* {@link javax.imageio.stream.ImageInputStream} as its input type.</p>
*
* @see javax.imageio.spi.ImageReaderSpi#ImageReaderSpi()
*/
public TGAImageReaderSpi()
{
super(VENDOR_NAME, VERSION, FORMAT_NAMES, SUFFIXES, MIME_TYPES,
READER_CLASSNAME,
ImageReaderSpi.STANDARD_INPUT_TYPE,
WRITER_SPI_CLASSNAMES,
SUPPORTS_STANDARD_STREAM_METADATA_FORMAT,
NATIVE_STREAM_METADATA_FORMAT_NAME,
NATIVE_STREAM_METADATA_FORMAT_CLASSNAME,
EXTRA_STREAM_METADATA_FORMAT_NAMES,
EXTRA_STREAM_METADATA_FORMAT_CLASSNAMES,
SUPPORTS_STANDARD_IMAGE_METADATA_FORMAT,
NATIVE_IMAGE_METADATA_FORMAT_NAME,
NATIVE_IMAGE_METADATA_FORMAT_CLASSNAME,
EXTRA_IMAGE_METADATA_FORMAT_NAMES,
EXTRA_IMAGE_METADATA_FORMAT_CLASSNAMES);
}
/**
* @see javax.imageio.spi.ImageReaderSpi#canDecodeInput(java.lang.Object)
*/
public boolean canDecodeInput(final Object source)
throws IOException
{
// NOTE: the input source must be left in the same state as it started
// at (mark() and reset() should be used on ImageInputStream)
// ensure that the input type is a ImageInputStream as that is all that
// is supported
if(!(source instanceof ImageInputStream))
return false;
/* else -- source is a ImageInputStream */
// cast to ImageInputStream for convenience
final ImageInputStream inputStream = (ImageInputStream)source;
try
{
// set a mark at the current position so that the stream can be reset
inputStream.mark();
// there's no ideidentifiable header on a TGA file so a punt must
// occur. This will attempt to read the image type and if it is
// not known or allowed then false is returned.
// NOTE: 1.0.0 only supports un/compressed true color
inputStream.readUnsignedByte(); // idLength
inputStream.readUnsignedByte(); // has color map
final int imageType = inputStream.readUnsignedByte();
if( (imageType != TGAConstants.TRUE_COLOR) &&
(imageType != TGAConstants.RLE_TRUE_COLOR) &&
(imageType != TGAConstants.COLOR_MAP) &&
(imageType != TGAConstants.RLE_COLOR_MAP) )
{
return false;
} /* else -- it's *possible* (though not known) that this is a TGA */
return true;
} finally
{
// reset so that the ImageInputStream is put back where it was
inputStream.reset();
}
}
/**
* @see javax.imageio.spi.ImageReaderSpi#createReaderInstance(java.lang.Object)
*/
public ImageReader createReaderInstance(final Object extension)
throws IOException
{
// construct and return an ImageReader using this SPI
return new TGAImageReader(this);
}
/**
* @see javax.imageio.spi.IIOServiceProvider#getDescription(java.util.Locale)
*/
public String getDescription(final Locale locale)
{
return "TGA"; // FIXME: localize
}
}
// =============================================================================
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/