/*
* #%L
* Fork of JAI Image I/O Tools.
* %%
* Copyright (C) 2008 - 2014 Open Microscopy Environment:
* - Board of Regents of the University of Wisconsin-Madison
* - Glencoe Software, Inc.
* - University of Dundee
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions 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.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are
* those of the authors and should not be interpreted as representing official
* policies, either expressed or implied, of any organization.
* #L%
*/
/*
* $RCSfile: TagTreeDecoder.java,v $
* $Revision: 1.1 $
* $Date: 2005/02/11 05:02:02 $
* $State: Exp $
*
* Class: TagTreeDecoder
*
* Description: Decoder of tag trees
*
*
*
* COPYRIGHT:
*
* This software module was originally developed by Raphaël Grosbois and
* Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
* Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
* Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
* Centre France S.A) in the course of development of the JPEG2000
* standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
* software module is an implementation of a part of the JPEG 2000
* Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
* Systems AB and Canon Research Centre France S.A (collectively JJ2000
* Partners) agree not to assert against ISO/IEC and users of the JPEG
* 2000 Standard (Users) any of their rights under the copyright, not
* including other intellectual property rights, for this software module
* with respect to the usage by ISO/IEC and Users of this software module
* or modifications thereof for use in hardware or software products
* claiming conformance to the JPEG 2000 Standard. Those intending to use
* this software module in hardware or software products are advised that
* their use may infringe existing patents. The original developers of
* this software module, JJ2000 Partners and ISO/IEC assume no liability
* for use of this software module or modifications thereof. No license
* or right to this software module is granted for non JPEG 2000 Standard
* conforming products. JJ2000 Partners have full right to use this
* software module for his/her own purpose, assign or donate this
* software module to any third party and to inhibit third parties from
* using this software module for non JPEG 2000 Standard conforming
* products. This copyright notice must be included in all copies or
* derivative works of this software module.
*
* Copyright (c) 1999/2000 JJ2000 Partners.
*
*
*
*/
package jj2000.j2k.codestream.reader;
import jj2000.j2k.io.*;
import jj2000.j2k.util.*;
import java.io.*;
/**
* This class implements the tag tree decoder. A tag tree codes a 2D
* matrix of integer elements in an efficient way. The decoding
* procedure 'update()' updates a value of the matrix from a stream of
* coded data, given a threshold. This procedure decodes enough
* information to identify whether or not the value is greater than
* or equal to the threshold, and updates the value accordingly.
*
* <P>In general the decoding procedure must follow the same sequence
* of elements and thresholds as the encoding one. The encoder is
* implemented by the TagTreeEncoder class.
*
* <P>Tag trees that have one dimension, or both, as 0 are allowed for
* convenience. Of course no values can be set or coded in such cases.
*
* @see jj2000.j2k.codestream.writer.TagTreeEncoder
* */
public class TagTreeDecoder {
/** The horizontal dimension of the base level */
protected int w;
/** The vertical dimensions of the base level */
protected int h;
/** The number of levels in the tag tree */
protected int lvls;
/** The tag tree values. The first index is the level,
* starting at level 0 (leafs). The second index is the element
* within the level, in lexicographical order. */
protected int treeV[][];
/** The tag tree state. The first index is the level, starting at
* level 0 (leafs). The second index is the element within the
* level, in lexicographical order. */
protected int treeS[][];
/**
* Creates a tag tree decoder with 'w' elements along the
* horizontal dimension and 'h' elements along the vertical
* direction. The total number of elements is thus 'vdim' x
* 'hdim'.
*
* <P>The values of all elements are initialized to
* Integer.MAX_VALUE (i.e. no information decoded so far). The
* states are initialized all to 0.
*
* @param h The number of elements along the vertical direction.
*
* @param w The number of elements along the horizontal direction.
*
*
* */
public TagTreeDecoder(int h, int w) {
int i;
// Check arguments
if ( w < 0 || h < 0 ) {
throw new IllegalArgumentException();
}
// Initialize dimensions
this.w = w;
this.h = h;
// Calculate the number of levels
if (w == 0 || h == 0) {
lvls = 0; // Empty tree
}
else {
lvls = 1;
while (h != 1 || w != 1) { // Loop until we reach root
w = (w+1)>>1;
h = (h+1)>>1;
lvls++;
}
}
// Allocate tree values and states
treeV = new int[lvls][];
treeS = new int[lvls][];
w = this.w;
h = this.h;
for (i=0; i<lvls; i++) {
treeV[i] = new int[h*w];
// Initialize to infinite value
ArrayUtil.intArraySet(treeV[i],Integer.MAX_VALUE);
// (no need to initialize to 0 since it's the default)
treeS[i] = new int[h*w];
w = (w+1)>>1;
h = (h+1)>>1;
}
}
/**
* Returns the number of leafs along the horizontal direction.
*
* @return The number of leafs along the horizontal direction.
*
*
* */
public final int getWidth() {
return w;
}
/**
* Returns the number of leafs along the vertical direction.
*
* @return The number of leafs along the vertical direction.
*
*
* */
public final int getHeight() {
return h;
}
/**
* Decodes information for the specified element of the tree,
* given the threshold, and updates its value. The information
* that can be decoded is whether or not the value of the element
* is greater than, or equal to, the value of the
* threshold.
*
* @param m The vertical index of the element.
*
* @param n The horizontal index of the element.
*
* @param t The threshold to use in decoding. It must be non-negative.
*
* @param in The stream from where to read the coded information.
*
* @return The updated value at position (m,n).
*
* @exception IOException If an I/O error occurs while reading
* from 'in'.
*
* @exception EOFException If the ned of the 'in' stream is
* reached before getting all the necessary data.
*
*
* */
public int update(int m, int n, int t, PktHeaderBitReader in)
throws IOException {
int k,tmin;
int idx,ts,tv;
// Check arguments
if (m >= h || n >= w || t < 0) {
throw new IllegalArgumentException();
}
// Initialize
k = lvls-1;
tmin = treeS[k][0];
// Loop on levels
idx = (m>>k)*((w+(1<<k)-1)>>k)+(n>>k);
while (true) {
// Cache state and value
ts = treeS[k][idx];
tv = treeV[k][idx];
if (ts < tmin) {
ts = tmin;
}
while (t > ts) {
if (tv >= ts) { // We are not done yet
if (in.readBit() == 0) { // '0' bit
// We know that 'value' > treeS[k][idx]
ts++;
}
else { // '1' bit
// We know that 'value' = treeS[k][idx]
tv = ts++;
}
// Increment of treeS[k][idx] done above
}
else { // We are done, we can set ts and get out
ts = t;
break; // get out of this while
}
}
// Update state and value
treeS[k][idx] = ts;
treeV[k][idx] = tv;
// Update tmin or terminate
if (k>0) {
tmin = ts < tv ? ts : tv;
k--;
// Index of element for next iteration
idx = (m>>k)*((w+(1<<k)-1)>>k)+(n>>k);
}
else {
// Return the updated value
return tv;
}
}
}
/**
* Returns the current value of the specified element in the tag
* tree. This is the value as last updated by the update() method.
*
* @param m The vertical index of the element.
*
* @param n The horizontal index of the element.
*
* @return The current value of the element.
*
* @see #update
*
*
* */
public int getValue(int m, int n) {
// Check arguments
if (m >= h || n >= w) {
throw new IllegalArgumentException();
}
// Return value
return treeV[0][m*w+n];
}
}