diff options
author | Kenneth Russel <[email protected]> | 2008-08-17 17:28:01 +0000 |
---|---|---|
committer | Kenneth Russel <[email protected]> | 2008-08-17 17:28:01 +0000 |
commit | 51439b65c6ec527345cbe8c08bb539a5b9a17c9b (patch) | |
tree | 8251c925ffcee62bedf9c1338bb12c1386c8c423 /src/classes/com/sun/opengl/util/texture/spi | |
parent | 9aa8828d84fc5f4ab6674268af114e06a6de7c4c (diff) |
Temporarily split some TextureIO-related classes into Java SE and Java
ME versions to be able to compile the majority of the TextureIO
package for Java ME / CDC / FP while waiting for full Java SE 5
classes on devices. Java ME ports have not been tested.
git-svn-id: file:///usr/local/projects/SUN/JOGL/git-svn/svn-server-sync/jogl/branches/JOGL_2_SANDBOX@1758 232f8b59-042b-4e1e-8c03-345bb8c30851
Diffstat (limited to 'src/classes/com/sun/opengl/util/texture/spi')
-rwxr-xr-x | src/classes/com/sun/opengl/util/texture/spi/DDSImage.java.javame_cdc_fp | 890 | ||||
-rwxr-xr-x | src/classes/com/sun/opengl/util/texture/spi/DDSImage.java.javase (renamed from src/classes/com/sun/opengl/util/texture/spi/DDSImage.java) | 0 | ||||
-rwxr-xr-x | src/classes/com/sun/opengl/util/texture/spi/LEDataOutputStream.java | 165 | ||||
-rwxr-xr-x | src/classes/com/sun/opengl/util/texture/spi/TGAImage.java.javame_cdc_fp | 385 | ||||
-rwxr-xr-x | src/classes/com/sun/opengl/util/texture/spi/TGAImage.java.javase (renamed from src/classes/com/sun/opengl/util/texture/spi/TGAImage.java) | 0 |
5 files changed, 1440 insertions, 0 deletions
diff --git a/src/classes/com/sun/opengl/util/texture/spi/DDSImage.java.javame_cdc_fp b/src/classes/com/sun/opengl/util/texture/spi/DDSImage.java.javame_cdc_fp new file mode 100755 index 000000000..de776a2e1 --- /dev/null +++ b/src/classes/com/sun/opengl/util/texture/spi/DDSImage.java.javame_cdc_fp @@ -0,0 +1,890 @@ +/* + * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.sun.opengl.util.texture.spi; + +import java.io.*; +import java.nio.*; + +import javax.media.opengl.*; +import javax.media.opengl.util.*; +import com.sun.opengl.util.io.*; +import com.sun.opengl.util.texture.*; + +/** A reader and writer for DirectDraw Surface (.dds) files, which are + used to describe textures. These files can contain multiple mipmap + levels in one file. This class is currently minimal and does not + support all of the possible file formats. */ + +public class DDSImage { + + /** Simple class describing images and data; does not encapsulate + image format information. User is responsible for transmitting + that information in another way. */ + + public static class ImageInfo { + private ByteBuffer data; + private int width; + private int height; + private boolean isCompressed; + private int compressionFormat; + + public ImageInfo(ByteBuffer data, int width, int height, boolean compressed, int compressionFormat) { + this.data = data; this.width = width; this.height = height; + this.isCompressed = compressed; this.compressionFormat = compressionFormat; + } + public int getWidth() { return width; } + public int getHeight() { return height; } + public ByteBuffer getData() { return data; } + public boolean isCompressed() { return isCompressed; } + public int getCompressionFormat() { + if (!isCompressed()) + throw new RuntimeException("Should not call unless compressed"); + return compressionFormat; + } + } + + private ByteBuffer buf; + private Header header; + + // + // Selected bits in header flags + // + + public static final int DDSD_CAPS = 0x00000001; // Capacities are valid + public static final int DDSD_HEIGHT = 0x00000002; // Height is valid + public static final int DDSD_WIDTH = 0x00000004; // Width is valid + public static final int DDSD_PITCH = 0x00000008; // Pitch is valid + public static final int DDSD_BACKBUFFERCOUNT = 0x00000020; // Back buffer count is valid + public static final int DDSD_ZBUFFERBITDEPTH = 0x00000040; // Z-buffer bit depth is valid (shouldn't be used in DDSURFACEDESC2) + public static final int DDSD_ALPHABITDEPTH = 0x00000080; // Alpha bit depth is valid + public static final int DDSD_LPSURFACE = 0x00000800; // lpSurface is valid + public static final int DDSD_PIXELFORMAT = 0x00001000; // ddpfPixelFormat is valid + public static final int DDSD_MIPMAPCOUNT = 0x00020000; // Mip map count is valid + public static final int DDSD_LINEARSIZE = 0x00080000; // dwLinearSize is valid + public static final int DDSD_DEPTH = 0x00800000; // dwDepth is valid + + public static final int DDPF_ALPHAPIXELS = 0x00000001; // Alpha channel is present + public static final int DDPF_ALPHA = 0x00000002; // Only contains alpha information + public static final int DDPF_FOURCC = 0x00000004; // FourCC code is valid + public static final int DDPF_PALETTEINDEXED4 = 0x00000008; // Surface is 4-bit color indexed + public static final int DDPF_PALETTEINDEXEDTO8 = 0x00000010; // Surface is indexed into a palette which stores indices + // into the destination surface's 8-bit palette + public static final int DDPF_PALETTEINDEXED8 = 0x00000020; // Surface is 8-bit color indexed + public static final int DDPF_RGB = 0x00000040; // RGB data is present + public static final int DDPF_COMPRESSED = 0x00000080; // Surface will accept pixel data in the format specified + // and compress it during the write + public static final int DDPF_RGBTOYUV = 0x00000100; // Surface will accept RGB data and translate it during + // the write to YUV data. The format of the data to be written + // will be contained in the pixel format structure. The DDPF_RGB + // flag will be set. + public static final int DDPF_YUV = 0x00000200; // Pixel format is YUV - YUV data in pixel format struct is valid + public static final int DDPF_ZBUFFER = 0x00000400; // Pixel format is a z buffer only surface + public static final int DDPF_PALETTEINDEXED1 = 0x00000800; // Surface is 1-bit color indexed + public static final int DDPF_PALETTEINDEXED2 = 0x00001000; // Surface is 2-bit color indexed + public static final int DDPF_ZPIXELS = 0x00002000; // Surface contains Z information in the pixels + + // Selected bits in DDS capabilities flags + public static final int DDSCAPS_TEXTURE = 0x00001000; // Can be used as a texture + public static final int DDSCAPS_MIPMAP = 0x00400000; // Is one level of a mip-map + public static final int DDSCAPS_COMPLEX = 0x00000008; // Complex surface structure, such as a cube map + + // Selected bits in DDS extended capabilities flags + public static final int DDSCAPS2_CUBEMAP = 0x00000200; + public static final int DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400; + public static final int DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800; + public static final int DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000; + public static final int DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000; + public static final int DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000; + public static final int DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000; + + // Known pixel formats + public static final int D3DFMT_UNKNOWN = 0; + public static final int D3DFMT_R8G8B8 = 20; + public static final int D3DFMT_A8R8G8B8 = 21; + public static final int D3DFMT_X8R8G8B8 = 22; + // The following are also valid FourCC codes + public static final int D3DFMT_DXT1 = 0x31545844; + public static final int D3DFMT_DXT2 = 0x32545844; + public static final int D3DFMT_DXT3 = 0x33545844; + public static final int D3DFMT_DXT4 = 0x34545844; + public static final int D3DFMT_DXT5 = 0x35545844; + + /** Reads a DirectDraw surface from the specified file name, + returning the resulting DDSImage. + + @param filename File name + @return DDS image object + @throws java.io.IOException if an I/O exception occurred + */ + public static DDSImage read(String filename) throws IOException { + return read(new File(filename)); + } + + /** Reads a DirectDraw surface from the specified file, returning + the resulting DDSImage. + + @param file File object + @return DDS image object + @throws java.io.IOException if an I/O exception occurred + */ + public static DDSImage read(File file) throws IOException { + DDSImage image = new DDSImage(); + image.readFromFile(file); + return image; + } + + /** Reads a DirectDraw surface from the specified InputStream, returning + the resulting DDSImage. + + @param input Input stream + @return DDS image object + @throws java.io.IOException if an I/O exception occurred + */ + public static DDSImage read(InputStream input) throws IOException { + DDSImage image = new DDSImage(); + image.readFromStream(input); + return image; + } + + /** Closes open files and resources associated with the open + DDSImage. No other methods may be called on this object once + this is called. */ + public void close() { + } + + /** + * Creates a new DDSImage from data supplied by the user. The + * resulting DDSImage can be written to disk using the write() + * method. + * + * @param d3dFormat the D3DFMT_ constant describing the data; it is + * assumed that it is packed tightly + * @param width the width in pixels of the topmost mipmap image + * @param height the height in pixels of the topmost mipmap image + * @param mipmapData the data for each mipmap level of the resulting + * DDSImage; either only one mipmap level should + * be specified, or they all must be + * @throws IllegalArgumentException if the data does not match the + * specified arguments + * @return DDS image object + */ + public static DDSImage createFromData(int d3dFormat, + int width, + int height, + ByteBuffer[] mipmapData) throws IllegalArgumentException { + DDSImage image = new DDSImage(); + image.initFromData(d3dFormat, width, height, mipmapData); + return image; + } + + /** Determines from the magic number whether the given InputStream + points to a DDS image. The given InputStream must return true + from markSupported() and support a minimum of four bytes of + read-ahead. + + @param in Stream to check + @return true if input stream is DDS image or false otherwise + @throws java.io.IOException if an I/O exception occurred + */ + public static boolean isDDSImage(InputStream in) throws IOException { + if (!(in instanceof BufferedInputStream)) { + in = new BufferedInputStream(in); + } + if (!in.markSupported()) { + throw new IOException("Can not test non-destructively whether given InputStream is a DDS image"); + } + in.mark(4); + int magic = 0; + for (int i = 0; i < 4; i++) { + int tmp = in.read(); + if (tmp < 0) { + in.reset(); + return false; + } + magic = ((magic >>> 8) | (tmp << 24)); + } + in.reset(); + return (magic == MAGIC); + } + + /** + * Writes this DDSImage to the specified file name. + * @param filename File name to write to + * @throws java.io.IOException if an I/O exception occurred + */ + public void write(String filename) throws IOException { + write(new File(filename)); + } + + /** + * Writes this DDSImage to the specified file name. + * @param file File object to write to + * @throws java.io.IOException if an I/O exception occurred + */ + public void write(File file) throws IOException { + LEDataOutputStream output = + new LEDataOutputStream(new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)))); + header.write(output); + output.write(buf.array()); + output.close(); + } + + /** Test for presence/absence of surface description flags (DDSD_*) + * @param flag DDSD_* flags set to test + * @return true if flag present or false otherwise + */ + public boolean isSurfaceDescFlagSet(int flag) { + return ((header.flags & flag) != 0); + } + + /** Test for presence/absence of pixel format flags (DDPF_*) */ + public boolean isPixelFormatFlagSet(int flag) { + return ((header.pfFlags & flag) != 0); + } + + /** Gets the pixel format of this texture (D3DFMT_*) based on some + heuristics. Returns D3DFMT_UNKNOWN if could not recognize the + pixel format. */ + public int getPixelFormat() { + if (isCompressed()) { + return getCompressionFormat(); + } else if (isPixelFormatFlagSet(DDPF_RGB)) { + if (isPixelFormatFlagSet(DDPF_ALPHAPIXELS)) { + if (getDepth() == 32 && + header.pfRBitMask == 0x00FF0000 && + header.pfGBitMask == 0x0000FF00 && + header.pfBBitMask == 0x000000FF && + header.pfABitMask == 0xFF000000) { + return D3DFMT_A8R8G8B8; + } + } else { + if (getDepth() == 24 && + header.pfRBitMask == 0x00FF0000 && + header.pfGBitMask == 0x0000FF00 && + header.pfBBitMask == 0x000000FF) { + return D3DFMT_R8G8B8; + } else if (getDepth() == 32 && + header.pfRBitMask == 0x00FF0000 && + header.pfGBitMask == 0x0000FF00 && + header.pfBBitMask == 0x000000FF) { + return D3DFMT_X8R8G8B8; + } + } + } + + return D3DFMT_UNKNOWN; + } + + /** + * Indicates whether this texture is cubemap + * @return true if cubemap or false otherwise + */ + public boolean isCubemap() { + return ((header.ddsCaps1 & DDSCAPS_COMPLEX) != 0) && ((header.ddsCaps2 & DDSCAPS2_CUBEMAP) != 0); + } + + /** + * Indicates whethe this cubemap side present + * @param side Side to test + * @return true if side present or false otherwise + */ + public boolean isCubemapSidePresent(int side) { + return isCubemap() && (header.ddsCaps2 & side) != 0; + } + + /** Indicates whether this texture is compressed. */ + public boolean isCompressed() { + return (isPixelFormatFlagSet(DDPF_FOURCC)); + } + + /** If this surface is compressed, returns the kind of compression + used (DXT1..DXT5). */ + public int getCompressionFormat() { + return header.pfFourCC; + } + + /** Width of the texture (or the top-most mipmap if mipmaps are + present) */ + public int getWidth() { + return header.width; + } + + /** Height of the texture (or the top-most mipmap if mipmaps are + present) */ + public int getHeight() { + return header.height; + } + + /** Total number of bits per pixel. Only valid if DDPF_RGB is + present. For A8R8G8B8, would be 32. */ + public int getDepth() { + return header.pfRGBBitCount; + } + + /** Number of mip maps in the texture */ + public int getNumMipMaps() { + if (!isSurfaceDescFlagSet(DDSD_MIPMAPCOUNT)) { + return 0; + } + return header.mipMapCountOrAux; + } + + /** Gets the <i>i</i>th mipmap data (0..getNumMipMaps() - 1) + * @param map Mipmap index + * @return Image object + */ + public ImageInfo getMipMap(int map) { + return getMipMap( 0, map ); + } + + /** + * Gets the <i>i</i>th mipmap data (0..getNumMipMaps() - 1) + * @param side Cubemap side or 0 for 2D texture + * @param map Mipmap index + * @return Image object + */ + public ImageInfo getMipMap(int side, int map) { + if (!isCubemap() && (side != 0)) { + throw new RuntimeException( "Illegal side for 2D texture: " + side ); + } + if (isCubemap() && !isCubemapSidePresent(side)) { + throw new RuntimeException( "Illegal side, side not present: " + side ); + } + if (getNumMipMaps() > 0 && + ((map < 0) || (map >= getNumMipMaps()))) { + throw new RuntimeException("Illegal mipmap number " + map + " (0.." + (getNumMipMaps() - 1) + ")"); + } + + // Figure out how far to seek + int seek = 0; + if (isCubemap()) { + seek += sideShiftInBytes(side); + } + for (int i = 0; i < map; i++) { + seek += mipMapSizeInBytes(i); + } + buf.limit(seek + mipMapSizeInBytes(map)); + buf.position(seek); + ByteBuffer next = buf.slice(); + buf.position(0); + buf.limit(buf.capacity()); + return new ImageInfo(next, mipMapWidth(map), mipMapHeight(map), isCompressed(), getCompressionFormat()); + } + + /** Returns an array of ImageInfos corresponding to all mipmap + levels of this DDS file. + @return Mipmap image objects set + */ + public ImageInfo[] getAllMipMaps() { + return getAllMipMaps(0); + } + + /** + * Returns an array of ImageInfos corresponding to all mipmap + * levels of this DDS file. + * @param side Cubemap side or 0 for 2D texture + * @return Mipmap image objects set + */ + public ImageInfo[] getAllMipMaps( int side ) { + int numLevels = getNumMipMaps(); + if (numLevels == 0) { + numLevels = 1; + } + ImageInfo[] result = new ImageInfo[numLevels]; + for (int i = 0; i < numLevels; i++) { + result[i] = getMipMap(side, i); + } + return result; + } + + /** Converts e.g. DXT1 compression format constant (see {@link + #getCompressionFormat}) into "DXT1". + @param compressionFormat Compression format constant + @return String format code + */ + public static String getCompressionFormatName(int compressionFormat) { + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < 4; i++) { + char c = (char) (compressionFormat & 0xFF); + buf.append(c); + compressionFormat = compressionFormat >> 8; + } + return buf.toString(); + } + + /** Allocates a temporary, empty ByteBuffer suitable for use in a + call to glCompressedTexImage2D. This is used by the Texture + class to expand non-power-of-two DDS compressed textures to + power-of-two sizes on hardware not supporting OpenGL 2.0 and the + NPOT texture extension. The specified OpenGL internal format + must be one of GL_COMPRESSED_RGB_S3TC_DXT1_EXT, + GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, + GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, or + GL_COMPRESSED_RGBA_S3TC_DXT5_EXT. + */ + public static ByteBuffer allocateBlankBuffer(int width, + int height, + int openGLInternalFormat) { + int size = width * height; + switch (openGLInternalFormat) { + case GL.GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL.GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + size /= 2; + break; + + case GL.GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + case GL.GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + break; + + default: + throw new IllegalArgumentException("Illegal OpenGL texture internal format " + + openGLInternalFormat); + } + if (size == 0) + size = 1; + return BufferUtil.newByteBuffer(size); + } + + public void debugPrint() { + PrintStream tty = System.err; + tty.println("Compressed texture: " + isCompressed()); + if (isCompressed()) { + int fmt = getCompressionFormat(); + String name = getCompressionFormatName(fmt); + tty.println("Compression format: 0x" + Integer.toHexString(fmt) + " (" + name + ")"); + } + tty.println("Width: " + header.width + " Height: " + header.height); + tty.println("header.pitchOrLinearSize: " + header.pitchOrLinearSize); + tty.println("header.pfRBitMask: 0x" + Integer.toHexString(header.pfRBitMask)); + tty.println("header.pfGBitMask: 0x" + Integer.toHexString(header.pfGBitMask)); + tty.println("header.pfBBitMask: 0x" + Integer.toHexString(header.pfBBitMask)); + tty.println("SurfaceDesc flags:"); + boolean recognizedAny = false; + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_CAPS, "DDSD_CAPS"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_HEIGHT, "DDSD_HEIGHT"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_WIDTH, "DDSD_WIDTH"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_PITCH, "DDSD_PITCH"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_BACKBUFFERCOUNT, "DDSD_BACKBUFFERCOUNT"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_ZBUFFERBITDEPTH, "DDSD_ZBUFFERBITDEPTH"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_ALPHABITDEPTH, "DDSD_ALPHABITDEPTH"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_LPSURFACE, "DDSD_LPSURFACE"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_PIXELFORMAT, "DDSD_PIXELFORMAT"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_MIPMAPCOUNT, "DDSD_MIPMAPCOUNT"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_LINEARSIZE, "DDSD_LINEARSIZE"); + recognizedAny |= printIfRecognized(tty, header.flags, DDSD_DEPTH, "DDSD_DEPTH"); + if (!recognizedAny) { + tty.println("(none)"); + } + tty.println("Raw SurfaceDesc flags: 0x" + Integer.toHexString(header.flags)); + tty.println("Pixel format flags:"); + recognizedAny = false; + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_ALPHAPIXELS, "DDPF_ALPHAPIXELS"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_ALPHA, "DDPF_ALPHA"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_FOURCC, "DDPF_FOURCC"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_PALETTEINDEXED4, "DDPF_PALETTEINDEXED4"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_PALETTEINDEXEDTO8, "DDPF_PALETTEINDEXEDTO8"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_PALETTEINDEXED8, "DDPF_PALETTEINDEXED8"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_RGB, "DDPF_RGB"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_COMPRESSED, "DDPF_COMPRESSED"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_RGBTOYUV, "DDPF_RGBTOYUV"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_YUV, "DDPF_YUV"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_ZBUFFER, "DDPF_ZBUFFER"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_PALETTEINDEXED1, "DDPF_PALETTEINDEXED1"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_PALETTEINDEXED2, "DDPF_PALETTEINDEXED2"); + recognizedAny |= printIfRecognized(tty, header.pfFlags, DDPF_ZPIXELS, "DDPF_ZPIXELS"); + if (!recognizedAny) { + tty.println("(none)"); + } + tty.println("Raw pixel format flags: 0x" + Integer.toHexString(header.pfFlags)); + tty.println("Depth: " + getDepth()); + tty.println("Number of mip maps: " + getNumMipMaps()); + int fmt = getPixelFormat(); + tty.print("Pixel format: "); + switch (fmt) { + case D3DFMT_R8G8B8: tty.println("D3DFMT_R8G8B8"); break; + case D3DFMT_A8R8G8B8: tty.println("D3DFMT_A8R8G8B8"); break; + case D3DFMT_X8R8G8B8: tty.println("D3DFMT_X8R8G8B8"); break; + case D3DFMT_DXT1: tty.println("D3DFMT_DXT1"); break; + case D3DFMT_DXT2: tty.println("D3DFMT_DXT2"); break; + case D3DFMT_DXT3: tty.println("D3DFMT_DXT3"); break; + case D3DFMT_DXT4: tty.println("D3DFMT_DXT4"); break; + case D3DFMT_DXT5: tty.println("D3DFMT_DXT5"); break; + case D3DFMT_UNKNOWN: tty.println("D3DFMT_UNKNOWN"); break; + default: tty.println("(unknown pixel format " + fmt + ")"); break; + } + } + + //---------------------------------------------------------------------- + // Internals only below this point + // + + private static final int MAGIC = 0x20534444; + + static class Header { + int size; // size of the DDSURFACEDESC structure + int flags; // determines what fields are valid + int height; // height of surface to be created + int width; // width of input surface + int pitchOrLinearSize; + int backBufferCountOrDepth; + int mipMapCountOrAux; // number of mip-map levels requested (in this context) + int alphaBitDepth; // depth of alpha buffer requested + int reserved1; // reserved + int surface; // pointer to the associated surface memory + // NOTE: following two entries are from DDCOLORKEY data structure + // Are overlaid with color for empty cubemap faces (unused in this reader) + int colorSpaceLowValue; + int colorSpaceHighValue; + int destBltColorSpaceLowValue; + int destBltColorSpaceHighValue; + int srcOverlayColorSpaceLowValue; + int srcOverlayColorSpaceHighValue; + int srcBltColorSpaceLowValue; + int srcBltColorSpaceHighValue; + // NOTE: following entries are from DDPIXELFORMAT data structure + // Are overlaid with flexible vertex format description of vertex + // buffers (unused in this reader) + int pfSize; // size of DDPIXELFORMAT structure + int pfFlags; // pixel format flags + int pfFourCC; // (FOURCC code) + // Following five entries have multiple interpretations, not just + // RGBA (but that's all we support right now) + int pfRGBBitCount; // how many bits per pixel + int pfRBitMask; // mask for red bits + int pfGBitMask; // mask for green bits + int pfBBitMask; // mask for blue bits + int pfABitMask; // mask for alpha channel + int ddsCaps1; // Texture and mip-map flags + int ddsCaps2; // Advanced capabilities including cubemap support + int ddsCapsReserved1; + int ddsCapsReserved2; + int textureStage; // stage in multitexture cascade + + void read(LEDataInputStream input) throws IOException { + int magic = input.readInt(); + if (magic != MAGIC) { + throw new IOException("Incorrect magic number 0x" + + Integer.toHexString(magic) + + " (expected " + MAGIC + ")"); + } + + size = input.readInt(); + flags = input.readInt(); + height = input.readInt(); + width = input.readInt(); + pitchOrLinearSize = input.readInt(); + backBufferCountOrDepth = input.readInt(); + mipMapCountOrAux = input.readInt(); + alphaBitDepth = input.readInt(); + reserved1 = input.readInt(); + surface = input.readInt(); + colorSpaceLowValue = input.readInt(); + colorSpaceHighValue = input.readInt(); + destBltColorSpaceLowValue = input.readInt(); + destBltColorSpaceHighValue = input.readInt(); + srcOverlayColorSpaceLowValue = input.readInt(); + srcOverlayColorSpaceHighValue = input.readInt(); + srcBltColorSpaceLowValue = input.readInt(); + srcBltColorSpaceHighValue = input.readInt(); + pfSize = input.readInt(); + pfFlags = input.readInt(); + pfFourCC = input.readInt(); + pfRGBBitCount = input.readInt(); + pfRBitMask = input.readInt(); + pfGBitMask = input.readInt(); + pfBBitMask = input.readInt(); + pfABitMask = input.readInt(); + ddsCaps1 = input.readInt(); + ddsCaps2 = input.readInt(); + ddsCapsReserved1 = input.readInt(); + ddsCapsReserved2 = input.readInt(); + textureStage = input.readInt(); + } + + // buf must be in little-endian byte order + void write(LEDataOutputStream output) throws IOException { + output.writeInt(MAGIC); + output.writeInt(size); + output.writeInt(flags); + output.writeInt(height); + output.writeInt(width); + output.writeInt(pitchOrLinearSize); + output.writeInt(backBufferCountOrDepth); + output.writeInt(mipMapCountOrAux); + output.writeInt(alphaBitDepth); + output.writeInt(reserved1); + output.writeInt(surface); + output.writeInt(colorSpaceLowValue); + output.writeInt(colorSpaceHighValue); + output.writeInt(destBltColorSpaceLowValue); + output.writeInt(destBltColorSpaceHighValue); + output.writeInt(srcOverlayColorSpaceLowValue); + output.writeInt(srcOverlayColorSpaceHighValue); + output.writeInt(srcBltColorSpaceLowValue); + output.writeInt(srcBltColorSpaceHighValue); + output.writeInt(pfSize); + output.writeInt(pfFlags); + output.writeInt(pfFourCC); + output.writeInt(pfRGBBitCount); + output.writeInt(pfRBitMask); + output.writeInt(pfGBitMask); + output.writeInt(pfBBitMask); + output.writeInt(pfABitMask); + output.writeInt(ddsCaps1); + output.writeInt(ddsCaps2); + output.writeInt(ddsCapsReserved1); + output.writeInt(ddsCapsReserved2); + output.writeInt(textureStage); + } + + private static int size() { + return 124; + } + + private static int pfSize() { + return 32; + } + + private static int writtenSize() { + return 128; + } + } + + private DDSImage() { + } + + private void readFromFile(File file) throws IOException { + readFromStream(new BufferedInputStream(new FileInputStream(file))); + } + + private void readFromStream(InputStream input) throws IOException { + LEDataInputStream leInput = new LEDataInputStream(input); + header = new Header(); + header.read(leInput); + fixupHeader(); + buf = ByteBuffer.wrap(StreamUtil.readAll(input)); + } + + private void initFromData(int d3dFormat, + int width, + int height, + ByteBuffer[] mipmapData) throws IllegalArgumentException { + // Check size of mipmap data compared against format, width and + // height + int topmostMipmapSize = width * height; + int pitchOrLinearSize = width; + boolean isCompressed = false; + switch (d3dFormat) { + case D3DFMT_R8G8B8: topmostMipmapSize *= 3; pitchOrLinearSize *= 3; break; + case D3DFMT_A8R8G8B8: topmostMipmapSize *= 4; pitchOrLinearSize *= 4; break; + case D3DFMT_X8R8G8B8: topmostMipmapSize *= 4; pitchOrLinearSize *= 4; break; + case D3DFMT_DXT1: + case D3DFMT_DXT2: + case D3DFMT_DXT3: + case D3DFMT_DXT4: + case D3DFMT_DXT5: + topmostMipmapSize = computeCompressedBlockSize(width, height, 1, d3dFormat); + pitchOrLinearSize = topmostMipmapSize; + isCompressed = true; + break; + default: + throw new IllegalArgumentException("d3dFormat must be one of the known formats"); + } + + // Now check the mipmaps against this size + int curSize = topmostMipmapSize; + int totalSize = 0; + for (int i = 0; i < mipmapData.length; i++) { + if (mipmapData[i].remaining() != curSize) { + throw new IllegalArgumentException("Mipmap level " + i + + " didn't match expected data size (expected " + curSize + ", got " + + mipmapData[i].remaining() + ")"); + } + curSize /= 4; + totalSize += mipmapData[i].remaining(); + } + + // OK, create one large byte array to hold all of the mipmap data + byte[] data = new byte[totalSize]; + ByteBuffer buf = ByteBuffer.wrap(data); + for (int i = 0; i < mipmapData.length; i++) { + buf.put(mipmapData[i]); + } + this.buf = buf; + + // Allocate and initialize a Header + header = new Header(); + header.size = Header.size(); + header.flags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; + if (mipmapData.length > 1) { + header.flags |= DDSD_MIPMAPCOUNT; + header.mipMapCountOrAux = mipmapData.length; + } + header.width = width; + header.height = height; + if (isCompressed) { + header.flags |= DDSD_LINEARSIZE; + header.pfFlags |= DDPF_FOURCC; + header.pfFourCC = d3dFormat; + } else { + header.flags |= DDSD_PITCH; + // Figure out the various settings from the pixel format + header.pfFlags |= DDPF_RGB; + switch (d3dFormat) { + case D3DFMT_R8G8B8: header.pfRGBBitCount = 24; break; + case D3DFMT_A8R8G8B8: header.pfRGBBitCount = 32; header.pfFlags |= DDPF_ALPHAPIXELS; break; + case D3DFMT_X8R8G8B8: header.pfRGBBitCount = 32; break; + } + header.pfRBitMask = 0x00FF0000; + header.pfGBitMask = 0x0000FF00; + header.pfBBitMask = 0x000000FF; + if (d3dFormat == D3DFMT_A8R8G8B8) { + header.pfABitMask = 0xFF000000; + } + } + header.pitchOrLinearSize = pitchOrLinearSize; + header.pfSize = Header.pfSize(); + // Not sure whether we can get away with leaving the rest of the + // header blank + } + + // Microsoft doesn't follow their own specifications and the + // simplest conversion using the DxTex tool to e.g. a DXT3 texture + // results in an illegal .dds file without either DDSD_PITCH or + // DDSD_LINEARSIZE set in the header's flags. This code, adapted + // from the DevIL library, fixes up the header in these situations. + private void fixupHeader() { + if (isCompressed() && !isSurfaceDescFlagSet(DDSD_LINEARSIZE)) { + // Figure out how big the linear size should be + int depth = header.backBufferCountOrDepth; + if (depth == 0) { + depth = 1; + } + + header.pitchOrLinearSize = computeCompressedBlockSize(getWidth(), getHeight(), depth, getCompressionFormat()); + header.flags |= DDSD_LINEARSIZE; + } + } + + private static int computeCompressedBlockSize(int width, + int height, + int depth, + int compressionFormat) { + int blockSize = ((width + 3)/4) * ((height + 3)/4) * ((depth + 3)/4); + switch (compressionFormat) { + case D3DFMT_DXT1: blockSize *= 8; break; + default: blockSize *= 16; break; + } + return blockSize; + } + + private int mipMapWidth(int map) { + int width = getWidth(); + for (int i = 0; i < map; i++) { + width >>= 1; + } + return Math.max(width, 1); + } + + private int mipMapHeight(int map) { + int height = getHeight(); + for (int i = 0; i < map; i++) { + height >>= 1; + } + return Math.max(height, 1); + } + + private int mipMapSizeInBytes(int map) { + int width = mipMapWidth(map); + int height = mipMapHeight(map); + if (isCompressed()) { + int blockSize = (getCompressionFormat() == D3DFMT_DXT1 ? 8 : 16); + return ((width+3)/4)*((height+3)/4)*blockSize; + } else { + return width * height * (getDepth() / 8); + } + } + + private int sideSizeInBytes() { + int numLevels = getNumMipMaps(); + if (numLevels == 0) { + numLevels = 1; + } + + int size = 0; + for (int i = 0; i < numLevels; i++) { + size += mipMapSizeInBytes(i); + } + + return size; + } + + private int sideShiftInBytes(int side) { + int[] sides = { + DDSCAPS2_CUBEMAP_POSITIVEX, + DDSCAPS2_CUBEMAP_NEGATIVEX, + DDSCAPS2_CUBEMAP_POSITIVEY, + DDSCAPS2_CUBEMAP_NEGATIVEY, + DDSCAPS2_CUBEMAP_POSITIVEZ, + DDSCAPS2_CUBEMAP_NEGATIVEZ + }; + + int shift = 0; + int sideSize = sideSizeInBytes(); + for (int i = 0; i < sides.length; i++) { + int temp = sides[i]; + if ((temp & side) != 0) { + return shift; + } + + shift += sideSize; + } + + throw new RuntimeException("Illegal side: " + side); + } + + private boolean printIfRecognized(PrintStream tty, int flags, int flag, String what) { + if ((flags & flag) != 0) { + tty.println(what); + return true; + } + return false; + } +} diff --git a/src/classes/com/sun/opengl/util/texture/spi/DDSImage.java b/src/classes/com/sun/opengl/util/texture/spi/DDSImage.java.javase index cca8dbd2b..cca8dbd2b 100755 --- a/src/classes/com/sun/opengl/util/texture/spi/DDSImage.java +++ b/src/classes/com/sun/opengl/util/texture/spi/DDSImage.java.javase diff --git a/src/classes/com/sun/opengl/util/texture/spi/LEDataOutputStream.java b/src/classes/com/sun/opengl/util/texture/spi/LEDataOutputStream.java new file mode 100755 index 000000000..730ec0dbd --- /dev/null +++ b/src/classes/com/sun/opengl/util/texture/spi/LEDataOutputStream.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.sun.opengl.util.texture.spi; + +import java.io.DataOutput; +import java.io.DataOutputStream; +import java.io.FilterOutputStream; +import java.io.OutputStream; +import java.io.IOException; + +/** + * Little Endian Data Output Stream. + * + * This class implements an output stream filter to allow writing + * of java native datatypes to an output stream which has those + * native datatypes stored in a little endian byte order.<p> + * + * This is the sister class of the DataOutputStream which allows + * for writing of java native datatypes to an output stream with + * the datatypes stored in big endian byte order.<p> + * + * This class implements the minimum required and calls DataOutputStream + * for some of the required methods for DataOutput.<p> + * + * Not all methods are implemented due to lack of immediate requirement + * for that functionality. It is not clear if it is ever going to be + * functionally required to be able to read UTF data in a LittleEndianManner<p> + * + */ +public class LEDataOutputStream extends FilterOutputStream implements DataOutput +{ + /** + * To reuse some of the non endian dependent methods from + * DataOutputStream's methods. + */ + DataOutputStream dataOut; + + public LEDataOutputStream(OutputStream out) + { + super(out); + dataOut = new DataOutputStream(out); + } + + public void close() throws IOException + { + dataOut.close(); // better close as we create it. + // this will close underlying as well. + } + + public synchronized final void write(byte b[]) throws IOException + { + dataOut.write(b, 0, b.length); + } + + public synchronized final void write(byte b[], int off, int len) throws IOException + { + dataOut.write(b, off, len); + } + + public final void write(int b) throws IOException + { + dataOut.write(b); + } + + public final void writeBoolean(boolean v) throws IOException + { + dataOut.writeBoolean(v); + } + + public final void writeByte(int v) throws IOException + { + dataOut.writeByte(v); + } + + /** Don't call this -- not implemented */ + public final void writeBytes(String s) throws IOException + { + throw new UnsupportedOperationException(); + } + + public final void writeChar(int v) throws IOException + { + dataOut.writeChar(((v >> 8) & 0xff) | + ((v & 0xff) << 8)); + } + + /** Don't call this -- not implemented */ + public final void writeChars(String s) throws IOException + { + throw new UnsupportedOperationException(); + } + + public final void writeDouble(double v) throws IOException + { + writeLong(Double.doubleToRawLongBits(v)); + } + + public final void writeFloat(float v) throws IOException + { + writeInt(Float.floatToRawIntBits(v)); + } + + public final void writeInt(int v) throws IOException + { + dataOut.writeInt((v >>> 24) | + ((v >>> 8) & 0xff00) | + ((v << 8) & 0x00ff00) | + (v << 24)); + } + + public final void writeLong(long v) throws IOException + { + writeInt((int) v); + writeInt((int) (v >>> 32)); + } + + public final void writeShort(int v) throws IOException + { + dataOut.writeShort(((v >> 8) & 0xff) | + ((v & 0xff) << 8)); + } + + /** Don't call this -- not implemented */ + public final void writeUTF(String s) throws IOException + { + throw new UnsupportedOperationException(); + } +} diff --git a/src/classes/com/sun/opengl/util/texture/spi/TGAImage.java.javame_cdc_fp b/src/classes/com/sun/opengl/util/texture/spi/TGAImage.java.javame_cdc_fp new file mode 100755 index 000000000..be4ac36d2 --- /dev/null +++ b/src/classes/com/sun/opengl/util/texture/spi/TGAImage.java.javame_cdc_fp @@ -0,0 +1,385 @@ +/* + * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of Sun Microsystems, Inc. or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + * + * You acknowledge that this software is not designed or intended for use + * in the design, construction, operation or maintenance of any nuclear + * facility. + * + * Sun gratefully acknowledges that this software was originally authored + * and developed by Kenneth Bradley Russell and Christopher John Kline. + */ + +package com.sun.opengl.util.texture.spi; + +import java.io.*; +import java.nio.*; +import javax.media.opengl.*; +import com.sun.opengl.util.*; +import com.sun.opengl.util.texture.spi.*; +import com.sun.opengl.util.texture.*; + +/** + * Targa image reader and writer adapted from sources of the <a href = + * "http://java.sun.com/products/jimi/">Jimi</a> image I/O class library. + * + * <P> + * + * Image decoder for image data stored in TGA file format. + * Currently only the original TGA file format is supported. This is + * because the new TGA format has data at the end of the file, getting + * to the end of a file in an InputStream orient environment presents + * several difficulties which are avoided at the moment. + * + * <P> + * + * This is a simple decoder and is only setup to load a single image + * from the input stream + * + * <P> + * + * @author Robin Luiten + * @author Kenneth Russell + * @version $Revision$ + */ + +public class TGAImage { + private Header header; + private int format; + private ByteBuffer data; + + private TGAImage(Header header) { + this.header = header; + } + + /** + * This class reads in all of the TGA image header in addition it also + * reads in the imageID field as it is convenient to handle that here. + * + * @author Robin Luiten + * @version 1.1 + */ + public static class Header { + /** Set of possible file format TGA types */ + public final static int TYPE_NEW = 0; + public final static int TYPE_OLD = 1; + public final static int TYPE_UNK = 2; // cant rewind stream so unknown for now. + + /** Set of possible image types in TGA file */ + public final static int NO_IMAGE = 0; // no image data + public final static int UCOLORMAPPED = 1; // uncompressed color mapped image + public final static int UTRUECOLOR = 2; // uncompressed true color image + public final static int UBLACKWHITE = 3; // uncompressed black and white image + public final static int COLORMAPPED = 9; // compressed color mapped image + public final static int TRUECOLOR = 10; // compressed true color image + public final static int BLACKWHITE = 11; // compressed black and white image + + /** Field image descriptor bitfield values definitions */ + public final static int ID_ATTRIBPERPIXEL = 0xF; + public final static int ID_RIGHTTOLEFT = 0x10; + public final static int ID_TOPTOBOTTOM = 0x20; + public final static int ID_INTERLEAVE = 0xC0; + + /** Field image descriptor / interleave values */ + public final static int I_NOTINTERLEAVED = 0; + public final static int I_TWOWAY = 1; + public final static int I_FOURWAY = 2; + + /** Type of this TGA file format */ + private int tgaType; + + /** initial TGA image data fields */ + private int idLength; // byte value + private int colorMapType; // byte value + private int imageType; // byte value + + /** TGA image colour map fields */ + private int firstEntryIndex; + private int colorMapLength; + private byte colorMapEntrySize; + + /** TGA image specification fields */ + private int xOrigin; + private int yOrigin; + private int width; + private int height; + private byte pixelDepth; + private byte imageDescriptor; + + private byte[] imageIDbuf; + private String imageID; + + // For construction from user data + Header() { + tgaType = TYPE_OLD; // dont try and get footer. + } + + Header(LEDataInputStream in) throws IOException { + int ret; + + tgaType = TYPE_OLD; // dont try and get footer. + + // initial header fields + idLength = in.readUnsignedByte(); + colorMapType = in.readUnsignedByte(); + imageType = in.readUnsignedByte(); + + // color map header fields + firstEntryIndex = in.readUnsignedShort(); + colorMapLength = in.readUnsignedShort(); + colorMapEntrySize = in.readByte(); + + // TGA image specification fields + xOrigin = in.readUnsignedShort(); + yOrigin = in.readUnsignedShort(); + width = in.readUnsignedShort(); + height = in.readUnsignedShort(); + pixelDepth = in.readByte(); + imageDescriptor = in.readByte(); + + if (idLength > 0) { + imageIDbuf = new byte[idLength]; + in.read(imageIDbuf, 0, idLength); + imageID = new String(imageIDbuf, "US-ASCII"); + } + } + + public int tgaType() { return tgaType; } + + /** initial TGA image data fields */ + public int idLength() { return idLength; } + public int colorMapType() { return colorMapType; } + public int imageType() { return imageType; } + + /** TGA image colour map fields */ + public int firstEntryIndex() { return firstEntryIndex; } + public int colorMapLength() { return colorMapLength; } + public byte colorMapEntrySize() { return colorMapEntrySize; } + + /** TGA image specification fields */ + public int xOrigin() { return xOrigin; } + public int yOrigin() { return yOrigin; } + public int width() { return width; } + public int height() { return height; } + public byte pixelDepth() { return pixelDepth; } + public byte imageDescriptor() { return imageDescriptor; } + + /** bitfields in imageDescriptor */ + public byte attribPerPixel() { return (byte)(imageDescriptor & ID_ATTRIBPERPIXEL); } + public boolean rightToLeft() { return ((imageDescriptor & ID_RIGHTTOLEFT) != 0); } + public boolean topToBottom() { return ((imageDescriptor & ID_TOPTOBOTTOM) != 0); } + public byte interleave() { return (byte)((imageDescriptor & ID_INTERLEAVE) >> 6); } + + public byte[] imageIDbuf() { return imageIDbuf; } + public String imageID() { return imageID; } + + public String toString() { + return "TGA Header " + + " id length: " + idLength + + " color map type: "+ colorMapType + + " image type: "+ imageType + + " first entry index: " + firstEntryIndex + + " color map length: " + colorMapLength + + " color map entry size: " + colorMapEntrySize + + " x Origin: " + xOrigin + + " y Origin: " + yOrigin + + " width: "+ width + + " height: "+ height + + " pixel depth: "+ pixelDepth + + " image descriptor: "+ imageDescriptor + + (imageIDbuf == null ? "" : (" ID String: " + imageID)); + } + + public int size() { return 18 + idLength; } + + private void write(LEDataOutputStream output) throws IOException { + output.write(idLength); + output.write(colorMapType); + output.write(imageType); + output.writeShort(firstEntryIndex); + output.writeShort(colorMapLength); + output.write(colorMapEntrySize); + output.writeShort(xOrigin); + output.writeShort(yOrigin); + output.writeShort(width); + output.writeShort(height); + output.write(pixelDepth); + output.write(imageDescriptor); + if (idLength > 0) { + try { + byte[] chars = imageID.getBytes("US-ASCII"); + output.write(chars); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + } + } + + + /** + * Identifies the image type of the tga image data and loads + * it into the JimiImage structure. This was taken from the + * prototype and modified for the new Jimi structure + */ + private void decodeImage(LEDataInputStream dIn) throws IOException { + switch (header.imageType()) { + case Header.UCOLORMAPPED: + throw new IOException("TGADecoder Uncompressed Colormapped images not supported"); + + case Header.UTRUECOLOR: // pixelDepth 15, 16, 24 and 32 + switch (header.pixelDepth) { + case 16: + throw new IOException("TGADecoder Compressed 16-bit True Color images not supported"); + + case 24: + case 32: + decodeRGBImageU24_32(dIn); + break; + } + break; + + case Header.UBLACKWHITE: + throw new IOException("TGADecoder Uncompressed Grayscale images not supported"); + + case Header.COLORMAPPED: + throw new IOException("TGADecoder Compressed Colormapped images not supported"); + + case Header.TRUECOLOR: + throw new IOException("TGADecoder Compressed True Color images not supported"); + + case Header.BLACKWHITE: + throw new IOException("TGADecoder Compressed Grayscale images not supported"); + } + } + + /** + * This assumes that the body is for a 24 bit or 32 bit for a + * RGB or ARGB image respectively. + */ + private void decodeRGBImageU24_32(LEDataInputStream dIn) throws IOException { + int i; // row index + int j; // column index + int y; // output row index + int raw; // index through the raw input buffer + int rawWidth = header.width() * (header.pixelDepth() / 8); + byte[] rawBuf = new byte[rawWidth]; + byte[] tmpData = new byte[rawWidth * header.height()]; + + if (header.pixelDepth() == 24) { + format = GL2.GL_BGR; + } else { + assert header.pixelDepth() == 32; + format = GL2.GL_BGRA; + } + + for (i = 0; i < header.height(); ++i) { + dIn.readFully(rawBuf, 0, rawWidth); + + if (header.topToBottom()) + y = header.height - i - 1; // range 0 to (header.height - 1) + else + y = i; + + System.arraycopy(rawBuf, 0, tmpData, y * rawWidth, rawBuf.length); + } + + data = ByteBuffer.wrap(tmpData); + } + + /** Returns the width of the image. */ + public int getWidth() { return header.width(); } + + /** Returns the height of the image. */ + public int getHeight() { return header.height(); } + + /** Returns the OpenGL format for this texture; e.g. GL.GL_BGR or GL.GL_BGRA. */ + public int getGLFormat() { return format; } + + /** Returns the raw data for this texture in the correct + (bottom-to-top) order for calls to glTexImage2D. */ + public ByteBuffer getData() { return data; } + + /** Reads a Targa image from the specified file. */ + public static TGAImage read(String filename) throws IOException { + return read(new FileInputStream(filename)); + } + + /** Reads a Targa image from the specified InputStream. */ + public static TGAImage read(InputStream in) throws IOException { + LEDataInputStream dIn = new LEDataInputStream(new BufferedInputStream(in)); + + Header header = new Header(dIn); + TGAImage res = new TGAImage(header); + res.decodeImage(dIn); + return res; + } + + /** Writes the image in Targa format to the specified file name. */ + public void write(String filename) throws IOException { + write(new File(filename)); + } + + /** Writes the image in Targa format to the specified file. */ + public void write(File file) throws IOException { + LEDataOutputStream output = + new LEDataOutputStream(new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)))); + header.write(output); + if (!data.isDirect()) { + output.write(data.array()); + } else { + for (int i = 0; i < data.limit(); i++) { + output.write(data.get(i)); + } + } + output.close(); + } + + /** Creates a TGAImage from data supplied by the end user. Shares + data with the passed ByteBuffer. Assumes the data is already in + the correct byte order for writing to disk, i.e., BGR or + BGRA. */ + public static TGAImage createFromData(int width, + int height, + boolean hasAlpha, + boolean topToBottom, + ByteBuffer data) { + Header header = new Header(); + header.imageType = Header.UTRUECOLOR; + header.width = width; + header.height = height; + header.pixelDepth = (byte) (hasAlpha ? 32 : 24); + header.imageDescriptor = (byte) (topToBottom ? Header.ID_TOPTOBOTTOM : 0); + // Note ID not supported + TGAImage ret = new TGAImage(header); + ret.data = data; + return ret; + } +} diff --git a/src/classes/com/sun/opengl/util/texture/spi/TGAImage.java b/src/classes/com/sun/opengl/util/texture/spi/TGAImage.java.javase index 2738536f0..2738536f0 100755 --- a/src/classes/com/sun/opengl/util/texture/spi/TGAImage.java +++ b/src/classes/com/sun/opengl/util/texture/spi/TGAImage.java.javase |