All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jogamp.opengl.util.texture.spi.TGAImage Maven / Gradle / Ivy

There is a newer version: 2.3.2
Show newest version
/*
 * 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.jogamp.opengl.util.texture.spi;

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import javax.media.opengl.*;

import com.jogamp.common.util.IOUtil;

/**
 * Targa image reader and writer adapted from sources of the Jimi image I/O class library.
 *
 * 

* * 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. * *

* * This is a simple decoder and is only setup to load a single image * from the input stream * *

* * @author Robin Luiten * @author Kenneth Russell * @version $Revision: 1768 $ */ public class TGAImage { private Header header; private int format; private int bpp; 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 { 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; } // buf must be in little-endian byte order private void write(ByteBuffer buf) { buf.put((byte) idLength); buf.put((byte) colorMapType); buf.put((byte) imageType); buf.putShort((short) firstEntryIndex); buf.putShort((short) colorMapLength); buf.put((byte) colorMapEntrySize); buf.putShort((short) xOrigin); buf.putShort((short) yOrigin); buf.putShort((short) width); buf.putShort((short) height); buf.put((byte) pixelDepth); buf.put((byte) imageDescriptor); if (idLength > 0) { try { byte[] chars = imageID.getBytes("US-ASCII"); buf.put(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(GLProfile glp, 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(glp, 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: switch (header.pixelDepth) { case 16: throw new IOException("TGADecoder Compressed 16-bit True Color images not supported"); case 24: case 32: decodeRGBImageRLE24_32(glp, dIn); break; } break; 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(GLProfile glp, LEDataInputStream dIn) throws IOException { setupImage24_32(glp); int i; // row index int y; // output row index int rawWidth = header.width() * bpp; byte[] rawBuf = new byte[rawWidth]; byte[] tmpData = new byte[rawWidth * header.height()]; 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); } if(format == GL.GL_RGB || format == GL.GL_RGBA) swapBGR(tmpData, rawWidth, header.height(), bpp); data = ByteBuffer.wrap(tmpData); } /** * This assumes that the body is for a 24 bit or 32 bit for a * RGB or ARGB image respectively. */ private void decodeRGBImageRLE24_32(GLProfile glp, LEDataInputStream dIn) throws IOException { setupImage24_32(glp); byte[] pixel = new byte[bpp]; int rawWidth = header.width() * bpp; byte[] tmpData = new byte[rawWidth * header.height()]; int i = 0, j; int packet, len; while (i < tmpData.length) { packet = dIn.readUnsignedByte(); len = (packet & 0x7F) + 1; if ((packet & 0x80) != 0) { dIn.read(pixel); for (j = 0; j < len; ++j) System.arraycopy(pixel, 0, tmpData, i + j * bpp, bpp); } else dIn.read(tmpData, i, len * bpp); i += bpp * len; } if(format == GL.GL_RGB || format == GL.GL_RGBA) swapBGR(tmpData, rawWidth, header.height(), bpp); data = ByteBuffer.wrap(tmpData); } private void setupImage24_32(GLProfile glp) { bpp = header.pixelDepth / 8; switch (header.pixelDepth) { case 24: format = glp.isGL2GL3() ? GL2GL3.GL_BGR : GL.GL_RGB; break; case 32: boolean useBGRA = glp.isGL2GL3(); if(!useBGRA) { final GLContext ctx = GLContext.getCurrent(); useBGRA = null != ctx && ctx.isTextureFormatBGRA8888Available(); } format = useBGRA ? GL.GL_BGRA : GL.GL_RGBA; break; default: assert false; } } private static void swapBGR(byte[] data, int bWidth, int height, int bpp) { byte r,b; int k; for(int i=0; i





© 2015 - 2024 Weber Informatics LLC | Privacy Policy