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