001/* 002 * $RCSfile: CBlkSizeSpec.java,v $ 003 * $Revision: 1.1 $ 004 * $Date: 2005/02/11 05:02:04 $ 005 * $State: Exp $ 006 * 007 * Class: CBlkSizeSpec 008 * 009 * Description: Specification of the code-blocks size 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 * */ 044package jj2000.j2k.entropy; 045 046import jj2000.j2k.codestream.*; 047import jj2000.j2k.wavelet.*; 048import jj2000.j2k.image.*; 049import jj2000.j2k.util.*; 050import jj2000.j2k.*; 051 052import java.util.*; 053 054import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriteParamJava; 055/** 056 * This class extends ModuleSpec class for code-blocks sizes holding purposes. 057 * 058 * <P>It stores the size a of code-block. 059 * */ 060public class CBlkSizeSpec extends ModuleSpec { 061 062 private String defaultValue = "64 64"; 063 064 /** Name of the option */ 065 private static final String optName = "Cblksiz"; 066 067 /** The maximum code-block width */ 068 private int maxCBlkWidth = 0; 069 070 /** The maximum code-block height */ 071 private int maxCBlkHeight = 0; 072 073 /** 074 * Creates a new CBlkSizeSpec object for the specified number of tiles and 075 * components. 076 * 077 * @param nt The number of tiles 078 * 079 * @param nc The number of components 080 * 081 * @param type the type of the specification module i.e. tile specific, 082 * component specific or both. 083 * */ 084 public CBlkSizeSpec(int nt, int nc, byte type) { 085 super(nt, nc, type); 086 } 087 088 /** 089 * Creates a new CBlkSizeSpec object for the specified number of tiles and 090 * components and the ParameterList instance. 091 * 092 * @param nt The number of tiles 093 * 094 * @param nc The number of components 095 * 096 * @param type the type of the specification module i.e. tile specific, 097 * component specific or both. 098 * 099 * @param imgsrc The image source (used to get the image size) 100 * 101 * @param pl The ParameterList instance 102 * */ 103 public CBlkSizeSpec(int nt, int nc, byte type, J2KImageWriteParamJava wp, String values) { 104 super(nt, nc, type); 105 106 boolean firstVal = true; 107 specified = values; 108 109 String param = values; //"64 64"; 110 if (param == null) 111 param = defaultValue; // the default 112 //pl.getParameter(optName); 113 114 // Precinct partition is used : parse arguments 115 StringTokenizer stk = new StringTokenizer(param); 116 byte curSpecType = SPEC_DEF; // Specification type of the 117 // current parameter 118 boolean[] tileSpec = null; // Tiles concerned by the specification 119 boolean[] compSpec = null; // Components concerned by the specification 120 int i, xIdx, ci, ti; 121 String word = null; // current word 122 String errMsg = null; 123 124 while( stk.hasMoreTokens() ) { 125 word = stk.nextToken(); 126 127 switch(word.charAt(0)){ 128 129 case 't': // Tiles specification 130 tileSpec = parseIdx(word, nTiles); 131 if(curSpecType==SPEC_COMP_DEF) { 132 curSpecType = SPEC_TILE_COMP; 133 } 134 else { 135 curSpecType = SPEC_TILE_DEF; 136 } 137 break; 138 139 case 'c': // Components specification 140 compSpec = parseIdx(word, nComp); 141 if(curSpecType==SPEC_TILE_DEF) { 142 curSpecType = SPEC_TILE_COMP; 143 } 144 else { 145 curSpecType = SPEC_COMP_DEF; 146 } 147 break; 148 149 default: 150 if ( !Character.isDigit(word.charAt(0)) ) { 151 errMsg = "Bad construction for parameter: "+word; 152 throw new IllegalArgumentException(errMsg); 153 } 154 Integer dim[] = new Integer[2]; 155 // Get code-block's width 156 try { 157 dim[0] = new Integer(word); 158 // Check that width is not > 159 // StdEntropyCoderOptions.MAX_CB_DIM 160 if( dim[0].intValue()>StdEntropyCoderOptions.MAX_CB_DIM ){ 161 errMsg = "'"+optName+"' option : the code-block's "+ 162 "width cannot be greater than "+ 163 StdEntropyCoderOptions.MAX_CB_DIM; 164 throw new IllegalArgumentException(errMsg); 165 } 166 // Check that width is not < 167 // StdEntropyCoderOptions.MIN_CB_DIM 168 if( dim[0].intValue()<StdEntropyCoderOptions.MIN_CB_DIM ){ 169 errMsg = "'"+optName+"' option : the code-block's "+ 170 "width cannot be less than "+ 171 StdEntropyCoderOptions.MIN_CB_DIM; 172 throw new IllegalArgumentException(errMsg); 173 } 174 // Check that width is a power of 2 175 if ( dim[0].intValue() != 176 (1<<MathUtil.log2(dim[0].intValue())) ) { 177 errMsg = "'"+optName+"' option : the code-block's "+ 178 "width must be a power of 2"; 179 throw new IllegalArgumentException(errMsg); 180 } 181 } 182 catch( NumberFormatException e) { 183 errMsg = "'"+optName+"' option : the code-block's "+ 184 "width could not be parsed."; 185 throw new IllegalArgumentException(errMsg); 186 } 187 // Get the next word in option 188 try { 189 word = stk.nextToken(); 190 } 191 catch (NoSuchElementException e) { 192 errMsg = "'"+optName+"' option : could not parse the "+ 193 "code-block's height"; 194 throw new IllegalArgumentException(errMsg); 195 196 } 197 // Get the code-block's height 198 try { 199 dim[1] = new Integer(word); 200 // Check that height is not > 201 // StdEntropyCoderOptions.MAX_CB_DIM 202 if ( dim[1].intValue()>StdEntropyCoderOptions.MAX_CB_DIM ){ 203 errMsg = "'"+optName+"' option : the code-block's "+ 204 "height cannot be greater than "+ 205 StdEntropyCoderOptions.MAX_CB_DIM; 206 throw new IllegalArgumentException(errMsg); 207 } 208 // Check that height is not < 209 // StdEntropyCoderOptions.MIN_CB_DIM 210 if ( dim[1].intValue()<StdEntropyCoderOptions.MIN_CB_DIM ){ 211 errMsg = "'"+optName+"' option : the code-block's "+ 212 "height cannot be less than "+ 213 StdEntropyCoderOptions.MIN_CB_DIM; 214 throw new IllegalArgumentException(errMsg); 215 } 216 // Check that height is a power of 2 217 if ( dim[1].intValue() != 218 (1<<MathUtil.log2(dim[1].intValue())) ) { 219 errMsg = "'"+optName+"' option : the code-block's "+ 220 "height must be a power of 2"; 221 throw new IllegalArgumentException(errMsg); 222 } 223 // Check that the code-block 'area' (i.e. width*height) is 224 // not greater than StdEntropyCoderOptions.MAX_CB_AREA 225 if ( dim[0].intValue()*dim[1].intValue() > 226 StdEntropyCoderOptions.MAX_CB_AREA ) 227 { 228 errMsg = "'"+optName+"' option : The "+ 229 "code-block's area (i.e. width*height) "+ 230 "cannot be greater than "+ 231 StdEntropyCoderOptions.MAX_CB_AREA; 232 throw new IllegalArgumentException(errMsg); 233 } 234 } 235 catch( NumberFormatException e) { 236 errMsg = "'"+optName+"' option : the code-block's height "+ 237 "could not be parsed."; 238 throw new IllegalArgumentException(errMsg); 239 } 240 241 // Store the maximum dimensions if necessary 242 if ( dim[0].intValue() > maxCBlkWidth ) { 243 maxCBlkWidth = dim[0].intValue(); 244 } 245 246 if ( dim[1].intValue() > maxCBlkHeight ) { 247 maxCBlkHeight = dim[1].intValue(); 248 } 249 250 if ( firstVal ) { 251 // This is the first time a value is given so we set it as 252 // the default one 253 setDefault(dim); 254 firstVal = false; 255 } 256 257 switch (curSpecType) { 258 case SPEC_DEF: 259 setDefault(dim); 260 break; 261 case SPEC_TILE_DEF: 262 for(ti=tileSpec.length-1; ti>=0; ti--) { 263 if( tileSpec[ti] ){ 264 setTileDef(ti,dim); 265 } 266 } 267 break; 268 case SPEC_COMP_DEF: 269 for(ci=compSpec.length-1; ci>=0; ci--) { 270 if( compSpec[ci] ){ 271 setCompDef(ci,dim); 272 } 273 } 274 break; 275 default: 276 for(ti=tileSpec.length-1; ti>=0; ti--){ 277 for(ci=compSpec.length-1; ci>=0 ; ci--){ 278 if(tileSpec[ti] && compSpec[ci]){ 279 setTileCompVal(ti,ci,dim); 280 } 281 } 282 } 283 break; 284 } 285 } // end switch 286 } 287 } 288 289 /** 290 * Returns the maximum code-block's width 291 * 292 */ 293 public int getMaxCBlkWidth() { 294 return maxCBlkWidth; 295 } 296 297 /** 298 * Returns the maximum code-block's height 299 * 300 */ 301 public int getMaxCBlkHeight() { 302 return maxCBlkHeight; 303 } 304 305 /** 306 * Returns the code-block width : 307 * 308 * <ul> 309 * <li>for the specified tile/component</li> 310 * <li>for the specified tile</li> 311 * <li>for the specified component</li> 312 * <li>default value</li> 313 * </ul> 314 * 315 * The value returned depends on the value of the variable 'type' which 316 * can take the following values :<br> 317 * 318 * <ul> 319 * <li>SPEC_DEF -> Default value is returned. t and c values are 320 * ignored</li> 321 * <li>SPEC_COMP_DEF -> Component default value is returned. t value is 322 * ignored</li> 323 * <li>SPEC_TILE_DEF -> Tile default value is returned. c value is 324 * ignored</li> 325 * <li>SPEC_TILE_COMP -> Tile/Component value is returned.</li> 326 * </ul> 327 * 328 * @param type The type of the value we want to be returned 329 * 330 * @param t The tile index 331 * 332 * @param c the component index 333 * 334 * @return The code-block width for the specified tile and component 335 * */ 336 public int getCBlkWidth(byte type, int t, int c) { 337 Integer dim[] = null; 338 switch (type) { 339 case SPEC_DEF: 340 dim = (Integer[])getDefault(); 341 break; 342 case SPEC_COMP_DEF: 343 dim = (Integer[])getCompDef(c); 344 break; 345 case SPEC_TILE_DEF: 346 dim = (Integer[])getTileDef(t); 347 break; 348 case SPEC_TILE_COMP: 349 dim = (Integer[])getTileCompVal(t, c); 350 } 351 return dim[0].intValue(); 352 } 353 354 /** 355 * Returns the code-block height: 356 * 357 * <ul> 358 * <li>for the specified tile/component</li> 359 * <li>for the specified tile</li> 360 * <li>for the specified component</li> 361 * <li>default value</li> 362 * </ul> 363 * 364 * The value returned depends on the value of the variable 'type' which 365 * can take the following values : 366 * 367 * <ul> 368 * <li>SPEC_DEF -> Default value is returned. t and c values are 369 * ignored</li> 370 * <li>SPEC_COMP_DEF -> Component default value is returned. t value is 371 * ignored</li> 372 * <li>SPEC_TILE_DEF -> Tile default value is returned. c value is 373 * ignored</li> 374 * <li>SPEC_TILE_COMP -> Tile/Component value is returned.</li> 375 * </ul> 376 * 377 * @param type The type of the value we want to be returned 378 * 379 * @param t The tile index 380 * 381 * @param c the component index 382 * 383 * @return The code-block height for the specified tile and component 384 * */ 385 public int getCBlkHeight(byte type, int t, int c) { 386 Integer dim[] = null; 387 switch (type) { 388 case SPEC_DEF: 389 dim = (Integer[])getDefault(); 390 break; 391 case SPEC_COMP_DEF: 392 dim = (Integer[])getCompDef(c); 393 break; 394 case SPEC_TILE_DEF: 395 dim = (Integer[])getTileDef(t); 396 break; 397 case SPEC_TILE_COMP: 398 dim = (Integer[])getTileCompVal(t, c); 399 } 400 return dim[1].intValue(); 401 } 402 403 /** 404 * Sets default value for this module 405 * 406 * @param value Default value 407 * */ 408 public void setDefault(Object value){ 409 super.setDefault(value); 410 411 // Store the biggest code-block dimensions 412 storeHighestDims((Integer[])value); 413 } 414 415 /** 416 * Sets default value for specified tile and specValType tag if allowed by 417 * its priority. 418 * 419 * @param c Tile index. 420 * 421 * @param value Tile's default value 422 * */ 423 public void setTileDef(int t, Object value){ 424 super.setTileDef(t, value); 425 426 // Store the biggest code-block dimensions 427 storeHighestDims((Integer[])value); 428 } 429 430 /** 431 * Sets default value for specified component and specValType tag if 432 * allowed by its priority. 433 * 434 * @param c Component index 435 * 436 * @param value Component's default value 437 * */ 438 public void setCompDef(int c, Object value){ 439 super.setCompDef(c, value); 440 441 // Store the biggest code-block dimensions 442 storeHighestDims((Integer[])value); 443 } 444 445 /** 446 * Sets value for specified tile-component. 447 * 448 * @param t Tie index 449 * 450 * @param c Component index 451 * 452 * @param value Tile-component's value 453 * */ 454 public void setTileCompVal(int t,int c, Object value){ 455 super.setTileCompVal(t, c, value); 456 457 // Store the biggest code-block dimensions 458 storeHighestDims((Integer[])value); 459 } 460 461 /** 462 * Stores the highest code-block width and height 463 * 464 * @param dim The 2 elements array that contains the code-block width and 465 * height. 466 * */ 467 private void storeHighestDims(Integer[] dim){ 468 // Store the biggest code-block dimensions 469 if ( dim[0].intValue() > maxCBlkWidth ) { 470 maxCBlkWidth = dim[0].intValue(); 471 } 472 if ( dim[1].intValue() > maxCBlkHeight ) { 473 maxCBlkHeight = dim[1].intValue(); 474 } 475 } 476}