001/*
002 * $RCSfile: TagTreeDecoder.java,v $
003 * $Revision: 1.1 $
004 * $Date: 2005/02/11 05:02:02 $
005 * $State: Exp $
006 *
007 * Class:                   TagTreeDecoder
008 *
009 * Description:             Decoder of tag trees
010 *
011 *
012 *
013 * COPYRIGHT:
014 *
015 * This software module was originally developed by Raphaël Grosbois and
016 * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
017 * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
018 * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
019 * Centre France S.A) in the course of development of the JPEG2000
020 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
021 * software module is an implementation of a part of the JPEG 2000
022 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
023 * Systems AB and Canon Research Centre France S.A (collectively JJ2000
024 * Partners) agree not to assert against ISO/IEC and users of the JPEG
025 * 2000 Standard (Users) any of their rights under the copyright, not
026 * including other intellectual property rights, for this software module
027 * with respect to the usage by ISO/IEC and Users of this software module
028 * or modifications thereof for use in hardware or software products
029 * claiming conformance to the JPEG 2000 Standard. Those intending to use
030 * this software module in hardware or software products are advised that
031 * their use may infringe existing patents. The original developers of
032 * this software module, JJ2000 Partners and ISO/IEC assume no liability
033 * for use of this software module or modifications thereof. No license
034 * or right to this software module is granted for non JPEG 2000 Standard
035 * conforming products. JJ2000 Partners have full right to use this
036 * software module for his/her own purpose, assign or donate this
037 * software module to any third party and to inhibit third parties from
038 * using this software module for non JPEG 2000 Standard conforming
039 * products. This copyright notice must be included in all copies or
040 * derivative works of this software module.
041 *
042 * Copyright (c) 1999/2000 JJ2000 Partners.
043 *
044 *
045 *
046 */
047
048
049package jj2000.j2k.codestream.reader;
050
051import java.io.EOFException;
052import java.io.IOException;
053
054import jj2000.j2k.util.ArrayUtil;
055
056/**
057 * This class implements the tag tree decoder. A tag tree codes a 2D
058 * matrix of integer elements in an efficient way. The decoding
059 * procedure 'update()' updates a value of the matrix from a stream of
060 * coded data, given a threshold. This procedure decodes enough
061 * information to identify whether or not the value is greater than
062 * or equal to the threshold, and updates the value accordingly.
063 *
064 * <P>In general the decoding procedure must follow the same sequence
065 * of elements and thresholds as the encoding one. The encoder is
066 * implemented by the TagTreeEncoder class.
067 *
068 * <P>Tag trees that have one dimension, or both, as 0 are allowed for
069 * convenience. Of course no values can be set or coded in such cases.
070 *
071 * @see jj2000.j2k.codestream.writer.TagTreeEncoder
072 * */
073public class TagTreeDecoder {
074
075    /** The horizontal dimension of the base level */
076    protected int w;
077
078    /** The vertical dimensions of the base level */
079    protected int h;
080
081    /** The number of levels in the tag tree */
082    protected int lvls;
083
084    /** The tag tree values. The first index is the level,
085     * starting at level 0 (leafs). The second index is the element
086     * within the level, in lexicographical order. */
087    protected int treeV[][];
088
089    /** The tag tree state. The first index is the level, starting at
090     * level 0 (leafs). The second index is the element within the
091     * level, in lexicographical order. */
092    protected int treeS[][];
093
094    /**
095     * Creates a tag tree decoder with 'w' elements along the
096     * horizontal dimension and 'h' elements along the vertical
097     * direction. The total number of elements is thus 'vdim' x
098     * 'hdim'.
099     *
100     * <P>The values of all elements are initialized to
101     * Integer.MAX_VALUE (i.e. no information decoded so far). The
102     * states are initialized all to 0.
103     *
104     * @param h The number of elements along the vertical direction.
105     *
106     * @param w The number of elements along the horizontal direction.
107     *
108     *
109     * */
110    public TagTreeDecoder(int h, int w) {
111        int i;
112
113        // Check arguments
114        if ( w < 0 || h < 0 ) {
115            throw new IllegalArgumentException();
116        }
117        // Initialize dimensions
118        this.w = w;
119        this.h = h;
120        // Calculate the number of levels
121        if (w == 0 || h == 0) {
122            lvls = 0; // Empty tree
123        }
124        else {
125            lvls = 1;
126            while (h != 1 || w != 1) { // Loop until we reach root
127                w = (w+1)>>1;
128                h = (h+1)>>1;
129                lvls++;
130            }
131        }
132        // Allocate tree values and states
133        treeV = new int[lvls][];
134        treeS = new int[lvls][];
135        w = this.w;
136        h = this.h;
137        for (i=0; i<lvls; i++) {
138            treeV[i] = new int[h*w];
139            // Initialize to infinite value
140            ArrayUtil.intArraySet(treeV[i],Integer.MAX_VALUE);
141
142            // (no need to initialize to 0 since it's the default)
143            treeS[i] = new int[h*w];
144            w = (w+1)>>1;
145            h = (h+1)>>1;
146        }
147    }
148
149    /**
150     * Returns the number of leafs along the horizontal direction.
151     *
152     * @return The number of leafs along the horizontal direction.
153     *
154     *
155     * */
156    public final int getWidth() {
157        return w;
158    }
159
160    /**
161     * Returns the number of leafs along the vertical direction.
162     *
163     * @return The number of leafs along the vertical direction.
164     *
165     *
166     * */
167    public final int getHeight() {
168        return h;
169    }
170
171    /**
172     * Decodes information for the specified element of the tree,
173     * given the threshold, and updates its value. The information
174     * that can be decoded is whether or not the value of the element
175     * is greater than, or equal to, the value of the
176     * threshold.
177     *
178     * @param m The vertical index of the element.
179     *
180     * @param n The horizontal index of the element.
181     *
182     * @param t The threshold to use in decoding. It must be non-negative.
183     *
184     * @param in The stream from where to read the coded information.
185     *
186     * @return The updated value at position (m,n).
187     *
188     * @exception IOException If an I/O error occurs while reading
189     * from 'in'.
190     *
191     * @exception EOFException If the ned of the 'in' stream is
192     * reached before getting all the necessary data.
193     *
194     *
195     * */
196    public int update(int m, int n, int t, PktHeaderBitReader in)
197        throws IOException {
198        int k,tmin;
199        int idx,ts,tv;
200
201        // Check arguments
202        if (m >= h || n >= w || t < 0) {
203            throw new IllegalArgumentException();
204        }
205
206        // Initialize
207        k = lvls-1;
208        tmin = treeS[k][0];
209
210        // Loop on levels
211        idx = (m>>k)*((w+(1<<k)-1)>>k)+(n>>k);
212        while (true) {
213            // Cache state and value
214            ts = treeS[k][idx];
215            tv = treeV[k][idx];
216            if (ts < tmin) {
217                ts = tmin;
218            }
219            while (t > ts) {
220                if (tv >= ts) { // We are not done yet
221                    if (in.readBit() == 0) { // '0' bit
222                        // We know that 'value' > treeS[k][idx]
223                        ts++;
224                    }
225                    else { // '1' bit
226                        // We know that 'value' = treeS[k][idx]
227                        tv = ts++;
228                    }
229                    // Increment of treeS[k][idx] done above
230                }
231                else { // We are done, we can set ts and get out
232                    ts = t;
233                    break; // get out of this while
234                }
235            }
236            // Update state and value
237            treeS[k][idx] = ts;
238            treeV[k][idx] = tv;
239            // Update tmin or terminate
240            if (k>0) {
241                tmin = ts < tv ? ts : tv;
242                k--;
243                // Index of element for next iteration
244                idx = (m>>k)*((w+(1<<k)-1)>>k)+(n>>k);
245            }
246            else {
247                // Return the updated value
248                return tv;
249            }
250        }
251    }
252
253    /**
254     * Returns the current value of the specified element in the tag
255     * tree. This is the value as last updated by the update() method.
256     *
257     * @param m The vertical index of the element.
258     *
259     * @param n The horizontal index of the element.
260     *
261     * @return The current value of the element.
262     *
263     * @see #update
264     *
265     *
266     * */
267    public int getValue(int m, int n) {
268        // Check arguments
269        if (m >= h || n >= w) {
270            throw new IllegalArgumentException();
271        }
272        // Return value
273        return treeV[0][m*w+n];
274    }
275}