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}