001/* 002 * $RCSfile: SubbandAn.java,v $ 003 * $Revision: 1.1 $ 004 * $Date: 2005/02/11 05:02:31 $ 005 * $State: Exp $ 006 * 007 * Class: SubbandAn 008 * 009 * Description: Element for a tree structure for a descripotion 010 * of subbands on the anslysis side. 011 * 012 * 013 * 014 * COPYRIGHT: 015 * 016 * This software module was originally developed by Raphaël Grosbois and 017 * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel 018 * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David 019 * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research 020 * Centre France S.A) in the course of development of the JPEG2000 021 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This 022 * software module is an implementation of a part of the JPEG 2000 023 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio 024 * Systems AB and Canon Research Centre France S.A (collectively JJ2000 025 * Partners) agree not to assert against ISO/IEC and users of the JPEG 026 * 2000 Standard (Users) any of their rights under the copyright, not 027 * including other intellectual property rights, for this software module 028 * with respect to the usage by ISO/IEC and Users of this software module 029 * or modifications thereof for use in hardware or software products 030 * claiming conformance to the JPEG 2000 Standard. Those intending to use 031 * this software module in hardware or software products are advised that 032 * their use may infringe existing patents. The original developers of 033 * this software module, JJ2000 Partners and ISO/IEC assume no liability 034 * for use of this software module or modifications thereof. No license 035 * or right to this software module is granted for non JPEG 2000 Standard 036 * conforming products. JJ2000 Partners have full right to use this 037 * software module for his/her own purpose, assign or donate this 038 * software module to any third party and to inhibit third parties from 039 * using this software module for non JPEG 2000 Standard conforming 040 * products. This copyright notice must be included in all copies or 041 * derivative works of this software module. 042 * 043 * Copyright (c) 1999/2000 JJ2000 Partners. 044 * 045 * 046 * 047 */ 048 049 050package jj2000.j2k.wavelet.analysis; 051 052import jj2000.j2k.wavelet.*; 053 054/** 055 * This class represents a subband in a bidirectional tree structure 056 * that describes the subband decomposition for a wavelet transform, 057 * specifically for the analysis side. 058 * 059 * <P>The element can be either a node or a leaf of the tree. If it is 060 * a node then ther are 4 descendants (LL, HL, LH and HH). If it is a 061 * leaf there are no descendants. 062 * 063 * <P>The tree is bidirectional. Each element in the tree structure 064 * has a "parent", which is the subband from which the element was 065 * obtained by decomposition. The only exception is the root element 066 * which has no parent (i.e.it's null), for obvious reasons. 067 * */ 068public class SubbandAn extends Subband { 069 070 /** 071 * The reference to the parent of this subband. It is null for the 072 * root element. It is null by default. */ 073 public SubbandAn parent = null; 074 075 /** 076 * The reference to the LL subband resulting from the 077 * decomposition of this subband. It is null by default. */ 078 public SubbandAn subb_LL; 079 080 /** 081 * The reference to the HL subband (horizontal high-pass) 082 * resulting from the decomposition of this subband. It is null by 083 * default. */ 084 public SubbandAn subb_HL; 085 086 /** 087 * The reference to the LH subband (vertical high-pass) resulting 088 * from the decomposition of this subband. It is null by default. 089 * */ 090 public SubbandAn subb_LH; 091 092 /** 093 * The reference to the HH subband resulting from the 094 * decomposition of this subband. It is null by default. 095 */ 096 public SubbandAn subb_HH; 097 098 /** The horizontal analysis filter used to decompose this 099 subband. This is applicable to "node" elements only. The 100 default value is null. */ 101 public AnWTFilter hFilter; 102 103 /** The vertical analysis filter used to decompose this 104 subband. This is applicable to "node" elements only. The 105 default value is null. */ 106 public AnWTFilter vFilter; 107 108 /** 109 * The L2-norm of the synthesis basis waveform of this subband, 110 * applicable to "leafs" only. By default it is -1 (i.e. not 111 * calculated yet). 112 * */ 113 public float l2Norm = -1.0f; 114 115 /** 116 * The contribution to the MSE or WMSE error that would result in the 117 * image if there was an error of exactly one quantization step size in 118 * the sample of the subband. This value is expressed relative to a 119 * nominal dynamic range in the image domain of exactly 1.0. This field 120 * contains valid data only after quantization 9See Quantizer). 121 * 122 * @see jj2000.j2k.quantization.quantizer.Quantizer 123 * */ 124 public float stepWMSE; 125 126 /** 127 * Creates a SubbandAn element with all the default values. The 128 * dimensions are (0,0) and the upper left corner is (0,0). 129 * 130 * 131 * */ 132 public SubbandAn() { 133 } 134 135 /** 136 * Creates the top-level node and the entire subband tree, with 137 * the top-level dimensions, the number of decompositions, and the 138 * decomposition tree as specified. 139 * 140 * <P>This constructor just calls the same constructor of the 141 * super class, and then calculates the L2-norm (or energy weight) 142 * of each leaf. 143 * 144 * <P>This constructor does not initialize the value of the magBits or 145 * stepWMSE member variables. This variables are normally initialized by 146 * the quantizer (see Quantizer). 147 * 148 * @param w The top-level width 149 * 150 * @param h The top-level height 151 * 152 * @param ulcx The horizontal coordinate of the upper-left corner with 153 * respect to the canvas origin, in the component grid. 154 * 155 * @param ulcy The vertical coordinate of the upper-left corner with 156 * respect to the canvas origin, in the component grid. 157 * 158 * @param lvls The number of levels (or LL decompositions) in the 159 * tree. 160 * 161 * @param hfilters The horizontal wavelet analysis filters for each 162 * resolution level, starting at resolution level 0. 163 * 164 * @param vfilters The vertical wavelet analysis filters for each 165 * resolution level, starting at resolution level 0. 166 * 167 * @see Subband#Subband(int,int,int,int,int, 168 * WaveletFilter[],WaveletFilter[]) 169 * 170 * @see jj2000.j2k.quantization.quantizer.Quantizer 171 * 172 * 173 * */ 174 public SubbandAn(int w, int h, int ulcx, int ulcy, int lvls, 175 WaveletFilter hfilters[], WaveletFilter vfilters[]) { 176 super(w,h,ulcx,ulcy,lvls,hfilters,vfilters); 177 // Caculate the L2-norms 178 calcL2Norms(); 179 } 180 181 /** 182 * Returns the parent of this subband. The parent of a subband is 183 * the subband from which this one was obtained by 184 * decomposition. The root element has no parent subband (null). 185 * 186 * @return The parent subband, or null for the root one. 187 * 188 * 189 * */ 190 public Subband getParent() { 191 return parent; 192 } 193 194 /** 195 * Returns the LL child subband of this subband. 196 * 197 * @return The LL child subband, or null if there are no childs. 198 * 199 * 200 * */ 201 public Subband getLL() { 202 return subb_LL; 203 } 204 205 /** 206 * Returns the HL (horizontal high-pass) child subband of this 207 * subband. 208 * 209 * @return The HL child subband, or null if there are no childs. 210 * 211 * 212 * */ 213 public Subband getHL() { 214 return subb_HL; 215 } 216 217 /** 218 * Returns the LH (vertical high-pass) child subband of this 219 * subband. 220 * 221 * @return The LH child subband, or null if there are no childs. 222 * 223 * 224 * */ 225 public Subband getLH() { 226 return subb_LH; 227 } 228 229 /** 230 * Returns the HH child subband of this subband. 231 * 232 * @return The HH child subband, or null if there are no childs. 233 * 234 * 235 * */ 236 public Subband getHH() { 237 return subb_HH; 238 } 239 240 /** 241 * Splits the current subband in its four subbands. It changes the 242 * status of this element (from a leaf to a node, and sets the 243 * filters), creates the childs and initializes them. An 244 * IllegalArgumentException is thrown if this subband is not a 245 * leaf. 246 * 247 * <P>It uses the initChilds() method to initialize the childs. 248 * 249 * @param hfilter The horizontal wavelet filter used to decompose 250 * this subband. It has to be a AnWTFilter object. 251 * 252 * @param vfilter The vertical wavelet filter used to decompose this 253 * subband. It has to be a AnWTFilter object. 254 * 255 * @return A reference to the LL leaf (subb_LL). 256 * 257 * @see Subband#initChilds 258 * 259 * 260 * */ 261 protected Subband split(WaveletFilter hfilter, WaveletFilter vfilter) { 262 // Test that this is a node 263 if (isNode) { 264 throw new IllegalArgumentException(); 265 } 266 267 // Modify this element into a node and set the filters 268 isNode = true; 269 this.hFilter = (AnWTFilter) hfilter; 270 this.vFilter = (AnWTFilter) vfilter; 271 272 // Create childs 273 subb_LL = new SubbandAn(); 274 subb_LH = new SubbandAn(); 275 subb_HL = new SubbandAn(); 276 subb_HH = new SubbandAn(); 277 278 // Assign parent 279 subb_LL.parent = this; 280 subb_HL.parent = this; 281 subb_LH.parent = this; 282 subb_HH.parent = this; 283 284 // Initialize childs 285 initChilds(); 286 287 // Return reference to LL subband 288 return subb_LL; 289 } 290 291 /** 292 * Calculates the basis waveform of the first leaf for which the 293 * L2-norm has not been calculated yet. This method searches 294 * recursively for the first leaf for which the value has not been 295 * calculated yet, and then calculates the L2-norm on the return 296 * path. 297 * 298 * <P>The wfs argument should be a size 2 array of float arrays 299 * (i.e. 2D array) and it must be of length 2 (or more). When 300 * returning, wfs[0] will contain the line waveform, and wfs[1] 301 * will contain the column waveform. 302 * 303 * <P>This method can not be called on an element that ahs a 304 * non-negative value in l2Norm, since that means that we are 305 * done. 306 * 307 * @param wfs An size 2 array where the line and column waveforms 308 * will be returned. 309 * 310 * 311 * */ 312 private void calcBasisWaveForms(float wfs[][]) { 313 if (l2Norm < 0) { 314 // We are not finished with this element yet 315 if (isNode) { 316 // We are on a node => search on childs 317 if (subb_LL.l2Norm < 0f) { 318 subb_LL.calcBasisWaveForms(wfs); 319 wfs[0] = 320 hFilter.getLPSynWaveForm(wfs[0],null); 321 wfs[1] = 322 vFilter.getLPSynWaveForm(wfs[1],null); 323 } 324 else if (subb_HL.l2Norm < 0f) { 325 subb_HL.calcBasisWaveForms(wfs); 326 wfs[0] = 327 hFilter.getHPSynWaveForm(wfs[0],null); 328 wfs[1] = 329 vFilter.getLPSynWaveForm(wfs[1],null); 330 } 331 else if (subb_LH.l2Norm < 0f) { 332 subb_LH.calcBasisWaveForms(wfs); 333 wfs[0] = 334 hFilter.getLPSynWaveForm(wfs[0],null); 335 wfs[1] = 336 vFilter.getHPSynWaveForm(wfs[1],null); 337 } 338 else if (subb_HH.l2Norm < 0f) { 339 subb_HH.calcBasisWaveForms(wfs); 340 wfs[0] = 341 hFilter.getHPSynWaveForm(wfs[0],null); 342 wfs[1] = 343 vFilter.getHPSynWaveForm(wfs[1],null); 344 } 345 else { 346 // There is an error! If all childs have 347 // non-negative l2norm, then this node should have 348 // non-negative l2norm 349 throw new Error("You have found a bug in JJ2000!"); 350 } 351 } 352 else { 353 // This is a leaf, just use diracs (null is 354 // equivalent to dirac) 355 wfs[0] = new float[1]; 356 wfs[0][0] = 1.0f; 357 wfs[1] = new float[1]; 358 wfs[1][0] = 1.0f; 359 } 360 361 } 362 else { 363 // This is an error! The calcBasisWaveForms() method is 364 // never called on an element with non-negative l2norm 365 throw new Error("You have found a bug in JJ2000!"); 366 } 367 } 368 369 /** 370 * Assigns the given L2-norm to the first leaf that does not have 371 * an L2-norm value yet (i.e. l2norm is negative). The search is 372 * done recursively and in the same order as that of the 373 * calcBasisWaveForms() method, so that this method is used to 374 * assigne the l2norm of the previously computed waveforms. 375 * 376 * <P>This method can not be called on an element that ahs a 377 * non-negative value in l2Norm, since that means that we are 378 * done. 379 * 380 * @param l2n The L2-norm to assign. 381 * 382 * 383 * */ 384 private void assignL2Norm(float l2n) { 385 if (l2Norm < 0) { 386 // We are not finished with this element yet 387 if (isNode) { 388 // We are on a node => search on childs 389 if (subb_LL.l2Norm < 0f) { 390 subb_LL.assignL2Norm(l2n); 391 } 392 else if (subb_HL.l2Norm < 0f) { 393 subb_HL.assignL2Norm(l2n); 394 } 395 else if (subb_LH.l2Norm < 0f) { 396 subb_LH.assignL2Norm(l2n); 397 } 398 else if (subb_HH.l2Norm < 0f) { 399 subb_HH.assignL2Norm(l2n); 400 // If child now is done, we are done 401 if (subb_HH.l2Norm >= 0f) { 402 l2Norm = 0f; // We are on a node, any non-neg value OK 403 } 404 } 405 else { 406 // There is an error! If all childs have 407 // non-negative l2norm, then this node should have 408 // non-negative l2norm 409 throw new Error("You have found a bug in JJ2000!"); 410 } 411 } 412 else { 413 // This is a leaf, assign the L2-norm 414 l2Norm = l2n; 415 } 416 417 } 418 else { 419 // This is an error! The assignL2Norm() method is 420 // never called on an element with non-negative l2norm 421 throw new Error("You have found a bug in JJ2000!"); 422 } 423 } 424 425 426 /** 427 * Calculates the L2-norm of the sythesis waveforms of every leaf 428 * in the tree. This method should only be called on the root 429 * element. 430 * 431 * 432 * */ 433 private void calcL2Norms() { 434 int i; 435 float wfs[][] = new float[2][]; 436 double acc; 437 float l2n; 438 439 // While we are not done on the root element, compute basis 440 // functions and assign L2-norm 441 while (l2Norm < 0f) { 442 calcBasisWaveForms(wfs); 443 // Compute line L2-norm, which is the product of the line 444 // and column L2-norms 445 acc = 0.0; 446 for (i=wfs[0].length-1; i>=0; i--) { 447 acc += wfs[0][i]*wfs[0][i]; 448 } 449 l2n = (float) Math.sqrt(acc); 450 // Compute column L2-norm 451 acc = 0.0; 452 for (i=wfs[1].length-1; i>=0; i--) { 453 acc += wfs[1][i]*wfs[1][i]; 454 } 455 l2n *= (float) Math.sqrt(acc); 456 // Release waveforms 457 wfs[0] = null; 458 wfs[1] = null; 459 // Assign the value 460 assignL2Norm(l2n); 461 } 462 } 463 464 /** 465 * This function returns the horizontal wavelet filter relevant to this 466 * subband 467 * 468 * @return The horizontal wavelet filter 469 * 470 * 471 */ 472 public WaveletFilter getHorWFilter(){ 473 return hFilter; 474 } 475 476 /** 477 * This function returns the vertical wavelet filter relevant to this 478 * subband 479 * 480 * @return The vertical wavelet filter 481 * 482 * 483 */ 484 public WaveletFilter getVerWFilter(){ 485 return hFilter; 486 } 487}