001/* 002 * $RCSfile: ModuleSpec.java,v $ 003 * $Revision: 1.1 $ 004 * $Date: 2005/02/11 05:01:58 $ 005 * $State: Exp $ 006 * 007 * Class: ModuleSpec 008 * 009 * Description: Generic class for storing module specs 010 * 011 * from WTFilterSpec (Diego Santa Cruz) 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 * */ 044package jj2000.j2k; 045 046import java.awt.Point; 047import java.util.Enumeration; 048import java.util.Hashtable; 049 050/** 051 * This generic class is used to handle values to be used by a module for each 052 * tile and component. It uses attribute to determine which value to use. It 053 * should be extended by each module needing this feature. 054 * 055 * This class might be used for values that are only tile specific or 056 * component specific but not both. 057 * 058 * <P>The attributes to use are defined by a hierarchy. The hierarchy is: 059 * 060 * <ul> 061 * <li> Tile and component specific attribute</li> 062 * <li> Tile specific default attribute</li> 063 * <li> Component main default attribute</li> 064 * <li> Main default attribute</li> 065 * </ul> 066 * */ 067 068public class ModuleSpec implements Cloneable { 069 070 /** The identifier for a specification module that applies only to 071 * components */ 072 public final static byte SPEC_TYPE_COMP = 0; 073 074 /** The identifier for a specification module that applies only to 075 tiles */ 076 public final static byte SPEC_TYPE_TILE = 1; 077 078 /** The identifier for a specification module that applies both to 079 * tiles and components */ 080 public final static byte SPEC_TYPE_TILE_COMP = 2; 081 082 /** The identifier for default specification */ 083 public final static byte SPEC_DEF = 0; 084 085 /** The identifier for "component default" specification */ 086 public final static byte SPEC_COMP_DEF = 1; 087 088 /** The identifier for "tile default" specification */ 089 public final static byte SPEC_TILE_DEF = 2; 090 091 /** The identifier for a "tile-component" specification */ 092 public final static byte SPEC_TILE_COMP = 3; 093 094 /** The type of the specification module */ 095 protected int specType; 096 097 /** The number of tiles */ 098 protected int nTiles = 0; 099 100 /** The number of components */ 101 protected int nComp = 0; 102 103 /** The spec type for each tile-component. The first index is 104 * the tile index, the second is the component index. 105 */ 106 protected byte[][] specValType; 107 108 /** Default value for each tile-component */ 109 protected Object def = null; 110 111 /** The default value for each component. Null if no component 112 specific value is defined */ 113 protected Object[] compDef = null; 114 115 /** The default value for each tile. Null if no tile specific 116 value is defined */ 117 protected Object[] tileDef = null; 118 119 /** The specific value for each tile-component. Value of tile 16 component 120 * 3 is accessible through the hash value "t16c3". Null if no 121 * tile-component specific value is defined */ 122 protected Hashtable tileCompVal; 123 124 /** The specified value in string format */ 125 protected String specified; 126 127 public ModuleSpec getCopy() { 128 return (ModuleSpec)this.clone(); 129 } 130 131 /** 132 * Constructs a 'ModuleSpec' object, initializing all the components and 133 * tiles to the 'SPEC_DEF' spec val type, for the specified number of 134 * components and tiles. 135 * 136 * @param nt The number of tiles 137 * 138 * @param nc The number of components 139 * 140 * @param type the type of the specification module i.e. tile specific, 141 * component specific or both. 142 * */ 143 public ModuleSpec(int nt, int nc, byte type) { 144 145 nTiles = nt; 146 nComp = nc; 147 specValType = new byte[nt][nc]; 148 switch (type) { 149 case SPEC_TYPE_TILE: 150 specType = SPEC_TYPE_TILE; 151 break; 152 case SPEC_TYPE_COMP: 153 specType = SPEC_TYPE_COMP; 154 break; 155 case SPEC_TYPE_TILE_COMP: 156 specType = SPEC_TYPE_TILE_COMP; 157 break; 158 } 159 } 160 161 protected Object clone() { 162 ModuleSpec ms; 163 try { 164 ms = (ModuleSpec)super.clone(); 165 } catch(CloneNotSupportedException e) { 166 throw new Error("Error when cloning ModuleSpec instance"); 167 } 168 // Create a copy of the specValType array 169 ms.specValType = new byte[nTiles][nComp]; 170 for(int t=0; t<nTiles; t++) { 171 for(int c=0; c<nComp; c++) { 172 ms.specValType[t][c] = specValType[t][c]; 173 } 174 } 175 // Create a copy of tileDef 176 if(tileDef!=null) { 177 ms.tileDef = new Object[nTiles]; 178 for(int t=0; t<nTiles; t++) { 179 ms.tileDef[t] = tileDef[t]; 180 } 181 } 182 // Create a copy of tileCompVal 183 if(tileCompVal!=null) { 184 ms.tileCompVal = new Hashtable(); 185 String tmpKey; 186 Object tmpVal; 187 for(Enumeration e=tileCompVal.keys(); e.hasMoreElements(); ) { 188 tmpKey = (String)e.nextElement(); 189 tmpVal = tileCompVal.get(tmpKey); 190 ms.tileCompVal.put(tmpKey,tmpVal); 191 } 192 } 193 return ms; 194 } 195 196 /** 197 * Rotate the ModuleSpec instance by 90 degrees (this modifies only tile 198 * and tile-component specifications). 199 * 200 * @param nT Number of tiles along horizontal and vertical axis after 201 * rotation. 202 * */ 203 public void rotate90(Point anT) { 204 // Rotate specValType 205 byte[][] tmpsvt = new byte[nTiles][]; 206 int ax,ay; 207 Point bnT = new Point(anT.y,anT.x); 208 for(int by=0; by<bnT.y; by++) { 209 for(int bx=0; bx<bnT.x; bx++) { 210 ay = bx; 211 ax = bnT.y-by-1; 212 tmpsvt[ay*anT.x+ax] = specValType[by*bnT.x+bx]; 213 } 214 } 215 specValType = tmpsvt; 216 217 // Rotate tileDef 218 if(tileDef!=null) { 219 Object[] tmptd = new Object[nTiles]; 220 for(int by=0; by<bnT.y; by++) { 221 for(int bx=0; bx<bnT.x; bx++) { 222 ay = bx; 223 ax = bnT.y-by-1; 224 tmptd[ay*anT.x+ax] = tileDef[by*bnT.x+bx]; 225 } 226 } 227 tileDef = tmptd; 228 } 229 230 // Rotate tileCompVal 231 if(tileCompVal!=null && tileCompVal.size()>0) { 232 Hashtable tmptcv = new Hashtable(); 233 String tmpKey; 234 Object tmpVal; 235 int btIdx,atIdx; 236 int i1,i2; 237 int bx,by; 238 for(Enumeration e=tileCompVal.keys(); e.hasMoreElements(); ) { 239 tmpKey = (String)e.nextElement(); 240 tmpVal = tileCompVal.get(tmpKey); 241 i1 = tmpKey.indexOf('t'); 242 i2 = tmpKey.indexOf('c'); 243 btIdx = (new Integer(tmpKey.substring(i1+1,i2))).intValue(); 244 bx = btIdx%bnT.x; 245 by = btIdx/bnT.x; 246 ay = bx; 247 ax = bnT.y-by-1; 248 atIdx = ax+ay*anT.x; 249 tmptcv.put("t"+atIdx+tmpKey.substring(i2),tmpVal); 250 } 251 tileCompVal = tmptcv; 252 } 253 } 254 255 /** 256 * Sets default value for this module 257 * */ 258 public void setDefault(Object value){ 259 def = value; 260 } 261 262 /** 263 * Gets default value for this module. 264 * 265 * @return The default value (Must be casted before use) 266 * */ 267 public Object getDefault(){ 268 return def; 269 } 270 271 /** 272 * Sets default value for specified component and specValType tag if 273 * allowed by its priority. 274 * 275 * @param c Component index 276 * */ 277 public void setCompDef(int c, Object value){ 278 if ( specType == SPEC_TYPE_TILE ) { 279 String errMsg = "Option whose value is '"+value+"' cannot be " 280 +"specified for components as it is a 'tile only' specific " 281 +"option"; 282 throw new Error(errMsg); 283 } 284 if(compDef==null) 285 compDef = new Object[nComp]; 286 for(int i=0; i<nTiles; i++){ 287 if(specValType[i][c]<SPEC_COMP_DEF) { 288 specValType[i][c] = SPEC_COMP_DEF; 289 } 290 } 291 compDef[c] = value; 292 } 293 294 /** 295 * Gets default value of the specified component. If no specification have 296 * been entered for this component, returns default value. 297 * 298 * @param c Component index 299 * 300 * @return The default value for this component (Must be casted before 301 * use) 302 * 303 * @see #setCompDef 304 * */ 305 public Object getCompDef(int c){ 306 if ( specType == SPEC_TYPE_TILE ) { 307 throw new Error("Illegal use of ModuleSpec class"); 308 } 309 if(compDef==null || compDef[c]==null){ 310 return getDefault(); 311 } 312 else 313 return compDef[c]; 314 } 315 316 /** 317 * Sets default value for specified tile and specValType tag if 318 * allowed by its priority. 319 * 320 * @param c Tile index. 321 * */ 322 public void setTileDef(int t, Object value){ 323 if ( specType == SPEC_TYPE_COMP ) { 324 String errMsg = "Option whose value is '"+value+"' cannot be " 325 + "specified for tiles as it is a 'component only' specific " 326 + "option"; 327 throw new Error(errMsg); 328 } 329 if(tileDef==null) 330 tileDef = new Object[nTiles]; 331 for(int i=0; i<nComp; i++){ 332 if(specValType[t][i]<SPEC_TILE_DEF){ 333 specValType[t][i] = SPEC_TILE_DEF; 334 } 335 } 336 tileDef[t] = value; 337 } 338 339 /** 340 * Gets default value of the specified tile. If no specification 341 * has been entered, it returns the default value. 342 * 343 * @param t Tile index 344 * 345 * @return The default value for this tile (Must be casted before use) 346 * 347 * @see #setTileDef 348 * */ 349 public Object getTileDef(int t){ 350 if ( specType == SPEC_TYPE_COMP ) { 351 throw new Error("Illegal use of ModuleSpec class"); 352 } 353 if(tileDef==null || tileDef[t]==null){ 354 return getDefault(); 355 } 356 else 357 return tileDef[t]; 358 } 359 360 /** 361 * Sets value for specified tile-component. 362 * 363 * @param t Tie index 364 * 365 * @param c Component index 366 * */ 367 public void setTileCompVal(int t,int c, Object value){ 368 if ( specType != SPEC_TYPE_TILE_COMP ) { 369 String errMsg = "Option whose value is '"+value+"' cannot be " 370 + "specified for "; 371 switch (specType) { 372 case SPEC_TYPE_TILE: 373 errMsg += "components as it is a 'tile only' specific option"; 374 break; 375 case SPEC_TYPE_COMP: 376 errMsg += "tiles as it is a 'component only' specific option"; 377 break; 378 } 379 throw new Error(errMsg); 380 } 381 if(tileCompVal==null) 382 tileCompVal = new Hashtable(); 383 specValType[t][c] = SPEC_TILE_COMP; 384 tileCompVal.put("t"+t+"c"+c,value); 385 } 386 387 /** 388 * Gets value of specified tile-component. This method calls getSpec but 389 * has a public access. 390 * 391 * @param t Tile index 392 * 393 * @param c Component index 394 * 395 * @return The value of this tile-component (Must be casted before use) 396 * 397 * @see #setTileCompVal 398 * 399 * @see #getSpec 400 * */ 401 public Object getTileCompVal(int t,int c){ 402 if ( specType != SPEC_TYPE_TILE_COMP ) { 403 throw new Error("Illegal use of ModuleSpec class"); 404 } 405 return getSpec(t,c); 406 } 407 408 /** 409 * Gets value of specified tile-component without knowing if a 410 * specific tile-component value has been previously entered. It 411 * first check if a tile-component specific value has been 412 * entered, then if a tile specific value exist, then if a 413 * component specific value exist. If not the default value is 414 * returned. 415 * 416 * @param t Tile index 417 * 418 * @param c Component index 419 * 420 * @return Value for this tile component. 421 * */ 422 protected Object getSpec(int t,int c){ 423 switch(specValType[t][c]){ 424 case SPEC_DEF: 425 return getDefault(); 426 case SPEC_COMP_DEF: 427 return getCompDef(c); 428 case SPEC_TILE_DEF: 429 return getTileDef(t); 430 case SPEC_TILE_COMP: 431 return tileCompVal.get("t"+t+"c"+c); 432 default: 433 throw new IllegalArgumentException("Not recognized spec type"); 434 } 435 } 436 437 /** 438 * Return the spec type of the given tile-component. 439 * 440 * @param t Tile index 441 * 442 * @param c Component index 443 * */ 444 public byte getSpecValType(int t,int c){ 445 return specValType[t][c]; 446 } 447 448 /** 449 * Whether or not specifications have been entered for the given 450 * component. 451 * 452 * @param c Index of the component 453 * 454 * @return True if component specification has been defined 455 * */ 456 public boolean isCompSpecified(int c){ 457 if(compDef==null || compDef[c]==null) 458 return false; 459 else 460 return true; 461 } 462 463 /** 464 * Whether or not specifications have been entered for the given 465 * tile. 466 * 467 * @param t Index of the tile 468 * 469 * @return True if tile specification has been entered 470 * */ 471 public boolean isTileSpecified(int t){ 472 if(tileDef==null || tileDef[t]==null) 473 return false; 474 else 475 return true; 476 } 477 478 /** 479 * Whether or not a tile-component specification has been defined 480 * 481 * @param t Tile index 482 * 483 * @param c Component index 484 * 485 * @return True if a tile-component specification has been defined. 486 * */ 487 public boolean isTileCompSpecified(int t,int c){ 488 if(tileCompVal==null || tileCompVal.get("t"+t+"c"+c)==null) 489 return false; 490 else 491 return true; 492 } 493 494 /** 495 * This method is responsible of parsing tile indexes set and 496 * component indexes set for an option. Such an argument must 497 * follow the following policy:<br> 498 * 499 * <tt>t\<indexes set\></tt> or <tt>c\<indexes set\></tt> where 500 * tile or component indexes are separated by commas or a 501 * dashes. 502 * 503 * <p><u>Example:</u><br> 504 * <li> <tt>t0,3,4</tt> means tiles with indexes 0, 3 and 4.<br> 505 * <li> <tt>t2-4</tt> means tiles with indexes 2,3 and 4.<br> 506 * 507 * It returns a boolean array skteching which tile or component are 508 * concerned by the next parameters. 509 * 510 * @param word The word to parse. 511 * 512 * @param maxIdx Maximum authorized index 513 * 514 * @return Indexes concerned by this parameter. 515 * */ 516 public static final boolean[] parseIdx(String word, int maxIdx){ 517 int nChar = word.length(); // Number of characters 518 char c = word.charAt(0); // current character 519 int idx = -1; // Current (tile or component) index 520 int lastIdx = -1; // Last (tile or component) index 521 boolean isDash = false; // Whether or not last separator was a dash 522 523 boolean[] idxSet = new boolean[maxIdx]; 524 int i=1; // index of the current character 525 526 while(i<nChar){ 527 c = word.charAt(i); 528 if(Character.isDigit(c)){ 529 if(idx==-1) 530 idx = 0; 531 idx = idx*10+ (c-'0'); 532 } 533 else{ 534 if(idx==-1 || (c!=',' && c!='-')){ 535 throw new IllegalArgumentException("Bad construction for "+ 536 "parameter: "+word); 537 } 538 if(idx<0 || idx>=maxIdx){ 539 throw new IllegalArgumentException("Out of range index in "+ 540 "parameter `"+word+"' : "+ 541 +idx); 542 } 543 544 // Found a comma 545 if(c==','){ 546 if(isDash){ // Previously found a dash, fill idxSet 547 for(int j=lastIdx+1; j<idx; j++){ 548 idxSet[j] = true; 549 } 550 } 551 isDash = false; 552 } 553 else // Found a dash 554 isDash = true; 555 556 // Udate idxSet 557 idxSet[idx] = true; 558 lastIdx = idx; 559 idx=-1; 560 } 561 i++; 562 } 563 564 // Process last found index 565 if(idx<0 || idx>=maxIdx){ 566 throw new IllegalArgumentException("Out of range index in "+ 567 "parameter `"+word+"' : "+idx); 568 } 569 if(isDash) 570 for(int j=lastIdx+1; j<idx; j++){ 571 idxSet[j] = true; 572 } 573 idxSet[idx] = true; 574 575 return idxSet; 576 } 577 578 /** 579 * Returns a tile-component representative using default value. 580 * 581 * @return Tile component index in an array (first element: tile 582 * index, second element: component index). 583 * */ 584/* 585 public int[] getDefRep(){ 586 int[] tcidx = new int[2]; 587 for(int t=nTiles-1; t>=0; t--){ 588 for(int c=nComp-1; c>=0; c--){ 589 if(specValType[t][c]==SPEC_DEF){ 590 tcidx[0] = t; 591 tcidx[1] = c; 592 return tcidx; 593 } 594 } 595 } 596 597 throw new IllegalArgumentException("No representative for "+ 598 "default value"); 599 } 600*/ 601 /** 602 * Returns a component representative using tile default value. 603 * 604 * @param t Tile index 605 * 606 * @return component index of the representant 607 * */ 608/* 609 public int getTileDefRep(int t){ 610 for(int c=nComp-1; c>=0; c--) 611 if(specValType[t][c]==SPEC_TILE_DEF){ 612 return c; 613 } 614 615 throw new IllegalArgumentException("No representative for tile "+ 616 "default value"); 617 } 618*/ 619 /** 620 * Returns a tile representative using component default value. 621 * 622 * @param c Component index 623 * 624 * @return tile index of the representant 625 * */ 626/* 627 public int getCompDefRep(int c){ 628 for(int t=nTiles-1; t>=0; t--) { 629 if(specValType[t][c]==SPEC_COMP_DEF){ 630 return t; 631 } 632 } 633 634 throw new IllegalArgumentException("No representative for component "+ 635 "default value, c="+c); 636 } 637*/ 638/* 639 public String getSpecified() { 640 return specified; 641 } 642*/ 643}