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