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}