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