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