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

org.scijava.java3d.utils.geometry.compression.CommandStream Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2007 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, licensed or
 * intended for use in the design, construction, operation or
 * maintenance of any nuclear facility.
 *
 */

package org.scijava.java3d.utils.geometry.compression;

/**
 * This class is used to build the bit-level compression command stream which
 * is the final result of the compression process.  It defines the bit
 * representations of the compression commands and provides a mechanism for
 * the interleaving and forwarding of command headers and bodies required by
 * the geometry compression specification.
 */
class CommandStream {
    // Geometry compression commands.
    static final int SET_NORM     = 0xC0 ;
    static final int SET_COLOR    = 0x80 ;
    static final int VERTEX       = 0x40 ;
    static final int MESH_B_R     = 0x20 ;
    static final int SET_STATE    = 0x18 ;
    static final int SET_TABLE    = 0x10 ;
    static final int V_NO_OP      = 0x01 ;

    // Huffman table indices.
    static final int POSITION_TABLE = 0 ;
    static final int COLOR_TABLE    = 1 ;
    static final int NORMAL_TABLE   = 2 ;

    // The buffer of compressed data and the current offset.
    private byte bytes[] ;
    private int byteOffset ;
    private int bitOffset ;

    // Last command body for header forwarding.
    private long lastBody ;
    private int lastBodyLength ;

    /**
     * Create an empty CommandStream with a default initial size.
     */
    CommandStream() {
	this(65536) ;
    }

    /**
     * Create an empty CommandStream with the given initial size.
     *
     * @param initSize initial capacity of CommandStream in bytes
     */
    CommandStream(int initSize) {
	bytes = new byte[initSize] ;
	clear() ;
    }

    /**
     * Mark the CommandStream as empty so that its storage will be reused.
     */
    void clear() {
	// Initialize the first byte to 0.
	// Subsequent bytes are cleared as they are written.
	bytes[0] = 0 ;

	// Reset the number of valid bits.
	bitOffset = 0 ;
	byteOffset = 0 ;

	// The first command header is always followed by the body of an
	// implicit variable length no-op to start the header-forwarding
	// interleave required by hardware decompressor implementations.  The
	// only necessary bits are 5 bits of length set to zeros to indicate a
	// fill of zero length.
	lastBody = 0 ;
	lastBodyLength = 5 ;
    }

    /**
     * Add a compression command to this instance.

* * A compression command includes an 8-bit header and can range up to 72 * bits in length. The command with the maximum length is a 2-bit color * command with a 6-bit tag in the header, followed by four 16-bit color * components of data.

* * A subcommand is either a position, normal, or color, though in practice * a position subcommand can only be part of a vertex command. Normal and * color subcommands can be parts of separate global normal and color * commands as well as parts of a vertex command.

* * A subcommand includes a 6-bit header. Its length is 2 bits less than * the length of the corresponding command. * * @param header contains compression command header bits, right-justified * within the bits of the int * @param headerLength number of bits in header, either 8 for commands or * 6 for subcommands * @param body contains the body of the compression command, * right-justified within the bits of the long * @param bodyLength number of bits in the body */ void addCommand(int header, int headerLength, long body, int bodyLength) { addByte(header, headerLength) ; addLong(lastBody, lastBodyLength) ; lastBody = body ; lastBodyLength = bodyLength ; } // // Add the rightmost bitCount bits of b to the end of the command stream. // private void addByte(int b, int bitCount) { int bitsEmpty = 8 - bitOffset ; b &= (int)CompressionStreamElement.lengthMask[bitCount] ; if (bitCount <= bitsEmpty) { bytes[byteOffset] |= (b << (bitsEmpty - bitCount)) ; bitOffset += bitCount ; return ; } if (bytes.length == byteOffset + 1) { byte newBytes[] = new byte[bytes.length * 2] ; System.arraycopy(bytes, 0, newBytes, 0, bytes.length) ; bytes = newBytes ; } bitOffset = bitCount - bitsEmpty ; bytes[byteOffset] |= (b >>> bitOffset) ; byteOffset++ ; bytes[byteOffset] = (byte)(b << (8 - bitOffset)) ; } // // Add the rightmost bitCount bits of l to the end of the command stream. // private void addLong(long l, int bitCount) { int byteCount = bitCount / 8 ; int excessBits = bitCount - byteCount * 8 ; if (excessBits > 0) addByte((int)(l >>> (byteCount * 8)), excessBits) ; while (byteCount > 0) { addByte((int)((l >>> ((byteCount - 1) * 8)) & 0xff), 8) ; byteCount-- ; } } /** * Add a no-op and the last command body. Pad out with additional no-ops * to a 64-bit boundary if necessary. A call to this method is required * in order to create a valid compression command stream. */ void end() { int excessBytes, padBits ; // Add the 1st no-op and the last body. addByte(V_NO_OP, 8) ; addLong(lastBody, lastBodyLength) ; excessBytes = (byteOffset + 1) % 8 ; if (excessBytes == 0 && bitOffset == 8) // No padding necessary. return ; // Need to add padding with a 2nd no-op. addByte(V_NO_OP, 8) ; excessBytes = (byteOffset + 1) % 8 ; if (excessBytes == 0) padBits = 8 - bitOffset ; else { int fillBytes = 8 - excessBytes ; padBits = (8 * fillBytes) + (8 - bitOffset) ; } // The minimum length for a no-op command body is 5 bits. if (padBits < 5) // Have to cross the next 64-bit boundary. padBits += 64 ; // The maximum length of a no-op body is a 5-bit length + 31 bits of // fill for a total of 36. if (padBits < 37) { // Pad with the body of the 1st no-op. addLong((padBits - 5) << (padBits - 5), padBits) ; return ; } // The number of bits to pad at this point is [37..68]. Knock off 24 // bits with the body of the 1st no-op to reduce the number of pad // bits to [13..44], which can be filled with 1 more no-op. addLong(19 << 19, 24) ; padBits -= 24 ; // Add a 3rd no-op. addByte(V_NO_OP, 8) ; padBits -= 8 ; // Complete padding with the body of the 2nd no-op. addLong((padBits - 5) << (padBits - 5), padBits) ; } /** * Get the number of bytes in the compression command stream. * * @return size of compressed data in bytes */ int getByteCount() { if (byteOffset + bitOffset == 0) return 0 ; else return byteOffset + 1 ; } /** * Get the bytes composing the compression command stream. * * @return reference to array of bytes containing the compressed data */ byte[] getBytes() { return bytes ; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy