001/* 002 * 003 * $RCSfile: Subband.java,v $ 004 * $Revision: 1.1 $ 005 * $Date: 2005/02/11 05:02:27 $ 006 * $State: Exp $ 007 * 008 * Class: Subband 009 * 010 * Description: Asbtract element for a tree strcuture for 011 * a description of subbands. 012 * 013 * 014 * 015 * COPYRIGHT: 016 * 017 * This software module was originally developed by Raphaël Grosbois and 018 * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel 019 * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David 020 * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research 021 * Centre France S.A) in the course of development of the JPEG2000 022 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This 023 * software module is an implementation of a part of the JPEG 2000 024 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio 025 * Systems AB and Canon Research Centre France S.A (collectively JJ2000 026 * Partners) agree not to assert against ISO/IEC and users of the JPEG 027 * 2000 Standard (Users) any of their rights under the copyright, not 028 * including other intellectual property rights, for this software module 029 * with respect to the usage by ISO/IEC and Users of this software module 030 * or modifications thereof for use in hardware or software products 031 * claiming conformance to the JPEG 2000 Standard. Those intending to use 032 * this software module in hardware or software products are advised that 033 * their use may infringe existing patents. The original developers of 034 * this software module, JJ2000 Partners and ISO/IEC assume no liability 035 * for use of this software module or modifications thereof. No license 036 * or right to this software module is granted for non JPEG 2000 Standard 037 * conforming products. JJ2000 Partners have full right to use this 038 * software module for his/her own purpose, assign or donate this 039 * software module to any third party and to inhibit third parties from 040 * using this software module for non JPEG 2000 Standard conforming 041 * products. This copyright notice must be included in all copies or 042 * derivative works of this software module. 043 * 044 * Copyright (c) 1999/2000 JJ2000 Partners. 045 * */ 046package jj2000.j2k.wavelet; 047 048import java.awt.Point; 049 050/** 051 * This abstract class represents a subband in a bidirectional tree structure 052 * that describes the subband decomposition for a wavelet transform. This 053 * class is implemented by the SubbandAn and SubbandSyn classes, which are for 054 * the analysis and synthesis sides, respectively. 055 * 056 * <P>The element can be either a node or a leaf of the tree. If it is a node 057 * then ther are 4 descendants (LL, HL, LH and HH). If it is a leaf ther are 058 * no descendants. 059 * 060 * <P>The tree is bidirectional. Each element in the tree structure has a 061 * "parent", which is the subband from which the element was obtained by 062 * decomposition. The only exception is the root element which has no parent 063 * (i.e.it's null), for obvious reasons. 064 * 065 * @see jj2000.j2k.wavelet.analysis.SubbandAn 066 * @see jj2000.j2k.wavelet.synthesis.SubbandSyn 067 * */ 068public abstract class Subband { 069 070 /** The ID for the LL orientation */ 071 public final static int WT_ORIENT_LL = 0; 072 073 /** The ID for the HL (horizontal high-pass) orientation */ 074 public final static int WT_ORIENT_HL = 1; 075 076 /** The ID for the LH (vertical high-pass) orientation */ 077 public final static int WT_ORIENT_LH = 2; 078 079 /** The ID for the HH orientation */ 080 public final static int WT_ORIENT_HH = 3; 081 082 /** 083 * True if it is a node in the tree, false if it is a leaf. False by 084 * default. */ 085 public boolean isNode; 086 087 /** 088 * The orientation of this subband (WT_ORIENT_LL, WT_ORIENT_HL, 089 * WT_ORIENT_LH, WT_ORIENT_HH). It is WT_ORIENT_LL by default. The 090 * orientation of the top-level node (i.e. the full image before any 091 * decomposition) is WT_ORIENT_LL. */ 092 // The default value is always 0, which is WT_ORIENT_LL. 093 public int orientation; 094 095 /** 096 * The level in the tree to which this subband belongs, which is the 097 * number of wavelet decompositions performed to produce this subband. It 098 * is 0 for the top-level (i.e. root) node. It is 0 by default. 099 * */ 100 public int level; 101 102 /** 103 * The resolution level to which this subband contributes. Level 0 is the 104 * smallest resolution level (the one with the lowest frequency LL 105 * subband). It is 0 by default. 106 * */ 107 public int resLvl; 108 109 /** The number of code-blocks (in both directions) contained in this 110 * subband. */ 111 public Point numCb = null; 112 113 /** 114 * The base 2 exponent of the analysis gain of the subband. The analysis 115 * gain of a subband is defined as the gain of the previous subband 116 * (i.e. the one from which this one was obtained) multiplied by the line 117 * gain and by the column gain. The line (column) gain is the gain of the 118 * line (column) filter that was used to obtain it, which is the DC gain 119 * for a low-pass filter and the Nyquist gain for a high-pass filter. It 120 * is 0 by default. 121 * 122 * <P>Using the base 2 exponent of the value contrains the possible gains 123 * to powers of 2. However this is perfectly compatible to the filter 124 * normalization policy assumed here. See the split() method for more 125 * details. 126 * 127 * @see #split 128 * */ 129 public int anGainExp; 130 131 /** 132 * The subband index within its resolution level. This value uniquely 133 * identifies a subband within a resolution level and a decomposition 134 * level within it. Note that only leaf elements represent "real" 135 * subbands, while node elements represent only intermediate stages. 136 * 137 * <P>It is defined recursively. The root node gets a value of 0. For a 138 * given node, with a subband index 'b', its LL descendant gets 4*b, its 139 * HL descendant 4*b+1, its LH descendant 4*b+2, and its HH descendant 140 * 4*b+3, for their subband indexes. 141 * */ 142 public int sbandIdx = 0; 143 144 /** 145 * The horizontal coordinate of the upper-left corner of the subband, with 146 * respect to the canvas origin, in the component's grid and subband's 147 * decomposition level. This is the real horizontal index of the first 148 * column of this subband. If even the horizontal decomposition of this 149 * subband should be done with the low-pass-first convention. If odd it 150 * should be done with the high-pass-first convention. 151 * */ 152 public int ulcx; 153 154 /** 155 * The vertical coordinate of the upper-left corner of the subband, with 156 * respect to the canvas origin, in the component's grid and subband's 157 * decomposition level. This is the real vertical index of the first 158 * column of this subband. If even the vertical decomposition of this 159 * subband should be done with the low-pass-first convention. If odd it 160 * should be done with the high-pass-first convention. 161 * */ 162 public int ulcy; 163 164 /** The horizontal coordinate of the upper-left corner of the subband */ 165 public int ulx; 166 167 /** The vertical coordinate of the upper-left corner of the subband */ 168 public int uly; 169 170 /** The width of the subband */ 171 public int w; 172 173 /** The height of the subband */ 174 public int h; 175 176 /** The nominal code-block width */ 177 public int nomCBlkW; 178 179 /** The nominal code-block height */ 180 public int nomCBlkH; 181 182 /** 183 * Returns the parent of this subband. The parent of a subband is the 184 * subband from which this one was obtained by decomposition. The root 185 * element has no parent subband (null). 186 * 187 * @return The parent subband, or null for the root one. 188 * */ 189 public abstract Subband getParent(); 190 191 /** 192 * Returns the LL child subband of this subband. 193 * 194 * @return The LL child subband, or null if there are no childs. 195 * */ 196 public abstract Subband getLL(); 197 198 /** 199 * Returns the HL (horizontal high-pass) child subband of this subband. 200 * 201 * @return The HL child subband, or null if there are no childs. 202 * */ 203 public abstract Subband getHL(); 204 205 /** 206 * Returns the LH (vertical high-pass) child subband of this subband. 207 * 208 * @return The LH child subband, or null if there are no childs. 209 * */ 210 public abstract Subband getLH(); 211 212 /** 213 * Returns the HH child subband of this subband. 214 * 215 * @return The HH child subband, or null if there are no childs. 216 * */ 217 public abstract Subband getHH(); 218 219 /** 220 * Splits the current subband in its four subbands. This creates the four 221 * childs (LL, HL, LH and HH) and converts the leaf in a node. 222 * 223 * @param hfilter The horizontal wavelet filter used to decompose this 224 * subband. 225 * 226 * @param vfilter The vertical wavelet filter used to decompose this 227 * subband. 228 * 229 * @return A reference to the LL leaf (getLL()). 230 * */ 231 protected abstract Subband split(WaveletFilter hfilter, 232 WaveletFilter vfilter); 233 234 /** 235 * Initializes the childs of this node with the correct values. The sizes 236 * of the child subbands are calculated by taking into account the 237 * position of the subband in the canvas. 238 * 239 * <P>For the analysis subband gain calculation it is assumed that 240 * analysis filters are normalized with a DC gain of 1 and a Nyquist gain 241 * of 2. 242 * */ 243 protected void initChilds() { 244 Subband subb_LL = getLL(); 245 Subband subb_HL = getHL(); 246 Subband subb_LH = getLH(); 247 Subband subb_HH = getHH(); 248 249 // LL subband 250 subb_LL.level = level+1; 251 subb_LL.ulcx = (ulcx+1)>>1; 252 subb_LL.ulcy = (ulcy+1)>>1; 253 subb_LL.ulx = ulx; 254 subb_LL.uly = uly; 255 subb_LL.w = ((ulcx+w+1)>>1)-subb_LL.ulcx; 256 subb_LL.h = ((ulcy+h+1)>>1)-subb_LL.ulcy; 257 // If this subband in in the all LL path (i.e. it's global orientation 258 // is LL) then child LL band contributes to a lower resolution level. 259 subb_LL.resLvl = (orientation == WT_ORIENT_LL) ? resLvl-1 : resLvl; 260 subb_LL.anGainExp = anGainExp; 261 subb_LL.sbandIdx = (sbandIdx<<2); 262 // HL subband 263 subb_HL.orientation = WT_ORIENT_HL; 264 subb_HL.level = subb_LL.level; 265 subb_HL.ulcx = ulcx>>1; 266 subb_HL.ulcy = subb_LL.ulcy; 267 subb_HL.ulx = ulx + subb_LL.w; 268 subb_HL.uly = uly; 269 subb_HL.w = ((ulcx+w)>>1)-subb_HL.ulcx; 270 subb_HL.h = subb_LL.h; 271 subb_HL.resLvl = resLvl; 272 subb_HL.anGainExp = anGainExp+1; 273 subb_HL.sbandIdx = (sbandIdx<<2)+1; 274 // LH subband 275 subb_LH.orientation = WT_ORIENT_LH; 276 subb_LH.level = subb_LL.level; 277 subb_LH.ulcx = subb_LL.ulcx; 278 subb_LH.ulcy = ulcy>>1; 279 subb_LH.ulx = ulx; 280 subb_LH.uly = uly + subb_LL.h; 281 subb_LH.w = subb_LL.w; 282 subb_LH.h = ((ulcy+h)>>1)-subb_LH.ulcy; 283 subb_LH.resLvl = resLvl; 284 subb_LH.anGainExp = anGainExp+1; 285 subb_LH.sbandIdx = (sbandIdx<<2)+2; 286 // HH subband 287 subb_HH.orientation = WT_ORIENT_HH; 288 subb_HH.level = subb_LL.level; 289 subb_HH.ulcx = subb_HL.ulcx; 290 subb_HH.ulcy = subb_LH.ulcy; 291 subb_HH.ulx = subb_HL.ulx; 292 subb_HH.uly = subb_LH.uly; 293 subb_HH.w = subb_HL.w; 294 subb_HH.h = subb_LH.h; 295 subb_HH.resLvl = resLvl; 296 subb_HH.anGainExp = anGainExp+2; 297 subb_HH.sbandIdx = (sbandIdx<<2)+3; 298 } 299 300 /** 301 * Creates a Subband element with all the default values. The dimensions 302 * are (0,0), the upper left corner is (0,0) and the upper-left corner 303 * with respect to the canvas is (0,0) too. 304 * */ 305 public Subband() { 306 } 307 308 /** 309 * Creates the top-level node and the entire subband tree, with the 310 * top-level dimensions, the number of decompositions, and the 311 * decomposition tree as specified. 312 * 313 * <P>For the analysis subband gain calculation it is assumed that 314 * analysis filters are normalized with a DC gain of 1 and a Nyquist gain 315 * of 2. 316 * 317 * <P>This constructor does not initialize the value of the magBits member 318 * variable. This variable is normally initialized by the quantizer, on 319 * the encoder side, or the bit stream reader, on the decoder side. 320 * 321 * @param w The top-level width 322 * 323 * @param h The top-level height 324 * 325 * @param ulcx The horizontal coordinate of the upper-left corner with 326 * respect to the canvas origin, in the component grid. 327 * 328 * @param ulcy The vertical coordinate of the upper-left corner with 329 * respect to the canvas origin, in the component grid. 330 * 331 * @param lvls The number of levels (or LL decompositions) in the tree. 332 * 333 * @param hfilters The horizontal wavelet filters (analysis or synthesis) 334 * for each resolution level, starting at resolution level 0. If there are 335 * less elements in the array than there are resolution levels, the last 336 * element is used for the remaining resolution levels. 337 * 338 * @param vfilters The vertical wavelet filters (analysis or synthesis) 339 * for each resolution level, starting at resolution level 0. If there are 340 * less elements in the array than there are resolution levels, the last 341 * element is used for the remaining resolution levels. 342 * 343 * @see WaveletTransform 344 * */ 345 public Subband(int w, int h, int ulcx, int ulcy, int lvls, 346 WaveletFilter hfilters[], WaveletFilter vfilters[]) { 347 int i,hi,vi; 348 Subband cur; // The current subband 349 350 // Initialize top-level node 351 this.w = w; 352 this.h = h; 353 this.ulcx = ulcx; 354 this.ulcy = ulcy; 355 this.resLvl = lvls; 356 // First create dyadic decomposition. 357 cur = this; 358 for (i=0; i<lvls; i++) { 359 hi = (cur.resLvl <= hfilters.length) ? cur.resLvl-1 : 360 hfilters.length-1; 361 vi = (cur.resLvl <= vfilters.length) ? cur.resLvl-1 : 362 vfilters.length-1; 363 cur = cur.split(hfilters[hi],vfilters[vi]); 364 } 365 } 366 367 /** 368 * Returns the next subband in the same resolution level, following the 369 * subband index order. If already at the last subband then null is 370 * returned. If this subband is not a leaf an IllegalArgumentException is 371 * thrown. 372 * 373 * @return The next subband in the same resolution level, following the 374 * subband index order, or null if already at last subband. 375 * */ 376 public Subband nextSubband() { 377 Subband sb; 378 379 if (isNode) { 380 throw new IllegalArgumentException(); 381 } 382 383 switch (orientation) { 384 case WT_ORIENT_LL: 385 sb = getParent(); 386 if (sb == null || sb.resLvl != resLvl) { 387 // Already at top-level or last subband in res. level 388 return null; 389 } 390 else { 391 return sb.getHL(); 392 } 393 case WT_ORIENT_HL: 394 return getParent().getLH(); 395 case WT_ORIENT_LH: 396 return getParent().getHH(); 397 case WT_ORIENT_HH: 398 // This is the complicated one 399 sb = this; 400 while (sb.orientation == WT_ORIENT_HH) { 401 sb = sb.getParent(); 402 } 403 switch (sb.orientation) { 404 case WT_ORIENT_LL: 405 sb = sb.getParent(); 406 if (sb == null || sb.resLvl != resLvl) { 407 // Already at top-level or last subband in res. level 408 return null; 409 } 410 else { 411 sb = sb.getHL(); 412 } 413 break; 414 case WT_ORIENT_HL: 415 sb = sb.getParent().getLH(); 416 break; 417 case WT_ORIENT_LH: 418 sb = sb.getParent().getHH(); 419 break; 420 default: 421 throw new Error("You have found a bug in JJ2000"); 422 } 423 while (sb.isNode) { 424 sb = sb.getLL(); 425 } 426 return sb; 427 default: 428 throw new Error("You have found a bug in JJ2000"); 429 } 430 } 431 432 /** 433 * Returns the first leaf subband element in the next higher resolution 434 * level. 435 * 436 * @return The first leaf element in the next higher resolution level, or 437 * null if there is no higher resolution level. 438 * */ 439 public Subband getNextResLevel() { 440 Subband sb; 441 442 if (level == 0) { // No higher res. level 443 return null; 444 } 445 // Go up until we get to a different resolution level 446 sb = this; 447 do { 448 sb = sb.getParent(); 449 if (sb == null) { // No higher resolution level 450 return null; 451 } 452 } while (sb.resLvl == resLvl); 453 // Now go down to HL, which is in next higher resolution level 454 sb = sb.getHL(); 455 // Now go down LL until get to a leaf 456 while (sb.isNode) { 457 sb = sb.getLL(); 458 } 459 return sb; 460 } 461 462 /** 463 * Returns a subband element in the tree, given its resolution level and 464 * subband index. This method searches through the tree. 465 * 466 * @param rl The resolution level. 467 * 468 * @param sbi The subband index, within the resolution level. 469 * */ 470 public Subband getSubbandByIdx(int rl, int sbi) { 471 Subband sb = this; 472 473 // Find the root subband for the resolution level 474 if (rl>sb.resLvl || rl<0) { 475 throw new IllegalArgumentException("Resolution level index "+ 476 "out of range"); 477 } 478 479 // Returns directly if it is itself 480 if(rl==sb.resLvl && sbi==sb.sbandIdx) return sb; 481 482 if(sb.sbandIdx!=0) sb = sb.getParent(); 483 484 while(sb.resLvl>rl) sb = sb.getLL(); 485 while(sb.resLvl<rl) sb = sb.getParent(); 486 487 switch(sbi) { 488 case 0: 489 default: 490 return sb; 491 case 1: 492 return sb.getHL(); 493 case 2: 494 return sb.getLH(); 495 case 3: 496 return sb.getHH(); 497 } 498 499 } 500 501 /** 502 * Returns a reference to the Subband element to which the specified point 503 * belongs. The specified point must be inside this (i.e. the one defined 504 * by this object) subband. This method searches through the tree. 505 * 506 * @param x horizontal coordinate of the specified point. 507 * 508 * @param y horizontal coordinate of the specified point. 509 * */ 510 public Subband getSubband(int x,int y) { 511 Subband cur,hhs; 512 513 // Check that we are inside this subband 514 if (x<ulx || y<uly || x>=ulx+w || y>=uly+h) { 515 throw new IllegalArgumentException(); 516 } 517 518 cur = this; 519 while (cur.isNode) { 520 hhs = cur.getHH(); 521 // While we are still at a node -> continue 522 if (x<hhs.ulx) { 523 // Is the result of horizontal low-pass 524 if (y<hhs.uly) { 525 // Vertical low-pass 526 cur = cur.getLL(); 527 } else { 528 // Vertical high-pass 529 cur = cur.getLH(); 530 } 531 } else { 532 // Is the result of horizontal high-pass 533 if (y<hhs.uly) { 534 // Vertical low-pass 535 cur = cur.getHL(); 536 } else { 537 // Vertical high-pass 538 cur = cur.getHH(); 539 } 540 } 541 } 542 543 return cur; 544 } 545 546 /** 547 * Returns subband informations in a string. 548 * 549 * @return Subband informations 550 * */ 551 public String toString() { 552 553 String string = 554 "w=" + w + ", h=" + h + ", ulx=" + ulx + ", uly=" + uly + 555 ", ulcx= "+ulcx+", ulcy="+ulcy+", idx=" + sbandIdx + 556 "\norient=" + orientation + ", node=" + isNode + 557 ", level=" + level + ", resLvl=" + resLvl+ ", nomCBlkW=" + 558 nomCBlkW + ", nomCBlkH=" + nomCBlkH; 559 560 return string; 561 } 562 563 /** 564 * This function returns the horizontal wavelet filter relevant to this 565 * subband 566 * 567 * @return The horizontal wavelet filter 568 * */ 569 public abstract WaveletFilter getHorWFilter(); 570 571 /** 572 * This function returns the vertical wavelet filter relevant to this 573 * subband 574 * 575 * @return The vertical wavelet filter 576 * */ 577 public abstract WaveletFilter getVerWFilter(); 578 579 580} 581