001/*
002 * $RCSfile: TagTreeEncoder.java,v $
003 * $Revision: 1.1 $
004 * $Date: 2005/02/11 05:02:03 $
005 * $State: Exp $
006 *
007 * Class:                   TagTreeEncoder
008 *
009 * Description:             Encoder 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 */
047package jj2000.j2k.codestream.writer;
048
049import jj2000.j2k.util.ArrayUtil;
050
051/**
052 * This class implements the tag tree encoder. A tag tree codes a 2D
053 * matrix of integer elements in an efficient way. The encoding
054 * procedure 'encode()' codes information about a value of the matrix,
055 * given a threshold. The procedure encodes the sufficient information
056 * to identify whether or not the value is greater than or equal to
057 * the threshold.
058 *
059 * <P>The tag tree saves encoded information to a BitOutputBuffer.
060 *
061 * <P>A particular and useful property of tag trees is that it is
062 * possible to change a value of the matrix, provided both new and old
063 * values of the element are both greater than or equal to the largest
064 * threshold which has yet been supplied to the coding procedure
065 * 'encode()'. This property can be exploited through the 'setValue()'
066 * method.
067 *
068 * <P>This class allows saving the state of the tree at any point and
069 * restoring it at a later time, by calling save() and restore().
070 *
071 * <P>A tag tree can also be reused, or restarted, if one of the
072 * reset() methods is called.
073 *
074 * <P>The TagTreeDecoder class implements the tag tree decoder.
075 *
076 * <P>Tag trees that have one dimension, or both, as 0 are allowed for
077 * convenience. Of course no values can be set or coded in such cases.
078 *
079 * @see BitOutputBuffer
080 *
081 * @see jj2000.j2k.codestream.reader.TagTreeDecoder
082 * */
083public class TagTreeEncoder {
084
085    /** The horizontal dimension of the base level */
086    protected int w;
087
088    /** The vertical dimensions of the base level */
089    protected int h;
090
091    /** The number of levels in the tag tree */
092    protected int lvls;
093
094    /** The tag tree values. The first index is the level, starting at
095     * level 0 (leafs). The second index is the element within the
096     * level, in lexicographical order. */
097    protected int treeV[][];
098
099    /** The tag tree state. The first index is the level, starting at
100     * level 0 (leafs). The second index is the element within the
101     * level, in lexicographical order. */
102    protected int treeS[][];
103
104    /** The saved tag tree values. The first index is the level,
105     * starting at level 0 (leafs). The second index is the element
106     * within the level, in lexicographical order. */
107    protected int treeVbak[][];
108
109    /** The saved tag tree state. The first index is the level, starting at
110     * level 0 (leafs). The second index is the element within the
111     * level, in lexicographical order. */
112    protected int treeSbak[][];
113
114    /** The saved state. If true the values and states of the tree
115     * have been saved since the creation or last reset. */
116    protected boolean saved;
117
118    /**
119     * Creates a tag tree encoder with 'w' elements along the
120     * horizontal dimension and 'h' elements along the vertical
121     * direction. The total number of elements is thus 'vdim' x
122     * 'hdim'.
123     *
124     * <P>The values of all elements are initialized to Integer.MAX_VALUE.
125     *
126     * @param h The number of elements along the horizontal direction.
127     *
128     * @param w The number of elements along the vertical direction.
129     *
130     *
131     * */
132    public TagTreeEncoder(int h, int w) {
133        int k;
134        // Check arguments
135        if ( w < 0 || h < 0 ) {
136            throw new IllegalArgumentException();
137        }
138        // Initialize elements
139        init(w,h);
140        // Set values to max
141        for (k = treeV.length-1; k >= 0; k--) {
142            ArrayUtil.intArraySet(treeV[k],Integer.MAX_VALUE);
143        }
144    }
145
146    /**
147     * Creates a tag tree encoder with 'w' elements along the
148     * horizontal dimension and 'h' elements along the vertical
149     * direction. The total number of elements is thus 'vdim' x
150     * 'hdim'. The values of the leafs in the tag tree are initialized
151     * to the values of the 'val' array.
152     *
153     * <P>The values in the 'val' array are supposed to appear in
154     * lexicographical order, starting at index 0.
155     *
156     * @param h The number of elements along the horizontal direction.
157     *
158     * @param w The number of elements along the vertical direction.
159     *
160     * @param val The values with which initialize the leafs of the
161     * tag tree.
162     *
163     *
164     * */
165    public TagTreeEncoder(int h, int w, int val[]) {
166        int k;
167        // Check arguments
168        if ( w < 0 || h < 0 || val.length < w*h ) {
169            throw new IllegalArgumentException();
170        }
171        // Initialize elements
172        init(w,h);
173        // Update leaf values
174        for (k=w*h-1; k>=0; k--) {
175            treeV[0][k]=val[k];
176        }
177        // Calculate values at other levels
178        recalcTreeV();
179    }
180
181    /**
182     * Returns the number of leafs along the horizontal direction.
183     *
184     * @return The number of leafs along the horizontal direction.
185     *
186     *
187     * */
188    public final int getWidth() {
189        return w;
190    }
191
192    /**
193     * Returns the number of leafs along the vertical direction.
194     *
195     * @return The number of leafs along the vertical direction.
196     *
197     *
198     * */
199    public final int getHeight() {
200        return h;
201    }
202
203    /**
204     * Initializes the variables of this class, given the dimensions
205     * at the base level (leaf level). All the state ('treeS' array)
206     * and values ('treeV' array) are intialized to 0. This method is
207     * called by the constructors.
208     *
209     * @param w The number of elements along the vertical direction.
210     *
211     * @param h The number of elements along the horizontal direction.
212     *
213     *
214     * */
215    private void init(int w, int h) {
216        int i;
217        // Initialize dimensions
218        this.w = w;
219        this.h = h;
220        // Calculate the number of levels
221        if (w == 0 || h == 0) {
222            lvls = 0;
223        }
224        else {
225            lvls = 1;
226            while (h != 1 || w != 1) { // Loop until we reach root
227                w = (w+1)>>1;
228                h = (h+1)>>1;
229                lvls++;
230            }
231        }
232        // Allocate tree values and states
233        // (no need to initialize to 0 since it's the default)
234        treeV = new int[lvls][];
235        treeS = new int[lvls][];
236        w = this.w;
237        h = this.h;
238        for (i=0; i<lvls; i++) {
239            treeV[i] = new int[h*w];
240            treeS[i] = new int[h*w];
241            w = (w+1)>>1;
242            h = (h+1)>>1;
243        }
244    }
245
246    /**
247     * Recalculates the values of the elements in the tag tree, in
248     * levels 1 and up, based on the values of the leafs (level 0).
249     *
250     *
251     * */
252    private void recalcTreeV() {
253        int m,n,bi,lw,tm1,tm2,lh,k;
254        // Loop on all other levels, updating minimum
255        for (k=0; k<lvls-1; k++) {
256            // Visit all elements in level
257            lw = (w+(1<<k)-1)>>k;
258            lh = (h+(1<<k)-1)>>k;
259            for (m=((lh>>1)<<1)-2;m>=0;m-=2) { // All quads with 2 lines
260                for (n=((lw>>1)<<1)-2;n>=0;n-=2) { // All quads with 2 columns
261                    // Take minimum of 4 elements and put it in higher
262                    // level
263                    bi = m*lw+n;
264                    tm1 = (treeV[k][bi] < treeV[k][bi+1]) ?
265                        treeV[k][bi] : treeV[k][bi+1];
266                    tm2 = (treeV[k][bi+lw] < treeV[k][bi+lw+1]) ?
267                        treeV[k][bi+lw] : treeV[k][bi+lw+1];
268                    treeV[k+1][(m>>1)*((lw+1)>>1)+(n>>1)] =
269                        tm1 < tm2 ? tm1 : tm2;
270                }
271                // Now we may have quad with 1 column, 2 lines
272                if (lw%2 != 0) {
273                    n = ((lw>>1)<<1);
274                    // Take minimum of 2 elements and put it in higher
275                    // level
276                    bi = m*lw+n;
277                    treeV[k+1][(m>>1)*((lw+1)>>1)+(n>>1)] =
278                        (treeV[k][bi] < treeV[k][bi+lw]) ?
279                        treeV[k][bi] : treeV[k][bi+lw];
280                }
281            }
282            // Now we may have quads with 1 line, 2 or 1 columns
283            if (lh%2 != 0) {
284                m = ((lh>>1)<<1);
285                for (n=((lw>>1)<<1)-2;n>=0;n-=2) { // All quads with 2 columns
286                    // Take minimum of 2 elements and put it in higher
287                    // level
288                    bi = m*lw+n;
289                    treeV[k+1][(m>>1)*((lw+1)>>1)+(n>>1)] =
290                        (treeV[k][bi] < treeV[k][bi+1]) ?
291                        treeV[k][bi] : treeV[k][bi+1];
292                }
293                // Now we may have quad with 1 column, 1 line
294                if (lw%2 != 0) {
295                    // Just copy the value
296                    n = ((lw>>1)<<1);
297                    treeV[k+1][(m>>1)*((lw+1)>>1)+(n>>1)] =
298                        treeV[k][m*lw+n];
299                }
300            }
301        }
302    }
303
304    /**
305     * Changes the value of a leaf in the tag tree. The new and old
306     * values of the element must be not smaller than the largest
307     * threshold which has yet been supplied to 'encode()'.
308     *
309     * @param m The vertical index of the element.
310     *
311     * @param n The horizontal index of the element.
312     *
313     * @param v The new value of the element.
314     *
315     *
316     * */
317    public void setValue(int m, int n, int v) {
318        int k,idx;
319        // Check arguments
320        if (lvls == 0 || n < 0 || n >= w || v < treeS[lvls-1][0] ||
321            treeV[0][m*w+n] < treeS[lvls-1][0]) {
322            throw new IllegalArgumentException();
323        }
324        // Update the leaf value
325        treeV[0][m*w+n] = v;
326        // Update all parents
327        for (k=1; k<lvls; k++) {
328            idx = (m>>k)*((w+(1<<k)-1)>>k)+(n>>k);
329            if (v < treeV[k][idx]) {
330                // We need to update minimum and continue checking
331                // in higher levels
332                treeV[k][idx] = v;
333            }
334            else {
335                // We are done: v is equal or less to minimum
336                // in this level, no other minimums to update.
337                break;
338            }
339        }
340    }
341
342    /**
343     * Sets the values of the leafs to the new set of values and
344     * updates the tag tree accordingly. No leaf can change its value
345     * if either the new or old value is smaller than largest
346     * threshold which has yet been supplied to 'encode()'. However
347     * such a leaf can keep its old value (i.e. new and old value must
348     * be identical.
349     *
350     * <P>This method is more efficient than the setValue() method if
351     * a large proportion of the leafs change their value. Note that
352     * for leafs which don't have their value defined yet the value
353     * should be Integer.MAX_VALUE (which is the default
354     * initialization value).
355     *
356     * @param val The new values for the leafs, in lexicographical order.
357     *
358     * @see #setValue
359     *
360     *
361     * */
362    public void setValues(int val[]) {
363        int i,maxt;
364        if (lvls == 0) { // Can't set values on empty tree
365            throw new IllegalArgumentException();
366        }
367        // Check the values
368        maxt = treeS[lvls-1][0];
369        for (i=w*h-1; i>=0; i--) {
370            if ((treeV[0][i] < maxt || val[i] < maxt) &&
371                treeV[0][i] != val[i]) {
372                throw new IllegalArgumentException();
373            }
374            // Update leaf value
375            treeV[0][i] = val[i];
376        }
377        // Recalculate tree at other levels
378        recalcTreeV();
379    }
380
381    /**
382     * Encodes information for the specified element of the tree,
383     * given the threshold and sends it to the 'out' stream. The
384     * information that is coded is whether or not the value of the
385     * element is greater than or equal to the value of the threshold.
386     *
387     * @param m The vertical index of the element.
388     *
389     * @param n The horizontal index of the element.
390     *
391     * @param t The threshold to use for encoding. It must be non-negative.
392     *
393     * @param out The stream where to write the coded information.
394     *
395     *
396     * */
397    public void encode(int m, int n, int t, BitOutputBuffer out) {
398        int k,ts,idx,tmin;
399
400        // Check arguments
401        if (m >= h || n >= w || t < 0) {
402            throw new IllegalArgumentException();
403        }
404
405        // Initialize
406        k = lvls-1;
407        tmin = treeS[k][0];
408
409        // Loop on levels
410        while (true) {
411            // Index of element in level 'k'
412            idx = (m>>k)*((w+(1<<k)-1)>>k)+(n>>k);
413            // Cache state
414            ts = treeS[k][idx];
415            if (ts < tmin) {
416                ts = tmin;
417            }
418            while (t > ts) {
419                if (treeV[k][idx] > ts) {
420                    out.writeBit(0); // Send '0' bit
421                }
422                else if (treeV[k][idx] == ts) {
423                    out.writeBit(1); // Send '1' bit
424                }
425                else { // we are done: set ts and get out of this while
426                    ts = t;
427                    break;
428                }
429                // Increment of treeS[k][idx]
430                ts++;
431            }
432            // Update state
433            treeS[k][idx] = ts;
434            // Update tmin or terminate
435            if (k>0) {
436                tmin = ts < treeV[k][idx] ? ts : treeV[k][idx];
437                k--;
438            }
439            else {
440                // Terminate
441                return;
442            }
443        }
444    }
445
446    /**
447     * Saves the current values and state of the tree. Calling
448     * restore() restores the tag tree the saved state.
449     *
450     * @see #restore
451     *
452     *
453     * */
454    public void save() {
455        int k,i;
456
457        if (treeVbak == null) { // Nothing saved yet
458            // Allocate saved arrays
459            // treeV and treeS have the same dimensions
460            treeVbak = new int[lvls][];
461            treeSbak = new int[lvls][];
462            for (k=lvls-1 ; k >= 0; k--) {
463                treeVbak[k] = new int[treeV[k].length];
464                treeSbak[k] = new int[treeV[k].length];
465            }
466        }
467
468        // Copy the arrays
469        for (k=treeV.length-1 ; k >= 0; k--) {
470            System.arraycopy(treeV[k],0,treeVbak[k],0,treeV[k].length);
471            System.arraycopy(treeS[k],0,treeSbak[k],0,treeS[k].length);
472        }
473
474        // Set saved state
475        saved = true;
476    }
477
478    /**
479     * Restores the saved values and state of the tree. An
480     * IllegalArgumentException is thrown if the tree values and state
481     * have not been saved yet.
482     *
483     * @see #save
484     *
485     *
486     * */
487    public void restore() {
488        int k,i;
489
490        if (!saved) { // Nothing saved yet
491            throw new IllegalArgumentException();
492        }
493
494        // Copy the arrays
495        for (k=lvls-1 ; k >= 0; k--) {
496            System.arraycopy(treeVbak[k],0,treeV[k],0,treeV[k].length);
497            System.arraycopy(treeSbak[k],0,treeS[k],0,treeS[k].length);
498        }
499
500    }
501
502    /**
503     * Resets the tree values and state. All the values are set to
504     * Integer.MAX_VALUE and the states to 0.
505     *
506     *
507     * */
508    public void reset() {
509        int k;
510        // Set all values to Integer.MAX_VALUE
511        // and states to 0
512        for (k = lvls-1; k >= 0; k--) {
513            ArrayUtil.intArraySet(treeV[k],Integer.MAX_VALUE);
514            ArrayUtil.intArraySet(treeS[k],0);
515        }
516        // Invalidate saved tree
517        saved = false;
518    }
519
520    /**
521     * Resets the tree values and state. The values are set to the
522     * values in 'val'. The states are all set to 0.
523     *
524     * @param val The new values for the leafs, in lexicographical order.
525     *
526     *
527     * */
528    public void reset(int val[]) {
529        int k;
530        // Set values for leaf level
531        for (k=w*h-1; k>=0; k--) {
532            treeV[0][k] = val[k];
533        }
534        // Calculate values at other levels
535        recalcTreeV();
536        // Set all states to 0
537        for (k = lvls-1; k >= 0; k--) {
538            ArrayUtil.intArraySet(treeS[k],0);
539        }
540        // Invalidate saved tree
541        saved = false;
542    }
543}