001/* 002 * $RCSfile: InvCompTransf.java,v $ 003 * $Revision: 1.1 $ 004 * $Date: 2005/02/11 05:02:14 $ 005 * $State: Exp $ 006 * 007 * Class: InvCompTransf 008 * 009 * Description: Inverse Component transformations applied to tiles 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.image.invcomptransf; 045 046import jj2000.j2k.ModuleSpec; 047import jj2000.j2k.decoder.DecoderSpecs; 048import jj2000.j2k.image.BlkImgDataSrc; 049import jj2000.j2k.image.CompTransfSpec; 050import jj2000.j2k.image.DataBlk; 051import jj2000.j2k.image.DataBlkFloat; 052import jj2000.j2k.image.DataBlkInt; 053import jj2000.j2k.image.ImgDataAdapter; 054import jj2000.j2k.util.MathUtil; 055import jj2000.j2k.wavelet.synthesis.SynWTFilterSpec; 056 057/** 058 * This class apply inverse component transformations to the tiles depending 059 * on specification read from the codestream header. These transformations can 060 * be used to improve compression efficiency but are not related to colour 061 * transforms used to map colour values for display purposes. JPEG 2000 part I 062 * defines 2 component transformations: RCT (Reversible Component 063 * Transformation) and ICT (Irreversible Component Transformation). 064 * 065 * @see ModuleSpec 066 * */ 067public class InvCompTransf extends ImgDataAdapter 068 implements BlkImgDataSrc{ 069 070 /** Identifier for no component transformation. Value is 0. */ 071 public static final int NONE = 0; 072 073 /** The prefix for inverse component transformation options: 'M' */ 074 public final static char OPT_PREFIX = 'M'; 075 076 /** The list of parameters that is accepted by the inverse 077 * component transformation module. They start with 'M'. */ 078 private final static String [][] pinfo = null; 079 080 /** Identifier for the Inverse Reversible Component Transformation 081 (INV_RCT). Value is 1. */ 082 public static final int INV_RCT = 1; 083 084 /** Identifier for the Inverse Irreversible Component 085 Transformation (INV_ICT). Value is 2 */ 086 public static final int INV_ICT = 2; 087 088 /** The source of image data */ 089 private BlkImgDataSrc src; 090 091 /** The component transformations specifications */ 092 private CompTransfSpec cts; 093 094 /** The wavelet filter specifications */ 095 private SynWTFilterSpec wfs; 096 097 /** The type of the current component transformation JPEG 2000 098 * part I only support NONE, FORW_RCT and FORW_ICT types*/ 099 private int transfType = NONE; 100 101 /** Buffer for each component of output data */ 102 private int[][] outdata = new int[3][]; 103 104 /** Block used to request component 0 */ 105 private DataBlk block0; 106 107 /** Block used to request component 1 */ 108 private DataBlk block1; 109 110 /** Block used to request component 2 */ 111 private DataBlk block2; 112 113 /** Data block used only to store coordinates and progressiveness 114 of the buffered blocks */ 115 private DataBlkInt dbi = new DataBlkInt(); 116 117 /** The bit-depths of un-transformed components */ 118 private int utdepth[]; 119 120 /** Flag indicating whether the decoder should skip the component 121 * transform*/ 122 private boolean noCompTransf = false; 123 124 /** 125 * Constructs a new ForwCompTransf object that operates on the 126 * specified source of image data. 127 * 128 * @param imgSrc The source from where to get the data to be 129 * transformed 130 * 131 * @param decSpec The decoder specifications 132 * 133 * @see BlkImgDataSrc 134 * */ 135 public InvCompTransf(BlkImgDataSrc imgSrc, DecoderSpecs decSpec, 136 int[] utdepth) { 137 super(imgSrc); 138 this.cts = decSpec.cts; 139 this.wfs = decSpec.wfs; 140 src = imgSrc; 141 this.utdepth = utdepth; 142 } 143 144 /** 145 * Returns the parameters that are used in this class and implementing 146 * classes. It returns a 2D String array. Each of the 1D arrays is for a 147 * different option, and they have 4 elements. The first element is the 148 * option name, the second one is the synopsis, the third one is a long 149 * description of what the parameter is and the fourth is its default 150 * value. The synopsis or description may be 'null', in which case it is 151 * assumed that there is no synopsis or description of the option, 152 * respectively. Null may be returned if no options are supported. 153 * 154 * @return the options name, their synopsis and their explanation, 155 * or null if no options are supported. 156 * */ 157 public static String[][] getParameterInfo() { 158 return pinfo; 159 } 160 161 /** 162 * Returns a string with a descriptive text of which inverse component 163 * transformation is used. This can be either "Inverse RCT" or "Inverse 164 * ICT" or "No component transformation" depending on the current tile. 165 * 166 * @return A descriptive string 167 * */ 168 public String toString() { 169 switch(transfType){ 170 case INV_RCT: 171 return "Inverse RCT"; 172 case INV_ICT: 173 return "Inverse ICT"; 174 case NONE: 175 return "No component transformation"; 176 default: 177 throw new IllegalArgumentException("Non JPEG 2000 part I"+ 178 " component transformation"); 179 } 180 } 181 182 /** 183 * Returns true if this transform is reversible in current 184 * tile. Reversible component transformations are those which operation 185 * can be completely reversed without any loss of information (not even 186 * due to rounding). 187 * 188 * @return Reversibility of component transformation in current 189 * tile 190 * */ 191 public boolean isReversible(){ 192 switch(transfType){ 193 case NONE: 194 case INV_RCT: 195 return true; 196 case INV_ICT: 197 return false; 198 default: 199 throw new IllegalArgumentException("Non JPEG 2000 part I"+ 200 " component transformation"); 201 } 202 } 203 204 /** 205 * Returns the position of the fixed point in the specified 206 * component. This is the position of the least significant integral 207 * (i.e. non-fractional) bit, which is equivalent to the number of 208 * fractional bits. For instance, for fixed-point values with 2 fractional 209 * bits, 2 is returned. For floating-point data this value does not apply 210 * and 0 should be returned. Position 0 is the position of the least 211 * significant bit in the data. 212 * 213 * <P>This default implementation assumes that the number of fractional 214 * bits is not modified by the component mixer. 215 * 216 * @param c The index of the component. 217 * 218 * @return The value of the fixed point position of the source since the 219 * color transform does not affect it. 220 * */ 221 public int getFixedPoint(int c) { 222 return src.getFixedPoint(c); 223 } 224 225 /** 226 * Calculates the bitdepths of the transformed components, given the 227 * bitdepth of the un-transformed components and the component 228 * tranformation type. 229 * 230 * @param utdepth The bitdepth of each un-transformed component 231 * 232 * @param ttype The type ID of the inverse component tranformation 233 * 234 * @param tdepth If not null the results are stored in this 235 * array, otherwise a new array is allocated and returned. 236 * 237 * @return The bitdepth of each transformed component. 238 * */ 239 public static 240 int[] calcMixedBitDepths(int utdepth[], int ttype, int tdepth[]) { 241 242 if (utdepth.length < 3 && ttype != NONE) { 243 throw new IllegalArgumentException(); 244 } 245 246 if (tdepth == null) { 247 tdepth = new int[utdepth.length]; 248 } 249 250 switch (ttype) { 251 case NONE: 252 System.arraycopy(utdepth,0,tdepth,0,utdepth.length); 253 break; 254 case INV_RCT: 255 if (utdepth.length >3) { 256 System.arraycopy(utdepth,3,tdepth,3,utdepth.length-3); 257 } 258 // The formulas are: 259 // tdepth[0] = ceil(log2(2^(utdepth[0])+2^utdepth[1]+ 260 // 2^(utdepth[2])))-2+1 261 // tdepth[1] = ceil(log2(2^(utdepth[0])+2^(utdepth[1])-1))+1 262 // tdepth[2] = ceil(log2(2^(utdepth[1])+2^(utdepth[2])-1))+1 263 // The MathUtil.log2(x) function calculates floor(log2(x)), so we 264 // use 'MathUtil.log2(2*x-1)+1', which calculates ceil(log2(x)) 265 // for any x>=1, x integer. 266 tdepth[0] = MathUtil.log2((1<<utdepth[0])+(2<<utdepth[1])+ 267 (1<<utdepth[2])-1)-2+1; 268 tdepth[1] = MathUtil.log2((1<<utdepth[2])+(1<<utdepth[1])-1)+1; 269 tdepth[2] = MathUtil.log2((1<<utdepth[0])+(1<<utdepth[1])-1)+1; 270 break; 271 case INV_ICT: 272 if (utdepth.length >3) { 273 System.arraycopy(utdepth,3,tdepth,3,utdepth.length-3); 274 } 275 // The MathUtil.log2(x) function calculates floor(log2(x)), so we 276 // use 'MathUtil.log2(2*x-1)+1', which calculates ceil(log2(x)) 277 // for any x>=1, x integer. 278 tdepth[0] = 279 MathUtil.log2((int)Math.floor((1<<utdepth[0])*0.299072+ 280 (1<<utdepth[1])*0.586914+ 281 (1<<utdepth[2])*0.114014)-1)+1; 282 tdepth[1] = 283 MathUtil.log2((int)Math.floor((1<<utdepth[0])*0.168701+ 284 (1<<utdepth[1])*0.331299+ 285 (1<<utdepth[2])*0.5)-1)+1; 286 tdepth[2] = 287 MathUtil.log2((int)Math.floor((1<<utdepth[0])*0.5+ 288 (1<<utdepth[1])*0.418701+ 289 (1<<utdepth[2])*0.081299)-1)+1; 290 break; 291 } 292 293 return tdepth; 294 } 295 296 /** 297 * Returns the number of bits, referred to as the "range bits", 298 * corresponding to the nominal range of the data in the specified 299 * component. If this number is <i>b</b> then for unsigned data the 300 * nominal range is between 0 and 2^b-1, and for signed data it is between 301 * -2^(b-1) and 2^(b-1)-1. 302 * 303 * @param c The index of the component. 304 * 305 * @return The bitdepth of un-transformed component 'c'. 306 * */ 307 public int getNomRangeBits(int c) { 308 return utdepth[c]; 309 } 310 311 /** 312 * Apply inverse component transformation associated with the current 313 * tile. If no component transformation has been requested by the user, 314 * data are not modified. 315 * 316 * <P>This method calls the getInternCompData() method, but respects the 317 * definitions of the getCompData() method defined in the BlkImgDataSrc 318 * interface. 319 * 320 * @param blk Determines the rectangular area to return, and the 321 * data is returned in this object. 322 * 323 * @param c Index of the output component. 324 * 325 * @return The requested DataBlk 326 * 327 * @see BlkImgDataSrc#getCompData 328 * */ 329 public DataBlk getCompData(DataBlk blk, int c){ 330 // If requesting a component whose index is greater than 3 or there is 331 // no transform return a copy of data (getInternCompData returns the 332 // actual data in those cases) 333 if (c>=3 || transfType == NONE) { 334 return src.getCompData(blk,c); 335 } 336 else { // We can use getInternCompData (since data is a copy anyways) 337 return getInternCompData(blk,c); 338 } 339 } 340 341 /** 342 * Apply the inverse component transformation associated with the current 343 * tile. If no component transformation has been requested by the user, 344 * data are not modified. Else, appropriate method is called (invRCT or 345 * invICT). 346 * 347 * @see #invRCT 348 * 349 * @see #invICT 350 * 351 * @param blk Determines the rectangular area to return. 352 * 353 * @param c Index of the output component. 354 * 355 * @return The requested DataBlk 356 * */ 357 public DataBlk getInternCompData(DataBlk blk, int c){ 358 // if specified in the command line that no component transform should 359 // be made, return original data 360 if(noCompTransf) 361 return src.getInternCompData(blk,c); 362 363 switch(transfType){ 364 case NONE: 365 return src.getInternCompData(blk,c); 366 case INV_RCT: 367 return invRCT(blk,c); 368 case INV_ICT: 369 return invICT(blk,c); 370 default: 371 throw new IllegalArgumentException("Non JPEG 2000 part I"+ 372 " component transformation"); 373 } 374 } 375 376 /** 377 * Apply inverse component transformation to obtain requested component 378 * from specified block of data. Whatever the type of requested DataBlk, 379 * it always returns a DataBlkInt. 380 * 381 * @param blk Determine the rectangular area to return 382 * 383 * @param c The index of the requested component 384 * 385 * @return Data of requested component 386 * */ 387 private DataBlk invRCT(DataBlk blk,int c){ 388 // If the component number is three or greater, return original data 389 if (c>=3 && c < getNumComps()) { 390 // Requesting a component whose index is greater than 3 391 return src.getInternCompData(blk,c); 392 } 393 394 // If asking a component for the first time for this block, 395 // do transform for the 3 components 396 if ((outdata[c] == null)|| 397 (dbi.ulx > blk.ulx) || (dbi.uly > blk.uly) || 398 (dbi.ulx+dbi.w < blk.ulx+blk.w) || 399 (dbi.uly+dbi.h < blk.uly+blk.h)) { 400 int k,k0,k1,k2,mink,i; 401 int w = blk.w; //width of output block 402 int h = blk.h; //height of ouput block 403 404 //Reference to output block data array 405 outdata[c] = (int[]) blk.getData(); 406 407 //Create data array of blk if necessary 408 if(outdata[c] == null || outdata[c].length!=h*w){ 409 outdata[c] = new int[h * w]; 410 blk.setData(outdata[c]); 411 } 412 413 outdata[(c+1)%3] = new int[outdata[c].length]; 414 outdata[(c+2)%3] = new int[outdata[c].length]; 415 416 if(block0==null || block0.getDataType()!=DataBlk.TYPE_INT) 417 block0 = new DataBlkInt(); 418 if(block1==null || block1.getDataType()!=DataBlk.TYPE_INT) 419 block1 = new DataBlkInt(); 420 if(block2==null || block2.getDataType()!=DataBlk.TYPE_INT) 421 block2 = new DataBlkInt(); 422 block0.w = block1.w = block2.w = blk.w; 423 block0.h = block1.h = block2.h = blk.h; 424 block0.ulx = block1.ulx = block2.ulx = blk.ulx; 425 block0.uly = block1.uly = block2.uly = blk.uly; 426 427 int data0[],data1[],data2[]; // input data arrays 428 429 // Fill in buffer blocks (to be read only) 430 // Returned blocks may have different size and position 431 block0 = (DataBlkInt)src.getInternCompData(block0, 0); 432 data0 = (int[]) block0.getData(); 433 block1 = (DataBlkInt)src.getInternCompData(block1, 1); 434 data1 = (int[]) block1.getData(); 435 block2 = (DataBlkInt)src.getInternCompData(block2, 2); 436 data2 = (int[]) block2.getData(); 437 438 // Set the progressiveness of the output data 439 blk.progressive = block0.progressive || block1.progressive || 440 block2.progressive; 441 blk.offset = 0; 442 blk.scanw = w; 443 444 // set attributes of the DataBlk used for buffering 445 dbi.progressive = blk.progressive; 446 dbi.ulx = blk.ulx; 447 dbi.uly = blk.uly; 448 dbi.w = blk.w; 449 dbi.h = blk.h; 450 451 // Perform conversion 452 453 // Initialize general indexes 454 k = w*h-1; 455 k0 = block0.offset+(h-1)*block0.scanw+w-1; 456 k1 = block1.offset+(h-1)*block1.scanw+w-1; 457 k2 = block2.offset+(h-1)*block2.scanw+w-1; 458 459 for( i = h-1; i >=0; i--){ 460 for(mink = k-w; k > mink; k--, k0--, k1--, k2--){ 461 outdata[1][k] = (data0[k0] - ((data1[k1]+data2[k2])>>2) ); 462 outdata[0][k] = data2[k2] + outdata[1][k]; 463 outdata[2][k] = data1[k1] + outdata[1][k]; 464 } 465 // Jump to beggining of previous line in input 466 k0 -= block0.scanw - w; 467 k1 -= block1.scanw - w; 468 k2 -= block2.scanw - w; 469 } 470 outdata[c] = null; 471 } 472 else if((c>=0)&&(c<=3)){ //Asking for the 2nd or 3rd block component 473 blk.setData(outdata[c]); 474 blk.progressive = dbi.progressive; 475 blk.offset = (blk.uly-dbi.uly)*dbi.w+blk.ulx-dbi.ulx; 476 blk.scanw = dbi.w; 477 outdata[c] = null; 478 } 479 else { 480 // Requesting a non valid component index 481 throw new IllegalArgumentException(); 482 } 483 return blk; 484 } 485 486 /** 487 * Apply inverse irreversible component transformation to obtain requested 488 * component from specified block of data. Whatever the type of requested 489 * DataBlk, it always returns a DataBlkFloat. 490 * 491 * @param blk Determine the rectangular area to return 492 * 493 * @param c The index of the requested component 494 * 495 * @return Data of requested component 496 * */ 497 private DataBlk invICT(DataBlk blk,int c){ 498 if(c>=3 && c<getNumComps()) { 499 // Requesting a component whose index is greater than 3 500 int k,k0,k1,k2,mink,i; 501 int w = blk.w; //width of output block 502 int h = blk.h; //height of ouput block 503 504 int outdata[]; // array of output data 505 506 //Reference to output block data array 507 outdata = (int[]) blk.getData(); 508 509 //Create data array of blk if necessary 510 if( outdata == null ) { 511 outdata = new int[h * w]; 512 blk.setData(outdata); 513 } 514 515 // Variables 516 DataBlkFloat indb = new DataBlkFloat(blk.ulx,blk.uly,w,h); 517 float indata[]; // input data array 518 519 // Get the input data 520 // (returned block may be larger than requested one) 521 src.getInternCompData(indb,c); 522 indata = (float[]) indb.getData(); 523 524 // Copy the data converting from int to int 525 k = w*h-1; 526 k0 = indb.offset+(h-1)*indb.scanw+w-1; 527 for (i=h-1; i >=0; i--) { 528 for (mink = k-w; k > mink; k--, k0--) { 529 outdata[k] = (int) (indata[k0]); 530 } 531 // Jump to beggining of previous line in input 532 k0 -= indb.scanw - w; 533 } 534 535 // Set the progressivity and offset 536 blk.progressive = indb.progressive; 537 blk.offset = 0; 538 blk.scanw = w; 539 } 540 541 // If asking a component for the first time for this block, 542 // do transform for the 3 components 543 else if((outdata[c] == null)|| 544 (dbi.ulx > blk.ulx) || (dbi.uly > blk.uly) || 545 (dbi.ulx+dbi.w < blk.ulx+blk.w) || 546 (dbi.uly+dbi.h < blk.uly+blk.h)) { 547 int k,k0,k1,k2,mink,i; 548 int w = blk.w; //width of output block 549 int h = blk.h; //height of ouput block 550 551 //Reference to output block data array 552 outdata[c] = (int[]) blk.getData(); 553 554 //Create data array of blk if necessary 555 if(outdata[c] == null || outdata[c].length!=w*h){ 556 outdata[c] = new int[h * w]; 557 blk.setData(outdata[c]); 558 } 559 560 outdata[(c+1)%3] = new int[outdata[c].length]; 561 outdata[(c+2)%3] = new int[outdata[c].length]; 562 563 if(block0==null || block0.getDataType()!=DataBlk.TYPE_FLOAT) 564 block0 = new DataBlkFloat(); 565 if(block2==null || block2.getDataType()!=DataBlk.TYPE_FLOAT) 566 block2 = new DataBlkFloat(); 567 if(block1==null || block1.getDataType()!=DataBlk.TYPE_FLOAT) 568 block1 = new DataBlkFloat(); 569 block0.w = block2.w = block1.w = blk.w; 570 block0.h = block2.h = block1.h = blk.h; 571 block0.ulx = block2.ulx = block1.ulx = blk.ulx; 572 block0.uly = block2.uly = block1.uly = blk.uly; 573 574 float data0[],data1[],data2[]; // input data arrays 575 576 // Fill in buffer blocks (to be read only) 577 // Returned blocks may have different size and position 578 block0 = (DataBlkFloat)src.getInternCompData(block0, 0); 579 data0 = (float[]) block0.getData(); 580 block2 = (DataBlkFloat)src.getInternCompData(block2, 1); 581 data2 = (float[]) block2.getData(); 582 block1 = (DataBlkFloat)src.getInternCompData(block1, 2); 583 data1 = (float[]) block1.getData(); 584 585 // Set the progressiveness of the output data 586 blk.progressive = block0.progressive || block1.progressive || 587 block2.progressive; 588 blk.offset = 0; 589 blk.scanw = w; 590 591 // set attributes of the DataBlk used for buffering 592 dbi.progressive = blk.progressive; 593 dbi.ulx = blk.ulx; 594 dbi.uly = blk.uly; 595 dbi.w = blk.w; 596 dbi.h = blk.h; 597 598 //Perform conversion 599 600 // Initialize general indexes 601 k = w*h-1; 602 k0 = block0.offset+(h-1)*block0.scanw+w-1; 603 k2 = block2.offset+(h-1)*block2.scanw+w-1; 604 k1 = block1.offset+(h-1)*block1.scanw+w-1; 605 606 for( i = h-1; i >=0; i--){ 607 for(mink = k-w; k > mink; k--, k0--, k2--, k1--){ 608 outdata[0][k] = (int)(data0[k0]+1.402f*data1[k1]+0.5f); 609 outdata[1][k] = 610 (int) (data0[k0]-0.34413f*data2[k2]-0.71414f*data1[k1] 611 + 0.5f); 612 outdata[2][k] = (int)(data0[k0]+1.772f*data2[k2]+0.5f); 613 } 614 // Jump to beggining of previous line in input 615 k0 -= block0.scanw - w; 616 k2 -= block2.scanw - w; 617 k1 -= block1.scanw - w; 618 } 619 outdata[c] = null; 620 } 621 else if((c>=0)&&(c<=3)){//Asking for the 2nd or 3rd block component 622 blk.setData(outdata[c]); 623 blk.progressive = dbi.progressive; 624 blk.offset = (blk.uly-dbi.uly)*dbi.w+blk.ulx-dbi.ulx; 625 blk.scanw = dbi.w; 626 outdata[c] = null; 627 } else { 628 // Requesting a non valid component index 629 throw new IllegalArgumentException(); 630 } 631 return blk; 632 } 633 634 /** 635 * Changes the current tile, given the new indexes. An 636 * IllegalArgumentException is thrown if the indexes do not 637 * correspond to a valid tile. 638 * 639 * <P>This default implementation changes the tile in the source 640 * and re-initializes properly component transformation variables.. 641 * 642 * @param x The horizontal index of the tile. 643 * 644 * @param y The vertical index of the new tile. 645 * 646 * */ 647 public void setTile(int x, int y) { 648 src.setTile(x,y); 649 tIdx = getTileIdx(); // index of the current tile 650 651 // initializations 652 if( ((Integer)cts.getTileDef(tIdx)).intValue()==NONE ) 653 transfType = NONE; 654 else { 655 int nc = src.getNumComps()> 3 ? 3 : src.getNumComps(); 656 int rev = 0; 657 for(int c=0; c<nc; c++) 658 rev += (wfs.isReversible(tIdx,c)?1:0); 659 if(rev==3){ 660 // All WT are reversible 661 transfType = INV_RCT; 662 } 663 else if(rev==0){ 664 // All WT irreversible 665 transfType = INV_ICT; 666 } 667 else{ 668 // Error 669 throw new IllegalArgumentException("Wavelet transformation and "+ 670 "component transformation"+ 671 " not coherent in tile"+tIdx); 672 } 673 } 674 } 675 676 /** 677 * Advances to the next tile, in standard scan-line order (by rows 678 * then columns). An NoNextElementException is thrown if the 679 * current tile is the last one (i.e. there is no next tile). 680 * 681 * <P>This default implementation just advances to the next tile 682 * in the source and re-initializes properly component 683 * transformation variables. 684 * 685 * */ 686 public void nextTile() { 687 src.nextTile(); 688 tIdx = getTileIdx(); // index of the current tile 689 690 // initializations 691 if( ((Integer)cts.getTileDef(tIdx)).intValue()==NONE ) 692 transfType = NONE; 693 else { 694 int nc = src.getNumComps() > 3 ? 3 : src.getNumComps(); 695 int rev = 0; 696 for(int c=0; c<nc; c++) 697 rev += (wfs.isReversible(tIdx,c)?1:0); 698 if(rev==3){ 699 // All WT are reversible 700 transfType = INV_RCT; 701 } 702 else if(rev==0){ 703 // All WT irreversible 704 transfType = INV_ICT; 705 } 706 else{ 707 // Error 708 throw new IllegalArgumentException("Wavelet transformation and "+ 709 "component transformation"+ 710 " not coherent in tile"+tIdx); 711 } 712 } 713 } 714 715} 716