org.scijava.java3d.utils.geometry.compression.CompressionStreamElement Maven / Gradle / Ivy
Show all versions of j3dutils Show documentation
/*
* 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;
/**
* Instances of this class are used as elements in a CompressionStream.
* @see CompressionStream
*/
abstract class CompressionStreamElement {
/**
* Bit length of quantized geometric components.
*/
int length ;
/**
* Number of trailing zeros in quantized geometric components.
*/
int shift ;
/**
* If false, geometric component values are represented as differences
* from those of the preceding element in the stream.
*/
boolean absolute ;
/**
* Array with elements that can be used as masks to apply a quantization
* to the number of bits indicated by the referencing index [0..16].
*/
static final int quantizationMask[] = {
0xFFFF0000, 0xFFFF8000, 0xFFFFC000, 0xFFFFE000,
0xFFFFF000, 0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00,
0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0,
0xFFFFFFF0, 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE,
0xFFFFFFFF
} ;
/**
* Array with elements that can be used as masks to retain the number of
* trailing bits of data indicated by the referencing index [0..64]. Used
* to clear the leading sign bits of fixed-point 2's complement numbers
* and in building the compressed output stream.
*/
static final long lengthMask[] = {
0x0000000000000000L, 0x0000000000000001L,
0x0000000000000003L, 0x0000000000000007L,
0x000000000000000FL, 0x000000000000001FL,
0x000000000000003FL, 0x000000000000007FL,
0x00000000000000FFL, 0x00000000000001FFL,
0x00000000000003FFL, 0x00000000000007FFL,
0x0000000000000FFFL, 0x0000000000001FFFL,
0x0000000000003FFFL, 0x0000000000007FFFL,
0x000000000000FFFFL, 0x000000000001FFFFL,
0x000000000003FFFFL, 0x000000000007FFFFL,
0x00000000000FFFFFL, 0x00000000001FFFFFL,
0x00000000003FFFFFL, 0x00000000007FFFFFL,
0x0000000000FFFFFFL, 0x0000000001FFFFFFL,
0x0000000003FFFFFFL, 0x0000000007FFFFFFL,
0x000000000FFFFFFFL, 0x000000001FFFFFFFL,
0x000000003FFFFFFFL, 0x000000007FFFFFFFL,
0x00000000FFFFFFFFL, 0x00000001FFFFFFFFL,
0x00000003FFFFFFFFL, 0x00000007FFFFFFFFL,
0x0000000FFFFFFFFFL, 0x0000001FFFFFFFFFL,
0x0000003FFFFFFFFFL, 0x0000007FFFFFFFFFL,
0x000000FFFFFFFFFFL, 0x000001FFFFFFFFFFL,
0x000003FFFFFFFFFFL, 0x000007FFFFFFFFFFL,
0x00000FFFFFFFFFFFL, 0x00001FFFFFFFFFFFL,
0x00003FFFFFFFFFFFL, 0x00007FFFFFFFFFFFL,
0x0000FFFFFFFFFFFFL, 0x0001FFFFFFFFFFFFL,
0x0003FFFFFFFFFFFFL, 0x0007FFFFFFFFFFFFL,
0x000FFFFFFFFFFFFFL, 0x001FFFFFFFFFFFFFL,
0x003FFFFFFFFFFFFFL, 0x007FFFFFFFFFFFFFL,
0x00FFFFFFFFFFFFFFL, 0x01FFFFFFFFFFFFFFL,
0x03FFFFFFFFFFFFFFL, 0x07FFFFFFFFFFFFFFL,
0x0FFFFFFFFFFFFFFFL, 0x1FFFFFFFFFFFFFFFL,
0x3FFFFFFFFFFFFFFFL, 0x7FFFFFFFFFFFFFFFL,
0xFFFFFFFFFFFFFFFFL
} ;
/**
* Computes the quantized representation of this stream element.
*
* @param stream CompressionStream associated with this element
* @param table HuffmanTable for collecting data about the quantized
* representation of this element
*/
abstract void quantize(CompressionStream stream, HuffmanTable table) ;
/**
* Outputs the compressed bits representing this stream element.
* Some instances of CompressionStreamElement don't require an
* implementation and will inherit the stub provided here.
*
* @param table HuffmanTable mapping quantized representations to
* compressed encodings
* @param output CommandStream for collecting compressed output
*/
void outputCommand(HuffmanTable table, CommandStream output) {
}
/**
* Finds the minimum bits needed to represent the given 16-bit signed 2's
* complement integer. For positive integers, this include the first
* 1 starting from the left, plus a 0 sign bit; for negative integers,
* this includes the first 0 starting from the left, plus a 1 sign bit.
* 0 is a special case returning 0; however, 0-length components are valid
* ONLY for normals.
*
* The decompressor uses the data length to determine how many bits of
* sign extension to add to the data coming in from the compressed stream
* in order to create a 16-bit signed 2's complement integer. E.g., a data
* length of 12 indicates that 16-12=4 bits of sign are to be extended.
*
* @param number a signed 2's complement integer representable in 16 bits
* or less
* @return minimum number of bits to represent the number
*/
private static final int getLength(int number) {
if (number == 0)
return 0 ;
else if ((number & 0x8000) > 0) {
// negative numbers
if ((number & 0x4000) == 0) return 16 ;
if ((number & 0x2000) == 0) return 15 ;
if ((number & 0x1000) == 0) return 14 ;
if ((number & 0x0800) == 0) return 13 ;
if ((number & 0x0400) == 0) return 12 ;
if ((number & 0x0200) == 0) return 11 ;
if ((number & 0x0100) == 0) return 10 ;
if ((number & 0x0080) == 0) return 9 ;
if ((number & 0x0040) == 0) return 8 ;
if ((number & 0x0020) == 0) return 7 ;
if ((number & 0x0010) == 0) return 6 ;
if ((number & 0x0008) == 0) return 5 ;
if ((number & 0x0004) == 0) return 4 ;
if ((number & 0x0002) == 0) return 3 ;
if ((number & 0x0001) == 0) return 2 ;
return 1 ;
} else {
// positive numbers
if ((number & 0x4000) > 0) return 16 ;
if ((number & 0x2000) > 0) return 15 ;
if ((number & 0x1000) > 0) return 14 ;
if ((number & 0x0800) > 0) return 13 ;
if ((number & 0x0400) > 0) return 12 ;
if ((number & 0x0200) > 0) return 11 ;
if ((number & 0x0100) > 0) return 10 ;
if ((number & 0x0080) > 0) return 9 ;
if ((number & 0x0040) > 0) return 8 ;
if ((number & 0x0020) > 0) return 7 ;
if ((number & 0x0010) > 0) return 6 ;
if ((number & 0x0008) > 0) return 5 ;
if ((number & 0x0004) > 0) return 4 ;
if ((number & 0x0002) > 0) return 3 ;
return 2 ;
}
}
/**
* Finds the rightmost 1 bit in the given 16-bit integer. This value is
* used by the decompressor to indicate the number of trailing zeros to be
* added to the end of the data coming in from the compressed stream,
* accomplished by left shifting the data by the indicated amount.
* 0 is a special case returning 0.
*
* @param number an integer representable in 16 bits or less
* @return number of trailing zeros
*/
private static final int getShift(int number) {
if (number == 0) return 0 ;
if ((number & 0x0001) > 0) return 0 ;
if ((number & 0x0002) > 0) return 1 ;
if ((number & 0x0004) > 0) return 2 ;
if ((number & 0x0008) > 0) return 3 ;
if ((number & 0x0010) > 0) return 4 ;
if ((number & 0x0020) > 0) return 5 ;
if ((number & 0x0040) > 0) return 6 ;
if ((number & 0x0080) > 0) return 7 ;
if ((number & 0x0100) > 0) return 8 ;
if ((number & 0x0200) > 0) return 9 ;
if ((number & 0x0400) > 0) return 10 ;
if ((number & 0x0800) > 0) return 11 ;
if ((number & 0x1000) > 0) return 12 ;
if ((number & 0x2000) > 0) return 13 ;
if ((number & 0x4000) > 0) return 14 ;
return 15 ;
}
/**
* Computes common length and shift of 2 numbers.
*/
final void computeLengthShift(int n0, int n1) {
int s0 = n0 & 0x8000 ;
int s1 = n1 & 0x8000 ;
// equal sign optimization
if (s0 == s1)
if (s0 == 0)
this.length = getLength(n0 | n1) ;
else
this.length = getLength(n0 & n1) ;
else
this.length = getMaximum(getLength(n0), getLength(n1)) ;
this.shift = getShift(n0 | n1) ;
}
/**
* Computes common length and shift of 3 numbers.
*/
final void computeLengthShift(int n0, int n1, int n2) {
int s0 = n0 & 0x8000 ;
int s1 = n1 & 0x8000 ;
int s2 = n2 & 0x8000 ;
// equal sign optimization
if (s0 == s1)
if (s1 == s2)
if (s2 == 0)
this.length = getLength(n0 | n1 | n2) ;
else
this.length = getLength(n0 & n1 & n2) ;
else
if (s1 == 0)
this.length = getMaximum(getLength(n0 | n1),
getLength(n2)) ;
else
this.length = getMaximum(getLength(n0 & n1),
getLength(n2)) ;
else
if (s1 == s2)
if (s2 == 0)
this.length = getMaximum(getLength(n1 | n2),
getLength(n0)) ;
else
this.length = getMaximum(getLength(n1 & n2),
getLength(n0)) ;
else
if (s0 == 0)
this.length = getMaximum(getLength(n0 | n2),
getLength(n1)) ;
else
this.length = getMaximum(getLength(n0 & n2),
getLength(n1)) ;
this.shift = getShift(n0 | n1 | n2) ;
}
/**
* Computes common length and shift of 4 numbers.
*/
final void computeLengthShift(int n0, int n1, int n2, int n3) {
this.length = getMaximum(getLength(n0), getLength(n1),
getLength(n2), getLength(n3)) ;
this.shift = getShift(n0 | n1 | n2 | n3) ;
}
/**
* Finds the maximum of two integers.
*/
private static final int getMaximum(int x, int y) {
if (x > y)
return x ;
else
return y ;
}
/**
* Finds the maximum of three integers.
*/
private static final int getMaximum(int x, int y, int z) {
if (x > y)
if (x > z)
return x ;
else
return z ;
else
if (y > z)
return y ;
else
return z ;
}
/**
* Finds the maximum of four integers.
*/
private static final int getMaximum(int x, int y, int z, int w) {
int n0, n1 ;
if (x > y)
n0 = x ;
else
n0 = y ;
if (z > w)
n1 = z ;
else
n1 = w ;
if (n0 > n1)
return n0 ;
else
return n1 ;
}
}