001/* 002 * $RCSfile: EBCOTRateAllocator.java,v $ 003 * $Revision: 1.1 $ 004 * $Date: 2005/02/11 05:02:08 $ 005 * $State: Exp $ 006 * 007 * Class: EBCOTRateAllocator 008 * 009 * Description: Generic interface for post-compression 010 * rate allocator. 011 * 012 * 013 * 014 * COPYRIGHT: 015 * 016 * This software module was originally developed by Raphaël Grosbois and 017 * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel 018 * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David 019 * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research 020 * Centre France S.A) in the course of development of the JPEG2000 021 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This 022 * software module is an implementation of a part of the JPEG 2000 023 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio 024 * Systems AB and Canon Research Centre France S.A (collectively JJ2000 025 * Partners) agree not to assert against ISO/IEC and users of the JPEG 026 * 2000 Standard (Users) any of their rights under the copyright, not 027 * including other intellectual property rights, for this software module 028 * with respect to the usage by ISO/IEC and Users of this software module 029 * or modifications thereof for use in hardware or software products 030 * claiming conformance to the JPEG 2000 Standard. Those intending to use 031 * this software module in hardware or software products are advised that 032 * their use may infringe existing patents. The original developers of 033 * this software module, JJ2000 Partners and ISO/IEC assume no liability 034 * for use of this software module or modifications thereof. No license 035 * or right to this software module is granted for non JPEG 2000 Standard 036 * conforming products. JJ2000 Partners have full right to use this 037 * software module for his/her own purpose, assign or donate this 038 * software module to any third party and to inhibit third parties from 039 * using this software module for non JPEG 2000 Standard conforming 040 * products. This copyright notice must be included in all copies or 041 * derivative works of this software module. 042 * 043 * Copyright (c) 1999/2000 JJ2000 Partners. 044 * */ 045package jj2000.j2k.entropy.encoder; 046import java.awt.Point; 047 048import jj2000.j2k.codestream.writer.*; 049import jj2000.j2k.wavelet.analysis.*; 050import jj2000.j2k.entropy.encoder.*; 051import jj2000.j2k.codestream.*; 052import jj2000.j2k.entropy.*; 053import jj2000.j2k.image.*; 054import jj2000.j2k.util.*; 055 056import java.util.Vector; 057import java.io.*; 058 059import com.sun.media.imageioimpl.plugins.jpeg2000.J2KImageWriteParamJava; 060/** 061 * This implements the EBCOT post compression rate allocation algorithm. This 062 * algorithm finds the most suitable truncation points for the set of 063 * code-blocks, for each layer target bitrate. It works by first collecting 064 * the rate distortion info from all code-blocks, in all tiles and all 065 * components, and then running the rate-allocation on the whole image at 066 * once, for each layer. 067 * 068 * <P>This implementation also provides some timing features. They can be 069 * enabled by setting the 'DO_TIMING' constant of this class to true and 070 * recompiling. The timing uses the 'System.currentTimeMillis()' Java API 071 * call, which returns wall clock time, not the actual CPU time used. The 072 * timing results will be printed on the message output. Since the times 073 * reported are wall clock times and not CPU usage times they can not be added 074 * to find the total used time (i.e. some time might be counted in several 075 * places). When timing is disabled ('DO_TIMING' is false) there is no penalty 076 * if the compiler performs some basic optimizations. Even if not the penalty 077 * should be negligeable. 078 * 079 * @see PostCompRateAllocator 080 * 081 * @see CodedCBlkDataSrcEnc 082 * 083 * @see jj2000.j2k.codestream.writer.CodestreamWriter 084 * */ 085public class EBCOTRateAllocator extends PostCompRateAllocator { 086 087 /** Whether to collect timing information or not: false. Used as a compile 088 * time directive. */ 089 private final static boolean DO_TIMING = false; 090 091 /** The wall time for the initialization. */ 092 private long initTime; 093 094 /** The wall time for the building of layers. */ 095 private long buildTime; 096 097 /** The wall time for the writing of layers. */ 098 private long writeTime; 099 100 /** 101 * 5D Array containing all the coded code-blocks: 102 * 103 * <ul> 104 * <li>1st index: tile index</li> 105 * <li>2nd index: component index</li> 106 * <li>3rd index: resolution level index</li> 107 * <li>4th index: subband index</li> 108 * <li>5th index: code-block index</li> 109 * </ul> 110 **/ 111 private CBlkRateDistStats cblks[][][][][]; 112 113 /** 114 * 6D Array containing the indices of the truncation points. It actually 115 * contains the index of the element in CBlkRateDistStats.truncIdxs that 116 * gives the real truncation point index. 117 * 118 * <ul> 119 * <li>1st index: tile index</li> 120 * <li>2nd index: layer index</li> 121 * <li>3rd index: component index</li> 122 * <li>4th index: resolution level index</li> 123 * <li>5th index: subband index</li> 124 * <li>6th index: code-block index</li> 125 * </ul> 126 **/ 127 private int truncIdxs[][][][][][]; 128 129 /** 130 * Maximum number of precincts : 131 * 132 * <ul> 133 * <li>1st dim: tile index.</li> 134 * <li>2nd dim: component index.</li> 135 * <li>3nd dim: resolution level index.</li> 136 * </ul> 137 */ 138 private Point numPrec[][][]; 139 140 /** Array containing the layers information. */ 141 private EBCOTLayer layers[]; 142 143 /** The log of 2, natural base */ 144 private static final double LOG2 = Math.log(2); 145 146 /** The normalization offset for the R-D summary table */ 147 private static final int RD_SUMMARY_OFF = 24; 148 149 /** The size of the summary table */ 150 private static final int RD_SUMMARY_SIZE = 64; 151 152 /** The relative precision for float data. This is the relative tolerance 153 * up to which the layer slope thresholds are calculated. */ 154 private static final float FLOAT_REL_PRECISION = 1e-4f; 155 156 /** The precision for float data type, in an absolute sense. Two float 157 * numbers are considered "equal" if they are within this precision. */ 158 private static final float FLOAT_ABS_PRECISION = 1e-10f; 159 160 /** 161 * Minimum average size of a packet. If layer has less bytes than the this 162 * constant multiplied by number of packets in the layer, then the layer 163 * is skipped. 164 * */ 165 private static final int MIN_AVG_PACKET_SZ = 32; 166 167 /** 168 * The R-D summary information collected from the coding of all 169 * code-blocks. For each entry it contains the accumulated length of all 170 * truncation points that have a slope not less than 171 * '2*(k-RD_SUMMARY_OFF)', where 'k' is the entry index. 172 * 173 * <P>Therefore, the length at entry 'k' is the total number of bytes of 174 * code-block data that would be obtained if the truncation slope was 175 * chosen as '2*(k-RD_SUMMARY_OFF)', without counting the overhead 176 * associated with the packet heads. 177 * 178 * <P>This summary is used to estimate the relation of the R-D slope to 179 * coded length, and to obtain absolute minimums on the slope given a 180 * length. 181 **/ 182 private int RDSlopesRates[]; 183 184 /** Packet encoder. */ 185 private PktEncoder pktEnc; 186 187 /** The layer specifications */ 188 private LayersInfo lyrSpec; 189 190 /** The maximum slope accross all code-blocks and truncation points. */ 191 private float maxSlope; 192 193 /** The minimum slope accross all code-blocks and truncation points. */ 194 private float minSlope; 195 196 /** 197 * Initializes the EBCOT rate allocator of entropy coded data. The layout 198 * of layers, and their bitrate constraints, is specified by the 'lyrs' 199 * parameter. 200 * 201 * @param src The source of entropy coded data. 202 * 203 * @param lyrs The layers layout specification. 204 * 205 * @param writer The bit stream writer. 206 * 207 * @see ProgressionType 208 * */ 209 public EBCOTRateAllocator(CodedCBlkDataSrcEnc src, LayersInfo lyrs, 210 CodestreamWriter writer, 211 J2KImageWriteParamJava wp) { 212 213 super(src,lyrs.getTotNumLayers(),writer,wp); 214 215 int minsbi, maxsbi; 216 int i; 217 SubbandAn sb, sb2; 218 Point ncblks = null; 219 220 // If we do timing create necessary structures 221 if (DO_TIMING) { 222 // If we are timing make sure that 'finalize' gets called. 223 System.runFinalizersOnExit(true); 224 // The System.runFinalizersOnExit() method is deprecated in Java 225 // 1.2 since it can cause a deadlock in some cases. However, here 226 // we use it only for profiling purposes and is disabled in 227 // production code. 228 initTime = 0L; 229 buildTime = 0L; 230 writeTime = 0L; 231 } 232 233 // Save the layer specs 234 lyrSpec = lyrs; 235 236 //Initialize the size of the RD slope rates array 237 RDSlopesRates = new int[RD_SUMMARY_SIZE]; 238 239 //Get number of tiles, components 240 int nt = src.getNumTiles(); 241 int nc = getNumComps(); 242 243 //Allocate the coded code-blocks and truncation points indexes arrays 244 cblks = new CBlkRateDistStats[nt][nc][][][]; 245 truncIdxs = new int[nt][numLayers][nc][][][]; 246 247 int cblkPerSubband; // Number of code-blocks per subband 248 int mrl; // Number of resolution levels 249 int l; // layer index 250 int s; //subband index 251 252 // Used to compute the maximum number of precincts for each resolution 253 // level 254 int tx0, ty0, tx1, ty1; // Current tile position in the reference grid 255 int tcx0, tcy0, tcx1, tcy1; // Current tile position in the domain of 256 // the image component 257 int trx0, try0, trx1, try1; // Current tile position in the reduced 258 // resolution image domain 259 int xrsiz, yrsiz; // Component sub-sampling factors 260 Point tileI = null; 261 Point nTiles = null; 262 int xsiz,ysiz,x0siz,y0siz; 263 int xt0siz,yt0siz; 264 int xtsiz,ytsiz; 265 266 int cb0x = src.getCbULX(); 267 int cb0y = src.getCbULY(); 268 269 src.setTile(0,0); 270 for (int t=0; t<nt; t++) { // Loop on tiles 271 nTiles = src.getNumTiles(nTiles); 272 tileI = src.getTile(tileI); 273 x0siz = getImgULX(); 274 y0siz = getImgULY(); 275 xsiz = x0siz + getImgWidth(); 276 ysiz = y0siz + getImgHeight(); 277 xt0siz = src.getTilePartULX(); 278 yt0siz = src.getTilePartULY(); 279 xtsiz = src.getNomTileWidth(); 280 ytsiz = src.getNomTileHeight(); 281 282 // Tile's coordinates on the reference grid 283 tx0 = (tileI.x==0) ? x0siz : xt0siz+tileI.x*xtsiz; 284 ty0 = (tileI.y==0) ? y0siz : yt0siz+tileI.y*ytsiz; 285 tx1 = (tileI.x!=nTiles.x-1) ? xt0siz+(tileI.x+1)*xtsiz : xsiz; 286 ty1 = (tileI.y!=nTiles.y-1) ? yt0siz+(tileI.y+1)*ytsiz : ysiz; 287 288 for(int c=0; c<nc; c++) { // loop on components 289 290 //Get the number of resolution levels 291 sb = src.getAnSubbandTree(t,c); 292 mrl = sb.resLvl+1; 293 294 // Initialize maximum number of precincts per resolution array 295 if (numPrec==null) { numPrec = new Point[nt][nc][]; } 296 if (numPrec[t][c]==null) { 297 numPrec[t][c] = new Point[mrl]; 298 } 299 300 // Subsampling factors 301 xrsiz = src.getCompSubsX(c); 302 yrsiz = src.getCompSubsY(c); 303 304 // Tile's coordinates in the image component domain 305 tcx0 = (int)Math.ceil(tx0/(double)(xrsiz)); 306 tcy0 = (int)Math.ceil(ty0/(double)(yrsiz)); 307 tcx1 = (int)Math.ceil(tx1/(double)(xrsiz)); 308 tcy1 = (int)Math.ceil(ty1/(double)(yrsiz)); 309 310 cblks[t][c] = new CBlkRateDistStats[mrl][][]; 311 312 for(l=0; l<numLayers; l++) { 313 truncIdxs[t][l][c] = new int[mrl][][]; 314 } 315 316 for(int r=0; r<mrl; r++) { // loop on resolution levels 317 318 // Tile's coordinates in the reduced resolution image 319 // domain 320 trx0 = (int)Math.ceil(tcx0/(double)(1<<(mrl-1-r))); 321 try0 = (int)Math.ceil(tcy0/(double)(1<<(mrl-1-r))); 322 trx1 = (int)Math.ceil(tcx1/(double)(1<<(mrl-1-r))); 323 try1 = (int)Math.ceil(tcy1/(double)(1<<(mrl-1-r))); 324 325 // Calculate the maximum number of precincts for each 326 // resolution level taking into account tile specific 327 // options. 328 double twoppx = (double)wp.getPrecinctPartition().getPPX(t,c,r); 329 double twoppy = (double)wp.getPrecinctPartition().getPPY(t,c,r); 330 numPrec[t][c][r] = new Point(); 331 if (trx1>trx0) { 332 numPrec[t][c][r].x = (int)Math.ceil((trx1-cb0x)/twoppx) 333 - (int)Math.floor((trx0-cb0x)/twoppx); 334 } else { 335 numPrec[t][c][r].x = 0; 336 } 337 if (try1>try0) { 338 numPrec[t][c][r].y = (int)Math.ceil((try1-cb0y)/twoppy) 339 - (int)Math.floor((try0-cb0y)/(double)twoppy); 340 } else { 341 numPrec[t][c][r].y = 0; 342 } 343 344 minsbi = (r==0) ? 0 : 1; 345 maxsbi = (r==0) ? 1 : 4; 346 347 cblks[t][c][r] = new CBlkRateDistStats[maxsbi][]; 348 for(l=0; l<numLayers; l++) { 349 truncIdxs[t][l][c][r] = new int[maxsbi][]; 350 } 351 352 for(s=minsbi; s<maxsbi; s++) { // loop on subbands 353 //Get the number of blocks in the current subband 354 sb2 = (SubbandAn)sb.getSubbandByIdx(r,s); 355 ncblks = sb2.numCb; 356 cblkPerSubband = ncblks.x*ncblks.y; 357 cblks[t][c][r][s] = 358 new CBlkRateDistStats[cblkPerSubband]; 359 360 for(l=0; l<numLayers; l++) { 361 truncIdxs[t][l][c][r][s] = new int[cblkPerSubband]; 362 for(i=0; i<cblkPerSubband; i++) { 363 truncIdxs[t][l][c][r][s][i] = -1; 364 } 365 } 366 } // End loop on subbands 367 } // End lopp on resolution levels 368 } // End loop on components 369 if (t!=nt-1) { 370 src.nextTile(); 371 } 372 } // End loop on tiles 373 374 //Initialize the packet encoder 375 pktEnc = new PktEncoder(src,wp,numPrec); 376 377 // The layers array has to be initialized after the constructor since 378 // it is needed that the bit stream header has been entirely written 379 } 380 381 /** 382 * Prints the timing information, if collected, and calls 'finalize' on 383 * the super class. 384 * */ 385 public void finalize() throws Throwable { 386 if (DO_TIMING) { 387 StringBuffer sb; 388 389 sb = new StringBuffer("EBCOTRateAllocator wall clock times:\n"); 390 sb.append(" initialization: "); 391 sb.append(initTime); 392 sb.append(" ms\n"); 393 sb.append(" layer building: "); 394 sb.append(buildTime); 395 sb.append(" ms\n"); 396 sb.append(" final writing: "); 397 sb.append(writeTime); 398 sb.append(" ms"); 399 FacilityManager.getMsgLogger(). 400 printmsg(MsgLogger.INFO,sb.toString()); 401 } 402 super.finalize(); 403 } 404 405 /** 406 * Runs the rate allocation algorithm and writes the data to the bit 407 * stream writer object provided to the constructor. 408 * */ 409 public void runAndWrite() throws IOException { 410 //Now, run the rate allocation 411 buildAndWriteLayers(); 412 } 413 414 /** 415 * Initializes the layers array. This must be called after the main header 416 * has been entirely written or simulated, so as to take its overhead into 417 * account. This method will get all the code-blocks and then initialize 418 * the target bitrates for each layer, according to the specifications. 419 * */ 420 public void initialize() throws IOException{ 421 int n,i,l; 422 int ho; // The header overhead (in bytes) 423 float np;// The number of pixels divided by the number of bits per byte 424 double ls; // Step for log-scale 425 double basebytes; 426 int lastbytes,newbytes,nextbytes; 427 int loopnlyrs; 428 int minlsz; // The minimum allowable number of bytes in a layer 429 int totenclength; 430 int maxpkt; 431 int numTiles = src.getNumTiles(); 432 int numComps = src.getNumComps(); 433 int numLvls; 434 int avgPktLen; 435 436 long stime = 0L; 437 438 // Start by getting all the code-blocks, we need this in order to have 439 // an idea of the total encoded bitrate. 440 getAllCodeBlocks(); 441 442 if (DO_TIMING) stime = System.currentTimeMillis(); 443 444 // Now get the total encoded length 445 totenclength = RDSlopesRates[0]; // all the encoded data 446 // Make a rough estimation of the packet head overhead, as 2 bytes per 447 // packet in average (plus EPH / SOP) , and add that to the total 448 // encoded length 449 for( int t=0 ; t<numTiles ; t++ ){ 450 avgPktLen = 2; 451 // Add SOP length if set 452 if (((String)wp.getSOP().getTileDef(t)).equalsIgnoreCase("true")) { 453 avgPktLen += Markers.SOP_LENGTH; 454 } 455 // Add EPH length if set 456 if (((String)wp.getEPH().getTileDef(t)).equalsIgnoreCase("true")) { 457 avgPktLen += Markers.EPH_LENGTH; 458 } 459 460 for( int c=0 ; c<numComps ; c++ ){ 461 numLvls = src.getAnSubbandTree(t,c).resLvl+1; 462 if( !src.precinctPartitionUsed(c,t) ) { 463 // Precinct partition is not used so there is only 464 // one packet per resolution level/layer 465 totenclength += numLayers*avgPktLen*numLvls; 466 } 467 else { 468 // Precinct partition is used so for each 469 // component/tile/resolution level, we get the maximum 470 // number of packets 471 for ( int rl=0 ; rl<numLvls ; rl++ ) { 472 maxpkt = numPrec[t][c][rl].x * numPrec[t][c][rl].y; 473 totenclength += numLayers*avgPktLen*maxpkt; 474 } 475 } 476 } // End loop on components 477 } // End loop on tiles 478 479 // If any layer specifies more than 'totenclength' as its target 480 // length then 'totenclength' is used. This is to prevent that 481 // estimated layers get excessively large target lengths due to an 482 // excessively large target bitrate. At the end the last layer is set 483 // to the target length corresponding to the overall target 484 // bitrate. Thus, 'totenclength' can not limit the total amount of 485 // encoded data, as intended. 486 487 ho = headEnc.getLength(); 488 np = src.getImgWidth()*src.getImgHeight()/8f; 489 490 // SOT marker must be taken into account 491 for(int t=0; t<numTiles; t++){ 492 headEnc.reset(); 493 headEnc.encodeTilePartHeader(0,t); 494 ho += headEnc.getLength(); 495 } 496 497 layers = new EBCOTLayer[numLayers]; 498 for (n = numLayers-1; n>=0; n--) { 499 layers[n] = new EBCOTLayer(); 500 } 501 502 minlsz = 0; // To keep compiler happy 503 for( int t=0 ; t<numTiles ; t++ ){ 504 for( int c=0 ; c<numComps ; c++ ){ 505 numLvls = src.getAnSubbandTree(t,c).resLvl+1; 506 507 if ( !src.precinctPartitionUsed(c,t) ) { 508 // Precinct partition is not used 509 minlsz += MIN_AVG_PACKET_SZ*numLvls; 510 } 511 else { 512 // Precinct partition is used 513 for ( int rl=0 ; rl<numLvls ; rl++ ) { 514 maxpkt = numPrec[t][c][rl].x * numPrec[t][c][rl].y; 515 minlsz += MIN_AVG_PACKET_SZ*maxpkt; 516 } 517 } 518 } // End loop on components 519 } // End loop on tiles 520 521 // Initialize layers 522 n = 0; 523 i = 0; 524 lastbytes = 0; 525 526 while (n < numLayers-1) { 527 // At an optimized layer 528 basebytes = Math.floor(lyrSpec.getTargetBitrate(i)*np); 529 if (i < lyrSpec.getNOptPoints()-1) { 530 nextbytes = (int) (lyrSpec.getTargetBitrate(i+1)*np); 531 // Limit target length to 'totenclength' 532 if (nextbytes > totenclength) 533 nextbytes = totenclength; 534 } 535 else { 536 nextbytes = 1; 537 } 538 loopnlyrs = lyrSpec.getExtraLayers(i)+1; 539 ls = Math.exp(Math.log((double)nextbytes/basebytes)/loopnlyrs); 540 layers[n].optimize = true; 541 for (l = 0; l < loopnlyrs; l++) { 542 newbytes = (int)basebytes - lastbytes - ho; 543 if (newbytes < minlsz) { // Skip layer (too small) 544 basebytes *= ls; 545 numLayers--; 546 continue; 547 } 548 lastbytes = (int)basebytes - ho; 549 layers[n].maxBytes = lastbytes; 550 basebytes *= ls; 551 n++; 552 } 553 i++; // Goto next optimization point 554 } 555 556 // Ensure minimum size of last layer (this one determines overall 557 // bitrate) 558 n = numLayers-2; 559 nextbytes = (int) (lyrSpec.getTotBitrate()*np) - ho; 560 newbytes = nextbytes - ((n>=0) ? layers[n].maxBytes : 0); 561 while (newbytes < minlsz) { 562 if (numLayers == 1) { 563 if (newbytes <= 0) { 564 throw new 565 IllegalArgumentException("Overall target bitrate too "+ 566 "low, given the current "+ 567 "bit stream header overhead"); 568 } 569 break; 570 } 571 // Delete last layer 572 numLayers--; 573 n--; 574 newbytes = nextbytes - ((n>=0) ? layers[n].maxBytes : 0); 575 } 576 // Set last layer to the overall target bitrate 577 n++; 578 layers[n].maxBytes = nextbytes; 579 layers[n].optimize = true; 580 581 // Re-initialize progression order changes if needed Default values 582 Progression[] prog1,prog2; 583 prog1 = (Progression[])wp.getProgressionType().getDefault(); 584 int nValidProg = prog1.length; 585 for(int prg=0; prg<prog1.length;prg++){ 586 if(prog1[prg].lye>numLayers){ 587 prog1[prg].lye = numLayers; 588 } 589 } 590 if(nValidProg==0) 591 throw new Error("Unable to initialize rate allocator: No "+ 592 "default progression type has been defined."); 593 594 // Tile specific values 595 for(int t=0; t<numTiles; t++){ 596 if(wp.getProgressionType().isTileSpecified(t)){ 597 prog1 = (Progression[])wp.getProgressionType().getTileDef(t); 598 nValidProg = prog1.length; 599 for(int prg=0; prg<prog1.length;prg++){ 600 if(prog1[prg].lye>numLayers){ 601 prog1[prg].lye = numLayers; 602 } 603 } 604 if(nValidProg==0) 605 throw new Error("Unable to initialize rate allocator: No "+ 606 "default progression type has been defined."); 607 } 608 } // End loop on tiles 609 610 if (DO_TIMING) initTime += System.currentTimeMillis()-stime; 611 } 612 613 /** 614 * This method gets all the coded code-blocks from the EBCOT entropy coder 615 * for every component and every tile. Each coded code-block is stored in 616 * a 5D array according to the component, the resolution level, the tile, 617 * the subband it belongs and its position in the subband. 618 * 619 * <P> For each code-block, the valid slopes are computed and converted 620 * into the mantissa-exponent representation. 621 * */ 622 private void getAllCodeBlocks() { 623 624 int numComps, numTiles, numBytes; 625 int c, r, t, s, sidx, k; 626 int slope; 627 SubbandAn subb; 628 CBlkRateDistStats ccb = null; 629 Point ncblks = null; 630 int last_sidx; 631 float fslope; 632 633 long stime = 0L; 634 635 maxSlope = 0f; 636 minSlope = Float.MAX_VALUE; 637 638 //Get the number of components and tiles 639 numComps = src.getNumComps(); 640 numTiles = src.getNumTiles(); 641 642 SubbandAn root,sb; 643 int cblkToEncode = 0; 644 int nEncCblk = 0; 645 ProgressWatch pw = FacilityManager.getProgressWatch(); 646 647 //Get all coded code-blocks Goto first tile 648 src.setTile(0,0); 649 for (t=0; t<numTiles; t++) { //loop on tiles 650 nEncCblk = 0; 651 cblkToEncode = 0; 652 for(c=0; c<numComps; c++) { 653 root = src.getAnSubbandTree(t,c); 654 for(r=0; r<=root.resLvl; r++) { 655 if(r==0) { 656 sb = (SubbandAn)root.getSubbandByIdx(0,0); 657 if(sb!=null) cblkToEncode += sb.numCb.x*sb.numCb.y; 658 } else { 659 sb = (SubbandAn)root.getSubbandByIdx(r,1); 660 if(sb!=null) cblkToEncode += sb.numCb.x*sb.numCb.y; 661 sb = (SubbandAn)root.getSubbandByIdx(r,2); 662 if(sb!=null) cblkToEncode += sb.numCb.x*sb.numCb.y; 663 sb = (SubbandAn)root.getSubbandByIdx(r,3); 664 if(sb!=null) cblkToEncode += sb.numCb.x*sb.numCb.y; 665 } 666 } 667 } 668 if(pw!=null) { 669 pw.initProgressWatch(0,cblkToEncode,"Encoding tile "+t+"..."); 670 } 671 672 for (c=0; c<numComps; c++) { //loop on components 673 674 //Get next coded code-block coordinates 675 while ( (ccb = src.getNextCodeBlock(c,ccb)) != null) { 676 if (DO_TIMING) stime = System.currentTimeMillis(); 677 678 if(pw!=null) { 679 nEncCblk++; 680 pw.updateProgressWatch(nEncCblk,null); 681 } 682 683 subb = ccb.sb; 684 685 //Get the coded code-block resolution level index 686 r = subb.resLvl; 687 688 //Get the coded code-block subband index 689 s = subb.sbandIdx; 690 691 //Get the number of blocks in the current subband 692 ncblks = subb.numCb; 693 694 // Add code-block contribution to summary R-D table 695 // RDSlopesRates 696 last_sidx = -1; 697 for (k=ccb.nVldTrunc-1; k>=0; k--) { 698 fslope = ccb.truncSlopes[k]; 699 if (fslope > maxSlope) maxSlope = fslope; 700 if (fslope < minSlope) minSlope = fslope; 701 sidx = getLimitedSIndexFromSlope(fslope); 702 for (; sidx > last_sidx; sidx--) { 703 RDSlopesRates[sidx] += 704 ccb.truncRates[ccb.truncIdxs[k]]; 705 } 706 last_sidx = getLimitedSIndexFromSlope(fslope); 707 } 708 709 //Fills code-blocks array 710 cblks[t][c][r][s][(ccb.m*ncblks.x)+ccb.n] = ccb; 711 ccb = null; 712 713 if(DO_TIMING) initTime += System.currentTimeMillis()-stime; 714 } 715 } 716 717 if(pw!=null) { 718 pw.terminateProgressWatch(); 719 } 720 721 //Goto next tile 722 if(t<numTiles-1) //not at last tile 723 src.nextTile(); 724 } 725 } 726 727 /** 728 * This method builds all the bit stream layers and then writes them to 729 * the output bit stream. Firstly it builds all the layers by computing 730 * the threshold according to the layer target bit-rate, and then it 731 * writes the layer bit streams according to the Progression type. 732 * */ 733 private void buildAndWriteLayers() throws IOException { 734 int nPrec = 0; 735 int maxBytes, actualBytes; 736 float rdThreshold; 737 SubbandAn sb; 738 float threshold; 739 BitOutputBuffer hBuff = null; 740 byte[] bBuff = null; 741 int[] tileLengths; // Length of each tile 742 int tmp; 743 boolean sopUsed; // Should SOP markers be used ? 744 boolean ephUsed; // Should EPH markers be used ? 745 int nc = src.getNumComps(); 746 int nt = src.getNumTiles(); 747 int mrl; 748 749 long stime = 0L; 750 751 if (DO_TIMING) stime = System.currentTimeMillis(); 752 753 // Start with the maximum slope 754 rdThreshold = maxSlope; 755 756 tileLengths = new int[nt]; 757 actualBytes = 0; 758 759 // +------------------------------+ 760 // | First we build the layers | 761 // +------------------------------+ 762 // Bitstream is simulated to know tile length 763 for(int l=0; l<numLayers; l++){ //loop on layers 764 765 maxBytes = layers[l].maxBytes; 766 if(layers[l].optimize) { 767 rdThreshold = 768 optimizeBitstreamLayer(l,rdThreshold,maxBytes,actualBytes); 769 } else { 770 if( l<=0 || l>=numLayers-1 ) { 771 throw new IllegalArgumentException("The first and the"+ 772 " last layer "+ 773 "thresholds"+ 774 " must be optimized"); 775 } 776 rdThreshold = estimateLayerThreshold(maxBytes,layers[l-1]); 777 } 778 779 for(int t=0; t<nt; t++) { //loop on tiles 780 if(l==0) { 781 // Tile header 782 headEnc.reset(); 783 headEnc.encodeTilePartHeader(0,t); 784 tileLengths[t] += headEnc.getLength(); 785 } 786 787 for(int c=0; c<nc; c++) { //loop on components 788 789 // set boolean sopUsed here (SOP markers) 790 sopUsed = ((String)wp.getSOP().getTileDef(t)). 791 equalsIgnoreCase("true"); 792 // set boolean ephUsed here (EPH markers) 793 ephUsed = ((String)wp.getEPH().getTileDef(t)). 794 equalsIgnoreCase("true"); 795 796 // Go to LL band 797 sb = src.getAnSubbandTree(t,c); 798 mrl = sb.resLvl+1; 799 800 while (sb.subb_LL!=null) { 801 sb = sb.subb_LL; 802 } 803 804 for(int r=0; r<mrl ; r++) { // loop on resolution levels 805 806 nPrec = numPrec[t][c][r].x*numPrec[t][c][r].y; 807 for(int p=0; p<nPrec; p++) { // loop on precincts 808 809 findTruncIndices(l,c,r,t,sb,rdThreshold,p); 810 811 hBuff = 812 pktEnc.encodePacket(l+1,c,r,t, 813 cblks[t][c][r], 814 truncIdxs[t][l][c][r], 815 hBuff, bBuff,p); 816 if(pktEnc.isPacketWritable()) { 817 tmp = bsWriter. 818 writePacketHead(hBuff.getBuffer(), 819 hBuff.getLength(), 820 true, sopUsed,ephUsed); 821 tmp += bsWriter. 822 writePacketBody(pktEnc.getLastBodyBuf(), 823 pktEnc.getLastBodyLen(), 824 true,pktEnc.isROIinPkt(), 825 pktEnc.getROILen()); 826 actualBytes += tmp; 827 tileLengths[t] += tmp; 828 } 829 } // End loop on precincts 830 sb = sb.parent; 831 } // End loop on resolution levels 832 } // End loop on components 833 } // end loop on tiles 834 layers[l].rdThreshold = rdThreshold; 835 layers[l].actualBytes = actualBytes; 836 } // end loop on layers 837 838 if (DO_TIMING) buildTime += System.currentTimeMillis()-stime; 839 840 // The bit-stream was not yet generated (only simulated). 841 842 if (DO_TIMING) stime = System.currentTimeMillis(); 843 844 // +--------------------------------------------------+ 845 // | Write tiles according to their Progression order | 846 // +--------------------------------------------------+ 847 // Reset the packet encoder before writing all packets 848 pktEnc.reset(); 849 Progression[] prog; // Progression(s) in each tile 850 int cs,ce,rs,re,lye; 851 852 int[] mrlc = new int[nc]; 853 for(int t=0; t<nt; t++) { //loop on tiles 854 int[][] lysA; // layer index start for each component and 855 // resolution level 856 int[][] lys = new int[nc][]; 857 for(int c=0; c<nc; c++){ 858 mrlc[c] = src.getAnSubbandTree(t,c).resLvl; 859 lys[c] = new int[mrlc[c]+1]; 860 } 861 862 // Tile header 863 headEnc.reset(); 864 headEnc.encodeTilePartHeader(tileLengths[t],t); 865 bsWriter.commitBitstreamHeader(headEnc); 866 prog = (Progression[])wp.getProgressionType().getTileDef(t); 867 868 for(int prg=0; prg<prog.length;prg++){ // Loop on progression 869 lye = prog[prg].lye; 870 cs = prog[prg].cs; 871 ce = prog[prg].ce; 872 rs = prog[prg].rs; 873 re = prog[prg].re; 874 875 switch(prog[prg].type){ 876 case ProgressionType.RES_LY_COMP_POS_PROG: 877 writeResLyCompPos(t,rs,re,cs,ce,lys,lye); 878 break; 879 case ProgressionType.LY_RES_COMP_POS_PROG: 880 writeLyResCompPos(t,rs,re,cs,ce,lys,lye); 881 break; 882 case ProgressionType.POS_COMP_RES_LY_PROG: 883 writePosCompResLy(t,rs,re,cs,ce,lys,lye); 884 break; 885 case ProgressionType.COMP_POS_RES_LY_PROG: 886 writeCompPosResLy(t,rs,re,cs,ce,lys,lye); 887 break; 888 case ProgressionType.RES_POS_COMP_LY_PROG: 889 writeResPosCompLy(t,rs,re,cs,ce,lys,lye); 890 break; 891 default: 892 throw new Error("Unsupported bit stream progression type"); 893 } // switch on progression 894 895 // Update next first layer index 896 for(int c=cs; c<ce; c++) 897 for(int r=rs; r<re; r++){ 898 if(r>mrlc[c]) continue; 899 lys[c][r] = lye; 900 } 901 } // End loop on progression 902 } // End loop on tiles 903 904 if (DO_TIMING) writeTime += System.currentTimeMillis()-stime; 905 } 906 907 /** 908 * Write a piece of bit stream according to the 909 * RES_LY_COMP_POS_PROG progression mode and between given bounds 910 * 911 * @param t Tile index. 912 * 913 * @param rs First resolution level index. 914 * 915 * @param re Last resolution level index. 916 * 917 * @param cs First component index. 918 * 919 * @param ce Last component index. 920 * 921 * @param lys First layer index for each component and resolution. 922 * 923 * @param lye Index of the last layer. 924 * */ 925 public void writeResLyCompPos(int t,int rs,int re,int cs,int ce, 926 int lys[][],int lye) throws IOException { 927 928 boolean sopUsed; // Should SOP markers be used ? 929 boolean ephUsed; // Should EPH markers be used ? 930 int nc = src.getNumComps(); 931 int[] mrl = new int[nc]; 932 SubbandAn sb; 933 float threshold; 934 BitOutputBuffer hBuff = null; 935 byte[] bBuff = null; 936 int nPrec = 0; 937 938 // Max number of resolution levels in the tile 939 int maxResLvl = 0; 940 for(int c=0; c<nc; c++) { 941 mrl[c] = src.getAnSubbandTree(t,c).resLvl; 942 if(mrl[c]>maxResLvl) maxResLvl = mrl[c]; 943 } 944 945 int minlys; // minimum layer start index of each component 946 947 for(int r=rs; r<re; r++) { //loop on resolution levels 948 if(r>maxResLvl) continue; 949 950 minlys = 100000; 951 for(int c=cs; c<ce; c++) { 952 if( r<lys[c].length && lys[c][r]<minlys ) { 953 minlys = lys[c][r]; 954 } 955 } 956 957 for(int l=minlys; l<lye; l++) { //loop on layers 958 for(int c=cs; c<ce; c++) {//loop on components 959 if(r>=lys[c].length) continue; 960 if(l<lys[c][r]) continue; 961 962 // If no more decomposition levels for this component 963 if(r>mrl[c]) continue; 964 965 nPrec = numPrec[t][c][r].x*numPrec[t][c][r].y; 966 for(int p=0; p<nPrec; p++) { // loop on precincts 967 968 // set boolean sopUsed here (SOP markers) 969 sopUsed = ((String)wp.getSOP().getTileDef(t)).equals("true"); 970 // set boolean ephUsed here (EPH markers) 971 ephUsed = ((String)wp.getEPH().getTileDef(t)).equals("true"); 972 973 sb = src.getAnSubbandTree(t,c); 974 for(int i=mrl[c]; i>r; i--) { 975 sb = sb.subb_LL; 976 } 977 978 threshold = layers[l].rdThreshold; 979 findTruncIndices(l,c,r,t,sb,threshold,p); 980 981 hBuff = pktEnc.encodePacket(l+1,c,r,t,cblks[t][c][r], 982 truncIdxs[t][l][c][r], 983 hBuff,bBuff,p); 984 985 if(pktEnc.isPacketWritable()) { 986 bsWriter.writePacketHead(hBuff.getBuffer(), 987 hBuff.getLength(), 988 false,sopUsed,ephUsed); 989 bsWriter.writePacketBody(pktEnc.getLastBodyBuf(), 990 pktEnc.getLastBodyLen(), 991 false,pktEnc.isROIinPkt(), 992 pktEnc.getROILen()); 993 } 994 995 } // End loop on precincts 996 } // End loop on components 997 } // End loop on layers 998 } // End loop on resolution levels 999 } 1000 1001 /** 1002 * Write a piece of bit stream according to the 1003 * LY_RES_COMP_POS_PROG progression mode and between given bounds 1004 * 1005 * @param t Tile index. 1006 * 1007 * @param rs First resolution level index. 1008 * 1009 * @param re Last resolution level index. 1010 * 1011 * @param cs First component index. 1012 * 1013 * @param ce Last component index. 1014 * 1015 * @param lys First layer index for each component and resolution. 1016 * 1017 * @param lye Index of the last layer. 1018 * */ 1019 public void writeLyResCompPos(int t,int rs,int re,int cs,int ce, 1020 int[][] lys,int lye) throws IOException { 1021 1022 boolean sopUsed; // Should SOP markers be used ? 1023 boolean ephUsed; // Should EPH markers be used ? 1024 int nc = src.getNumComps(); 1025 int mrl; 1026 SubbandAn sb; 1027 float threshold; 1028 BitOutputBuffer hBuff = null; 1029 byte[] bBuff = null; 1030 int nPrec = 0; 1031 1032 int minlys = 100000; // minimum layer start index of each component 1033 for(int c=cs; c<ce; c++) { 1034 for(int r=0; r<lys.length; r++) { 1035 if(lys[c]!=null && r<lys[c].length && lys[c][r]<minlys ) { 1036 minlys = lys[c][r]; 1037 } 1038 } 1039 } 1040 1041 for(int l=minlys; l<lye; l++) { // loop on layers 1042 for(int r=rs; r<re; r++) { // loop on resolution level 1043 for(int c=cs; c<ce; c++) { // loop on components 1044 mrl = src.getAnSubbandTree(t,c).resLvl; 1045 if(r>mrl) continue; 1046 if(r>=lys[c].length) continue; 1047 if(l<lys[c][r]) continue; 1048 nPrec = numPrec[t][c][r].x*numPrec[t][c][r].y; 1049 for(int p=0; p<nPrec; p++) { // loop on precincts 1050 1051 // set boolean sopUsed here (SOP markers) 1052 sopUsed = ((String)wp.getSOP().getTileDef(t)).equals("true"); 1053 // set boolean ephUsed here (EPH markers) 1054 ephUsed = ((String)wp.getEPH().getTileDef(t)).equals("true"); 1055 1056 sb = src.getAnSubbandTree(t,c); 1057 for(int i=mrl; i>r; i--) { 1058 sb = sb.subb_LL; 1059 } 1060 1061 threshold = layers[l].rdThreshold; 1062 findTruncIndices(l,c,r,t,sb,threshold,p); 1063 1064 hBuff = pktEnc.encodePacket(l+1,c,r,t,cblks[t][c][r], 1065 truncIdxs[t][l][c][r], 1066 hBuff,bBuff,p); 1067 1068 if(pktEnc.isPacketWritable()) { 1069 bsWriter.writePacketHead(hBuff.getBuffer(), 1070 hBuff.getLength(), 1071 false,sopUsed,ephUsed); 1072 bsWriter.writePacketBody(pktEnc.getLastBodyBuf(), 1073 pktEnc.getLastBodyLen(), 1074 false,pktEnc.isROIinPkt(), 1075 pktEnc.getROILen()); 1076 } 1077 } // end loop on precincts 1078 } // end loop on components 1079 } // end loop on resolution levels 1080 } // end loop on layers 1081 } 1082 1083 /** 1084 * Write a piece of bit stream according to the 1085 * COMP_POS_RES_LY_PROG progression mode and between given bounds 1086 * 1087 * @param t Tile index. 1088 * 1089 * @param rs First resolution level index. 1090 * 1091 * @param re Last resolution level index. 1092 * 1093 * @param cs First component index. 1094 * 1095 * @param ce Last component index. 1096 * 1097 * @param lys First layer index for each component and resolution. 1098 * 1099 * @param lye Index of the last layer. 1100 * */ 1101 public void writePosCompResLy(int t,int rs,int re,int cs,int ce, 1102 int[][] lys,int lye) throws IOException { 1103 1104 boolean sopUsed; // Should SOP markers be used ? 1105 boolean ephUsed; // Should EPH markers be used ? 1106 int nc = src.getNumComps(); 1107 int mrl; 1108 SubbandAn sb; 1109 float threshold; 1110 BitOutputBuffer hBuff = null; 1111 byte[] bBuff = null; 1112 1113 // Computes current tile offset in the reference grid 1114 Point nTiles = src.getNumTiles(null); 1115 Point tileI = src.getTile(null); 1116 int x0siz = src.getImgULX(); 1117 int y0siz = src.getImgULY(); 1118 int xsiz = x0siz + src.getImgWidth(); 1119 int ysiz = y0siz + src.getImgHeight(); 1120 int xt0siz = src.getTilePartULX(); 1121 int yt0siz = src.getTilePartULY(); 1122 int xtsiz = src.getNomTileWidth(); 1123 int ytsiz = src.getNomTileHeight(); 1124 int tx0 = (tileI.x==0) ? x0siz : xt0siz+tileI.x*xtsiz; 1125 int ty0 = (tileI.y==0) ? y0siz : yt0siz+tileI.y*ytsiz; 1126 int tx1 = (tileI.x!=nTiles.x-1) ? xt0siz+(tileI.x+1)*xtsiz : xsiz; 1127 int ty1 = (tileI.y!=nTiles.y-1) ? yt0siz+(tileI.y+1)*ytsiz : ysiz; 1128 1129 // Get precinct information (number,distance between two consecutive 1130 // precincts in the reference grid) in each component and resolution 1131 // level 1132 PrecInfo prec; // temporary variable 1133 int p; // Current precinct index 1134 int gcd_x = 0; // Horiz. distance between 2 precincts in the ref. grid 1135 int gcd_y = 0; // Vert. distance between 2 precincts in the ref. grid 1136 int nPrec = 0; // Total number of found precincts 1137 int[][] nextPrec = new int [ce][]; // Next precinct index in each 1138 // component and resolution level 1139 int minlys = 100000; // minimum layer start index of each component 1140 int minx = tx1; // Horiz. offset of the second precinct in the 1141 // reference grid 1142 int miny = ty1; // Vert. offset of the second precinct in the 1143 // reference grid. 1144 int maxx = tx0; // Max. horiz. offset of precincts in the ref. grid 1145 int maxy = ty0; // Max. vert. offset of precincts in the ref. grid 1146 for(int c=cs; c<ce; c++) { 1147 mrl = src.getAnSubbandTree(t,c).resLvl; 1148 nextPrec[c] = new int[mrl+1]; 1149 for(int r=rs; r<re; r++) { 1150 if(r>mrl) continue; 1151 if (r<lys[c].length && lys[c][r]<minlys) { 1152 minlys = lys[c][r]; 1153 } 1154 p = numPrec[t][c][r].y*numPrec[t][c][r].x-1; 1155 for(; p>=0; p--) { 1156 prec = pktEnc.getPrecInfo(t,c,r,p); 1157 if(prec.rgulx!=tx0) { 1158 if(prec.rgulx<minx) minx = prec.rgulx; 1159 if(prec.rgulx>maxx) maxx = prec.rgulx; 1160 } 1161 if(prec.rguly!=ty0){ 1162 if(prec.rguly<miny) miny = prec.rguly; 1163 if(prec.rguly>maxy) maxy = prec.rguly; 1164 } 1165 1166 if(nPrec==0) { 1167 gcd_x = prec.rgw; 1168 gcd_y = prec.rgh; 1169 } else { 1170 gcd_x = MathUtil.gcd(gcd_x,prec.rgw); 1171 gcd_y = MathUtil.gcd(gcd_y,prec.rgh); 1172 } 1173 nPrec++; 1174 } // precincts 1175 } // resolution levels 1176 } // components 1177 if(nPrec==0) { 1178 throw new Error("Image cannot have no precinct"); 1179 } 1180 1181 int pyend = (maxy-miny)/gcd_y+1; 1182 int pxend = (maxx-minx)/gcd_x+1; 1183 int y = ty0; 1184 int x = tx0; 1185 for(int py=0; py<=pyend; py++) { // Vertical precincts 1186 for(int px=0; px<=pxend; px++) { // Horiz. precincts 1187 for(int c=cs; c<ce; c++) { // Components 1188 mrl = src.getAnSubbandTree(t,c).resLvl; 1189 for(int r=rs; r<re; r++) { // Resolution levels 1190 if(r>mrl) continue; 1191 if(nextPrec[c][r] >= 1192 numPrec[t][c][r].x*numPrec[t][c][r].y) { 1193 continue; 1194 } 1195 prec = pktEnc.getPrecInfo(t,c,r,nextPrec[c][r]); 1196 if((prec.rgulx!=x) || (prec.rguly!=y)) { 1197 continue; 1198 } 1199 for(int l=minlys; l<lye; l++) { // Layers 1200 if(r>=lys[c].length) continue; 1201 if(l<lys[c][r]) continue; 1202 1203 // set boolean sopUsed here (SOP markers) 1204 sopUsed = ((String)wp.getSOP().getTileDef(t)).equals("true"); 1205 // set boolean ephUsed here (EPH markers) 1206 ephUsed = ((String)wp.getEPH().getTileDef(t)).equals("true"); 1207 1208 sb = src.getAnSubbandTree(t,c); 1209 for(int i=mrl; i>r; i--) { 1210 sb = sb.subb_LL; 1211 } 1212 1213 threshold = layers[l].rdThreshold; 1214 findTruncIndices(l,c,r,t,sb,threshold, 1215 nextPrec[c][r]); 1216 1217 1218 hBuff = pktEnc.encodePacket(l+1,c,r,t, 1219 cblks[t][c][r], 1220 truncIdxs[t][l][c][r], 1221 hBuff,bBuff, 1222 nextPrec[c][r]); 1223 1224 if(pktEnc.isPacketWritable()) { 1225 bsWriter.writePacketHead(hBuff.getBuffer(), 1226 hBuff.getLength(), 1227 false,sopUsed, 1228 ephUsed); 1229 bsWriter.writePacketBody(pktEnc. 1230 getLastBodyBuf(), 1231 pktEnc. 1232 getLastBodyLen(), 1233 false, 1234 pktEnc.isROIinPkt(), 1235 pktEnc.getROILen()); 1236 } 1237 } // layers 1238 nextPrec[c][r]++; 1239 } // Resolution levels 1240 } // Components 1241 if(px!=pxend) { 1242 x = minx+px*gcd_x; 1243 } else { 1244 x = tx0; 1245 } 1246 } // Horizontal precincts 1247 if(py!=pyend) { 1248 y = miny+py*gcd_y; 1249 } else { 1250 y = ty0; 1251 } 1252 } // Vertical precincts 1253 1254 // Check that all precincts have been written 1255 for(int c=cs; c<ce; c++) { 1256 mrl = src.getAnSubbandTree(t,c).resLvl; 1257 for(int r=rs; r<re; r++) { 1258 if(r>mrl) continue; 1259 if(nextPrec[c][r]<numPrec[t][c][r].x*numPrec[t][c][r].y-1) { 1260 throw new Error("JJ2000 bug: One precinct at least has "+ 1261 "not been written for resolution level "+r 1262 +" of component "+c+" in tile "+t+"."); 1263 } 1264 } 1265 } 1266 } 1267 1268 /** 1269 * Write a piece of bit stream according to the 1270 * COMP_POS_RES_LY_PROG progression mode and between given bounds 1271 * 1272 * @param t Tile index. 1273 * 1274 * @param rs First resolution level index. 1275 * 1276 * @param re Last resolution level index. 1277 * 1278 * @param cs First component index. 1279 * 1280 * @param ce Last component index. 1281 * 1282 * @param lys First layer index for each component and resolution. 1283 * 1284 * @param lye Index of the last layer. 1285 * */ 1286 public void writeCompPosResLy(int t,int rs,int re,int cs,int ce, 1287 int[][] lys,int lye) throws IOException { 1288 1289 boolean sopUsed; // Should SOP markers be used ? 1290 boolean ephUsed; // Should EPH markers be used ? 1291 int nc = src.getNumComps(); 1292 int mrl; 1293 SubbandAn sb; 1294 float threshold; 1295 BitOutputBuffer hBuff = null; 1296 byte[] bBuff = null; 1297 1298 // Computes current tile offset in the reference grid 1299 Point nTiles = src.getNumTiles(null); 1300 Point tileI = src.getTile(null); 1301 int x0siz = src.getImgULX(); 1302 int y0siz = src.getImgULY(); 1303 int xsiz = x0siz + src.getImgWidth(); 1304 int ysiz = y0siz + src.getImgHeight(); 1305 int xt0siz = src.getTilePartULX(); 1306 int yt0siz = src.getTilePartULY(); 1307 int xtsiz = src.getNomTileWidth(); 1308 int ytsiz = src.getNomTileHeight(); 1309 int tx0 = (tileI.x==0) ? x0siz : xt0siz+tileI.x*xtsiz; 1310 int ty0 = (tileI.y==0) ? y0siz : yt0siz+tileI.y*ytsiz; 1311 int tx1 = (tileI.x!=nTiles.x-1) ? xt0siz+(tileI.x+1)*xtsiz : xsiz; 1312 int ty1 = (tileI.y!=nTiles.y-1) ? yt0siz+(tileI.y+1)*ytsiz : ysiz; 1313 1314 // Get precinct information (number,distance between two consecutive 1315 // precincts in the reference grid) in each component and resolution 1316 // level 1317 PrecInfo prec; // temporary variable 1318 int p; // Current precinct index 1319 int gcd_x = 0; // Horiz. distance between 2 precincts in the ref. grid 1320 int gcd_y = 0; // Vert. distance between 2 precincts in the ref. grid 1321 int nPrec = 0; // Total number of found precincts 1322 int[][] nextPrec = new int [ce][]; // Next precinct index in each 1323 // component and resolution level 1324 int minlys = 100000; // minimum layer start index of each component 1325 int minx = tx1; // Horiz. offset of the second precinct in the 1326 // reference grid 1327 int miny = ty1; // Vert. offset of the second precinct in the 1328 // reference grid. 1329 int maxx = tx0; // Max. horiz. offset of precincts in the ref. grid 1330 int maxy = ty0; // Max. vert. offset of precincts in the ref. grid 1331 for(int c=cs; c<ce; c++) { 1332 mrl = src.getAnSubbandTree(t,c).resLvl; 1333 for(int r=rs; r<re; r++) { 1334 if(r>mrl) continue; 1335 nextPrec[c] = new int[mrl+1]; 1336 if (r<lys[c].length && lys[c][r]<minlys) { 1337 minlys = lys[c][r]; 1338 } 1339 p = numPrec[t][c][r].y*numPrec[t][c][r].x-1; 1340 for(; p>=0; p--) { 1341 prec = pktEnc.getPrecInfo(t,c,r,p); 1342 if(prec.rgulx!=tx0) { 1343 if(prec.rgulx<minx) minx = prec.rgulx; 1344 if(prec.rgulx>maxx) maxx = prec.rgulx; 1345 } 1346 if(prec.rguly!=ty0){ 1347 if(prec.rguly<miny) miny = prec.rguly; 1348 if(prec.rguly>maxy) maxy = prec.rguly; 1349 } 1350 1351 if(nPrec==0) { 1352 gcd_x = prec.rgw; 1353 gcd_y = prec.rgh; 1354 } else { 1355 gcd_x = MathUtil.gcd(gcd_x,prec.rgw); 1356 gcd_y = MathUtil.gcd(gcd_y,prec.rgh); 1357 } 1358 nPrec++; 1359 } // precincts 1360 } // resolution levels 1361 } // components 1362 if(nPrec==0) { 1363 throw new Error("Image cannot have no precinct"); 1364 } 1365 1366 int pyend = (maxy-miny)/gcd_y+1; 1367 int pxend = (maxx-minx)/gcd_x+1; 1368 int y; 1369 int x; 1370 for(int c=cs; c<ce; c++) { // Loop on components 1371 y = ty0; 1372 x = tx0; 1373 mrl = src.getAnSubbandTree(t,c).resLvl; 1374 for(int py=0; py<=pyend; py++) { // Vertical precincts 1375 for(int px=0; px<=pxend; px++) { // Horiz. precincts 1376 for(int r=rs; r<re; r++) { // Resolution levels 1377 if(r>mrl) continue; 1378 if(nextPrec[c][r] >= 1379 numPrec[t][c][r].x*numPrec[t][c][r].y) { 1380 continue; 1381 } 1382 prec = pktEnc.getPrecInfo(t,c,r,nextPrec[c][r]); 1383 if((prec.rgulx!=x) || (prec.rguly!=y)) { 1384 continue; 1385 } 1386 1387 for(int l=minlys; l<lye; l++) { // Layers 1388 if(r>=lys[c].length) continue; 1389 if(l<lys[c][r]) continue; 1390 1391 // set boolean sopUsed here (SOP markers) 1392 sopUsed = ((String)wp.getSOP().getTileDef(t)).equals("true"); 1393 // set boolean ephUsed here (EPH markers) 1394 ephUsed = ((String)wp.getEPH().getTileDef(t)).equals("true"); 1395 1396 sb = src.getAnSubbandTree(t,c); 1397 for(int i=mrl; i>r; i--) { 1398 sb = sb.subb_LL; 1399 } 1400 1401 threshold = layers[l].rdThreshold; 1402 findTruncIndices(l,c,r,t,sb,threshold, 1403 nextPrec[c][r]); 1404 1405 hBuff = pktEnc.encodePacket(l+1,c,r,t, 1406 cblks[t][c][r], 1407 truncIdxs[t][l][c][r], 1408 hBuff,bBuff, 1409 nextPrec[c][r]); 1410 1411 if(pktEnc.isPacketWritable()) { 1412 bsWriter.writePacketHead(hBuff.getBuffer(), 1413 hBuff.getLength(), 1414 false,sopUsed, 1415 ephUsed); 1416 bsWriter.writePacketBody(pktEnc. 1417 getLastBodyBuf(), 1418 pktEnc. 1419 getLastBodyLen(), 1420 false, 1421 pktEnc.isROIinPkt(), 1422 pktEnc.getROILen()); 1423 } 1424 1425 } // Layers 1426 nextPrec[c][r]++; 1427 } // Resolution levels 1428 if(px!=pxend) { 1429 x = minx+px*gcd_x; 1430 } else { 1431 x = tx0; 1432 } 1433 } // Horizontal precincts 1434 if(py!=pyend) { 1435 y = miny+py*gcd_y; 1436 } else { 1437 y = ty0; 1438 } 1439 } // Vertical precincts 1440 } // components 1441 1442 // Check that all precincts have been written 1443 for(int c=cs; c<ce; c++) { 1444 mrl = src.getAnSubbandTree(t,c).resLvl; 1445 for(int r=rs; r<re; r++) { 1446 if(r>mrl) continue; 1447 if(nextPrec[c][r]<numPrec[t][c][r].x*numPrec[t][c][r].y-1) { 1448 throw new Error("JJ2000 bug: One precinct at least has "+ 1449 "not been written for resolution level "+r 1450 +" of component "+c+" in tile "+t+"."); 1451 } 1452 } 1453 } 1454 } 1455 1456 /** 1457 * Write a piece of bit stream according to the 1458 * RES_POS_COMP_LY_PROG progression mode and between given bounds 1459 * 1460 * @param t Tile index. 1461 * 1462 * @param rs First resolution level index. 1463 * 1464 * @param re Last resolution level index. 1465 * 1466 * @param cs First component index. 1467 * 1468 * @param ce Last component index. 1469 * 1470 * @param lys First layer index for each component and resolution. 1471 * 1472 * @param lye Last layer index. 1473 * */ 1474 public void writeResPosCompLy(int t,int rs,int re,int cs,int ce, 1475 int[][] lys,int lye) throws IOException { 1476 1477 boolean sopUsed; // Should SOP markers be used ? 1478 boolean ephUsed; // Should EPH markers be used ? 1479 int nc = src.getNumComps(); 1480 int mrl; 1481 SubbandAn sb; 1482 float threshold; 1483 BitOutputBuffer hBuff = null; 1484 byte[] bBuff = null; 1485 1486 // Computes current tile offset in the reference grid 1487 Point nTiles = src.getNumTiles(null); 1488 Point tileI = src.getTile(null); 1489 int x0siz = src.getImgULX(); 1490 int y0siz = src.getImgULY(); 1491 int xsiz = x0siz + src.getImgWidth(); 1492 int ysiz = y0siz + src.getImgHeight(); 1493 int xt0siz = src.getTilePartULX(); 1494 int yt0siz = src.getTilePartULY(); 1495 int xtsiz = src.getNomTileWidth(); 1496 int ytsiz = src.getNomTileHeight(); 1497 int tx0 = (tileI.x==0) ? x0siz : xt0siz+tileI.x*xtsiz; 1498 int ty0 = (tileI.y==0) ? y0siz : yt0siz+tileI.y*ytsiz; 1499 int tx1 = (tileI.x!=nTiles.x-1) ? xt0siz+(tileI.x+1)*xtsiz : xsiz; 1500 int ty1 = (tileI.y!=nTiles.y-1) ? yt0siz+(tileI.y+1)*ytsiz : ysiz; 1501 1502 // Get precinct information (number,distance between two consecutive 1503 // precincts in the reference grid) in each component and resolution 1504 // level 1505 PrecInfo prec; // temporary variable 1506 int p; // Current precinct index 1507 int gcd_x = 0; // Horiz. distance between 2 precincts in the ref. grid 1508 int gcd_y = 0; // Vert. distance between 2 precincts in the ref. grid 1509 int nPrec = 0; // Total number of found precincts 1510 int[][] nextPrec = new int [ce][]; // Next precinct index in each 1511 // component and resolution level 1512 int minlys = 100000; // minimum layer start index of each component 1513 int minx = tx1; // Horiz. offset of the second precinct in the 1514 // reference grid 1515 int miny = ty1; // Vert. offset of the second precinct in the 1516 // reference grid. 1517 int maxx = tx0; // Max. horiz. offset of precincts in the ref. grid 1518 int maxy = ty0; // Max. vert. offset of precincts in the ref. grid 1519 for(int c=cs; c<ce; c++) { 1520 mrl = src.getAnSubbandTree(t,c).resLvl; 1521 nextPrec[c] = new int[mrl+1]; 1522 for(int r=rs; r<re; r++) { 1523 if(r>mrl) continue; 1524 if (r<lys[c].length && lys[c][r]<minlys) { 1525 minlys = lys[c][r]; 1526 } 1527 p = numPrec[t][c][r].y*numPrec[t][c][r].x-1; 1528 for(; p>=0; p--) { 1529 prec = pktEnc.getPrecInfo(t,c,r,p); 1530 if(prec.rgulx!=tx0) { 1531 if(prec.rgulx<minx) minx = prec.rgulx; 1532 if(prec.rgulx>maxx) maxx = prec.rgulx; 1533 } 1534 if(prec.rguly!=ty0){ 1535 if(prec.rguly<miny) miny = prec.rguly; 1536 if(prec.rguly>maxy) maxy = prec.rguly; 1537 } 1538 1539 if(nPrec==0) { 1540 gcd_x = prec.rgw; 1541 gcd_y = prec.rgh; 1542 } else { 1543 gcd_x = MathUtil.gcd(gcd_x,prec.rgw); 1544 gcd_y = MathUtil.gcd(gcd_y,prec.rgh); 1545 } 1546 nPrec++; 1547 } // precincts 1548 } // resolution levels 1549 } // components 1550 1551 if(nPrec==0) { 1552 throw new Error("Image cannot have no precinct"); 1553 } 1554 1555 int pyend = (maxy-miny)/gcd_y+1; 1556 int pxend = (maxx-minx)/gcd_x+1; 1557 int x,y; 1558 for(int r=rs; r<re; r++) { // Resolution levels 1559 y = ty0; 1560 x = tx0; 1561 for(int py=0; py<=pyend; py++) { // Vertical precincts 1562 for(int px=0; px<=pxend; px++) { // Horiz. precincts 1563 for(int c=cs; c<ce; c++) { // Components 1564 mrl = src.getAnSubbandTree(t,c).resLvl; 1565 if(r>mrl) continue; 1566 if(nextPrec[c][r] >= 1567 numPrec[t][c][r].x*numPrec[t][c][r].y) { 1568 continue; 1569 } 1570 prec = pktEnc.getPrecInfo(t,c,r,nextPrec[c][r]); 1571 if((prec.rgulx!=x) || (prec.rguly!=y)) { 1572 continue; 1573 } 1574 for(int l=minlys; l<lye; l++) { 1575 if(r>=lys[c].length) continue; 1576 if(l<lys[c][r]) continue; 1577 1578 // set boolean sopUsed here (SOP markers) 1579 sopUsed = ((String)wp.getSOP().getTileDef(t)).equals("true"); 1580 // set boolean ephUsed here (EPH markers) 1581 ephUsed = ((String)wp.getEPH().getTileDef(t)).equals("true"); 1582 1583 sb = src.getAnSubbandTree(t,c); 1584 for(int i=mrl; i>r; i--) { 1585 sb = sb.subb_LL; 1586 } 1587 1588 threshold = layers[l].rdThreshold; 1589 findTruncIndices(l,c,r,t,sb,threshold, 1590 nextPrec[c][r]); 1591 1592 hBuff = pktEnc.encodePacket(l+1,c,r,t, 1593 cblks[t][c][r], 1594 truncIdxs[t][l][c][r], 1595 hBuff,bBuff, 1596 nextPrec[c][r]); 1597 1598 if(pktEnc.isPacketWritable()) { 1599 bsWriter.writePacketHead(hBuff.getBuffer(), 1600 hBuff.getLength(), 1601 false,sopUsed, 1602 ephUsed); 1603 bsWriter.writePacketBody(pktEnc. 1604 getLastBodyBuf(), 1605 pktEnc. 1606 getLastBodyLen(), 1607 false, 1608 pktEnc.isROIinPkt(), 1609 pktEnc.getROILen()); 1610 } 1611 1612 } // layers 1613 nextPrec[c][r]++; 1614 } // Components 1615 if(px!=pxend) { 1616 x = minx+px*gcd_x; 1617 } else { 1618 x = tx0; 1619 } 1620 } // Horizontal precincts 1621 if(py!=pyend) { 1622 y = miny+py*gcd_y; 1623 } else { 1624 y = ty0; 1625 } 1626 } // Vertical precincts 1627 } // Resolution levels 1628 1629 // Check that all precincts have been written 1630 for(int c=cs; c<ce; c++) { 1631 mrl = src.getAnSubbandTree(t,c).resLvl; 1632 for(int r=rs; r<re; r++) { 1633 if(r>mrl) continue; 1634 if(nextPrec[c][r]<numPrec[t][c][r].x*numPrec[t][c][r].y-1) { 1635 throw new Error("JJ2000 bug: One precinct at least has "+ 1636 "not been written for resolution level "+r 1637 +" of component "+c+" in tile "+t+"."); 1638 } 1639 } 1640 } 1641 } 1642 1643 /** 1644 * This function implements the rate-distortion optimization algorithm. 1645 * It saves the state of any previously generated bit-stream layers and 1646 * then simulate the formation of a new layer in the bit stream as often 1647 * as necessary to find the smallest rate-distortion threshold such that 1648 * the total number of bytes required to represent the layer does not 1649 * exceed `maxBytes' minus `prevBytes'. It then restores the state of any 1650 * previously generated bit-stream layers and returns the threshold. 1651 * 1652 * @param layerIdx The index of the current layer 1653 * 1654 * @param fmaxt The maximum admissible slope value. Normally the threshold 1655 * slope of the previous layer. 1656 * 1657 * @param maxBytes The maximum number of bytes that can be written. It 1658 * includes the length of the current layer bistream length and all the 1659 * previous layers bit streams. 1660 * 1661 * @param prevBytes The number of bytes of all the previous layers. 1662 * 1663 * @return The value of the slope threshold. 1664 * */ 1665 private float optimizeBitstreamLayer (int layerIdx, float fmaxt, 1666 int maxBytes, int prevBytes) 1667 throws IOException { 1668 1669 int nt; // The total number of tiles 1670 int nc; // The total number of components 1671 int numLvls; // The total number of resolution levels 1672 int actualBytes; // Actual number of bytes for a layer 1673 float fmint; // Minimum of the current threshold interval 1674 float ft; // Current threshold 1675 SubbandAn sb; // Current subband 1676 BitOutputBuffer hBuff;// The packet head buffer 1677 byte[] bBuff; // The packet body buffer 1678 int sidx; // The index in the summary table 1679 boolean sopUsed; // Should SOP markers be used ? 1680 boolean ephUsed; // Should EPH markers be used ? 1681 int precinctIdx; // Precinct index for current packet 1682 int nPrec; // Number of precincts in the current resolution level 1683 1684 // Save the packet encoder state 1685 pktEnc.save(); 1686 1687 nt = src.getNumTiles(); 1688 nc = src.getNumComps(); 1689 hBuff = null; 1690 bBuff = null; 1691 1692 // Estimate the minimum slope to start with from the summary 1693 // information in 'RDSlopesRates'. This is a real minimum since it 1694 // does not include the packet head overhead, which is always 1695 // non-zero. 1696 1697 // Look for the summary entry that gives 'maxBytes' or more data 1698 for (sidx=RD_SUMMARY_SIZE-1; sidx > 0; sidx--) { 1699 if (RDSlopesRates[sidx] >= maxBytes) { 1700 break; 1701 } 1702 } 1703 // Get the corresponding minimum slope 1704 fmint = getSlopeFromSIndex(sidx); 1705 // Ensure that it is smaller the maximum slope 1706 if (fmint>=fmaxt) { 1707 sidx--; 1708 fmint = getSlopeFromSIndex(sidx); 1709 } 1710 // If we are using the last entry of the summary, then that 1711 // corresponds to all the data, Thus, set the minimum slope to 0. 1712 if (sidx<=0) fmint = 0; 1713 1714 // We look for the best threshold 'ft', which is the lowest threshold 1715 // that generates no more than 'maxBytes' code bytes. 1716 1717 // The search is done iteratively using a binary split algorithm. We 1718 // start with 'fmaxt' as the maximum possible threshold, and 'fmint' 1719 // as the minimum threshold. The threshold 'ft' is calculated as the 1720 // middle point of 'fmaxt'-'fmint' interval. The 'fmaxt' or 'fmint' 1721 // bounds are moved according to the number of bytes obtained from a 1722 // simulation, where 'ft' is used as the threshold. 1723 1724 // We stop whenever the interval is sufficiently small, and thus 1725 // enough precision is achieved. 1726 1727 // Initialize threshold as the middle point of the interval. 1728 ft = (fmaxt+fmint)/2f; 1729 // If 'ft' reaches 'fmint' it means that 'fmaxt' and 'fmint' are so 1730 // close that the average is 'fmint', due to rounding. Force it to 1731 // 'fmaxt' instead, since 'fmint' is normally an exclusive lower 1732 // bound. 1733 if (ft <= fmint) ft = fmaxt; 1734 1735 do { 1736 // Get the number of bytes used by this layer, if 'ft' is the 1737 // threshold, by simulation. 1738 actualBytes = prevBytes; 1739 src.setTile(0,0); 1740 1741 for (int t=0; t<nt; t++){ 1742 for (int c=0; c<nc; c++) { 1743 // set boolean sopUsed here (SOP markers) 1744 sopUsed = ((String)wp.getSOP().getTileDef(t)).equalsIgnoreCase("true"); 1745 // set boolean ephUsed here (EPH markers) 1746 ephUsed = ((String)wp.getEPH().getTileDef(t)).equalsIgnoreCase("true"); 1747 1748 // Get LL subband 1749 sb = (SubbandAn) src.getAnSubbandTree(t,c); 1750 numLvls = sb.resLvl + 1; 1751 sb = (SubbandAn) sb.getSubbandByIdx(0,0); 1752 //loop on resolution levels 1753 for(int r=0; r<numLvls; r++) { 1754 1755 nPrec = numPrec[t][c][r].x*numPrec[t][c][r].y; 1756 for(int p=0; p<nPrec; p++) { 1757 1758 findTruncIndices(layerIdx,c,r,t,sb,ft,p); 1759 hBuff = pktEnc.encodePacket(layerIdx+1,c,r,t, 1760 cblks[t][c][r], 1761 truncIdxs[t][layerIdx] 1762 [c][r],hBuff,bBuff,p); 1763 1764 if(pktEnc.isPacketWritable()) { 1765 bBuff = pktEnc.getLastBodyBuf(); 1766 actualBytes += bsWriter. 1767 writePacketHead(hBuff.getBuffer(), 1768 hBuff.getLength(), 1769 true, sopUsed,ephUsed); 1770 actualBytes += bsWriter. 1771 writePacketBody(bBuff, 1772 pktEnc.getLastBodyLen(), 1773 true,pktEnc.isROIinPkt(), 1774 pktEnc.getROILen()); 1775 } 1776 } // end loop on precincts 1777 sb = sb.parent; 1778 } // End loop on resolution levels 1779 } // End loop on components 1780 } // End loop on tiles 1781 1782 // Move the interval bounds according to simulation result 1783 if (actualBytes>maxBytes) { 1784 // 'ft' is too low and generates too many bytes, make it the 1785 // new minimum. 1786 fmint = ft; 1787 } else { 1788 // 'ft' is too high and does not generate as many bytes as we 1789 // are allowed too, make it the new maximum. 1790 fmaxt = ft; 1791 } 1792 1793 // Update 'ft' for the new iteration as the middle point of the 1794 // new interval. 1795 ft = (fmaxt+fmint)/2f; 1796 // If 'ft' reaches 'fmint' it means that 'fmaxt' and 'fmint' are 1797 // so close that the average is 'fmint', due to rounding. Force it 1798 // to 'fmaxt' instead, since 'fmint' is normally an exclusive 1799 // lower bound. 1800 if (ft <= fmint) ft = fmaxt; 1801 1802 // Restore previous packet encoder state 1803 pktEnc.restore(); 1804 1805 // We continue to iterate, until the threshold reaches the upper 1806 // limit of the interval, within a FLOAT_REL_PRECISION relative 1807 // tolerance, or a FLOAT_ABS_PRECISION absolute tolerance. This is 1808 // the sign that the interval is sufficiently small. 1809 } while (ft < fmaxt*(1f-FLOAT_REL_PRECISION) && 1810 ft < (fmaxt-FLOAT_ABS_PRECISION)); 1811 1812 // If we have a threshold which is close to 0, set it to 0 so that 1813 // everything is taken into the layer. This is to avoid not sending 1814 // some least significant bit-planes in the lossless case. We use the 1815 // FLOAT_ABS_PRECISION value as a measure of "close" to 0. 1816 if (ft <= FLOAT_ABS_PRECISION) { 1817 ft = 0f; 1818 } else { 1819 // Otherwise make the threshold 'fmaxt', just to be sure that we 1820 // will not send more bytes than allowed. 1821 ft = fmaxt; 1822 } 1823 return ft; 1824 } 1825 1826 /** 1827 * This function attempts to estimate a rate-distortion slope threshold 1828 * which will achieve a target number of code bytes close the 1829 * `targetBytes' value. 1830 * 1831 * @param targetBytes The target number of bytes for the current layer 1832 * 1833 * @param lastLayer The previous layer information. 1834 * 1835 * @return The value of the slope threshold for the estimated layer 1836 * */ 1837 private float estimateLayerThreshold(int targetBytes, 1838 EBCOTLayer lastLayer) { 1839 float log_sl1; // The log of the first slope used for interpolation 1840 float log_sl2; // The log of the second slope used for interpolation 1841 float log_len1; // The log of the first length used for interpolation 1842 float log_len2; // The log of the second length used for interpolation 1843 float log_isl; // The log of the interpolated slope 1844 float log_ilen; // Log of the interpolated length 1845 float log_ab; // Log of actual bytes in last layer 1846 int sidx; // Index into the summary R-D info array 1847 float log_off; // The log of the offset proportion 1848 int tlen; // The corrected target layer length 1849 float lthresh; // The threshold of the last layer 1850 float eth; // The estimated threshold 1851 1852 // In order to estimate the threshold we base ourselves in the summary 1853 // R-D info in RDSlopesRates. In order to use it we must compensate 1854 // for the overhead of the packet heads. The proportion of overhead is 1855 // estimated using the last layer simulation results. 1856 1857 // NOTE: the model used in this method is that the slope varies 1858 // linearly with the log of the rate (i.e. length). 1859 1860 // NOTE: the model used in this method is that the distortion is 1861 // proprotional to a power of the rate. Thus, the slope is also 1862 // proportional to another power of the rate. This translates as the 1863 // log of the slope varies linearly with the log of the rate, which is 1864 // what we use. 1865 1866 // 1) Find the offset of the length predicted from the summary R-D 1867 // information, to the actual length by using the last layer. 1868 1869 // We ensure that the threshold we use for estimation actually 1870 // includes some data. 1871 lthresh = lastLayer.rdThreshold; 1872 if (lthresh > maxSlope) lthresh = maxSlope; 1873 // If the slope of the last layer is too small then we just include 1874 // all the rest (not possible to do better). 1875 if (lthresh < FLOAT_ABS_PRECISION) return 0f; 1876 sidx = getLimitedSIndexFromSlope(lthresh); 1877 // If the index is outside of the summary info array use the last two, 1878 // or first two, indexes, as appropriate 1879 if (sidx >= RD_SUMMARY_SIZE-1) sidx = RD_SUMMARY_SIZE-2; 1880 1881 // Get the logs of the lengths and the slopes 1882 1883 if (RDSlopesRates[sidx+1] == 0) { 1884 // Pathological case, we can not use log of 0. Add 1885 // RDSlopesRates[sidx]+1 bytes to the rates (just a crude simple 1886 // solution to this rare case) 1887 log_len1 = (float)Math.log((RDSlopesRates[sidx]<<1)+1); 1888 log_len2 = (float)Math.log(RDSlopesRates[sidx]+1); 1889 log_ab = (float)Math.log(lastLayer.actualBytes+ 1890 RDSlopesRates[sidx]+1); 1891 } 1892 else { 1893 log_len1 = (float)Math.log(RDSlopesRates[sidx]); 1894 log_len2 = (float)Math.log(RDSlopesRates[sidx+1]); 1895 log_ab = (float)Math.log(lastLayer.actualBytes); 1896 } 1897 1898 log_sl1 = (float)Math.log(getSlopeFromSIndex(sidx)); 1899 log_sl2 = (float)Math.log(getSlopeFromSIndex(sidx+1)); 1900 1901 log_isl = (float)Math.log(lthresh); 1902 1903 log_ilen = log_len1 + 1904 (log_isl-log_sl1)*(log_len1-log_len2)/(log_sl1-log_sl2); 1905 1906 log_off = log_ab - log_ilen; 1907 1908 // Do not use negative offsets (i.e. offset proportion larger than 1) 1909 // since that is probably a sign that our model is off. To be 1910 // conservative use an offset of 0 (i.e. offset proportiojn 1). 1911 if (log_off < 0) log_off = 0f; 1912 1913 // 2) Correct the target layer length by the offset. 1914 1915 tlen = (int)(targetBytes/(float)Math.exp(log_off)); 1916 1917 // 3) Find, from the summary R-D info, the thresholds that generate 1918 // lengths just above and below our corrected target layer length. 1919 1920 // Look for the index in the summary info array that gives the largest 1921 // length smaller than the target length 1922 for (sidx = RD_SUMMARY_SIZE-1; sidx>=0 ; sidx--) { 1923 if (RDSlopesRates[sidx] >= tlen) break; 1924 } 1925 sidx++; 1926 // Correct if out of the array 1927 if (sidx >= RD_SUMMARY_SIZE) sidx = RD_SUMMARY_SIZE-1; 1928 if (sidx <= 0) sidx = 1; 1929 1930 // Get the log of the lengths and the slopes that are just above and 1931 // below the target length. 1932 1933 if (RDSlopesRates[sidx] == 0) { 1934 // Pathological case, we can not use log of 0. Add 1935 // RDSlopesRates[sidx-1]+1 bytes to the rates (just a crude simple 1936 // solution to this rare case) 1937 log_len1 = (float)Math.log(RDSlopesRates[sidx-1]+1); 1938 log_len2 = (float)Math.log((RDSlopesRates[sidx-1]<<1)+1); 1939 log_ilen = (float)Math.log(tlen+RDSlopesRates[sidx-1]+1); 1940 } 1941 else { 1942 // Normal case, we can safely take the logs. 1943 log_len1 = (float)Math.log(RDSlopesRates[sidx]); 1944 log_len2 = (float)Math.log(RDSlopesRates[sidx-1]); 1945 log_ilen = (float)Math.log(tlen); 1946 } 1947 1948 log_sl1 = (float)Math.log(getSlopeFromSIndex(sidx)); 1949 log_sl2 = (float)Math.log(getSlopeFromSIndex(sidx-1)); 1950 1951 // 4) Interpolate the two thresholds to find the target threshold. 1952 1953 log_isl = log_sl1 + 1954 (log_ilen-log_len1)*(log_sl1-log_sl2)/(log_len1-log_len2); 1955 1956 eth = (float)Math.exp(log_isl); 1957 1958 // Correct out of bounds results 1959 if (eth > lthresh) eth = lthresh; 1960 if (eth < FLOAT_ABS_PRECISION) eth = 0f; 1961 1962 // Return the estimated threshold 1963 return eth; 1964 } 1965 1966 /** 1967 * This function finds the new truncation points indices for a packet. It 1968 * does so by including the data from the code-blocks in the component, 1969 * resolution level and tile, associated with a R-D slope which is larger 1970 * than or equal to 'fthresh'. 1971 * 1972 * @param layerIdx The index of the current layer 1973 * 1974 * @param compIdx The index of the current component 1975 * 1976 * @param lvlIdx The index of the current resolution level 1977 * 1978 * @param tileIdx The index of the current tile 1979 * 1980 * @param subb The LL subband in the resolution level lvlIdx, which is 1981 * parent of all the subbands in the packet. Except for resolution level 0 1982 * this subband is always a node. 1983 * 1984 * @param fthresh The value of the rate-distortion threshold 1985 * */ 1986 private void findTruncIndices(int layerIdx, int compIdx, int lvlIdx, 1987 int tileIdx, SubbandAn subb, 1988 float fthresh, int precinctIdx) { 1989 int minsbi, maxsbi, b, bIdx, n; 1990 Point ncblks = null; 1991 SubbandAn sb; 1992 CBlkRateDistStats cur_cblk; 1993 PrecInfo prec = pktEnc.getPrecInfo(tileIdx,compIdx,lvlIdx,precinctIdx); 1994 Point cbCoord; 1995 1996 sb = subb; 1997 while(sb.subb_HH != null) { 1998 sb = sb.subb_HH; 1999 } 2000 minsbi = (lvlIdx==0) ? 0 : 1; 2001 maxsbi = (lvlIdx==0) ? 1 : 4; 2002 2003 int yend,xend; 2004 2005 sb = (SubbandAn)subb.getSubbandByIdx(lvlIdx, minsbi); 2006 for(int s=minsbi; s<maxsbi; s++) { //loop on subbands 2007 yend = (prec.cblk[s]!=null) ? prec.cblk[s].length : 0; 2008 for(int y=0; y<yend; y++) { 2009 xend = (prec.cblk[s][y]!=null) ? prec.cblk[s][y].length : 0; 2010 for (int x=0; x<xend; x++) { 2011 cbCoord = prec.cblk[s][y][x].idx; 2012 b = cbCoord.x+cbCoord.y*sb.numCb.x; 2013 //Get the current code-block 2014 cur_cblk = cblks[tileIdx][compIdx][lvlIdx][s][b]; 2015 for(n=0; n<cur_cblk.nVldTrunc; n++) { 2016 if(cur_cblk.truncSlopes[n] < fthresh) { 2017 break; 2018 } else { 2019 continue; 2020 } 2021 } 2022 // Store the index in the code-block truncIdxs that gives 2023 // the real truncation index. 2024 truncIdxs[tileIdx][layerIdx][compIdx][lvlIdx][s][b] = n-1; 2025 2026 } // End loop on horizontal code-blocks 2027 } // End loop on vertical code-blocks 2028 sb = (SubbandAn)sb.nextSubband(); 2029 } // End loop on subbands 2030 } 2031 2032 2033 /** 2034 * Returns the index of a slope for the summary table, limiting to the 2035 * admissible values. The index is calculated as RD_SUMMARY_OFF plus the 2036 * maximum exponent, base 2, that yields a value not larger than the slope 2037 * itself. 2038 * 2039 * <P>If the value to return is lower than 0, 0 is returned. If it is 2040 * larger than the maximum table index, then the maximum is returned. 2041 * 2042 * @param slope The slope value 2043 * 2044 * @return The index for the summary table of the slope. 2045 * */ 2046 private static int getLimitedSIndexFromSlope(float slope) { 2047 int idx; 2048 2049 idx = (int)Math.floor(Math.log(slope)/LOG2) + RD_SUMMARY_OFF; 2050 2051 if (idx < 0) { 2052 return 0; 2053 } 2054 else if (idx >= RD_SUMMARY_SIZE) { 2055 return RD_SUMMARY_SIZE-1; 2056 } 2057 else { 2058 return idx; 2059 } 2060 } 2061 2062 /** 2063 * Returns the minimum slope value associated with a summary table 2064 * index. This minimum slope is just 2^(index-RD_SUMMARY_OFF). 2065 * 2066 * @param index The summary index value. 2067 * 2068 * @return The minimum slope value associated with a summary table index. 2069 * */ 2070 private static float getSlopeFromSIndex(int index) { 2071 return (float)Math.pow(2,(index-RD_SUMMARY_OFF)); 2072 } 2073}