001/* 002 * $RCSfile: FileBitstreamReaderAgent.java,v $ 003 * $Revision: 1.4 $ 004 * $Date: 2006/10/05 01:10:31 $ 005 * $State: Exp $ 006 * 007 * Class: FileBitstreamReaderAgent 008 * 009 * Description: Retrieve code-blocks codewords in the bit stream 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.codestream.reader; 045import java.awt.Point; 046import java.io.ByteArrayInputStream; 047import java.io.EOFException; 048import java.io.IOException; 049import java.util.ArrayList; 050import java.util.Vector; 051 052import javax.imageio.stream.ImageInputStream; 053import javax.imageio.stream.MemoryCacheImageInputStream; 054 055import jj2000.j2k.JJ2KExceptionHandler; 056import jj2000.j2k.NoNextElementException; 057import jj2000.j2k.NotImplementedError; 058import jj2000.j2k.codestream.CorruptedCodestreamException; 059import jj2000.j2k.codestream.HeaderInfo; 060import jj2000.j2k.codestream.Markers; 061import jj2000.j2k.codestream.PrecInfo; 062import jj2000.j2k.codestream.ProgressionType; 063import jj2000.j2k.decoder.DecoderSpecs; 064import jj2000.j2k.entropy.StdEntropyCoderOptions; 065import jj2000.j2k.entropy.decoder.DecLyrdCBlk; 066import jj2000.j2k.io.RandomAccessIO; 067import jj2000.j2k.quantization.dequantizer.StdDequantizerParams; 068import jj2000.j2k.util.ArrayUtil; 069import jj2000.j2k.util.FacilityManager; 070import jj2000.j2k.util.MathUtil; 071import jj2000.j2k.util.MsgLogger; 072import jj2000.j2k.wavelet.synthesis.SubbandSyn; 073 074import com.github.jaiimageio.jpeg2000.impl.J2KImageReadParamJava; 075 076/** 077 * This class reads the bit stream (with the help of HeaderDecoder for tile 078 * headers and PktDecoder for packets header and body) and retrives location 079 * of all code-block's codewords. 080 * 081 * <P>Note: All tile-parts headers are read by the constructor whereas packets 082 * are processed when decoding related tile (when setTile method is called). 083 * 084 * <P>In parsing mode, the reader simulates a virtual layer-resolution 085 * progressive bit stream with the same truncation points in each code-block, 086 * whereas in truncation mode, only the first bytes are taken into account (it 087 * behaves like if it is a real truncated codestream). 088 * 089 * @see HeaderDecoder 090 * @see PktDecoder 091 * */ 092public class FileBitstreamReaderAgent extends BitstreamReaderAgent 093 implements Markers, ProgressionType, StdEntropyCoderOptions{ 094 095 /** Whether or not the last read Psot value was zero. Only the Psot in the 096 * last tile-part in the codestream can have such a value. */ 097 private boolean isPsotEqualsZero = true; 098 099 /** Reference to the PktDecoder instance */ 100 public PktDecoder pktDec; 101 102 /** Reference to the J2KImageReadParamJava instance */ 103 private J2KImageReadParamJava j2krparam; 104 105 /** The RandomAccessIO where to get data from */ 106 private RandomAccessIO in; 107 108 /** The number of tiles in the image */ 109 private int nt; 110 111 /** Offset of the first packet in each tile-part in each tile */ 112 private int[][] firstPackOff; 113 114 /** 115 * Returns the number of tile-part found for a given tile 116 * 117 * @param t Tile index 118 * 119 * */ 120 public int getNumTileParts(int t) { 121 if(firstPackOff==null || firstPackOff[t]==null) { 122 throw new Error("Tile "+t+" not found in input codestream."); 123 } 124 return firstPackOff[t].length; 125 } 126 127 /** Number of bytes allocated to each tile. In parsing mode, this number 128 * is related to the tile length in the codestream whereas in truncation 129 * mode all the rate is affected to the first tiles. */ 130 private int[] nBytes; 131 132 /** Whether or not to print information found in codestream */ 133 private boolean printInfo = false; 134 135 /** 136 * Backup of the number of bytes allocated to each tile. This array is 137 * used to restore the number of bytes to read in each tile when the 138 * codestream is read several times (for instance when decoding an R,G,B 139 * image to three output files) 140 * */ 141 private int[] baknBytes; 142 143 /** Length of each tile-part (written in Psot) */ 144 private int[][] tilePartLen; 145 146 /** Total length of each tile */ 147 private int[] totTileLen; 148 149 /** Total length of tiles' header */ 150 private int[] totTileHeadLen; 151 152 /** First tile part header length*/ 153 private int firstTilePartHeadLen; 154 155 /** Total length of all tile parts in all tiles */ 156 private double totAllTileLen; 157 158 /** Length of main header */ 159 private int mainHeadLen; 160 161 /** Length of main and tile-parts headers */ 162 private int headLen = 0; 163 164 /** Length of all tile-part headers */ 165 private int[][] tilePartHeadLen; 166 167 /** Length of each packet head found in the tile */ 168 private Vector pktHL; 169 170 /** True if truncation mode is used. False if parsing mode */ 171 private boolean isTruncMode; 172 173 /** The number of tile-parts that remain to read */ 174 private int remainingTileParts; 175 176 /** The number of tile-parts read so far for each tile */ 177 private int[] tilePartsRead; 178 179 /** Thetotal number of tile-parts read so far */ 180 private int totTilePartsRead=0; 181 182 /** The number of tile-parts in each tile */ 183 private int[] tileParts; 184 185 /** The total number of tile-parts in each tile */ 186 private int[] totTileParts; 187 188 /** The current tile part being used */ 189 private int curTilePart; 190 191 /** The number of the tile-part in the codestream */ 192 private int[][] tilePartNum; 193 194 /** Whether or not a EOC marker has been found instead of a SOT */ 195 private boolean isEOCFound = false; 196 197 /** Reference to the HeaderInfo instance (used when reading SOT marker 198 * segments) */ 199 private HeaderInfo hi; 200 201 /** Array containing info. for all the code-blocks:<br> 202 * - 1st dim: component index.<br> 203 * - 2nd dim: resolution level index.<br> 204 * - 3rd dim: subband index.<br> 205 * - 4th/5th dim: code-block index (vert. and horiz.).<br> 206 */ 207 private CBlkInfo[][][][][] cbI; 208 209 /** Gets the reference to the CBlkInfo array */ 210 public CBlkInfo[][][][][] getCBlkInfo() { 211 return cbI; 212 } 213 214 /** The maximum number of layers to decode for any code-block */ 215 private int lQuit; 216 217 /** Whether or not to use only first progression order */ 218 private boolean usePOCQuit = false; 219 220 /** 221 * Reads all tiles headers and keep offset of their first 222 * packet. Finally it calls the rate allocation method. 223 * 224 * @param hd HeaderDecoder of the codestream. 225 * 226 * @param ehs The input stream where to read bit-stream. 227 * 228 * @param decSpec The decoder specifications 229 * 230 * @param j2krparam The J2KImageReadParam instance created from the 231 * command-line arguments. 232 * 233 * @param cdstrInfo Whether or not to print information found in 234 * codestream. 235 * 236 * @see #allocateRate 237 * */ 238 public FileBitstreamReaderAgent(HeaderDecoder hd,RandomAccessIO ehs, 239 DecoderSpecs decSpec, 240 J2KImageReadParamJava j2krparam, 241 boolean cdstrInfo,HeaderInfo hi) 242 throws IOException { 243 super(hd,decSpec); 244 245 this.j2krparam = j2krparam; 246 this.printInfo = cdstrInfo; 247 this.hi = hi; 248 249 String strInfo = printInfo ? 250 "Codestream elements information in bytes "+ 251 "(offset, total length, header length):\n\n" : null; 252 253 // Check whether quit conditiosn used 254 //usePOCQuit = j2krparam.getPOCQuit(); 255 256 // Get decoding rate 257 if (j2krparam.getDecodingRate() == Double.MAX_VALUE) 258 tnbytes = Integer.MAX_VALUE; 259 else 260 tnbytes = (int)(j2krparam.getDecodingRate() * hd.getMaxCompImgWidth() * 261 hd.getMaxCompImgHeight()) / 8; 262 //isTruncMode = !j2krparam.getParsing(); 263 isTruncMode = true; 264 265 // Check if quit conditions are being used 266 //int ncbQuit = j2krparam.getNCBQuit(); 267 int ncbQuit = -1; 268 if(ncbQuit != -1 && !isTruncMode){ 269 throw new Error("Cannot use -parsing and -ncb_quit condition at "+ 270 "the same time."); 271 } 272 273// lQuit = j2krparam.getLQuit(); 274 lQuit = -1; 275 276 // initializations 277 nt = ntX * ntY; 278 in = ehs; 279 pktDec = new PktDecoder(decSpec,hd,ehs,this,isTruncMode, ncbQuit); 280 281 tileParts = new int[nt]; 282 totTileParts = new int[nt]; 283 totTileLen = new int[nt]; 284 tilePartLen = new int[nt][]; 285 tilePartNum = new int[nt][]; 286 firstPackOff = new int[nt][]; 287 tilePartsRead = new int[nt]; 288 totTileHeadLen = new int[nt]; 289 tilePartHeadLen = new int[nt][]; 290 nBytes = new int[nt]; 291 baknBytes = new int[nt]; 292 hd.nTileParts = new int[nt]; 293 294 295 this.isTruncMode = isTruncMode; 296 297 // Keeps main header's length, takes file format overhead into account 298 cdstreamStart = hd.mainHeadOff; // Codestream offset in the file 299 mainHeadLen = in.getPos() - cdstreamStart; 300 headLen = mainHeadLen; 301 302 // If ncb and lbody quit conditions are used, headers are not counted 303 if(ncbQuit == -1) { 304 anbytes = mainHeadLen; 305 } else { 306 anbytes = 0; 307 } 308 309 if(printInfo) 310 strInfo += "Main header length : "+cdstreamStart+", "+mainHeadLen+ 311 ", "+mainHeadLen+"\n"; 312 313 // If cannot even read the first tile-part 314 if(anbytes>tnbytes) { 315 throw new Error("Requested bitrate is too small."); 316 } 317 318 // Initialize variables used when reading tile-part headers. 319 totAllTileLen = 0; 320 remainingTileParts = nt; // at least as many tile-parts as tiles 321 maxPos = lastPos = in.getPos(); 322 323 // Update 'res' value according to the parameter and the main header. 324 if(j2krparam.getResolution()== -1) { 325 targetRes = decSpec.dls.getMin(); 326 } else { 327 targetRes = j2krparam.getResolution(); 328 if(targetRes<0) { 329 throw new 330 IllegalArgumentException("Specified negative "+ 331 "resolution level index: "+ 332 targetRes); 333 } 334 } 335 336 // Verify reduction in resolution level 337 int mdl = decSpec.dls.getMin(); 338 if(targetRes>mdl) { 339 FacilityManager.getMsgLogger(). 340 printmsg(MsgLogger.WARNING, 341 "Specified resolution level ("+targetRes+ 342 ") is larger"+ 343 " than the maximum possible. Setting it to "+ 344 mdl +" (maximum possible)"); 345 targetRes = mdl; 346 } 347 348 // Initialize tile part positions from TLM marker segment. 349 initTLM(); 350 } 351 352 // An array of the positions of tile parts: 353 // - length of tilePartPositions is nt. 354 // - length of tilePartPositions[i] is totTileParts[i]. 355 long[][] tilePartPositions = null; 356 357 // 358 // Initialize the tilePartPositions positions array if a TLM marker 359 // segment is present in the main header. If no such marker segment 360 // is present the array will remain null. This method rewinds to the 361 // start of the codestream and scans until the first SOT marker is 362 // encountered. Before return the stream is returned to its position 363 // when the method was invoked. 364 // 365 private void initTLM() throws IOException { 366 // Save the position to return to at the end of this method. 367 int savePos = in.getPos(); 368 369 // Array to store contents of TLM segments. The first index is 370 // Ztlm. The contents of tlmSegments[i] is the bytes in the TLM 371 // segment with Ztlm == i after the Ztlm byte. 372 byte[][] tlmSegments = null; 373 374 // Number of TLM segments. The first numTLM elements of tlmSegments 375 // should be non-null if the segments are correct. 376 int numTLM = 0; 377 378 try { 379 // Rewind to the start of the main header. 380 in.seek(cdstreamStart + 2); // skip SOC 381 382 // Loop over marker segments. 383 short marker; 384 while((marker = in.readShort()) != SOT) { 385 // Get the length (which includes the 2-byte length parameter). 386 int markerLength = in.readUnsignedShort(); 387 388 // Process TLM segments. 389 if(marker == TLM) { 390 numTLM++; 391 392 if(tlmSegments == null) { 393 tlmSegments = new byte[256][]; // 0 <= Ztlm <= 255 394 } 395 396 // Save contents after Ztlm in array. 397 int Ztlm = in.read(); 398 tlmSegments[Ztlm] = new byte[markerLength - 3]; 399 in.readFully(tlmSegments[Ztlm], 0, markerLength - 3); 400 } else { 401 in.skipBytes(markerLength - 2); 402 } 403 } 404 } catch(IOException e) { 405 // Reset so that the TLM segments are not processed further. 406 tlmSegments = null; 407 } 408 409 if(tlmSegments != null) { 410 ArrayList[] tlmOffsets = null; 411 412 // Tiles start after the main header. 413 long tilePos = cdstreamStart + mainHeadLen; 414 415 // Tile counter for when tile indexes are not included. 416 int tileCounter = 0; 417 418 for(int itlm = 0; itlm < numTLM; itlm++) { 419 if(tlmSegments[itlm] == null) { 420 // Null segment among first numTLM entries: error. 421 tlmOffsets = null; 422 break; 423 } else if(tlmOffsets == null) { 424 tlmOffsets = new ArrayList[nt]; 425 } 426 427 // Create a stream. 428 ByteArrayInputStream bais = 429 new ByteArrayInputStream(tlmSegments[itlm]); 430 ImageInputStream iis = new MemoryCacheImageInputStream(bais); 431 432 try { 433 int Stlm = iis.read(); 434 int ST = (Stlm >> 4) & 0x3; 435 int SP = (Stlm >> 6) & 0x1; 436 437 int tlmLength = tlmSegments[itlm].length; 438 while(iis.getStreamPosition() < tlmLength) { 439 int tileIndex = tileCounter; 440 switch(ST) { 441 case 1: 442 tileIndex = iis.read(); 443 break; 444 case 2: 445 tileIndex = iis.readUnsignedShort(); 446 } 447 448 if(tlmOffsets[tileIndex] == null) { 449 tlmOffsets[tileIndex] = new ArrayList(); 450 } 451 tlmOffsets[tileIndex].add(new Long(tilePos)); 452 453 long tileLength = 0L; 454 switch(SP) { 455 case 0: 456 tileLength = iis.readUnsignedShort(); 457 break; 458 case 1: 459 tileLength = iis.readUnsignedInt(); 460 break; 461 } 462 463 tilePos += tileLength; 464 465 if(ST == 0) tileCounter++; 466 } 467 } catch(IOException e) { 468 // XXX? 469 } 470 } 471 472 if(tlmOffsets != null) { 473 tilePartPositions = new long[nt][]; 474 for(int i = 0; i < nt; i++) { 475 if(tlmOffsets[i] == null) { 476 tilePartPositions = null; 477 break; 478 } else { 479 ArrayList list = tlmOffsets[i]; 480 int count = list.size(); 481 tilePartPositions[i] = new long[count]; 482 long[] tpPos = tilePartPositions[i]; 483 for(int j = 0; j < count; j++) { 484 tpPos[j] = ((Long)list.get(j)).longValue(); 485 } 486 } 487 } 488 } 489 } 490 491 in.seek(savePos); 492 } 493 494 int cdstreamStart = 0; 495 int t=0, pos=-1, tp=0, tptot=0; 496 int tilePartStart = 0; 497 boolean rateReached = false; 498 int numtp = 0; 499 int maxTP = nt; // If maximum 1 tile part per tile specified 500 int lastPos = 0, maxPos = 0; 501 502 /** 503 * Read all tile-part headers of the requested tile. All tile-part 504 * headers prior to the last tile-part header of the current tile will 505 * also be read. 506 * 507 * @param tileNum The index of the tile for which to read tile-part 508 * headers. 509 */ 510 private void initTile(int tileNum) throws IOException { 511 if(tilePartPositions == null) in.seek(lastPos); 512 String strInfo = ""; 513 int ncbQuit = -1; 514 boolean isTilePartRead = false; 515 boolean isEOFEncountered = false; 516 try { 517 int tpNum = 0; 518 while(remainingTileParts!=0 && 519 (totTileParts[tileNum] == 0 || 520 tilePartsRead[tileNum] < totTileParts[tileNum])) { 521 isTilePartRead = true; 522 523 if(tilePartPositions != null) { 524 in.seek((int)tilePartPositions[tileNum][tpNum++]); 525 } 526 tilePartStart = in.getPos(); 527 528 // Read tile-part header 529 try { 530 t = readTilePartHeader(); 531 if(isEOCFound) { // Some tiles are missing but the 532 // codestream is OK 533 break; 534 } 535 tp = tilePartsRead[t]; 536 if(isPsotEqualsZero) { // Psot may equals zero for the 537 // last tile-part: it is assumed that this tile-part 538 // contain all data until EOC 539 tilePartLen[t][tp] = in.length()-2-tilePartStart; 540 } 541 } catch(EOFException e) { 542 firstPackOff[t][tp] = in.length(); 543 throw e; 544 } 545 546 pos = in.getPos(); 547 548 // In truncation mode, if target decoding rate is reached in 549 // tile-part header, skips the tile-part and stop reading 550 // unless the ncb and lbody quit condition is in use 551 if(isTruncMode && ncbQuit == -1) { 552 if((pos-cdstreamStart)>tnbytes) { 553 firstPackOff[t][tp] = in.length(); 554 rateReached = true; 555 break; 556 } 557 } 558 559 // Set tile part position and header length 560 firstPackOff[t][tp] = pos; 561 tilePartHeadLen[t][tp] = (pos-tilePartStart); 562 563 if(printInfo) 564 strInfo += "Tile-part "+tp+" of tile "+t+" : "+tilePartStart 565 +", "+tilePartLen[t][tp]+", "+tilePartHeadLen[t][tp]+"\n"; 566 567 // Update length counters 568 totTileLen[t] += tilePartLen[t][tp]; 569 totTileHeadLen[t] += tilePartHeadLen[t][tp]; 570 totAllTileLen += tilePartLen[t][tp]; 571 if(isTruncMode) { 572 if(anbytes+tilePartLen[t][tp]>tnbytes) { 573 anbytes += tilePartHeadLen[t][tp]; 574 headLen += tilePartHeadLen[t][tp]; 575 rateReached = true; 576 nBytes[t] += (tnbytes-anbytes); 577 break; 578 } else { 579 anbytes += tilePartHeadLen[t][tp]; 580 headLen += tilePartHeadLen[t][tp]; 581 nBytes[t] += (tilePartLen[t][tp]- 582 tilePartHeadLen[t][tp]); 583 } 584 } else { 585 if(anbytes+tilePartHeadLen[t][tp]>tnbytes) { 586 break; 587 } else { 588 anbytes += tilePartHeadLen[t][tp]; 589 headLen += tilePartHeadLen[t][tp]; 590 } 591 } 592 593 // If this is first tile-part, remember header length 594 if(tptot==0) 595 firstTilePartHeadLen = tilePartHeadLen[t][tp]; 596 597 // Go to the beginning of next tile part 598 tilePartsRead[t]++; 599 int nextMarkerPos = tilePartStart+tilePartLen[t][tp]; 600 if(tilePartPositions == null) { 601 in.seek(nextMarkerPos); 602 } 603 if(nextMarkerPos > maxPos) { 604 maxPos = nextMarkerPos; 605 } 606 remainingTileParts--; 607 maxTP--; 608 tptot++; 609 // If Psot of the current tile-part was equal to zero, it is 610 // assumed that it contains all data until the EOC marker 611 if(isPsotEqualsZero) { 612 if(remainingTileParts!=0) { 613 FacilityManager.getMsgLogger().printmsg 614 (MsgLogger.WARNING,"Some tile-parts have not "+ 615 "been found. The codestream may be corrupted."); 616 } 617 break; 618 } 619 } 620 } catch(EOFException e) { 621 isEOFEncountered = true; 622 623 if(printInfo) { 624 FacilityManager.getMsgLogger(). 625 printmsg(MsgLogger.INFO,strInfo); 626 } 627 FacilityManager.getMsgLogger(). 628 printmsg(MsgLogger.WARNING,"Codestream truncated in tile "+t); 629 630 // Set specified rate to end of file if valid 631 int fileLen = in.length(); 632 if(fileLen<tnbytes) { 633 tnbytes = fileLen; 634 trate = tnbytes*8f/hd.getMaxCompImgWidth()/ 635 hd.getMaxCompImgHeight(); 636 } 637 } 638 639 // If no tile-parts read then return. 640 if(!isTilePartRead) return; 641 642 /* XXX: BEGIN Updating the resolution here is logical when all tile-part 643 headers are read as was the case with the original version of this 644 class. With initTile() however the tiles could be read in random 645 order so modifying the resolution value could cause unexpected 646 results if a given tile-part has fewer levels than the main header 647 indicated. 648 // Update 'res' value once all tile-part headers are read 649 if(j2krparam.getResolution()== -1) { 650 targetRes = decSpec.dls.getMin(); 651 } else { 652 targetRes = j2krparam.getResolution(); 653 if(targetRes<0) { 654 throw new 655 IllegalArgumentException("Specified negative "+ 656 "resolution level index: "+ 657 targetRes); 658 } 659 } 660 661 // Verify reduction in resolution level 662 int mdl = decSpec.dls.getMin(); 663 if(targetRes>mdl) { 664 FacilityManager.getMsgLogger(). 665 printmsg(MsgLogger.WARNING, 666 "Specified resolution level ("+targetRes+ 667 ") is larger"+ 668 " than the maximum possible. Setting it to "+ 669 mdl +" (maximum possible)"); 670 targetRes = mdl; 671 } 672 XXX: END */ 673 674 if(!isEOFEncountered) { 675 if(printInfo) { 676 FacilityManager.getMsgLogger().printmsg(MsgLogger.INFO,strInfo); 677 } 678 679 if(remainingTileParts == 0) { 680 // Check presence of EOC marker is decoding rate not reached or 681 // if this marker has not been found yet 682 if(!isEOCFound && !isPsotEqualsZero && !rateReached) { 683 try { 684 int savePos = in.getPos(); 685 in.seek(maxPos); 686 if(in.readShort()!=EOC) { 687 FacilityManager.getMsgLogger(). 688 printmsg(MsgLogger.WARNING,"EOC marker not found. "+ 689 "Codestream is corrupted."); 690 } 691 in.seek(savePos); 692 } catch(EOFException e) { 693 FacilityManager.getMsgLogger(). 694 printmsg(MsgLogger.WARNING,"EOC marker is missing"); 695 } 696 } 697 } 698 } 699 700 // Bit-rate allocation 701 if(!isTruncMode) { 702 allocateRate(); 703 } else if(remainingTileParts == 0 && !isEOFEncountered) { 704 // Take EOC into account if rate is not reached 705 if(in.getPos()>=tnbytes) 706 anbytes += 2; 707 } 708 709 if(tilePartPositions == null) lastPos = in.getPos(); 710 711 // Backup nBytes 712 for (int tIdx=0; tIdx<nt; tIdx++) { 713 baknBytes[tIdx] = nBytes[tIdx]; 714 if(printInfo) { 715 FacilityManager.getMsgLogger(). 716 println(""+hi.toStringTileHeader(tIdx,tilePartLen[tIdx]. 717 length),2,2); 718 } 719 } 720 } 721 722 /** 723 * Allocates output bit-rate for each tile in parsing mode: The allocator 724 * simulates the truncation of a virtual layer-resolution progressive 725 * codestream. 726 * */ 727 private void allocateRate() throws IOException { 728 int stopOff = tnbytes; 729 730 // In parsing mode, the bitrate is allocated related to each tile's 731 // length in the bit stream 732 733 // EOC marker's length 734 if(remainingTileParts == 0) anbytes += 2; 735 736 // If there are too few bytes to read the tile part headers throw an 737 // error 738 if(anbytes > stopOff){ 739 throw new Error("Requested bitrate is too small for parsing"); 740 } 741 742 // Calculate bitrate for each tile 743 int rem = stopOff-anbytes; 744 int totnByte = rem; 745 for(int t=nt-1; t>0; t--){ 746 rem -= nBytes[t]=(int)(totnByte*(totTileLen[t]/totAllTileLen)); 747 } 748 nBytes[0] = rem; 749 } 750 751 /** 752 * Reads SOT marker segment of the tile-part header and calls related 753 * methods of the HeaderDecoder to read other markers segments. The 754 * tile-part header is entirely read when a SOD marker is encountered. 755 * 756 * @return The tile number of the tile part that was read 757 * */ 758 private int readTilePartHeader() throws IOException{ 759 HeaderInfo.SOT ms = hi.getNewSOT(); 760 761 // SOT marker 762 short marker = in.readShort(); 763 if(marker!=SOT) { 764 if(marker==EOC) { 765 isEOCFound = true; 766 return -1; 767 } else { 768 throw new CorruptedCodestreamException("SOT tag not found "+ 769 "in tile-part start"); 770 } 771 } 772 isEOCFound = false; 773 774 // Lsot (shall equals 10) 775 int lsot = in.readUnsignedShort(); 776 ms.lsot = lsot; 777 if(lsot!=10) 778 throw new CorruptedCodestreamException("Wrong length for "+ 779 "SOT marker segment: "+ 780 lsot); 781 782 // Isot 783 int tile = in.readUnsignedShort(); 784 ms.isot = tile; 785 if(tile>65534){ 786 throw new CorruptedCodestreamException("Tile index too high in "+ 787 "tile-part."); 788 } 789 790 // Psot 791 int psot = in.readInt(); 792 ms.psot = psot; 793 isPsotEqualsZero = (psot!=0) ? false : true; 794 if(psot<0) { 795 throw new NotImplementedError("Tile length larger "+ 796 "than maximum supported"); 797 } 798 // TPsot 799 int tilePart = in.read(); 800 ms.tpsot = tilePart; 801 if( tilePart!=tilePartsRead[tile] || tilePart<0 || tilePart>254 ) { 802 throw new CorruptedCodestreamException("Out of order tile-part"); 803 } 804 // TNsot 805 int nrOfTileParts = in.read(); 806 ms.tnsot = nrOfTileParts; 807 hi.sot.put("t"+tile+"_tp"+tilePart,ms); 808 if(nrOfTileParts==0) { // The number of tile-part is not specified in 809 // this tile-part header. 810 811 // Assumes that there will be another tile-part in the codestream 812 // that will indicate the number of tile-parts for this tile) 813 int nExtraTp; 814 if(tileParts[tile]==0 || tileParts[tile]==tilePartLen.length ) { 815 // Then there are two tile-parts (one is the current and the 816 // other will indicate the number of tile-part for this tile) 817 nExtraTp = 2; 818 remainingTileParts += 1; 819 } else { 820 // There is already one scheduled extra tile-part. In this 821 // case just add place for the current one 822 nExtraTp = 1; 823 } 824 825 tileParts[tile] += nExtraTp; 826 nrOfTileParts = tileParts[tile]; 827 FacilityManager.getMsgLogger(). 828 printmsg(MsgLogger.WARNING,"Header of tile-part "+tilePart+ 829 " of tile "+tile+", does not indicate the total"+ 830 " number of tile-parts. Assuming that there are "+ 831 nrOfTileParts+" tile-parts for this tile."); 832 833 // Increase and re-copy tilePartLen array 834 int[] tmpA = tilePartLen[tile]; 835 tilePartLen[tile] = new int[nrOfTileParts]; 836 for(int i=0; i<nrOfTileParts-nExtraTp; i++) { 837 tilePartLen[tile][i] = tmpA[i]; 838 } 839 // Increase and re-copy tilePartNum array 840 tmpA = tilePartNum[tile]; 841 tilePartNum[tile] = new int[nrOfTileParts]; 842 for(int i=0; i<nrOfTileParts-nExtraTp; i++) { 843 tilePartNum[tile][i] = tmpA[i]; 844 } 845 846 // Increase and re-copy firsPackOff array 847 tmpA = firstPackOff[tile]; 848 firstPackOff[tile] = new int[nrOfTileParts]; 849 for(int i=0; i<nrOfTileParts-nExtraTp; i++) { 850 firstPackOff[tile][i] = tmpA[i]; 851 } 852 853 // Increase and re-copy tilePartHeadLen array 854 tmpA = tilePartHeadLen[tile]; 855 tilePartHeadLen[tile] = new int[nrOfTileParts]; 856 for(int i=0; i<nrOfTileParts-nExtraTp; i++) { 857 tilePartHeadLen[tile][i] = tmpA[i]; 858 } 859 } else { // The number of tile-parts is specified in the tile-part 860 // header 861 totTileParts[tile] = nrOfTileParts; 862 863 // Check if it is consistant with what was found in previous 864 // tile-part headers 865 866 if(tileParts[tile]==0) { // First tile-part: OK 867 remainingTileParts += nrOfTileParts- 1; 868 tileParts[tile] = nrOfTileParts; 869 tilePartLen[tile] = new int[nrOfTileParts]; 870 tilePartNum[tile] = new int[nrOfTileParts]; 871 firstPackOff[tile] = new int[nrOfTileParts]; 872 tilePartHeadLen[tile] = new int[nrOfTileParts]; 873 } else if(tileParts[tile] > nrOfTileParts ) { 874 // Already found more tile-parts than signaled here 875 throw new CorruptedCodestreamException("Invalid number "+ 876 "of tile-parts in"+ 877 " tile "+tile+": "+ 878 nrOfTileParts); 879 } else { // Signaled number of tile-part fits with number of 880 // previously found tile-parts 881 remainingTileParts += nrOfTileParts-tileParts[tile]; 882 883 if(tileParts[tile]!=nrOfTileParts) { 884 885 // Increase and re-copy tilePartLen array 886 int[] tmpA = tilePartLen[tile]; 887 tilePartLen[tile] = new int[nrOfTileParts]; 888 for(int i=0; i<tileParts[tile]-1; i++) { 889 tilePartLen[tile][i] = tmpA[i]; 890 } 891 892 // Increase and re-copy tilePartNum array 893 tmpA = tilePartNum[tile]; 894 tilePartNum[tile] = new int[nrOfTileParts]; 895 for(int i=0; i<tileParts[tile]-1; i++) { 896 tilePartNum[tile][i] = tmpA[i]; 897 } 898 899 // Increase and re-copy firstPackOff array 900 tmpA = firstPackOff[tile]; 901 firstPackOff[tile] = new int[nrOfTileParts]; 902 for(int i=0; i<tileParts[tile]-1; i++) { 903 firstPackOff[tile][i] = tmpA[i]; 904 } 905 906 // Increase and re-copy tilePartHeadLen array 907 tmpA = tilePartHeadLen[tile]; 908 tilePartHeadLen[tile] = new int[nrOfTileParts]; 909 for(int i=0; i<tileParts[tile]-1; i++) { 910 tilePartHeadLen[tile][i] = tmpA[i]; 911 } 912 } 913 } 914 } 915 916 // Other markers 917 hd.resetHeaderMarkers(); 918 hd.nTileParts[tile] = nrOfTileParts; 919 // Decode and store the tile-part header (i.e. until a SOD marker is 920 // found) 921 do { 922 hd.extractTilePartMarkSeg(in.readShort(),in,tile,tilePart); 923 } while ((hd.getNumFoundMarkSeg() & hd.SOD_FOUND)==0); 924 925 // Read each marker segment previously found 926 hd.readFoundTilePartMarkSeg(tile,tilePart); 927 928 tilePartLen[tile][tilePart] = psot; 929 930 tilePartNum[tile][tilePart] = totTilePartsRead; 931 totTilePartsRead++; 932 933 // Add to list of which tile each successive tile-part belongs. 934 // This list is needed if there are PPM markers used 935 hd.setTileOfTileParts(tile); 936 937 return tile; 938 939 } 940 941 /** 942 * Reads packets of the current tile according to the 943 * layer-resolution-component-position progressiveness. 944 * 945 * @param lys Index of the first layer for each component and resolution. 946 * 947 * @param lye Index of the last layer. 948 * 949 * @param ress Index of the first resolution level. 950 * 951 * @param rese Index of the last resolution level. 952 * 953 * @param comps Index of the first component. 954 * 955 * @param compe Index of the last component. 956 * 957 * @return True if rate has been reached. 958 * */ 959 private boolean readLyResCompPos(int[][] lys,int lye,int ress,int rese, 960 int comps,int compe) 961 throws IOException { 962 963 int minlys = 10000; 964 for(int c=comps; c<compe; c++) { //loop on components 965 // Check if this component exists 966 if(c>=mdl.length) continue; 967 968 for(int r=ress; r<rese; r++) {//loop on resolution levels 969 if(lys[c]!=null && r<lys[c].length && lys[c][r]<minlys) { 970 minlys = lys[c][r]; 971 } 972 } 973 } 974 975 int t = getTileIdx(); 976 int start; 977 boolean status = false; 978 int lastByte = firstPackOff[t][curTilePart]+ 979 tilePartLen[t][curTilePart]-1- 980 tilePartHeadLen[t][curTilePart]; 981 int numLayers = ((Integer)decSpec.nls.getTileDef(t)).intValue(); 982 int nPrec = 1; 983 int hlen,plen; 984 String strInfo = printInfo ? 985 "Tile "+getTileIdx()+" (tile-part:"+curTilePart+ 986 "): offset, length, header length\n" : null; 987 boolean pph = false; 988 if(((Boolean)decSpec.pphs.getTileDef(t)).booleanValue()) { 989 pph = true; 990 } 991 for(int l=minlys; l<lye; l++) { // loop on layers 992 for(int r=ress; r<rese; r++) { // loop on resolution levels 993 for(int c=comps; c<compe; c++) { // loop on components 994 // Checks if component exists 995 if(c>=mdl.length) continue; 996 // Checks if resolution level exists 997 if(r>=lys[c].length) continue; 998 if(r>mdl[c]) continue; 999 // Checks if layer exists 1000 if(l<lys[c][r] || l>=numLayers) continue; 1001 1002 nPrec = pktDec.getNumPrecinct(c,r); 1003 for(int p=0; p<nPrec; p++) { // loop on precincts 1004 start = in.getPos(); 1005 1006 // If packed packet headers are used, there is no need 1007 // to check that there are bytes enough to read header 1008 if(pph) { 1009 pktDec.readPktHead(l,r,c,p,cbI[c][r],nBytes); 1010 } 1011 1012 // If we are about to read outside of tile-part, 1013 // skip to next tile-part 1014 if(start>lastByte && 1015 curTilePart<firstPackOff[t].length-1) { 1016 curTilePart++; 1017 in.seek(firstPackOff[t][curTilePart]); 1018 lastByte = in.getPos()+ 1019 tilePartLen[t][curTilePart]-1- 1020 tilePartHeadLen[t][curTilePart]; 1021 } 1022 1023 // Read SOP marker segment if necessary 1024 status = pktDec.readSOPMarker(nBytes,p,c,r); 1025 1026 if(status) { 1027 if(printInfo) { 1028 FacilityManager.getMsgLogger(). 1029 printmsg(MsgLogger.INFO,strInfo); 1030 } 1031 return true; 1032 } 1033 1034 if(!pph) { 1035 status = 1036 pktDec.readPktHead(l,r,c,p,cbI[c][r],nBytes); 1037 } 1038 1039 if(status) { 1040 if(printInfo) { 1041 FacilityManager.getMsgLogger(). 1042 printmsg(MsgLogger.INFO,strInfo); 1043 } 1044 return true; 1045 } 1046 1047 // Store packet's head length 1048 hlen = in.getPos()-start; 1049 pktHL.addElement(new Integer(hlen)); 1050 1051 // Reads packet's body 1052 status = pktDec.readPktBody(l,r,c,p,cbI[c][r],nBytes); 1053 plen = in.getPos()-start; 1054 if(printInfo) 1055 strInfo+= " Pkt l="+l+",r="+r+",c="+c+",p="+p+": "+ 1056 start+", "+plen+", "+hlen+"\n"; 1057 1058 if(status) { 1059 if(printInfo) { 1060 FacilityManager.getMsgLogger(). 1061 printmsg(MsgLogger.INFO,strInfo); 1062 } 1063 return true; 1064 } 1065 1066 } // end loop on precincts 1067 } // end loop on components 1068 } // end loop on resolution levels 1069 } // end loop on layers 1070 1071 if(printInfo) { 1072 FacilityManager.getMsgLogger().printmsg(MsgLogger.INFO,strInfo); 1073 } 1074 return false; // Decoding rate was not reached 1075 } 1076 1077 /** 1078 * Reads packets of the current tile according to the 1079 * resolution-layer-component-position progressiveness. 1080 * 1081 * @param lys Index of the first layer for each component and resolution. 1082 * 1083 * @param lye Index of the last layer. 1084 * 1085 * @param ress Index of the first resolution level. 1086 * 1087 * @param rese Index of the last resolution level. 1088 * 1089 * @param comps Index of the first component. 1090 * 1091 * @param compe Index of the last component. 1092 * 1093 * @return True if rate has been reached. 1094 * */ 1095 private boolean readResLyCompPos(int lys[][],int lye,int ress,int rese, 1096 int comps,int compe) 1097 throws IOException { 1098 1099 int t = getTileIdx(); // Current tile index 1100 boolean status=false; // True if decoding rate is reached when 1101 int lastByte = firstPackOff[t][curTilePart]+ 1102 tilePartLen[t][curTilePart]-1- 1103 tilePartHeadLen[t][curTilePart]; 1104 int minlys = 10000; 1105 for(int c=comps; c<compe; c++) { //loop on components 1106 // Check if this component exists 1107 if(c>=mdl.length) continue; 1108 1109 for(int r=ress; r<rese; r++) {//loop on resolution levels 1110 if(r>mdl[c]) continue; 1111 if(lys[c]!=null && r<lys[c].length && lys[c][r]<minlys) { 1112 minlys = lys[c][r]; 1113 } 1114 } 1115 } 1116 1117 String strInfo = printInfo ? 1118 "Tile "+getTileIdx()+" (tile-part:"+curTilePart+ 1119 "): offset, length, header length\n" : null; 1120 int numLayers = ((Integer)decSpec.nls.getTileDef(t)).intValue(); 1121 boolean pph = false; 1122 if(((Boolean)decSpec.pphs.getTileDef(t)).booleanValue()) { 1123 pph = true; 1124 } 1125 int nPrec = 1; 1126 int start; 1127 int hlen,plen; 1128 for(int r=ress; r<rese; r++) { // loop on resolution levels 1129 for(int l=minlys; l<lye; l++) { // loop on layers 1130 for(int c=comps; c<compe; c++) { // loop on components 1131 // Checks if component exists 1132 if(c>=mdl.length) continue; 1133 // Checks if resolution level exists 1134 if(r>mdl[c]) continue; 1135 if(r>=lys[c].length) continue; 1136 // Checks if layer exists 1137 if(l<lys[c][r] || l>=numLayers) continue; 1138 1139 nPrec = pktDec.getNumPrecinct(c,r); 1140 1141 for(int p=0; p<nPrec; p++) { // loop on precincts 1142 start = in.getPos(); 1143 1144 // If packed packet headers are used, there is no need 1145 // to check that there are bytes enough to read header 1146 if(pph) { 1147 pktDec.readPktHead(l,r,c,p,cbI[c][r],nBytes); 1148 } 1149 1150 // If we are about to read outside of tile-part, 1151 // skip to next tile-part 1152 if(start>lastByte && 1153 curTilePart<firstPackOff[t].length-1) { 1154 curTilePart++; 1155 in.seek(firstPackOff[t][curTilePart]); 1156 lastByte = in.getPos()+ 1157 tilePartLen[t][curTilePart]-1- 1158 tilePartHeadLen[t][curTilePart]; 1159 } 1160 1161 // Read SOP marker segment if necessary 1162 status = pktDec.readSOPMarker(nBytes,p,c,r); 1163 1164 if(status) { 1165 if(printInfo) { 1166 FacilityManager.getMsgLogger(). 1167 printmsg(MsgLogger.INFO,strInfo); 1168 } 1169 return true; 1170 } 1171 1172 if(!pph) { 1173 status = pktDec. 1174 readPktHead(l,r,c,p,cbI[c][r],nBytes); 1175 } 1176 1177 if(status) { 1178 if(printInfo) { 1179 FacilityManager.getMsgLogger(). 1180 printmsg(MsgLogger.INFO,strInfo); 1181 } 1182 // Output rate of EOF reached 1183 return true; 1184 } 1185 1186 // Store packet's head length 1187 hlen = in.getPos()-start; 1188 pktHL.addElement(new Integer(hlen)); 1189 1190 // Reads packet's body 1191 status = pktDec.readPktBody(l,r,c,p,cbI[c][r],nBytes); 1192 plen = in.getPos()-start; 1193 if(printInfo) 1194 strInfo+= " Pkt l="+l+",r="+r+",c="+c+",p="+p+": "+ 1195 start+", "+plen+", "+hlen+"\n"; 1196 1197 if(status) { 1198 if(printInfo) { 1199 FacilityManager.getMsgLogger(). 1200 printmsg(MsgLogger.INFO,strInfo); 1201 } 1202 // Output rate or EOF reached 1203 return true; 1204 } 1205 1206 } // end loop on precincts 1207 } // end loop on components 1208 } // end loop on layers 1209 } // end loop on resolution levels 1210 1211 if(printInfo) { 1212 FacilityManager.getMsgLogger().printmsg(MsgLogger.INFO,strInfo); 1213 } 1214 return false; // Decoding rate was not reached 1215 } 1216 1217 1218 /** 1219 * Reads packets of the current tile according to the 1220 * resolution-position-component-layer progressiveness. 1221 * 1222 * @param lys Index of the first layer for each component and resolution. 1223 * 1224 * @param lye Index of the last layer. 1225 * 1226 * @param ress Index of the first resolution level. 1227 * 1228 * @param rese Index of the last resolution level. 1229 * 1230 * @param comps Index of the first component. 1231 * 1232 * @param compe Index of the last component. 1233 * 1234 * @return True if rate has been reached. 1235 * */ 1236 private boolean readResPosCompLy(int[][] lys,int lye,int ress,int rese, 1237 int comps,int compe) 1238 throws IOException { 1239 // Computes current tile offset in the reference grid 1240 1241 Point nTiles = getNumTiles(null); 1242 Point tileI = getTile(null); 1243 int x0siz = hd.getImgULX(); 1244 int y0siz = hd.getImgULY(); 1245 int xsiz = x0siz + hd.getImgWidth(); 1246 int ysiz = y0siz + hd.getImgHeight(); 1247 int xt0siz = getTilePartULX(); 1248 int yt0siz = getTilePartULY(); 1249 int xtsiz = getNomTileWidth(); 1250 int ytsiz = getNomTileHeight(); 1251 int tx0 = (tileI.x==0) ? x0siz : xt0siz+tileI.x*xtsiz; 1252 int ty0 = (tileI.y==0) ? y0siz : yt0siz+tileI.y*ytsiz; 1253 int tx1 = (tileI.x!=nTiles.x-1) ? xt0siz+(tileI.x+1)*xtsiz : xsiz; 1254 int ty1 = (tileI.y!=nTiles.y-1) ? yt0siz+(tileI.y+1)*ytsiz : ysiz; 1255 1256 // Get precinct information (number,distance between two consecutive 1257 // precincts in the reference grid) in each component and resolution 1258 // level 1259 int t = getTileIdx(); // Current tile index 1260 PrecInfo prec; // temporary variable 1261 int p; // Current precinct index 1262 int gcd_x = 0; // Horiz. distance between 2 precincts in the ref. grid 1263 int gcd_y = 0; // Vert. distance between 2 precincts in the ref. grid 1264 int nPrec = 0; // Total number of found precincts 1265 int[][] nextPrec = new int [compe][]; // Next precinct index in each 1266 // component and resolution level 1267 int minlys = 100000; // minimum layer start index of each component 1268 int minx = tx1; // Horiz. offset of the second precinct in the 1269 // reference grid 1270 int miny = ty1; // Vert. offset of the second precinct in the 1271 // reference grid. 1272 int maxx = tx0; // Max. horiz. offset of precincts in the ref. grid 1273 int maxy = ty0; // Max. vert. offset of precincts in the ref. grid 1274 Point numPrec; 1275 for(int c=comps; c<compe; c++) { // components 1276 for(int r=ress; r<rese; r++) { // resolution levels 1277 if(c>=mdl.length) continue; 1278 if(r>mdl[c]) continue; 1279 nextPrec[c] = new int[mdl[c]+1]; 1280 if (lys[c]!=null && r<lys[c].length && lys[c][r]<minlys) { 1281 minlys = lys[c][r]; 1282 } 1283 p = pktDec.getNumPrecinct(c,r)-1; 1284 for(; p>=0; p--) { 1285 prec = pktDec.getPrecInfo(c,r,p); 1286 if(prec.rgulx!=tx0) { 1287 if(prec.rgulx<minx) minx = prec.rgulx; 1288 if(prec.rgulx>maxx) maxx = prec.rgulx; 1289 } 1290 if(prec.rguly!=ty0) { 1291 if(prec.rguly<miny) miny = prec.rguly; 1292 if(prec.rguly>maxy) maxy = prec.rguly; 1293 } 1294 1295 if(nPrec==0) { 1296 gcd_x = prec.rgw; 1297 gcd_y = prec.rgh; 1298 } else { 1299 gcd_x = MathUtil.gcd(gcd_x,prec.rgw); 1300 gcd_y = MathUtil.gcd(gcd_y,prec.rgh); 1301 } 1302 nPrec++; 1303 } // precincts 1304 } // resolution levels 1305 } // components 1306 1307 if(nPrec==0) { 1308 throw new Error("Image cannot have no precinct"); 1309 } 1310 1311 int pyend = (maxy-miny)/gcd_y+1; 1312 int pxend = (maxx-minx)/gcd_x+1; 1313 int x,y; 1314 int hlen,plen; 1315 int start; 1316 boolean status = false; 1317 int lastByte = firstPackOff[t][curTilePart]+ 1318 tilePartLen[t][curTilePart]-1- 1319 tilePartHeadLen[t][curTilePart]; 1320 int numLayers = ((Integer)decSpec.nls.getTileDef(t)).intValue(); 1321 String strInfo = printInfo ? 1322 "Tile "+getTileIdx()+" (tile-part:"+curTilePart+ 1323 "): offset, length, header length\n" : null; 1324 boolean pph = false; 1325 if(((Boolean)decSpec.pphs.getTileDef(t)).booleanValue()) { 1326 pph = true; 1327 } 1328 for(int r=ress; r<rese; r++) { // loop on resolution levels 1329 y = ty0; 1330 x = tx0; 1331 for(int py=0; py<=pyend; py++) { // Vertical precincts 1332 for(int px=0; px<=pxend; px++) { // Horiz. precincts 1333 for(int c=comps; c<compe; c++) { // Components 1334 if(c>=mdl.length) continue; 1335 if(r>mdl[c]) continue; 1336 if(nextPrec[c][r]>=pktDec.getNumPrecinct(c,r)) { 1337 continue; 1338 } 1339 prec = pktDec.getPrecInfo(c,r,nextPrec[c][r]); 1340 if((prec.rgulx!=x) || (prec.rguly!=y)) { 1341 continue; 1342 } 1343 for(int l=minlys; l<lye; l++) { // layers 1344 if(r>=lys[c].length) continue; 1345 if(l<lys[c][r] || l>=numLayers) continue; 1346 1347 start = in.getPos(); 1348 1349 // If packed packet headers are used, there is no 1350 // need to check that there are bytes enough to 1351 // read header 1352 if(pph) { 1353 pktDec.readPktHead(l,r,c,nextPrec[c][r], 1354 cbI[c][r],nBytes); 1355 } 1356 // If we are about to read outside of tile-part, 1357 // skip to next tile-part 1358 if(start>lastByte && 1359 curTilePart<firstPackOff[t].length-1) { 1360 curTilePart++; 1361 in.seek(firstPackOff[t][curTilePart]); 1362 lastByte = in.getPos()+ 1363 tilePartLen[t][curTilePart]-1- 1364 tilePartHeadLen[t][curTilePart]; 1365 } 1366 1367 // Read SOP marker segment if necessary 1368 status = pktDec.readSOPMarker(nBytes, 1369 nextPrec[c][r],c,r); 1370 1371 if(status) { 1372 if(printInfo) { 1373 FacilityManager.getMsgLogger(). 1374 printmsg(MsgLogger.INFO,strInfo); 1375 } 1376 return true; 1377 } 1378 1379 if(!pph) { 1380 status = 1381 pktDec.readPktHead(l,r,c, 1382 nextPrec[c][r], 1383 cbI[c][r],nBytes); 1384 } 1385 1386 if(status) { 1387 if(printInfo) { 1388 FacilityManager.getMsgLogger(). 1389 printmsg(MsgLogger.INFO,strInfo); 1390 } 1391 return true; 1392 } 1393 1394 // Store packet's head length 1395 hlen = in.getPos()-start; 1396 pktHL.addElement(new Integer(hlen)); 1397 1398 1399 // Reads packet's body 1400 status = pktDec.readPktBody(l,r,c,nextPrec[c][r], 1401 cbI[c][r],nBytes); 1402 plen = in.getPos()-start; 1403 if(printInfo) 1404 strInfo+= " Pkt l="+l+",r="+r+",c="+c+",p="+ 1405 nextPrec[c][r]+": "+ 1406 start+", "+plen+", "+hlen+"\n"; 1407 1408 if(status) { 1409 if(printInfo) { 1410 FacilityManager.getMsgLogger(). 1411 printmsg(MsgLogger.INFO,strInfo); 1412 } 1413 return true; 1414 } 1415 } // layers 1416 nextPrec[c][r]++; 1417 } // Components 1418 if(px!=pxend) { 1419 x = minx+px*gcd_x; 1420 } else { 1421 x = tx0; 1422 } 1423 } // Horizontal precincts 1424 if(py!=pyend) { 1425 y = miny+py*gcd_y; 1426 } else { 1427 y = ty0; 1428 } 1429 } // Vertical precincts 1430 } // end loop on resolution levels 1431 1432 if(printInfo) { 1433 FacilityManager.getMsgLogger().printmsg(MsgLogger.INFO,strInfo); 1434 } 1435 return false; // Decoding rate was not reached 1436 } 1437 1438 /** 1439 * Reads packets of the current tile according to the 1440 * position-component-resolution-layer progressiveness. 1441 * 1442 * @param lys Index of the first layer for each component and resolution. 1443 * 1444 * @param lye Index of the last layer. 1445 * 1446 * @param ress Index of the first resolution level. 1447 * 1448 * @param rese Index of the last resolution level. 1449 * 1450 * @param comps Index of the first component. 1451 * 1452 * @param compe Index of the last component. 1453 * 1454 * @return True if rate has been reached. 1455 * */ 1456 private boolean readPosCompResLy(int[][] lys,int lye,int ress,int rese, 1457 int comps,int compe) 1458 throws IOException { 1459 Point nTiles = getNumTiles(null); 1460 Point tileI = getTile(null); 1461 int x0siz = hd.getImgULX(); 1462 int y0siz = hd.getImgULY(); 1463 int xsiz = x0siz + hd.getImgWidth(); 1464 int ysiz = y0siz + hd.getImgHeight(); 1465 int xt0siz = getTilePartULX(); 1466 int yt0siz = getTilePartULY(); 1467 int xtsiz = getNomTileWidth(); 1468 int ytsiz = getNomTileHeight(); 1469 int tx0 = (tileI.x==0) ? x0siz : xt0siz+tileI.x*xtsiz; 1470 int ty0 = (tileI.y==0) ? y0siz : yt0siz+tileI.y*ytsiz; 1471 int tx1 = (tileI.x!=nTiles.x-1) ? xt0siz+(tileI.x+1)*xtsiz : xsiz; 1472 int ty1 = (tileI.y!=nTiles.y-1) ? yt0siz+(tileI.y+1)*ytsiz : ysiz; 1473 1474 // Get precinct information (number,distance between two consecutive 1475 // precincts in the reference grid) in each component and resolution 1476 // level 1477 int t = getTileIdx(); // Current tile index 1478 PrecInfo prec; // temporary variable 1479 int p; // Current precinct index 1480 int gcd_x = 0; // Horiz. distance between 2 precincts in the ref. grid 1481 int gcd_y = 0; // Vert. distance between 2 precincts in the ref. grid 1482 int nPrec = 0; // Total number of found precincts 1483 int[][] nextPrec = new int [compe][]; // Next precinct index in each 1484 // component and resolution level 1485 int minlys = 100000; // minimum layer start index of each component 1486 int minx = tx1; // Horiz. offset of the second precinct in the 1487 // reference grid 1488 int miny = ty1; // Vert. offset of the second precinct in the 1489 // reference grid. 1490 int maxx = tx0; // Max. horiz. offset of precincts in the ref. grid 1491 int maxy = ty0; // Max. vert. offset of precincts in the ref. grid 1492 Point numPrec; 1493 for(int c=comps; c<compe; c++) { // components 1494 for(int r=ress; r<rese; r++) { // resolution levels 1495 if(c>=mdl.length) continue; 1496 if(r>mdl[c]) continue; 1497 nextPrec[c] = new int[mdl[c]+1]; 1498 if (lys[c]!=null && r<lys[c].length && lys[c][r]<minlys) { 1499 minlys = lys[c][r]; 1500 } 1501 p = pktDec.getNumPrecinct(c,r)-1; 1502 for(; p>=0; p--) { 1503 prec = pktDec.getPrecInfo(c,r,p); 1504 if(prec.rgulx!=tx0) { 1505 if(prec.rgulx<minx) minx = prec.rgulx; 1506 if(prec.rgulx>maxx) maxx = prec.rgulx; 1507 } 1508 if(prec.rguly!=ty0) { 1509 if(prec.rguly<miny) miny = prec.rguly; 1510 if(prec.rguly>maxy) maxy = prec.rguly; 1511 } 1512 1513 if(nPrec==0) { 1514 gcd_x = prec.rgw; 1515 gcd_y = prec.rgh; 1516 } else { 1517 gcd_x = MathUtil.gcd(gcd_x,prec.rgw); 1518 gcd_y = MathUtil.gcd(gcd_y,prec.rgh); 1519 } 1520 nPrec++; 1521 } // precincts 1522 } // resolution levels 1523 } // components 1524 1525 if(nPrec==0) { 1526 throw new Error("Image cannot have no precinct"); 1527 } 1528 1529 int pyend = (maxy-miny)/gcd_y+1; 1530 int pxend = (maxx-minx)/gcd_x+1; 1531 int hlen,plen; 1532 int start; 1533 boolean status = false; 1534 int lastByte = firstPackOff[t][curTilePart]+ 1535 tilePartLen[t][curTilePart]-1- 1536 tilePartHeadLen[t][curTilePart]; 1537 int numLayers = ((Integer)decSpec.nls.getTileDef(t)).intValue(); 1538 String strInfo = printInfo ? 1539 "Tile "+getTileIdx()+" (tile-part:"+curTilePart+ 1540 "): offset, length, header length\n" : null; 1541 boolean pph = false; 1542 if(((Boolean)decSpec.pphs.getTileDef(t)).booleanValue()) { 1543 pph = true; 1544 } 1545 1546 int y = ty0; 1547 int x = tx0; 1548 for(int py=0; py<=pyend; py++) { // Vertical precincts 1549 for(int px=0; px<=pxend; px++) { // Horiz. precincts 1550 for(int c=comps; c<compe; c++) { // Components 1551 if(c>=mdl.length) continue; 1552 for(int r=ress; r<rese; r++) { // Resolution levels 1553 if(r>mdl[c]) continue; 1554 if(nextPrec[c][r]>=pktDec.getNumPrecinct(c,r)) { 1555 continue; 1556 } 1557 prec = pktDec.getPrecInfo(c,r,nextPrec[c][r]); 1558 if((prec.rgulx!=x) || (prec.rguly!=y)) { 1559 continue; 1560 } 1561 for(int l=minlys; l<lye; l++) { // Layers 1562 if(r>=lys[c].length) continue; 1563 if(l<lys[c][r] || l>=numLayers) continue; 1564 1565 start = in.getPos(); 1566 1567 // If packed packet headers are used, there is no 1568 // need to check that there are bytes enough to 1569 // read header 1570 if(pph) { 1571 pktDec.readPktHead(l,r,c,nextPrec[c][r], 1572 cbI[c][r],nBytes); 1573 } 1574 // Read SOP marker segment if necessary 1575 status = pktDec.readSOPMarker(nBytes, 1576 nextPrec[c][r],c,r); 1577 1578 if(status) { 1579 if(printInfo) { 1580 FacilityManager.getMsgLogger(). 1581 printmsg(MsgLogger.INFO,strInfo); 1582 } 1583 return true; 1584 } 1585 1586 if(!pph) { 1587 status = 1588 pktDec.readPktHead(l,r,c, 1589 nextPrec[c][r], 1590 cbI[c][r],nBytes); 1591 } 1592 1593 if(status) { 1594 if(printInfo) { 1595 FacilityManager.getMsgLogger(). 1596 printmsg(MsgLogger.INFO,strInfo); 1597 } 1598 return true; 1599 } 1600 1601 // Store packet's head length 1602 hlen = in.getPos()-start; 1603 pktHL.addElement(new Integer(hlen)); 1604 1605 // Reads packet's body 1606 status = pktDec.readPktBody(l,r,c,nextPrec[c][r], 1607 cbI[c][r],nBytes); 1608 plen = in.getPos()-start; 1609 if(printInfo) 1610 strInfo+= " Pkt l="+l+",r="+r+",c="+c+",p="+ 1611 nextPrec[c][r]+": "+ 1612 start+", "+plen+", "+hlen+"\n"; 1613 1614 if(status) { 1615 if(printInfo) { 1616 FacilityManager.getMsgLogger(). 1617 printmsg(MsgLogger.INFO,strInfo); 1618 } 1619 return true; 1620 } 1621 1622 } // layers 1623 nextPrec[c][r]++; 1624 } // Resolution levels 1625 } // Components 1626 if(px!=pxend) { 1627 x = minx+px*gcd_x; 1628 } else { 1629 x = tx0; 1630 } 1631 } // Horizontal precincts 1632 if(py!=pyend) { 1633 y = miny+py*gcd_y; 1634 } else { 1635 y = ty0; 1636 } 1637 } // Vertical precincts 1638 1639 if(printInfo) { 1640 FacilityManager.getMsgLogger().printmsg(MsgLogger.INFO,strInfo); 1641 } 1642 return false; // Decoding rate was not reached 1643 } 1644 1645 /** 1646 * Reads packets of the current tile according to the 1647 * component-position-resolution-layer progressiveness. 1648 * 1649 * @param lys Index of the first layer for each component and resolution. 1650 * 1651 * @param lye Index of the last layer. 1652 * 1653 * @param ress Index of the first resolution level. 1654 * 1655 * @param rese Index of the last resolution level. 1656 * 1657 * @param comps Index of the first component. 1658 * 1659 * @param compe Index of the last component. 1660 * 1661 * @return True if rate has been reached. 1662 * */ 1663 private boolean readCompPosResLy(int lys[][],int lye,int ress,int rese, 1664 int comps,int compe) 1665 throws IOException { 1666 Point nTiles = getNumTiles(null); 1667 Point tileI = getTile(null); 1668 int x0siz = hd.getImgULX(); 1669 int y0siz = hd.getImgULY(); 1670 int xsiz = x0siz + hd.getImgWidth(); 1671 int ysiz = y0siz + hd.getImgHeight(); 1672 int xt0siz = getTilePartULX(); 1673 int yt0siz = getTilePartULY(); 1674 int xtsiz = getNomTileWidth(); 1675 int ytsiz = getNomTileHeight(); 1676 int tx0 = (tileI.x==0) ? x0siz : xt0siz+tileI.x*xtsiz; 1677 int ty0 = (tileI.y==0) ? y0siz : yt0siz+tileI.y*ytsiz; 1678 int tx1 = (tileI.x!=nTiles.x-1) ? xt0siz+(tileI.x+1)*xtsiz : xsiz; 1679 int ty1 = (tileI.y!=nTiles.y-1) ? yt0siz+(tileI.y+1)*ytsiz : ysiz; 1680 1681 // Get precinct information (number,distance between two consecutive 1682 // precincts in the reference grid) in each component and resolution 1683 // level 1684 int t = getTileIdx(); // Current tile index 1685 PrecInfo prec; // temporary variable 1686 int p; // Current precinct index 1687 int gcd_x = 0; // Horiz. distance between 2 precincts in the ref. grid 1688 int gcd_y = 0; // Vert. distance between 2 precincts in the ref. grid 1689 int nPrec = 0; // Total number of found precincts 1690 int[][] nextPrec = new int [compe][]; // Next precinct index in each 1691 // component and resolution level 1692 int minlys = 100000; // minimum layer start index of each component 1693 int minx = tx1; // Horiz. offset of the second precinct in the 1694 // reference grid 1695 int miny = ty1; // Vert. offset of the second precinct in the 1696 // reference grid. 1697 int maxx = tx0; // Max. horiz. offset of precincts in the ref. grid 1698 int maxy = ty0; // Max. vert. offset of precincts in the ref. grid 1699 Point numPrec; 1700 for(int c=comps; c<compe; c++) { // components 1701 for(int r=ress; r<rese; r++) { // resolution levels 1702 if(c>=mdl.length) continue; 1703 if(r>mdl[c]) continue; 1704 nextPrec[c] = new int[mdl[c]+1]; 1705 if (lys[c]!=null && r<lys[c].length && lys[c][r]<minlys) { 1706 minlys = lys[c][r]; 1707 } 1708 p = pktDec.getNumPrecinct(c,r)-1; 1709 for(; p>=0; p--) { 1710 prec = pktDec.getPrecInfo(c,r,p); 1711 if(prec.rgulx!=tx0) { 1712 if(prec.rgulx<minx) minx = prec.rgulx; 1713 if(prec.rgulx>maxx) maxx = prec.rgulx; 1714 } 1715 if(prec.rguly!=ty0) { 1716 if(prec.rguly<miny) miny = prec.rguly; 1717 if(prec.rguly>maxy) maxy = prec.rguly; 1718 } 1719 1720 if(nPrec==0) { 1721 gcd_x = prec.rgw; 1722 gcd_y = prec.rgh; 1723 } else { 1724 gcd_x = MathUtil.gcd(gcd_x,prec.rgw); 1725 gcd_y = MathUtil.gcd(gcd_y,prec.rgh); 1726 } 1727 nPrec++; 1728 } // precincts 1729 } // resolution levels 1730 } // components 1731 1732 if(nPrec==0) { 1733 throw new Error("Image cannot have no precinct"); 1734 } 1735 1736 int pyend = (maxy-miny)/gcd_y+1; 1737 int pxend = (maxx-minx)/gcd_x+1; 1738 int hlen,plen; 1739 int start; 1740 boolean status = false; 1741 int lastByte = firstPackOff[t][curTilePart]+ 1742 tilePartLen[t][curTilePart]-1- 1743 tilePartHeadLen[t][curTilePart]; 1744 int numLayers = ((Integer)decSpec.nls.getTileDef(t)).intValue(); 1745 String strInfo = printInfo ? 1746 "Tile "+getTileIdx()+" (tile-part:"+curTilePart+ 1747 "): offset, length, header length\n" : null; 1748 boolean pph = false; 1749 if(((Boolean)decSpec.pphs.getTileDef(t)).booleanValue()) { 1750 pph = true; 1751 } 1752 1753 int x,y; 1754 for(int c=comps; c<compe; c++) { // components 1755 if(c>=mdl.length) continue; 1756 y = ty0; 1757 x = tx0; 1758 for(int py=0; py<=pyend; py++) { // Vertical precincts 1759 for(int px=0; px<=pxend; px++) { // Horiz. precincts 1760 for(int r=ress; r<rese; r++) { // Resolution levels 1761 if(r>mdl[c]) continue; 1762 if(nextPrec[c][r]>=pktDec.getNumPrecinct(c,r)) { 1763 continue; 1764 } 1765 prec = pktDec.getPrecInfo(c,r,nextPrec[c][r]); 1766 if((prec.rgulx!=x) || (prec.rguly!=y)) { 1767 continue; 1768 } 1769 1770 for(int l=minlys; l<lye; l++) { // Layers 1771 if(r>=lys[c].length) continue; 1772 if(l<lys[c][r]) continue; 1773 1774 start = in.getPos(); 1775 1776 // If packed packet headers are used, there is no 1777 // need to check that there are bytes enough to 1778 // read header 1779 if(pph) { 1780 pktDec.readPktHead(l,r,c,nextPrec[c][r], 1781 cbI[c][r],nBytes); 1782 } 1783 // If we are about to read outside of tile-part, 1784 // skip to next tile-part 1785 if(start>lastByte && 1786 curTilePart<firstPackOff[t].length-1) { 1787 curTilePart++; 1788 in.seek(firstPackOff[t][curTilePart]); 1789 lastByte = in.getPos()+ 1790 tilePartLen[t][curTilePart]-1- 1791 tilePartHeadLen[t][curTilePart]; 1792 } 1793 1794 // Read SOP marker segment if necessary 1795 status = pktDec.readSOPMarker(nBytes, 1796 nextPrec[c][r],c,r); 1797 1798 if(status) { 1799 if(printInfo) { 1800 FacilityManager.getMsgLogger(). 1801 printmsg(MsgLogger.INFO,strInfo); 1802 } 1803 return true; 1804 } 1805 1806 if(!pph) { 1807 status = 1808 pktDec.readPktHead(l,r,c, 1809 nextPrec[c][r], 1810 cbI[c][r],nBytes); 1811 } 1812 1813 if(status) { 1814 if(printInfo) { 1815 FacilityManager.getMsgLogger(). 1816 printmsg(MsgLogger.INFO,strInfo); 1817 } 1818 return true; 1819 } 1820 1821 // Store packet's head length 1822 hlen = in.getPos()-start; 1823 pktHL.addElement(new Integer(hlen)); 1824 1825 // Reads packet's body 1826 status = pktDec.readPktBody(l,r,c,nextPrec[c][r], 1827 cbI[c][r],nBytes); 1828 plen = in.getPos()-start; 1829 if(printInfo) 1830 strInfo+= " Pkt l="+l+",r="+r+",c="+c+",p="+ 1831 nextPrec[c][r]+": "+ 1832 start+", "+plen+", "+hlen+"\n"; 1833 1834 if(status) { 1835 if(printInfo) { 1836 FacilityManager.getMsgLogger(). 1837 printmsg(MsgLogger.INFO,strInfo); 1838 } 1839 return true; 1840 } 1841 1842 } // layers 1843 nextPrec[c][r]++; 1844 } // Resolution levels 1845 if(px!=pxend) { 1846 x = minx+px*gcd_x; 1847 } else { 1848 x = tx0; 1849 } 1850 } // Horizontal precincts 1851 if(py!=pyend) { 1852 y = miny+py*gcd_y; 1853 } else { 1854 y = ty0; 1855 } 1856 } // Vertical precincts 1857 } // components 1858 1859 if(printInfo) { 1860 FacilityManager.getMsgLogger().printmsg(MsgLogger.INFO,strInfo); 1861 } 1862 return false; // Decoding rate was not reached 1863 } 1864 1865 /** 1866 * Finish initialization of members for specified tile, reads packets head 1867 * of each tile and keeps location of each code-block's codewords. The 1868 * last 2 tasks are done by calling specific methods of PktDecoder. 1869 * 1870 * <p>Then, if a parsing output rate is defined, it keeps information of 1871 * first layers only. This operation simulates a creation of a 1872 * layer-resolution-component progressive bit-stream which will be next 1873 * truncated and decoded.</p> 1874 * 1875 * @param t Tile index 1876 * 1877 * @see PktDecoder 1878 * */ 1879 private void readTilePkts(int t) throws IOException { 1880 pktHL = new Vector(); 1881 1882 int oldNBytes = nBytes[t]; 1883 1884 // Number of layers 1885 int nl = ((Integer)decSpec.nls.getTileDef(t)).intValue(); 1886 1887 // If packed packet headers was used, get the packet headers for this 1888 // tile 1889 if(((Boolean)decSpec.pphs.getTileDef(t)).booleanValue()) { 1890 // Gets packed headers as separate input stream 1891 ByteArrayInputStream pphbais = hd.getPackedPktHead(t); 1892 1893 // Restarts PktDecoder instance 1894 cbI = pktDec.restart(nc,mdl,nl,cbI,true,pphbais); 1895 } else { 1896 // Restarts PktDecoder instance 1897 cbI = pktDec.restart(nc,mdl,nl,cbI,false,null); 1898 } 1899 1900 // Reads packets of the tile according to the progression order 1901 int[][] pocSpec = ((int[][])decSpec.pcs.getTileDef(t)); 1902 int nChg = (pocSpec==null) ? 1 : pocSpec.length; 1903 1904 // Create an array containing information about changes (progression 1905 // order type, layers index start, layer index end, resolution level 1906 // start, resolution level end, component index start, component index 1907 // end). There is one row per progresion order 1908 int[][] change = new int[nChg][6]; 1909 int idx = 0; // Index of the current progression order 1910 1911 change[0][1] = 0; // layer start 1912 1913 if(pocSpec==null) { 1914 change[idx][0] = ((Integer)decSpec.pos.getTileDef(t)).intValue(); 1915 // Progression type found in COx marker segments 1916 change[idx][1] = nl; // Layer index end 1917 change[idx][2] = 0; // resolution level start 1918 change[idx][3] = decSpec.dls.getMaxInTile(t)+1; // res. level end 1919 change[idx][4] = 0; // Component index start 1920 change[idx][5] = nc; // Component index end 1921 } else { 1922 for(idx=0; idx<nChg; idx++){ 1923 change[idx][0] = pocSpec[idx][5]; 1924 change[idx][1] = pocSpec[idx][2]; // layer end 1925 change[idx][2] = pocSpec[idx][0]; // res. lev. start 1926 change[idx][3] = pocSpec[idx][3]; // res. lev. end 1927 change[idx][4] = pocSpec[idx][1]; // Comp. index start 1928 change[idx][5] = pocSpec[idx][4]; // Comp. index end 1929 } 1930 } 1931 1932 // Seeks to the first packet of the first tile-part 1933 try { 1934 // If in truncation mode, the first tile-part may be beyond the 1935 // target decoding rate. In this case, the offset of the first 1936 // packet is not defined. 1937 if(isTruncMode && firstPackOff==null || firstPackOff[t]==null) { 1938 return; 1939 } 1940 in.seek(firstPackOff[t][0]); 1941 } catch(EOFException e) { 1942 FacilityManager.getMsgLogger(). 1943 printmsg(MsgLogger.WARNING,"Codestream truncated in tile "+t); 1944 return; 1945 } 1946 1947 curTilePart = 0; 1948 1949 // Start and end indexes for layers, resolution levels and components. 1950 int lye,ress,rese,comps,compe; 1951 boolean status = false; 1952 int nb = nBytes[t]; 1953 int[][] lys = new int[nc][]; 1954 for(int c=0; c<nc; c++) { 1955 lys[c] = new int[((Integer)decSpec.dls.getTileCompVal(t,c)). 1956 intValue()+1]; 1957 } 1958 1959 1960 try { 1961 for(int chg=0; chg<nChg; chg++) { 1962 1963 lye = change[chg][1]; 1964 ress = change[chg][2]; 1965 rese = change[chg][3]; 1966 comps = change[chg][4]; 1967 compe = change[chg][5]; 1968 1969 switch(change[chg][0]) { 1970 case LY_RES_COMP_POS_PROG: 1971 status = readLyResCompPos(lys,lye,ress,rese,comps,compe); 1972 break; 1973 case RES_LY_COMP_POS_PROG: 1974 status = readResLyCompPos(lys,lye,ress,rese,comps,compe); 1975 break; 1976 case RES_POS_COMP_LY_PROG: 1977 status = readResPosCompLy(lys,lye,ress,rese,comps,compe); 1978 break; 1979 case POS_COMP_RES_LY_PROG: 1980 status = readPosCompResLy(lys,lye,ress,rese,comps,compe); 1981 break; 1982 case COMP_POS_RES_LY_PROG: 1983 status = readCompPosResLy(lys,lye,ress,rese,comps,compe); 1984 break; 1985 default: 1986 throw new IllegalArgumentException("Not recognized "+ 1987 "progression type"); 1988 } 1989 1990 // Update next first layer index 1991 for(int c=comps; c<compe; c++) { 1992 if(c>=lys.length) continue; 1993 for(int r=ress; r<rese; r++) { 1994 if(r>=lys[c].length) continue; 1995 lys[c][r] = lye; 1996 } 1997 } 1998 1999 if(status || usePOCQuit) { 2000 break; 2001 } 2002 } 2003 } catch(EOFException e) { 2004 // Should never happen. Truncated codestream are normally found by 2005 // the class constructor 2006 throw e; 2007 } 2008 2009 // In truncation mode, update the number of read bytes 2010 if(isTruncMode) { 2011 anbytes += nb-nBytes[t]; 2012 2013 // If truncation rate is reached 2014 if(status) { 2015 nBytes[t] = 0; 2016 } 2017 } else if(nBytes[t]<(totTileLen[t]-totTileHeadLen[t])) { 2018 // In parsing mode, if there is not enough rate to entirely read the 2019 // tile. Then, parses the bit stream so as to create a virtual 2020 // layer-resolution-component progressive bit stream that will be 2021 // truncated and decoded afterwards. 2022 CBlkInfo cb; 2023 2024 // Systematicaly reject all remaining code-blocks if one 2025 // code-block, at least, is refused. 2026 boolean reject; 2027 // Stop reading any data from the bit stream 2028 boolean stopCount = false; 2029 // Length of each packet's head (in an array) 2030 int[] pktHeadLen = new int[pktHL.size()]; 2031 for(int i=pktHL.size()-1;i>=0;i--) { 2032 pktHeadLen[i] = ((Integer)pktHL.elementAt(i)).intValue(); 2033 } 2034 2035 // Parse each code-block, layer per layer until nBytes[t] is 2036 // reached 2037 reject = false; 2038 for(int l=0; l<nl; l++) { // layers 2039 if(cbI==null) continue; 2040 int nc = cbI.length; 2041 2042 int mres = 0; 2043 for(int c=0; c<nc; c++) { 2044 if(cbI[c]!=null && cbI[c].length>mres) 2045 mres = cbI[c].length; 2046 } 2047 for(int r=0; r<mres; r++) { // resolutions 2048 2049 2050 int msub = 0; 2051 for(int c=0; c<nc; c++) { 2052 if(cbI[c]!=null && cbI[c][r]!=null 2053 && cbI[c][r].length>msub) 2054 msub = cbI[c][r].length; 2055 } 2056 for(int s=0; s<msub; s++) { // subbands 2057 // Only LL subband resolution level 0 2058 if(r==0 && s!=0) { 2059 continue; 2060 } else if(r!=0 && s==0) { 2061 // No LL subband in resolution level > 0 2062 continue; 2063 } 2064 2065 int mnby=0; 2066 for(int c=0; c<nc; c++) { 2067 if(cbI[c]!=null && cbI[c][r]!=null && 2068 cbI[c][r][s]!=null && 2069 cbI[c][r][s].length>mnby) 2070 mnby = cbI[c][r][s].length; 2071 } 2072 for(int m=0; m<mnby; m++) { 2073 2074 int mnbx = 0; 2075 for(int c=0; c<nc; c++) { 2076 if(cbI[c]!=null && cbI[c][r]!=null && 2077 cbI[c][r][s]!=null && cbI[c][r][s][m]!=null 2078 && cbI[c][r][s][m].length>mnbx) 2079 mnbx = cbI[c][r][s][m].length; 2080 } 2081 for(int n=0; n<mnbx; n++) { 2082 2083 for(int c=0; c<nc; c++) { 2084 2085 if(cbI[c]==null || cbI[c][r]==null || 2086 cbI[c][r][s]==null || 2087 cbI[c][r][s][m]==null || 2088 cbI[c][r][s][m][n]==null ) { 2089 continue; 2090 } 2091 cb = cbI[c][r][s][m][n]; 2092 2093 // If no code-block has been refused until 2094 // now 2095 if(!reject) { 2096 // Rate is to low to allow reading of 2097 // packet's head 2098 if(nBytes[t]<pktHeadLen[cb.pktIdx[l]]){ 2099 // Stop parsing 2100 stopCount = true; 2101 // Reject all next 2102 // code-blocks 2103 reject=true; 2104 } else { 2105 // Rate is enough to read packet's 2106 // head 2107 if(!stopCount) { 2108 //If parsing was not stopped 2109 //Takes into account packet's 2110 //head length 2111 nBytes[t] -= 2112 pktHeadLen[cb.pktIdx[l]]; 2113 anbytes += 2114 pktHeadLen[cb.pktIdx[l]]; 2115 // Set packet's head length to 2116 // 0, so that it won't be 2117 // taken into account next 2118 // time 2119 pktHeadLen[cb.pktIdx[l]]=0; 2120 } 2121 } 2122 } 2123 // Code-block has no data in this layer 2124 if(cb.len[l]==0) { 2125 continue; 2126 } 2127 2128 // Accepts code-block if length is enough, 2129 // if this code-block was not refused in a 2130 // previous layer and if no code-block was 2131 // refused in current component 2132 if(cb.len[l]<nBytes[t] 2133 && !reject){ 2134 nBytes[t] -= cb.len[l]; 2135 anbytes += cb.len[l]; 2136 } else { 2137 // Refuses code-block 2138 // Forgets code-block's data 2139 cb.len[l]=cb.off[l]=cb.ntp[l]= 0; 2140 // Refuses all other code-block in 2141 // current and next component 2142 reject=true; 2143 } 2144 2145 } // End loop on components 2146 } // End loop on horiz. code-blocks 2147 } // End loop on vert. code-blocks 2148 } // End loop on subbands 2149 } // End loop on resolutions 2150 } // End loop on layers 2151 } else { 2152 // No parsing for this tile, adds tile's body to the total 2153 // number of read bytes. 2154 anbytes += totTileLen[t]-totTileHeadLen[t]; 2155 if(t<getNumTiles()-1) { 2156 nBytes[t+1] += nBytes[t]-(totTileLen[t]-totTileHeadLen[t]); 2157 } 2158 } 2159 2160 // In this method nBytes[t] might be changed. This change will affect 2161 // to decode this tile next time. So cache the old nByte[t] and 2162 // recover it here. -- Qinghuai Gao 2163 nBytes[t] = oldNBytes; 2164 } 2165 2166 /** 2167 * Changes the current tile, given the new indexes. An 2168 * IllegalArgumentException is thrown if the indexes do not correspond to 2169 * a valid tile. 2170 * 2171 * @param x The horizontal indexes the tile. 2172 * 2173 * @param y The vertical indexes of the new tile. 2174 * */ 2175 public void setTile(int x,int y) { 2176 2177 int i; // counter 2178 // Check validity of tile indexes 2179 if (x<0 || y<0 || x>=ntX || y>=ntY) { 2180 throw new IllegalArgumentException(); 2181 } 2182 int t = (y*ntX+x); 2183 try { 2184 initTile(t); 2185 } catch(IOException ioe) { 2186 // XXX Do something! 2187 } 2188 2189 // Reset number of read bytes if needed 2190 if(t==0) { 2191 anbytes = headLen; 2192 if(!isTruncMode) { 2193 anbytes += 2; 2194 } 2195 // Restore values of nBytes 2196 for(int tIdx=0; tIdx<nt; tIdx++) { 2197 nBytes[tIdx] = baknBytes[tIdx]; 2198 } 2199 } 2200 2201 // Set the new current tile 2202 ctX = x; 2203 ctY = y; 2204 // Calculate tile relative points 2205 int ctox = (x == 0) ? ax : px+x*ntW; 2206 int ctoy = (y == 0) ? ay : py+y*ntH; 2207 for (i=nc-1; i>=0; i--) { 2208 culx[i] = (ctox+hd.getCompSubsX(i)-1)/hd.getCompSubsX(i); 2209 culy[i] = (ctoy+hd.getCompSubsY(i)-1)/hd.getCompSubsY(i); 2210 offX[i] = (px+x*ntW+hd.getCompSubsX(i)-1)/hd.getCompSubsX(i); 2211 offY[i] = (py+y*ntH+hd.getCompSubsY(i)-1)/hd.getCompSubsY(i); 2212 } 2213 2214 // Initialize subband tree and number of resolution levels 2215 subbTrees = new SubbandSyn[nc]; 2216 mdl = new int[nc]; 2217 derived = new boolean[nc]; 2218 params = new StdDequantizerParams[nc]; 2219 gb = new int[nc]; 2220 2221 for(int c=0; c<nc; c++){ 2222 derived[c] = decSpec.qts.isDerived(t,c); 2223 params[c] = 2224 (StdDequantizerParams)decSpec.qsss.getTileCompVal(t,c); 2225 gb[c] = ((Integer)decSpec.gbs.getTileCompVal(t,c)).intValue(); 2226 mdl[c] = ((Integer)decSpec.dls.getTileCompVal(t,c)).intValue(); 2227 2228 subbTrees[c] = 2229 new SubbandSyn(getTileCompWidth(t,c,mdl[c]), 2230 getTileCompHeight(t,c,mdl[c]), 2231 getResULX(c,mdl[c]),getResULY(c,mdl[c]),mdl[c], 2232 decSpec.wfs.getHFilters(t,c), 2233 decSpec.wfs.getVFilters(t,c)); 2234 initSubbandsFields(c,subbTrees[c]); 2235 } 2236 2237 // Read tile's packets 2238 try { 2239 readTilePkts(t); 2240 } catch(IOException e) { 2241 e.printStackTrace(); 2242 throw new Error("IO Error when reading tile "+x+" x "+y); 2243 } 2244 } 2245 2246 2247 /** 2248 * Advances to the next tile, in standard scan-line order (by rows 2249 * then columns). An NoNextElementException is thrown if the 2250 * current tile is the last one (i.e. there is no next tile). 2251 * */ 2252 public void nextTile(){ 2253 if (ctX == ntX-1 && ctY == ntY-1) { // Already at last tile 2254 throw new NoNextElementException(); 2255 } 2256 else if (ctX < ntX-1) { // If not at end of current tile line 2257 setTile(ctX+1,ctY); 2258 } 2259 else { // Go to first tile at next line 2260 setTile(0,ctY+1); 2261 } 2262 } 2263 2264 /** 2265 * Returns the specified coded code-block, for the specified component, in 2266 * the current tile. The first layer to return is indicated by 'fl'. The 2267 * number of layers that is returned depends on 'nl' and the amount of 2268 * available data. 2269 * 2270 * <p>The argument 'fl' is to be used by subsequent calls to this method 2271 * for the same code-block. In this way supplemental data can be retrieved 2272 * at a later time. The fact that data from more than one layer can be 2273 * returned means that several packets from the same code-block, of the 2274 * same component, and the same tile, have been concatenated.</p> 2275 * 2276 * <p>The returned compressed code-block can have its progressive 2277 * attribute set. If this attribute is set it means that more data can be 2278 * obtained by subsequent calls to this method (subject to transmission 2279 * delays, etc). If the progressive attribute is not set it means that the 2280 * returned data is all the data that can be obtained for the specified 2281 * code-block.</p> 2282 * 2283 * <p>The compressed code-block is uniquely specified by the current tile, 2284 * the component (identified by 'c'), the subband (indentified by 'sb') 2285 * and the code-block vertical and horizontal indexes 'n' and 'm'.</p> 2286 * 2287 * <p>The 'ulx' and 'uly' members of the returned 'DecLyrdCBlk' object 2288 * contain the coordinates of the top-left corner of the block, with 2289 * respect to the tile, not the subband.</p> 2290 * 2291 * @param c The index of the component, from 0 to N-1. 2292 * 2293 * @param m The vertical index of the code-block to return, in the 2294 * specified subband. 2295 * 2296 * @param n The horizontal index of the code-block to return, in the 2297 * specified subband. 2298 * 2299 * @param sb The subband in whic the requested code-block is. 2300 * 2301 * @param fl The first layer to return. 2302 * 2303 * @param nl The number of layers to return, if negative all available 2304 * layers are returned, starting at 'fl'. 2305 * 2306 * @param ccb If not null this object is used to return the compressed 2307 * code-block. If null a new object is created and returned. If the data 2308 * array in ccb is not null then it can be reused to return the compressed 2309 * data. 2310 * @return The compressed code-block, with a certain number of layers 2311 * determined by the available data and 'nl'. 2312 * */ 2313 public DecLyrdCBlk getCodeBlock(int c,int m,int n,SubbandSyn sb,int fl, 2314 int nl,DecLyrdCBlk ccb) { 2315 2316 int t = getTileIdx(); 2317 CBlkInfo rcb; // requested code-block 2318 int r = sb.resLvl; // Resolution level 2319 int s = sb.sbandIdx; // Subband index 2320 int tpidx; 2321 int passtype; 2322 2323 // Number of layers 2324 int numLayers = ((Integer)decSpec.nls.getTileDef(t)).intValue(); 2325 int options = ((Integer)decSpec.ecopts.getTileCompVal(t,c)).intValue(); 2326 if(nl<0) { 2327 nl = numLayers-fl+1; 2328 } 2329 2330 // If the l quit condition is used, Make sure that no layer 2331 // after lquit is returned 2332 if(lQuit != -1 && fl+nl>lQuit){ 2333 nl = lQuit - fl; 2334 } 2335 2336 // Check validity of resquested resolution level (according to the 2337 // "-res" option). 2338 int maxdl = getSynSubbandTree(t,c).resLvl; 2339 /* XXX Suppress error check for speed performance reasons. 2340 if(r>targetRes+maxdl-decSpec.dls.getMin()) { 2341 throw new Error("JJ2000 error: requesting a code-block "+ 2342 "disallowed by the '-res' option."); 2343 } 2344 */ 2345 2346 // Check validity of all the arguments 2347 try { 2348 rcb = cbI[c][r][s][m][n]; 2349 2350 if(fl<1 || fl>numLayers || fl+nl-1>numLayers) { 2351 throw new IllegalArgumentException(); 2352 } 2353 } catch(ArrayIndexOutOfBoundsException e) { 2354 throw new IllegalArgumentException("Code-block (t:"+t+", c:"+ 2355 c+", r:"+r+", s:"+s+", "+m+"x"+ 2356 +n+") not found in codestream"); 2357 } catch(NullPointerException e) { 2358 throw new IllegalArgumentException("Code-block (t:"+t+", c:"+ 2359 c+", r:"+r+", s:"+s+", "+m+"x" 2360 +n+") not found in bit stream"); 2361 } 2362 2363 // Create DecLyrdCBlk object if necessary 2364 if(ccb==null) { 2365 ccb = new DecLyrdCBlk(); 2366 } 2367 ccb.m = m; 2368 ccb.n = n; 2369 ccb.nl = 0; 2370 ccb.dl = 0; 2371 ccb.nTrunc = 0; 2372 2373 if(rcb==null) { 2374 // This code-block was skipped when reading. Returns no data 2375 ccb.skipMSBP = 0; 2376 ccb.prog = false; 2377 ccb.w = ccb.h = ccb.ulx = ccb.uly = 0; 2378 return ccb; 2379 } 2380 2381 // ccb initialization 2382 ccb.skipMSBP = rcb.msbSkipped; 2383 ccb.ulx = rcb.ulx; 2384 ccb.uly = rcb.uly; 2385 ccb.w = rcb.w; 2386 ccb.h = rcb.h; 2387 ccb.ftpIdx = 0; 2388 2389 // Search for index of first truncation point (first layer where 2390 // length of data is not zero) 2391 int l=0; 2392 while( (l<rcb.len.length) && (rcb.len[l]==0)) { 2393 ccb.ftpIdx += rcb.ntp[l]; 2394 l++; 2395 } 2396 2397 // Calculate total length, number of included layer and number of 2398 // truncation points 2399 for(l=fl-1; l<fl+nl-1; l++) { 2400 ccb.nl++; 2401 ccb.dl += rcb.len[l]; 2402 ccb.nTrunc += rcb.ntp[l]; 2403 } 2404 2405 // Calculate number of terminated segments 2406 int nts; 2407 if((options & OPT_TERM_PASS) != 0) { 2408 // Regular termination in use One segment per pass 2409 // (i.e. truncation point) 2410 nts = ccb.nTrunc-ccb.ftpIdx; 2411 } else if((options & OPT_BYPASS) != 0) { 2412 // Selective arithmetic coding bypass mode in use, but no regular 2413 // termination: 1 segment upto the end of the last pass of the 4th 2414 // most significant bit-plane, and, in each following bit-plane, 2415 // one segment upto the end of the 2nd pass and one upto the end 2416 // of the 3rd pass. 2417 2418 if(ccb.nTrunc <= FIRST_BYPASS_PASS_IDX) { 2419 nts = 1; 2420 } else { 2421 nts = 1; 2422 // Adds one for each terminated pass 2423 for (tpidx = ccb.ftpIdx; tpidx < ccb.nTrunc; tpidx++) { 2424 if (tpidx >= FIRST_BYPASS_PASS_IDX-1) { 2425 passtype = 2426 (tpidx+NUM_EMPTY_PASSES_IN_MS_BP)%NUM_PASSES; 2427 if (passtype == 1 || passtype == 2) { 2428 // lazy pass just before MQ pass or MQ pass just 2429 // before lazy pass => terminated 2430 nts++; 2431 } 2432 } 2433 } 2434 } 2435 } else { 2436 // Nothing special in use, just one terminated segment 2437 nts = 1; 2438 } 2439 2440 // ccb.data creation 2441 if(ccb.data==null || ccb.data.length<ccb.dl) { 2442 ccb.data = new byte[ccb.dl]; 2443 } 2444 2445 // ccb.tsLengths creation 2446 if (nts>1 && (ccb.tsLengths==null || ccb.tsLengths.length<nts)) { 2447 ccb.tsLengths = new int[nts]; 2448 } else if (nts>1 && 2449 (options & (OPT_BYPASS|OPT_TERM_PASS)) == OPT_BYPASS) { 2450 ArrayUtil.intArraySet(ccb.tsLengths,0); 2451 } 2452 2453 // Fill ccb with compressed data 2454 int dataIdx = -1; 2455 tpidx = ccb.ftpIdx; 2456 int ctp = ccb.ftpIdx; // Cumulative number of truncation 2457 // point for the current layer layer 2458 int tsidx=0; 2459 int j; 2460 2461 for(l=fl-1; l<fl+nl-1; l++) { 2462 ctp += rcb.ntp[l]; 2463 // No data in this layer 2464 if(rcb.len[l]==0) continue; 2465 2466 // Read data 2467 // NOTE: we should never get an EOFException here since all 2468 // data is checked to be within the file. 2469 try { 2470 in.seek(rcb.off[l]); 2471 in.readFully(ccb.data,dataIdx+1,rcb.len[l]); 2472 dataIdx += rcb.len[l]; 2473 } catch (IOException e) { 2474 JJ2KExceptionHandler.handleException(e); 2475 } 2476 2477 // Get the terminated segment lengths, if any 2478 if(nts==1) continue; 2479 if((options & OPT_TERM_PASS) != 0) { 2480 // Regular termination => each pass is terminated 2481 for(j=0; tpidx<ctp; j++,tpidx++) { 2482 if(rcb.segLen[l]!=null) { 2483 ccb.tsLengths[tsidx++] = rcb.segLen[l][j]; 2484 } else { // Only one terminated segment in packet 2485 ccb.tsLengths[tsidx++] = rcb.len[l]; 2486 } 2487 } 2488 } else { 2489 // Lazy coding without regular termination 2490 for(j=0; tpidx<ctp; tpidx++) { 2491 if(tpidx>=FIRST_BYPASS_PASS_IDX-1) { 2492 passtype = 2493 (tpidx+NUM_EMPTY_PASSES_IN_MS_BP)%NUM_PASSES; 2494 if(passtype!=0) { 2495 // lazy pass just before MQ pass or MQ 2496 // pass just before lazy pass => 2497 // terminated 2498 if(rcb.segLen[l]!=null) { 2499 ccb.tsLengths[tsidx++] += rcb.segLen[l][j++]; 2500 rcb.len[l] -= rcb.segLen[l][j-1]; 2501 } else { // Only one terminated segment in packet 2502 ccb.tsLengths[tsidx++] += rcb.len[l]; 2503 rcb.len[l] = 0; 2504 } 2505 } 2506 2507 } 2508 } 2509 2510 // Last length in packet always in (either terminated segment 2511 // or contribution to terminated segment) 2512 if(rcb.segLen[l]!=null && j<rcb.segLen[l].length) { 2513 ccb.tsLengths[tsidx] += rcb.segLen[l][j]; 2514 rcb.len[l] -= rcb.segLen[l][j]; 2515 } else { // Only one terminated segment in packet 2516 if(tsidx<nts) { 2517 ccb.tsLengths[tsidx] += rcb.len[l]; 2518 rcb.len[l] = 0; 2519 } 2520 } 2521 } 2522 } 2523 if(nts==1 && ccb.tsLengths!=null) { 2524 ccb.tsLengths[0] = ccb.dl; 2525 } 2526 2527 // Set the progressive flag 2528 int lastlayer = fl+nl-1; 2529 if(lastlayer<numLayers-1){ 2530 for(l=lastlayer+1; l<numLayers; l++){ 2531 // It remains data for this code-block in the bit stream 2532 if(rcb.len[l]!=0){ 2533 ccb.prog = true; 2534 } 2535 } 2536 } 2537 2538 return ccb; 2539 } 2540 2541}