001/* 002 * $RCSfile: PrecinctSizeSpec.java,v $ 003 * $Revision: 1.1 $ 004 * $Date: 2005/02/11 05:02:04 $ 005 * $State: Exp $ 006 * 007 * Class: PrecinctSizeSpec 008 * 009 * Description: Specification of the precinct sizes 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.*; 053import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriteParamJava; 054 055/** 056 * This class extends ModuleSpec class for precinct partition sizes holding 057 * purposes. 058 * 059 * <p>It stores the size a of precinct when precinct partition is used or not. 060 * If precinct partition is used, we can have several packets for a given 061 * resolution level whereas there is only one packet per resolution level if 062 * no precinct partition is used. 063 * */ 064public class PrecinctSizeSpec extends ModuleSpec { 065 066 /** Name of the option */ 067 private static final String optName = "Cpp"; 068 069 /** Reference to wavelet number of decomposition levels for each 070 * tile-component. */ 071 private IntegerSpec dls; 072 073 /** 074 * Creates a new PrecinctSizeSpec object for the specified number of tiles 075 * and 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 * @param dls Reference to the number of decomposition levels 085 * specification 086 * */ 087 public PrecinctSizeSpec(int nt, int nc, byte type, IntegerSpec dls) { 088 super(nt, nc, type); 089 this.dls = dls; 090 } 091 092 /** 093 * Creates a new PrecinctSizeSpec object for the specified number of tiles 094 * and components and the J2KImageWriteParamJava instance. 095 * 096 * @param nt The number of tiles 097 * 098 * @param nc The number of components 099 * 100 * @param type the type of the specification module i.e. tile specific, 101 * component specific or both. 102 * 103 * @param imgsrc The image source (used to get the image size) 104 * 105 * @param wp The J2KImageWriteParamJava instance 106 * */ 107 public PrecinctSizeSpec(int nt, int nc, byte type, BlkImgDataSrc imgsrc, 108 IntegerSpec dls, J2KImageWriteParamJava wp, String values) { 109 super(nt, nc, type); 110 111 this.dls = dls; 112 113 // The precinct sizes are stored in a 2 elements vector array, the 114 // first element containing a vector for the precincts width for each 115 // resolution level and the second element containing a vector for the 116 // precincts height for each resolution level. The precincts sizes are 117 // specified from the highest resolution level to the lowest one 118 // (i.e. 0). If there are less elements than the number of 119 // decomposition levels, the last element is used for all remaining 120 // resolution levels (i.e. if the precincts sizes are specified only 121 // for resolutions levels 5, 4 and 3, then the precincts size for 122 // resolution levels 2, 1 and 0 will be the same as the size used for 123 // resolution level 3). 124 125 // Boolean used to know if we were previously reading a precinct's 126 // size or if we were reading something else. 127 boolean wasReadingPrecinctSize = false; 128 129 String param = values; 130/* 131 if (values == null) 132 param = defaultValue; // the default is null 133*/ 134 // Set precinct sizes to default i.e. 2^15 = 135 // Markers.PRECINCT_PARTITION_DEF_SIZE 136 Vector tmpv[] = new Vector[2]; 137 tmpv[0] = new Vector(); // ppx 138 tmpv[0].addElement(new Integer(Markers.PRECINCT_PARTITION_DEF_SIZE)); 139 tmpv[1] = new Vector(); // ppy 140 tmpv[1].addElement(new Integer(Markers.PRECINCT_PARTITION_DEF_SIZE)); 141 setDefault(tmpv); 142 143 if ( param==null ) { 144 // No precinct size specified in the command line so we do not try 145 // to parse it. 146 return; 147 } 148 149 // Precinct partition is used : parse arguments 150 StringTokenizer stk = new StringTokenizer(param); 151 byte curSpecType = SPEC_DEF; // Specification type of the 152 // current parameter 153 boolean[] tileSpec = null; // Tiles concerned by the specification 154 boolean[] compSpec = null; // Components concerned by the specification 155 int i, xIdx, ci, ti; 156 157 boolean endOfParamList = false; 158 String word = null; // current word 159 Integer w, h; 160 String errMsg = null; 161 162 while((stk.hasMoreTokens() || wasReadingPrecinctSize) && 163 !endOfParamList){ 164 165 Vector v[] = new Vector[2]; // v[0] : ppx, v[1] : ppy 166 167 // We do not read the next token if we were reading a precinct's 168 // size argument as we have already read the next token into word. 169 if ( !wasReadingPrecinctSize ) { 170 word = stk.nextToken(); 171 } 172 173 wasReadingPrecinctSize = false; 174 175 switch(word.charAt(0)){ 176 177 case 't': // Tiles specification 178 tileSpec = parseIdx(word,nTiles); 179 if(curSpecType==SPEC_COMP_DEF) { 180 curSpecType = SPEC_TILE_COMP; 181 } 182 else { 183 curSpecType = SPEC_TILE_DEF; 184 } 185 break; 186 187 case 'c': // Components specification 188 compSpec = parseIdx(word,nComp); 189 if(curSpecType==SPEC_TILE_DEF) { 190 curSpecType = SPEC_TILE_COMP; 191 } 192 else { 193 curSpecType = SPEC_COMP_DEF; 194 } 195 break; 196 197 default: 198 if ( !Character.isDigit(word.charAt(0)) ) { 199 errMsg = "Bad construction for parameter: "+word; 200 throw new IllegalArgumentException(errMsg); 201 } 202 203 // Initialises Vector objects 204 v[0] = new Vector(); // ppx 205 v[1] = new Vector(); // ppy 206 207 while ( true ) { 208 209 // Now get the precinct dimensions 210 try { 211 // Get precinct width 212 w = new Integer(word); 213 214 // Get next word in argument list 215 try { 216 word = stk.nextToken(); 217 } 218 catch (NoSuchElementException e) { 219 errMsg = "'"+optName+"' option : could not "+ 220 "parse the precinct's width"; 221 throw new IllegalArgumentException(errMsg); 222 223 } 224 // Get precinct height 225 h = new Integer(word); 226 if (w.intValue() != (1<<MathUtil.log2(w.intValue())) 227 || h.intValue() != 228 (1<<MathUtil.log2(h.intValue())) ) { 229 errMsg = "Precinct dimensions must be powers of 2"; 230 throw new IllegalArgumentException(errMsg); 231 } 232 } 233 catch( NumberFormatException e) { 234 errMsg = "'"+optName+"' option : the argument '"+word+ 235 "' could not be parsed."; 236 throw new IllegalArgumentException(errMsg); 237 } 238 // Store packet's dimensions in Vector arrays 239 v[0].addElement(w); 240 v[1].addElement(h); 241 242 // Try to get the next token 243 if ( stk.hasMoreTokens() ) { 244 word = stk.nextToken(); 245 if ( !Character.isDigit(word.charAt(0)) ) { 246 // The next token does not start with a digit so 247 // it is not a precinct's size argument. We set 248 // the wasReadingPrecinctSize booleen such that we 249 // know that we don't have to read another token 250 // and check for the end of the parameters list. 251 wasReadingPrecinctSize = true; 252 253 if(curSpecType==SPEC_DEF){ 254 setDefault(v); 255 } 256 else if(curSpecType==SPEC_TILE_DEF){ 257 for(ti=tileSpec.length-1; ti>=0; ti--) { 258 if( tileSpec[ti] ){ 259 setTileDef(ti,v); 260 } 261 } 262 } 263 else if(curSpecType==SPEC_COMP_DEF){ 264 for(ci=compSpec.length-1; ci>=0; ci--) { 265 if( compSpec[ci] ){ 266 setCompDef(ci,v); 267 } 268 } 269 } 270 else{ 271 for(ti=tileSpec.length-1; ti>=0; ti--){ 272 for(ci=compSpec.length-1; ci>=0 ; ci--){ 273 if(tileSpec[ti] && compSpec[ci]){ 274 setTileCompVal(ti,ci,v); 275 } 276 } 277 } 278 } 279 // Re-initialize 280 curSpecType = SPEC_DEF; 281 tileSpec = null; 282 compSpec = null; 283 284 // Go back to 'normal' parsing 285 break; 286 } 287 else { 288 // Next token starts with a digit so read it 289 } 290 } 291 else { 292 // We have reached the end of the parameters list so 293 // we store the last precinct's sizes and we stop 294 if(curSpecType==SPEC_DEF){ 295 setDefault(v); 296 } 297 else if(curSpecType==SPEC_TILE_DEF){ 298 for(ti=tileSpec.length-1; ti>=0; ti--) { 299 if( tileSpec[ti] ){ 300 setTileDef(ti,v); 301 } 302 } 303 } 304 else if(curSpecType==SPEC_COMP_DEF){ 305 for(ci=compSpec.length-1; ci>=0; ci--) { 306 if( compSpec[ci] ){ 307 setCompDef(ci,v); 308 } 309 } 310 } 311 else{ 312 for(ti=tileSpec.length-1; ti>=0; ti--){ 313 for(ci=compSpec.length-1; ci>=0 ; ci--){ 314 if( tileSpec[ti] && compSpec[ci] ){ 315 setTileCompVal(ti,ci,v); 316 } 317 } 318 } 319 } 320 endOfParamList = true; 321 break; 322 } 323 } // while (true) 324 break; 325 } // switch 326 } // while 327 } 328 329 /** 330 * Returns the precinct partition width in component 'n' and tile 't' at 331 * resolution level 'rl'. If the tile index is equal to -1 or if the 332 * component index is equal to -1 it means that those should not be taken 333 * into account. 334 * 335 * @param t The tile index, in raster scan order. Specify -1 if it is not 336 * a specific tile. 337 * 338 * @param c The component index. Specify -1 if it is not a specific 339 * component. 340 * 341 * @param rl The resolution level 342 * 343 * @return The precinct partition width in component 'c' and tile 't' at 344 * resolution level 'rl'. 345 * */ 346 public int getPPX(int t, int c, int rl) { 347 int mrl, idx; 348 Vector[] v=null; 349 boolean tileSpecified = (t!=-1 ? true : false); 350 boolean compSpecified = (c!=-1 ? true : false); 351 352 // Get the maximum number of decomposition levels and the object 353 // (Vector array) containing the precinct dimensions (width and 354 // height) for the specified (or not) tile/component 355 if ( tileSpecified && compSpecified ) { 356 mrl = ((Integer)dls.getTileCompVal(t, c)).intValue(); 357 v = (Vector[])getTileCompVal(t, c); 358 } 359 else if ( tileSpecified && !compSpecified ) { 360 mrl = ((Integer)dls.getTileDef(t)).intValue(); 361 v = (Vector[])getTileDef(t); 362 } 363 else if ( !tileSpecified && compSpecified ) { 364 mrl = ((Integer)dls.getCompDef(c)).intValue(); 365 v = (Vector[])getCompDef(c); 366 } 367 else { 368 mrl = ((Integer)dls.getDefault()).intValue(); 369 v = (Vector[])getDefault(); 370 } 371 idx = mrl - rl; 372 if ( v[0].size() > idx ) { 373 return ((Integer)v[0].elementAt(idx)).intValue(); 374 } 375 else { 376 return ((Integer)v[0].elementAt(v[0].size()-1)).intValue(); 377 } 378 } 379 380 /** 381 * Returns the precinct partition height in component 'n' and tile 't' at 382 * resolution level 'rl'. If the tile index is equal to -1 or if the 383 * component index is equal to -1 it means that those should not be taken 384 * into account. 385 * 386 * @param t The tile index, in raster scan order. Specify -1 if it is not 387 * a specific tile. 388 * 389 * @param c The component index. Specify -1 if it is not a specific 390 * component. 391 * 392 * @param rl The resolution level. 393 * 394 * @return The precinct partition width in component 'n' and tile 't' at 395 * resolution level 'rl'. 396 * */ 397 public int getPPY(int t, int c, int rl) { 398 int mrl, idx; 399 Vector[] v=null; 400 boolean tileSpecified = (t!=-1 ? true : false); 401 boolean compSpecified = (c!=-1 ? true : false); 402 403 // Get the maximum number of decomposition levels and the object 404 // (Vector array) containing the precinct dimensions (width and 405 // height) for the specified (or not) tile/component 406 if ( tileSpecified && compSpecified ) { 407 mrl = ((Integer)dls.getTileCompVal(t, c)).intValue(); 408 v = (Vector[])getTileCompVal(t, c); 409 } 410 else if ( tileSpecified && !compSpecified ) { 411 mrl = ((Integer)dls.getTileDef(t)).intValue(); 412 v = (Vector[])getTileDef(t); 413 } 414 else if ( !tileSpecified && compSpecified ) { 415 mrl = ((Integer)dls.getCompDef(c)).intValue(); 416 v = (Vector[])getCompDef(c); 417 } 418 else { 419 mrl = ((Integer)dls.getDefault()).intValue(); 420 v = (Vector[])getDefault(); 421 } 422 idx = mrl - rl; 423 if ( v[1].size() > idx ) { 424 return ((Integer)v[1].elementAt(idx)).intValue(); 425 } 426 else { 427 return ((Integer)v[1].elementAt(v[1].size()-1)).intValue(); 428 } 429 } 430}