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