2009-09-30 23:50:03 +00:00
/ *
* CVS identifier :
*
* $ Id : FileBitstreamReaderAgent . java , v 1.68 2002 / 07 / 19 12 : 34 : 38 grosbois Exp $
*
* Class : FileBitstreamReaderAgent
*
* Description : Retrieve code - blocks codewords in the bit stream
*
*
*
* COPYRIGHT :
*
* This software module was originally developed by Rapha <EFBFBD> l Grosbois and
* Diego Santa Cruz ( Swiss Federal Institute of Technology - EPFL ) ; Joel
* Askel <EFBFBD> f ( Ericsson Radio Systems AB ) ; and Bertrand Berthelot , David
* Bouchard , F <EFBFBD> lix Henry , Gerard Mozelle and Patrice Onno ( Canon Research
* Centre France S . A ) in the course of development of the JPEG2000
* standard as specified by ISO / IEC 15444 ( JPEG 2000 Standard ) . This
* software module is an implementation of a part of the JPEG 2000
* Standard . Swiss Federal Institute of Technology - EPFL , Ericsson Radio
* Systems AB and Canon Research Centre France S . A ( collectively JJ2000
* Partners ) agree not to assert against ISO / IEC and users of the JPEG
* 2000 Standard ( Users ) any of their rights under the copyright , not
* including other intellectual property rights , for this software module
* with respect to the usage by ISO / IEC and Users of this software module
* or modifications thereof for use in hardware or software products
* claiming conformance to the JPEG 2000 Standard . Those intending to use
* this software module in hardware or software products are advised that
* their use may infringe existing patents . The original developers of
* this software module , JJ2000 Partners and ISO / IEC assume no liability
* for use of this software module or modifications thereof . No license
* or right to this software module is granted for non JPEG 2000 Standard
* conforming products . JJ2000 Partners have full right to use this
* software module for his / her own purpose , assign or donate this
* software module to any third party and to inhibit third parties from
* using this software module for non JPEG 2000 Standard conforming
* products . This copyright notice must be included in all copies or
* derivative works of this software module .
*
* Copyright ( c ) 1999 / 2000 JJ2000 Partners .
* * /
using System ;
using CSJ2K.j2k.quantization.dequantizer ;
using CSJ2K.j2k.wavelet.synthesis ;
using CSJ2K.j2k.entropy.decoder ;
using CSJ2K.j2k.codestream ;
using CSJ2K.j2k.decoder ;
using CSJ2K.j2k.entropy ;
using CSJ2K.j2k.image ;
using CSJ2K.j2k.util ;
using CSJ2K.j2k.io ;
using CSJ2K.j2k ;
namespace CSJ2K.j2k.codestream.reader
{
/// <summary> This class reads the bit stream (with the help of HeaderDecoder for tile
/// headers and PktDecoder for packets header and body) and retrives location
/// of all code-block's codewords.
///
/// <p>Note: All tile-parts headers are read by the constructor whereas packets
/// are processed when decoding related tile (when setTile method is
/// called).</p>
///
/// <p>In parsing mode, the reader simulates a virtual layer-resolution
/// progressive bit stream with the same truncation points in each code-block,
/// whereas in truncation mode, only the first bytes are taken into account (it
/// behaves like if it is a real truncated codestream).</p>
///
/// </summary>
/// <seealso cref="HeaderDecoder">
/// </seealso>
/// <seealso cref="PktDecoder">
///
/// </seealso>
public class FileBitstreamReaderAgent : BitstreamReaderAgent
{
/// <summary>Gets the reference to the CBlkInfo array </summary>
virtual public CBlkInfo [ ] [ ] [ ] [ ] [ ] CBlkInfo
{
get
{
return cbI ;
}
}
/// <summary>Whether or not the last read Psot value was zero. Only the Psot in the
/// last tile-part in the codestream can have such a value.
/// </summary>
private bool isPsotEqualsZero = true ;
/// <summary>Reference to the PktDecoder instance </summary>
public PktDecoder pktDec ;
/// <summary>Reference to the ParameterList instance </summary>
private ParameterList pl ;
/// <summary>The RandomAccessIO where to get data from </summary>
private RandomAccessIO in_Renamed ;
/// <summary>Offset of the first packet in each tile-part in each tile </summary>
private int [ ] [ ] firstPackOff ;
/// <summary> Returns the number of tile-part found for a given tile
///
/// </summary>
/// <param name="t">Tile index
///
///
/// </param>
public virtual int getNumTileParts ( int t )
{
if ( firstPackOff = = null | | firstPackOff [ t ] = = null )
{
throw new System . ApplicationException ( "Tile " + t + " not found in input codestream." ) ;
}
return firstPackOff [ t ] . Length ;
}
/// <summary> Number of bytes allocated to each tile. In parsing mode, this number
/// is related to the tile length in the codestream whereas in truncation
/// mode all the rate is affected to the first tiles.
/// </summary>
private int [ ] nBytes ;
/// <summary>Whether or not to print information found in codestream </summary>
private bool printInfo = false ;
/// <summary> Backup of the number of bytes allocated to each tile. This array is
/// used to restore the number of bytes to read in each tile when the
/// codestream is read several times (for instance when decoding an R,G,B
/// image to three output files)
///
/// </summary>
private int [ ] baknBytes ;
/// <summary>Length of each tile-part (written in Psot) </summary>
private int [ ] [ ] tilePartLen ;
/// <summary>Total length of each tile </summary>
private int [ ] totTileLen ;
/// <summary>Total length of tiles' header </summary>
private int [ ] totTileHeadLen ;
/// <summary>First tile part header length</summary>
private int firstTilePartHeadLen ;
/// <summary>Total length of all tile parts in all tiles </summary>
private double totAllTileLen ;
/// <summary>Length of main header </summary>
private int mainHeadLen ;
/// <summary>Length of main and tile-parts headers </summary>
private int headLen = 0 ;
/// <summary>Length of all tile-part headers </summary>
private int [ ] [ ] tilePartHeadLen ;
/// <summary>Length of each packet head found in the tile </summary>
private System . Collections . ArrayList pktHL ;
2009-10-01 00:25:27 +00:00
/// <summary>Layer starting positions</summary>
public System . Collections . Generic . List < int > layerStarts ;
2009-09-30 23:50:03 +00:00
/// <summary>True if truncation mode is used. False if parsing mode </summary>
private bool isTruncMode ;
/// <summary>The number of tile-parts that remain to read </summary>
private int remainingTileParts ;
/// <summary>The number of tile-parts read so far for each tile </summary>
private int [ ] tilePartsRead ;
/// <summary>Thetotal number of tile-parts read so far </summary>
private int totTilePartsRead = 0 ;
/// <summary>The number of found tile-parts in each tile. </summary>
private int [ ] tileParts ;
/// <summary>The current tile part being used </summary>
private int curTilePart ;
/// <summary>The number of the tile-parts found in the codestream after reading the
/// tp'th tile-part of tile t
/// </summary>
private int [ ] [ ] tilePartNum ;
/// <summary>Whether or not a EOC marker has been found instead of a SOT </summary>
private bool isEOCFound = false ;
/// <summary>Reference to the HeaderInfo instance (used when reading SOT marker
/// segments)
/// </summary>
private HeaderInfo hi ;
/// <summary>Array containing information for all the code-blocks:
///
/// <ul>
/// <li>1st dim: component index.</li>
/// <li>2nd dim: resolution level index.</li>
/// <li>3rd dim: subband index.</li>
/// <li>4th/5th dim: code-block index (vert. and horiz.).</li>
/// </ul>
/// </summary>
private CBlkInfo [ ] [ ] [ ] [ ] [ ] cbI ;
/// <summary>The maximum number of layers to decode for any code-block </summary>
private int lQuit ;
/// <summary>Whether or not to use only first progression order </summary>
private bool usePOCQuit = false ;
/// <summary> Reads all tiles headers and keep offset of their first
/// packet. Finally it calls the rate allocation method.
///
/// </summary>
/// <param name="hd">HeaderDecoder of the codestream.
///
/// </param>
/// <param name="ehs">The input stream where to read bit-stream.
///
/// </param>
/// <param name="decSpec">The decoder specifications
///
/// </param>
/// <param name="pl">The ParameterList instance created from the
/// command-line arguments.
///
/// </param>
/// <param name="cdstrInfo">Whether or not to print information found in
/// codestream.
///
/// </param>
/// <seealso cref="allocateRate">
///
/// </seealso>
public FileBitstreamReaderAgent ( HeaderDecoder hd , RandomAccessIO ehs , DecoderSpecs decSpec , ParameterList pl , bool cdstrInfo , HeaderInfo hi ) : base ( hd , decSpec )
{
this . pl = pl ;
this . printInfo = cdstrInfo ;
this . hi = hi ;
// Check whether quit conditiosn used
usePOCQuit = pl . getBooleanParameter ( "poc_quit" ) ;
// Get decoding rate
bool rateInBytes ;
bool parsing = pl . getBooleanParameter ( "parsing" ) ;
try
{
trate = pl . getFloatParameter ( "rate" ) ;
if ( trate = = - 1 )
{
trate = System . Single . MaxValue ;
}
}
2009-10-01 00:19:01 +00:00
catch ( System . FormatException )
2009-09-30 23:50:03 +00:00
{
throw new System . ApplicationException ( "Invalid value in 'rate' option: " + pl . getParameter ( "rate" ) ) ;
}
2009-10-01 00:19:01 +00:00
catch ( System . ArgumentException )
2009-09-30 23:50:03 +00:00
{
throw new System . ApplicationException ( "'rate' option is missing" ) ;
}
try
{
tnbytes = pl . getIntParameter ( "nbytes" ) ;
}
2009-10-01 00:19:01 +00:00
catch ( System . FormatException )
2009-09-30 23:50:03 +00:00
{
throw new System . ApplicationException ( "Invalid value in 'nbytes' option: " + pl . getParameter ( "nbytes" ) ) ;
}
2009-10-01 00:19:01 +00:00
catch ( System . ArgumentException )
2009-09-30 23:50:03 +00:00
{
throw new System . ApplicationException ( "'nbytes' option is missing" ) ;
}
// Check that '-rate' and '-nbytes' are not used at the same time
ParameterList defaults = pl . DefaultParameterList ;
if ( tnbytes ! = defaults . getFloatParameter ( "nbytes" ) )
{
rateInBytes = true ;
}
else
{
rateInBytes = false ;
}
if ( rateInBytes )
{
trate = tnbytes * 8f / hd . MaxCompImgWidth / hd . MaxCompImgHeight ;
}
else
{
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
tnbytes = ( int ) ( trate * hd . MaxCompImgWidth * hd . MaxCompImgHeight ) / 8 ;
if ( tnbytes < 0 ) tnbytes = int . MaxValue ;
}
isTruncMode = ! pl . getBooleanParameter ( "parsing" ) ;
// Check if quit conditions are being used
int ncbQuit ;
try
{
ncbQuit = pl . getIntParameter ( "ncb_quit" ) ;
}
2009-10-01 00:19:01 +00:00
catch ( System . FormatException )
2009-09-30 23:50:03 +00:00
{
throw new System . ApplicationException ( "Invalid value in 'ncb_quit' option: " + pl . getParameter ( "ncb_quit" ) ) ;
}
2009-10-01 00:19:01 +00:00
catch ( System . ArgumentException )
2009-09-30 23:50:03 +00:00
{
throw new System . ApplicationException ( "'ncb_quit' option is missing" ) ;
}
if ( ncbQuit ! = - 1 & & ! isTruncMode )
{
throw new System . ApplicationException ( "Cannot use -parsing and -ncb_quit condition at " + "the same time." ) ;
}
try
{
lQuit = pl . getIntParameter ( "l_quit" ) ;
}
2009-10-01 00:19:01 +00:00
catch ( System . FormatException )
2009-09-30 23:50:03 +00:00
{
throw new System . ApplicationException ( "Invalid value in 'l_quit' option: " + pl . getParameter ( "l_quit" ) ) ;
}
2009-10-01 00:19:01 +00:00
catch ( System . ArgumentException )
2009-09-30 23:50:03 +00:00
{
throw new System . ApplicationException ( "'l_quit' option is missing" ) ;
}
// initializations
in_Renamed = ehs ;
pktDec = new PktDecoder ( decSpec , hd , ehs , this , isTruncMode , ncbQuit ) ;
tileParts = new int [ nt ] ;
totTileLen = new int [ nt ] ;
tilePartLen = new int [ nt ] [ ] ;
tilePartNum = new int [ nt ] [ ] ;
firstPackOff = new int [ nt ] [ ] ;
tilePartsRead = new int [ nt ] ;
totTileHeadLen = new int [ nt ] ;
tilePartHeadLen = new int [ nt ] [ ] ;
nBytes = new int [ nt ] ;
baknBytes = new int [ nt ] ;
hd . nTileParts = new int [ nt ] ;
// CONVERSION PROBLEM?
//this.isTruncMode = isTruncMode;
int t = 0 , pos , tp = 0 , tptot = 0 ;
// Keeps main header's length, takes file format overhead into account
int cdstreamStart = hd . mainHeadOff ; // Codestream offset in the file
mainHeadLen = in_Renamed . Pos - cdstreamStart ;
headLen = mainHeadLen ;
// If ncb and lbody quit conditions are used, headers are not counted
if ( ncbQuit = = - 1 )
{
anbytes = mainHeadLen ;
}
else
{
anbytes = 0 ;
}
// If cannot even read the first tile-part
if ( anbytes > tnbytes )
{
throw new System . ApplicationException ( "Requested bitrate is too small." ) ;
}
// Read all tile-part headers from all tiles.
int tilePartStart ;
bool rateReached = false ;
int mdl ;
//int numtp = 0;
totAllTileLen = 0 ;
remainingTileParts = nt ; // at least as many tile-parts as tiles
int maxTP = nt ; // If maximum 1 tile part per tile specified
try
{
while ( remainingTileParts ! = 0 )
{
tilePartStart = in_Renamed . Pos ;
// Read tile-part header
try
{
t = readTilePartHeader ( ) ;
if ( isEOCFound )
{
// Some tiles are missing but the
// codestream is OK
break ;
}
tp = tilePartsRead [ t ] ;
if ( isPsotEqualsZero )
{
// Psot may equals zero for the
// last tile-part: it is assumed that this tile-part
// contain all data until EOC
tilePartLen [ t ] [ tp ] = in_Renamed . length ( ) - 2 - tilePartStart ;
}
}
catch ( System . IO . EndOfStreamException e )
{
firstPackOff [ t ] [ tp ] = in_Renamed . length ( ) ;
throw e ;
}
pos = in_Renamed . Pos ;
// In truncation mode, if target decoding rate is reached in
// tile-part header, skips the tile-part and stop reading
// unless the ncb and lbody quit condition is in use
if ( isTruncMode & & ncbQuit = = - 1 )
{
if ( ( pos - cdstreamStart ) > tnbytes )
{
firstPackOff [ t ] [ tp ] = in_Renamed . length ( ) ;
rateReached = true ;
break ;
}
}
// Set tile part position and header length
firstPackOff [ t ] [ tp ] = pos ;
tilePartHeadLen [ t ] [ tp ] = ( pos - tilePartStart ) ;
// Update length counters
totTileLen [ t ] + = tilePartLen [ t ] [ tp ] ;
totTileHeadLen [ t ] + = tilePartHeadLen [ t ] [ tp ] ;
totAllTileLen + = tilePartLen [ t ] [ tp ] ;
if ( isTruncMode )
{
if ( anbytes + tilePartLen [ t ] [ tp ] > tnbytes )
{
anbytes + = tilePartHeadLen [ t ] [ tp ] ;
headLen + = tilePartHeadLen [ t ] [ tp ] ;
rateReached = true ;
nBytes [ t ] + = ( tnbytes - anbytes ) ;
break ;
}
else
{
anbytes + = tilePartHeadLen [ t ] [ tp ] ;
headLen + = tilePartHeadLen [ t ] [ tp ] ;
nBytes [ t ] + = ( tilePartLen [ t ] [ tp ] - tilePartHeadLen [ t ] [ tp ] ) ;
}
}
else
{
if ( anbytes + tilePartHeadLen [ t ] [ tp ] > tnbytes )
{
break ;
}
else
{
anbytes + = tilePartHeadLen [ t ] [ tp ] ;
headLen + = tilePartHeadLen [ t ] [ tp ] ;
}
}
// If this is first tile-part, remember header length
if ( tptot = = 0 )
firstTilePartHeadLen = tilePartHeadLen [ t ] [ tp ] ;
// Go to the beginning of next tile part
tilePartsRead [ t ] + + ;
in_Renamed . seek ( tilePartStart + tilePartLen [ t ] [ tp ] ) ;
remainingTileParts - - ;
maxTP - - ;
tptot + + ;
// If Psot of the current tile-part was equal to zero, it is
// assumed that it contains all data until the EOC marker
if ( isPsotEqualsZero )
{
if ( remainingTileParts ! = 0 )
{
FacilityManager . getMsgLogger ( ) . printmsg ( CSJ2K . j2k . util . MsgLogger_Fields . WARNING , "Some tile-parts have not " + "been found. The codestream may be corrupted." ) ;
}
break ;
}
}
}
2009-10-01 00:19:01 +00:00
catch ( System . IO . EndOfStreamException )
2009-09-30 23:50:03 +00:00
{
if ( printInfo )
{
}
FacilityManager . getMsgLogger ( ) . printmsg ( CSJ2K . j2k . util . MsgLogger_Fields . WARNING , "Codestream truncated in tile " + t ) ;
// Set specified rate to end of file if valid
int fileLen = in_Renamed . length ( ) ;
if ( fileLen < tnbytes )
{
tnbytes = fileLen ;
trate = tnbytes * 8f / hd . MaxCompImgWidth / hd . MaxCompImgHeight ;
}
// Bit-rate allocation
if ( ! isTruncMode )
{
allocateRate ( ) ;
}
// Update 'res' value once all tile-part headers are read
if ( pl . getParameter ( "res" ) = = null )
{
targetRes = decSpec . dls . Min ;
}
else
{
try
{
targetRes = pl . getIntParameter ( "res" ) ;
if ( targetRes < 0 )
{
throw new System . ArgumentException ( "Specified negative " + "resolution level " + "index: " + targetRes ) ;
}
}
2009-10-01 00:19:01 +00:00
catch ( System . FormatException )
2009-09-30 23:50:03 +00:00
{
throw new System . ArgumentException ( "Invalid resolution level " + "index ('-res' option) " + pl . getParameter ( "res" ) ) ;
}
}
// Verify reduction in resolution level
mdl = decSpec . dls . Min ;
if ( targetRes > mdl )
{
FacilityManager . getMsgLogger ( ) . printmsg ( CSJ2K . j2k . util . MsgLogger_Fields . WARNING , "Specified resolution level (" + targetRes + ") is larger" + " than the maximum value. Setting it to " + mdl + " (maximum value)" ) ;
targetRes = mdl ;
}
// Backup nBytes
for ( int tIdx = 0 ; tIdx < nt ; tIdx + + )
{
baknBytes [ tIdx ] = nBytes [ tIdx ] ;
}
return ;
}
remainingTileParts = 0 ;
// Update 'res' value once all tile-part headers are read
if ( pl . getParameter ( "res" ) = = null )
{
targetRes = decSpec . dls . Min ;
}
else
{
try
{
targetRes = pl . getIntParameter ( "res" ) ;
if ( targetRes < 0 )
{
throw new System . ArgumentException ( "Specified negative " + "resolution level index: " + targetRes ) ;
}
}
2009-10-01 00:19:01 +00:00
catch ( System . FormatException )
2009-09-30 23:50:03 +00:00
{
throw new System . ArgumentException ( "Invalid resolution level " + "index ('-res' option) " + pl . getParameter ( "res" ) ) ;
}
}
// Verify reduction in resolution level
mdl = decSpec . dls . Min ;
if ( targetRes > mdl )
{
FacilityManager . getMsgLogger ( ) . printmsg ( CSJ2K . j2k . util . MsgLogger_Fields . WARNING , "Specified resolution level (" + targetRes + ") is larger" + " than the maximum possible. Setting it to " + mdl + " (maximum possible)" ) ;
targetRes = mdl ;
}
if ( printInfo )
{
}
// Check presence of EOC marker is decoding rate not reached or if
// this marker has not been found yet
if ( ! isEOCFound & & ! isPsotEqualsZero )
{
try
{
2010-08-04 22:01:25 +00:00
short eocCheck = 0 ;
2010-08-04 22:14:23 +00:00
if ( in_Renamed . Pos + sizeof ( short ) < = in_Renamed . length ( ) )
2010-08-04 22:01:25 +00:00
eocCheck = in_Renamed . readShort ( ) ;
if ( ! rateReached & & ! isPsotEqualsZero & & eocCheck ! = CSJ2K . j2k . codestream . Markers . EOC )
2009-09-30 23:50:03 +00:00
{
FacilityManager . getMsgLogger ( ) . printmsg ( CSJ2K . j2k . util . MsgLogger_Fields . WARNING , "EOC marker not found. " + "Codestream is corrupted." ) ;
}
}
2009-10-01 00:19:01 +00:00
catch ( System . IO . EndOfStreamException )
2009-09-30 23:50:03 +00:00
{
FacilityManager . getMsgLogger ( ) . printmsg ( CSJ2K . j2k . util . MsgLogger_Fields . WARNING , "EOC marker is missing" ) ;
}
}
// Bit-rate allocation
if ( ! isTruncMode )
{
allocateRate ( ) ;
}
else
{
// Take EOC into account if rate is not reached
if ( in_Renamed . Pos > = tnbytes )
anbytes + = 2 ;
}
// Backup nBytes
for ( int tIdx = 0 ; tIdx < nt ; tIdx + + )
{
baknBytes [ tIdx ] = nBytes [ tIdx ] ;
if ( printInfo )
{
FacilityManager . getMsgLogger ( ) . println ( "" + hi . toStringTileHeader ( tIdx , tilePartLen [ tIdx ] . Length ) , 2 , 2 ) ;
}
}
}
/// <summary> Allocates output bit-rate for each tile in parsing mode: The allocator
/// simulates the truncation of a virtual layer-resolution progressive
/// codestream.
///
/// </summary>
private void allocateRate ( )
{
int stopOff = tnbytes ;
// In parsing mode, the bitrate is allocated related to each tile's
// length in the bit stream
// EOC marker's length
anbytes + = 2 ;
// If there are too few bytes to read the tile part headers throw an
// error
if ( anbytes > stopOff )
{
throw new System . ApplicationException ( "Requested bitrate is too small for parsing" ) ;
}
// Calculate bitrate for each tile
int rem = stopOff - anbytes ;
int totnByte = rem ;
for ( int t = nt - 1 ; t > 0 ; t - - )
{
//UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
rem - = ( nBytes [ t ] = ( int ) ( totnByte * ( totTileLen [ t ] / totAllTileLen ) ) ) ;
}
nBytes [ 0 ] = rem ;
}
/// <summary> Reads SOT marker segment of the tile-part header and calls related
/// methods of the HeaderDecoder to read other markers segments. The
/// tile-part header is entirely read when a SOD marker is encountered.
///
/// </summary>
/// <returns> The tile number of the tile part that was read
///
/// </returns>
private int readTilePartHeader ( )
{
HeaderInfo . SOT ms = hi . NewSOT ;
// SOT marker
short marker = in_Renamed . readShort ( ) ;
if ( marker ! = CSJ2K . j2k . codestream . Markers . SOT )
{
if ( marker = = CSJ2K . j2k . codestream . Markers . EOC )
{
isEOCFound = true ;
return - 1 ;
}
else
{
throw new CorruptedCodestreamException ( "SOT tag not found " + "in tile-part start" ) ;
}
}
isEOCFound = false ;
// Lsot (shall equals 10)
int lsot = in_Renamed . readUnsignedShort ( ) ;
ms . lsot = lsot ;
if ( lsot ! = 10 )
throw new CorruptedCodestreamException ( "Wrong length for " + "SOT marker segment: " + lsot ) ;
// Isot
int tile = in_Renamed . readUnsignedShort ( ) ;
ms . isot = tile ;
if ( tile > 65534 )
{
throw new CorruptedCodestreamException ( "Tile index too high in " + "tile-part." ) ;
}
// Psot
int psot = in_Renamed . readInt ( ) ;
ms . psot = psot ;
isPsotEqualsZero = ( psot ! = 0 ) ? false : true ;
if ( psot < 0 )
{
2009-10-13 22:31:18 +00:00
throw new NotImplementedException ( "Tile length larger " + "than maximum supported" ) ;
2009-09-30 23:50:03 +00:00
}
// TPsot
int tilePart = in_Renamed . read ( ) ;
ms . tpsot = tilePart ;
if ( tilePart ! = tilePartsRead [ tile ] | | tilePart < 0 | | tilePart > 254 )
{
throw new CorruptedCodestreamException ( "Out of order tile-part" ) ;
}
// TNsot
int nrOfTileParts = in_Renamed . read ( ) ;
ms . tnsot = nrOfTileParts ;
hi . sotValue [ "t" + tile + "_tp" + tilePart ] = ms ;
if ( nrOfTileParts = = 0 )
{
// The number of tile-part is not specified in
// this tile-part header.
// Assumes that there will be another tile-part in the codestream
// that will indicate the number of tile-parts for this tile)
int nExtraTp ;
if ( tileParts [ tile ] = = 0 | | tileParts [ tile ] = = tilePartLen . Length )
{
// Then there are two tile-parts (one is the current and the
// other will indicate the number of tile-part for this tile)
nExtraTp = 2 ;
remainingTileParts + = 1 ;
}
else
{
// There is already one scheduled extra tile-part. In this
// case just add place for the current one
nExtraTp = 1 ;
}
tileParts [ tile ] + = nExtraTp ;
nrOfTileParts = tileParts [ tile ] ;
FacilityManager . getMsgLogger ( ) . printmsg ( CSJ2K . j2k . util . MsgLogger_Fields . WARNING , "Header of tile-part " + tilePart + " of tile " + tile + ", does not indicate the total" + " number of tile-parts. Assuming that there are " + nrOfTileParts + " tile-parts for this tile." ) ;
// Increase and re-copy tilePartLen array
int [ ] tmpA = tilePartLen [ tile ] ;
tilePartLen [ tile ] = new int [ nrOfTileParts ] ;
for ( int i = 0 ; i < nrOfTileParts - nExtraTp ; i + + )
{
tilePartLen [ tile ] [ i ] = tmpA [ i ] ;
}
// Increase and re-copy tilePartNum array
tmpA = tilePartNum [ tile ] ;
tilePartNum [ tile ] = new int [ nrOfTileParts ] ;
for ( int i = 0 ; i < nrOfTileParts - nExtraTp ; i + + )
{
tilePartNum [ tile ] [ i ] = tmpA [ i ] ;
}
// Increase and re-copy firsPackOff array
tmpA = firstPackOff [ tile ] ;
firstPackOff [ tile ] = new int [ nrOfTileParts ] ;
for ( int i = 0 ; i < nrOfTileParts - nExtraTp ; i + + )
{
firstPackOff [ tile ] [ i ] = tmpA [ i ] ;
}
// Increase and re-copy tilePartHeadLen array
tmpA = tilePartHeadLen [ tile ] ;
tilePartHeadLen [ tile ] = new int [ nrOfTileParts ] ;
for ( int i = 0 ; i < nrOfTileParts - nExtraTp ; i + + )
{
tilePartHeadLen [ tile ] [ i ] = tmpA [ i ] ;
}
}
else
{
// The number of tile-parts is specified in the tile-part
// header
// Check if it is consistant with what was found in previous
// tile-part headers
if ( tileParts [ tile ] = = 0 )
{
// First tile-part: OK
remainingTileParts + = nrOfTileParts - 1 ;
tileParts [ tile ] = nrOfTileParts ;
tilePartLen [ tile ] = new int [ nrOfTileParts ] ;
tilePartNum [ tile ] = new int [ nrOfTileParts ] ;
firstPackOff [ tile ] = new int [ nrOfTileParts ] ;
tilePartHeadLen [ tile ] = new int [ nrOfTileParts ] ;
}
else if ( tileParts [ tile ] > nrOfTileParts )
{
// Already found more tile-parts than signaled here
throw new CorruptedCodestreamException ( "Invalid number " + "of tile-parts in" + " tile " + tile + ": " + nrOfTileParts ) ;
}
else
{
// Signaled number of tile-part fits with number of
// previously found tile-parts
remainingTileParts + = nrOfTileParts - tileParts [ tile ] ;
if ( tileParts [ tile ] ! = nrOfTileParts )
{
// Increase and re-copy tilePartLen array
int [ ] tmpA = tilePartLen [ tile ] ;
tilePartLen [ tile ] = new int [ nrOfTileParts ] ;
for ( int i = 0 ; i < tileParts [ tile ] - 1 ; i + + )
{
tilePartLen [ tile ] [ i ] = tmpA [ i ] ;
}
// Increase and re-copy tilePartNum array
tmpA = tilePartNum [ tile ] ;
tilePartNum [ tile ] = new int [ nrOfTileParts ] ;
for ( int i = 0 ; i < tileParts [ tile ] - 1 ; i + + )
{
tilePartNum [ tile ] [ i ] = tmpA [ i ] ;
}
// Increase and re-copy firstPackOff array
tmpA = firstPackOff [ tile ] ;
firstPackOff [ tile ] = new int [ nrOfTileParts ] ;
for ( int i = 0 ; i < tileParts [ tile ] - 1 ; i + + )
{
firstPackOff [ tile ] [ i ] = tmpA [ i ] ;
}
// Increase and re-copy tilePartHeadLen array
tmpA = tilePartHeadLen [ tile ] ;
tilePartHeadLen [ tile ] = new int [ nrOfTileParts ] ;
for ( int i = 0 ; i < tileParts [ tile ] - 1 ; i + + )
{
tilePartHeadLen [ tile ] [ i ] = tmpA [ i ] ;
}
}
}
}
// Other markers
hd . resetHeaderMarkers ( ) ;
hd . nTileParts [ tile ] = nrOfTileParts ;
// Decode and store the tile-part header (i.e. until a SOD marker is
// found)
do
{
hd . extractTilePartMarkSeg ( in_Renamed . readShort ( ) , in_Renamed , tile , tilePart ) ;
}
while ( ( hd . NumFoundMarkSeg & CSJ2K . j2k . codestream . reader . HeaderDecoder . SOD_FOUND ) = = 0 ) ;
// Read each marker segment previously found
hd . readFoundTilePartMarkSeg ( tile , tilePart ) ;
tilePartLen [ tile ] [ tilePart ] = psot ;
tilePartNum [ tile ] [ tilePart ] = totTilePartsRead ;
totTilePartsRead + + ;
// Add to list of which tile each successive tile-part belongs.
// This list is needed if there are PPM markers used
hd . TileOfTileParts = tile ;
return tile ;
}
/// <summary> Reads packets of the current tile according to the
/// layer-resolution-component-position progressiveness.
///
/// </summary>
/// <param name="lys">Index of the first layer for each component and resolution.
///
/// </param>
/// <param name="lye">Index of the last layer.
///
/// </param>
/// <param name="ress">Index of the first resolution level.
///
/// </param>
/// <param name="rese">Index of the last resolution level.
///
/// </param>
/// <param name="comps">Index of the first component.
///
/// </param>
/// <param name="compe">Index of the last component.
///
/// </param>
/// <returns> True if rate has been reached.
///
/// </returns>
private bool readLyResCompPos ( int [ ] [ ] lys , int lye , int ress , int rese , int comps , int compe )
{
int minlys = 10000 ;
for ( int c = comps ; c < compe ; c + + )
{
//loop on components
// Check if this component exists
if ( c > = mdl . Length )
continue ;
for ( int r = ress ; r < rese ; r + + )
{
//loop on resolution levels
if ( lys [ c ] ! = null & & r < lys [ c ] . Length & & lys [ c ] [ r ] < minlys )
{
minlys = lys [ c ] [ r ] ;
}
}
}
int t = TileIdx ;
int start ;
bool status = false ;
int lastByte = firstPackOff [ t ] [ curTilePart ] + tilePartLen [ t ] [ curTilePart ] - 1 - tilePartHeadLen [ t ] [ curTilePart ] ;
int numLayers = ( ( System . Int32 ) decSpec . nls . getTileDef ( t ) ) ;
int nPrec = 1 ;
int hlen , plen ;
bool pph = false ;
if ( ( ( System . Boolean ) decSpec . pphs . getTileDef ( t ) ) )
{
pph = true ;
}
for ( int l = minlys ; l < lye ; l + + )
{
2009-10-01 00:25:27 +00:00
// store the layer starting position
layerStarts . Add ( in_Renamed . Pos ) ;
2009-09-30 23:50:03 +00:00
// loop on layers
for ( int r = ress ; r < rese ; r + + )
{
// loop on resolution levels
for ( int c = comps ; c < compe ; c + + )
{
// loop on components
// Checks if component exists
if ( c > = mdl . Length )
continue ;
// Checks if resolution level exists
if ( r > = lys [ c ] . Length )
continue ;
if ( r > mdl [ c ] )
continue ;
// Checks if layer exists
if ( l < lys [ c ] [ r ] | | l > = numLayers )
continue ;
nPrec = pktDec . getNumPrecinct ( c , r ) ;
for ( int p = 0 ; p < nPrec ; p + + )
{
// loop on precincts
start = in_Renamed . Pos ;
// If packed packet headers are used, there is no need
// to check that there are bytes enough to read header
if ( pph )
{
pktDec . readPktHead ( l , r , c , p , cbI [ c ] [ r ] , nBytes ) ;
}
// If we are about to read outside of tile-part,
// skip to next tile-part
if ( start > lastByte & & curTilePart < firstPackOff [ t ] . Length - 1 )
{
curTilePart + + ;
in_Renamed . seek ( firstPackOff [ t ] [ curTilePart ] ) ;
lastByte = in_Renamed . Pos + tilePartLen [ t ] [ curTilePart ] - 1 - tilePartHeadLen [ t ] [ curTilePart ] ;
}
// Read SOP marker segment if necessary
status = pktDec . readSOPMarker ( nBytes , p , c , r ) ;
if ( status )
{
if ( printInfo )
{
}
return true ;
}
if ( ! pph )
{
status = pktDec . readPktHead ( l , r , c , p , cbI [ c ] [ r ] , nBytes ) ;
}
if ( status )
{
if ( printInfo )
{
}
return true ;
}
// Store packet's head length
hlen = in_Renamed . Pos - start ;
pktHL . Add ( ( System . Int32 ) hlen ) ;
// Reads packet's body
status = pktDec . readPktBody ( l , r , c , p , cbI [ c ] [ r ] , nBytes ) ;
plen = in_Renamed . Pos - start ;
if ( status )
{
if ( printInfo )
{
}
return true ;
}
} // end loop on precincts
} // end loop on components
} // end loop on resolution levels
} // end loop on layers
if ( printInfo )
{
}
return false ; // Decoding rate was not reached
}
/// <summary> Reads packets of the current tile according to the
/// resolution-layer-component-position progressiveness.
///
/// </summary>
/// <param name="lys">Index of the first layer for each component and resolution.
///
/// </param>
/// <param name="lye">Index of the last layer.
///
/// </param>
/// <param name="ress">Index of the first resolution level.
///
/// </param>
/// <param name="rese">Index of the last resolution level.
///
/// </param>
/// <param name="comps">Index of the first component.
///
/// </param>
/// <param name="compe">Index of the last component.
///
/// </param>
/// <returns> True if rate has been reached.
///
/// </returns>
private bool readResLyCompPos ( int [ ] [ ] lys , int lye , int ress , int rese , int comps , int compe )
{
int t = TileIdx ; // Current tile index
bool status = false ; // True if decoding rate is reached when
int lastByte = firstPackOff [ t ] [ curTilePart ] + tilePartLen [ t ] [ curTilePart ] - 1 - tilePartHeadLen [ t ] [ curTilePart ] ;
int minlys = 10000 ;
for ( int c = comps ; c < compe ; c + + )
{
//loop on components
// Check if this component exists
if ( c > = mdl . Length )
continue ;
for ( int r = ress ; r < rese ; r + + )
{
//loop on resolution levels
if ( r > mdl [ c ] )
continue ;
if ( lys [ c ] ! = null & & r < lys [ c ] . Length & & lys [ c ] [ r ] < minlys )
{
minlys = lys [ c ] [ r ] ;
}
}
}
int numLayers = ( ( System . Int32 ) decSpec . nls . getTileDef ( t ) ) ;
bool pph = false ;
if ( ( ( System . Boolean ) decSpec . pphs . getTileDef ( t ) ) )
{
pph = true ;
}
int nPrec = 1 ;
int start ;
int hlen , plen ;
for ( int r = ress ; r < rese ; r + + )
{
// loop on resolution levels
for ( int l = minlys ; l < lye ; l + + )
{
// loop on layers
for ( int c = comps ; c < compe ; c + + )
{
// loop on components
// Checks if component exists
if ( c > = mdl . Length )
continue ;
// Checks if resolution level exists
if ( r > mdl [ c ] )
continue ;
if ( r > = lys [ c ] . Length )
continue ;
// Checks if layer exists
if ( l < lys [ c ] [ r ] | | l > = numLayers )
continue ;
nPrec = pktDec . getNumPrecinct ( c , r ) ;
for ( int p = 0 ; p < nPrec ; p + + )
{
// loop on precincts
start = in_Renamed . Pos ;
// If packed packet headers are used, there is no need
// to check that there are bytes enough to read header
if ( pph )
{
pktDec . readPktHead ( l , r , c , p , cbI [ c ] [ r ] , nBytes ) ;
}
// If we are about to read outside of tile-part,
// skip to next tile-part
if ( start > lastByte & & curTilePart < firstPackOff [ t ] . Length - 1 )
{
curTilePart + + ;
in_Renamed . seek ( firstPackOff [ t ] [ curTilePart ] ) ;
lastByte = in_Renamed . Pos + tilePartLen [ t ] [ curTilePart ] - 1 - tilePartHeadLen [ t ] [ curTilePart ] ;
}
// Read SOP marker segment if necessary
status = pktDec . readSOPMarker ( nBytes , p , c , r ) ;
if ( status )
{
if ( printInfo )
{
}
return true ;
}
if ( ! pph )
{
status = pktDec . readPktHead ( l , r , c , p , cbI [ c ] [ r ] , nBytes ) ;
}
if ( status )
{
if ( printInfo )
{
}
// Output rate of EOF reached
return true ;
}
// Store packet's head length
hlen = in_Renamed . Pos - start ;
pktHL . Add ( ( System . Int32 ) hlen ) ;
// Reads packet's body
status = pktDec . readPktBody ( l , r , c , p , cbI [ c ] [ r ] , nBytes ) ;
plen = in_Renamed . Pos - start ;
if ( status )
{
if ( printInfo )
{
}
// Output rate or EOF reached
return true ;
}
} // end loop on precincts
} // end loop on components
} // end loop on layers
} // end loop on resolution levels
if ( printInfo )
{
}
return false ; // Decoding rate was not reached
}
/// <summary> Reads packets of the current tile according to the
/// resolution-position-component-layer progressiveness.
///
/// </summary>
/// <param name="lys">Index of the first layer for each component and resolution.
///
/// </param>
/// <param name="lye">Index of the last layer.
///
/// </param>
/// <param name="ress">Index of the first resolution level.
///
/// </param>
/// <param name="rese">Index of the last resolution level.
///
/// </param>
/// <param name="comps">Index of the first component.
///
/// </param>
/// <param name="compe">Index of the last component.
///
/// </param>
/// <returns> True if rate has been reached.
///
/// </returns>
private bool readResPosCompLy ( int [ ] [ ] lys , int lye , int ress , int rese , int comps , int compe )
{
// Computes current tile offset in the reference grid
Coord nTiles = getNumTiles ( null ) ;
Coord tileI = getTile ( null ) ;
int x0siz = hd . ImgULX ;
int y0siz = hd . ImgULY ;
int xsiz = x0siz + hd . ImgWidth ;
int ysiz = y0siz + hd . ImgHeight ;
int xt0siz = TilePartULX ;
int yt0siz = TilePartULY ;
int xtsiz = NomTileWidth ;
int ytsiz = NomTileHeight ;
int tx0 = ( tileI . x = = 0 ) ? x0siz : xt0siz + tileI . x * xtsiz ;
int ty0 = ( tileI . y = = 0 ) ? y0siz : yt0siz + tileI . y * ytsiz ;
int tx1 = ( tileI . x ! = nTiles . x - 1 ) ? xt0siz + ( tileI . x + 1 ) * xtsiz : xsiz ;
int ty1 = ( tileI . y ! = nTiles . y - 1 ) ? yt0siz + ( tileI . y + 1 ) * ytsiz : ysiz ;
// Get precinct information (number,distance between two consecutive
// precincts in the reference grid) in each component and resolution
// level
int t = TileIdx ; // Current tile index
PrecInfo prec ; // temporary variable
int p ; // Current precinct index
int gcd_x = 0 ; // Horiz. distance between 2 precincts in the ref. grid
int gcd_y = 0 ; // Vert. distance between 2 precincts in the ref. grid
int nPrec = 0 ; // Total number of found precincts
int [ ] [ ] nextPrec = new int [ compe ] [ ] ; // Next precinct index in each
// component and resolution level
int minlys = 100000 ; // minimum layer start index of each component
int minx = tx1 ; // Horiz. offset of the second precinct in the
// reference grid
int miny = ty1 ; // Vert. offset of the second precinct in the
// reference grid.
int maxx = tx0 ; // Max. horiz. offset of precincts in the ref. grid
int maxy = ty0 ; // Max. vert. offset of precincts in the ref. grid
//Coord numPrec;
for ( int c = comps ; c < compe ; c + + )
{
// components
for ( int r = ress ; r < rese ; r + + )
{
// resolution levels
if ( c > = mdl . Length )
continue ;
if ( r > mdl [ c ] )
continue ;
nextPrec [ c ] = new int [ mdl [ c ] + 1 ] ;
if ( lys [ c ] ! = null & & r < lys [ c ] . Length & & lys [ c ] [ r ] < minlys )
{
minlys = lys [ c ] [ r ] ;
}
p = pktDec . getNumPrecinct ( c , r ) - 1 ;
for ( ; p > = 0 ; p - - )
{
prec = pktDec . getPrecInfo ( c , r , p ) ;
if ( prec . rgulx ! = tx0 )
{
if ( prec . rgulx < minx )
minx = prec . rgulx ;
if ( prec . rgulx > maxx )
maxx = prec . rgulx ;
}
if ( prec . rguly ! = ty0 )
{
if ( prec . rguly < miny )
miny = prec . rguly ;
if ( prec . rguly > maxy )
maxy = prec . rguly ;
}
if ( nPrec = = 0 )
{
gcd_x = prec . rgw ;
gcd_y = prec . rgh ;
}
else
{
gcd_x = MathUtil . gcd ( gcd_x , prec . rgw ) ;
gcd_y = MathUtil . gcd ( gcd_y , prec . rgh ) ;
}
nPrec + + ;
} // precincts
} // resolution levels
} // components
if ( nPrec = = 0 )
{
throw new System . ApplicationException ( "Image cannot have no precinct" ) ;
}
int pyend = ( maxy - miny ) / gcd_y + 1 ;
int pxend = ( maxx - minx ) / gcd_x + 1 ;
int x , y ;
int hlen , plen ;
int start ;
bool status = false ;
int lastByte = firstPackOff [ t ] [ curTilePart ] + tilePartLen [ t ] [ curTilePart ] - 1 - tilePartHeadLen [ t ] [ curTilePart ] ;
int numLayers = ( ( System . Int32 ) decSpec . nls . getTileDef ( t ) ) ;
bool pph = false ;
if ( ( ( System . Boolean ) decSpec . pphs . getTileDef ( t ) ) )
{
pph = true ;
}
for ( int r = ress ; r < rese ; r + + )
{
// loop on resolution levels
y = ty0 ;
x = tx0 ;
for ( int py = 0 ; py < = pyend ; py + + )
{
// Vertical precincts
for ( int px = 0 ; px < = pxend ; px + + )
{
// Horiz. precincts
for ( int c = comps ; c < compe ; c + + )
{
// Components
if ( c > = mdl . Length )
continue ;
if ( r > mdl [ c ] )
continue ;
if ( nextPrec [ c ] [ r ] > = pktDec . getNumPrecinct ( c , r ) )
{
continue ;
}
prec = pktDec . getPrecInfo ( c , r , nextPrec [ c ] [ r ] ) ;
if ( ( prec . rgulx ! = x ) | | ( prec . rguly ! = y ) )
{
continue ;
}
for ( int l = minlys ; l < lye ; l + + )
{
// layers
if ( r > = lys [ c ] . Length )
continue ;
if ( l < lys [ c ] [ r ] | | l > = numLayers )
continue ;
start = in_Renamed . Pos ;
// If packed packet headers are used, there is no
// need to check that there are bytes enough to
// read header
if ( pph )
{
pktDec . readPktHead ( l , r , c , nextPrec [ c ] [ r ] , cbI [ c ] [ r ] , nBytes ) ;
}
// If we are about to read outside of tile-part,
// skip to next tile-part
if ( start > lastByte & & curTilePart < firstPackOff [ t ] . Length - 1 )
{
curTilePart + + ;
in_Renamed . seek ( firstPackOff [ t ] [ curTilePart ] ) ;
lastByte = in_Renamed . Pos + tilePartLen [ t ] [ curTilePart ] - 1 - tilePartHeadLen [ t ] [ curTilePart ] ;
}
// Read SOP marker segment if necessary
status = pktDec . readSOPMarker ( nBytes , nextPrec [ c ] [ r ] , c , r ) ;
if ( status )
{
if ( printInfo )
{
}
return true ;
}
if ( ! pph )
{
status = pktDec . readPktHead ( l , r , c , nextPrec [ c ] [ r ] , cbI [ c ] [ r ] , nBytes ) ;
}
if ( status )
{
if ( printInfo )
{
}
return true ;
}
// Store packet's head length
hlen = in_Renamed . Pos - start ;
pktHL . Add ( ( System . Int32 ) hlen ) ;
// Reads packet's body
status = pktDec . readPktBody ( l , r , c , nextPrec [ c ] [ r ] , cbI [ c ] [ r ] , nBytes ) ;
plen = in_Renamed . Pos - start ;
if ( status )
{
if ( printInfo )
{
}
return true ;
}
} // layers
nextPrec [ c ] [ r ] + + ;
} // Components
if ( px ! = pxend )
{
x = minx + px * gcd_x ;
}
else
{
x = tx0 ;
}
} // Horizontal precincts
if ( py ! = pyend )
{
y = miny + py * gcd_y ;
}
else
{
y = ty0 ;
}
} // Vertical precincts
} // end loop on resolution levels
if ( printInfo )
{
}
return false ; // Decoding rate was not reached
}
/// <summary> Reads packets of the current tile according to the
/// position-component-resolution-layer progressiveness.
///
/// </summary>
/// <param name="lys">Index of the first layer for each component and resolution.
///
/// </param>
/// <param name="lye">Index of the last layer.
///
/// </param>
/// <param name="ress">Index of the first resolution level.
///
/// </param>
/// <param name="rese">Index of the last resolution level.
///
/// </param>
/// <param name="comps">Index of the first component.
///
/// </param>
/// <param name="compe">Index of the last component.
///
/// </param>
/// <returns> True if rate has been reached.
///
/// </returns>
private bool readPosCompResLy ( int [ ] [ ] lys , int lye , int ress , int rese , int comps , int compe )
{
Coord nTiles = getNumTiles ( null ) ;
Coord tileI = getTile ( null ) ;
int x0siz = hd . ImgULX ;
int y0siz = hd . ImgULY ;
int xsiz = x0siz + hd . ImgWidth ;
int ysiz = y0siz + hd . ImgHeight ;
int xt0siz = TilePartULX ;
int yt0siz = TilePartULY ;
int xtsiz = NomTileWidth ;
int ytsiz = NomTileHeight ;
int tx0 = ( tileI . x = = 0 ) ? x0siz : xt0siz + tileI . x * xtsiz ;
int ty0 = ( tileI . y = = 0 ) ? y0siz : yt0siz + tileI . y * ytsiz ;
int tx1 = ( tileI . x ! = nTiles . x - 1 ) ? xt0siz + ( tileI . x + 1 ) * xtsiz : xsiz ;
int ty1 = ( tileI . y ! = nTiles . y - 1 ) ? yt0siz + ( tileI . y + 1 ) * ytsiz : ysiz ;
// Get precinct information (number,distance between two consecutive
// precincts in the reference grid) in each component and resolution
// level
int t = TileIdx ; // Current tile index
PrecInfo prec ; // temporary variable
int p ; // Current precinct index
int gcd_x = 0 ; // Horiz. distance between 2 precincts in the ref. grid
int gcd_y = 0 ; // Vert. distance between 2 precincts in the ref. grid
int nPrec = 0 ; // Total number of found precincts
int [ ] [ ] nextPrec = new int [ compe ] [ ] ; // Next precinct index in each
// component and resolution level
int minlys = 100000 ; // minimum layer start index of each component
int minx = tx1 ; // Horiz. offset of the second precinct in the
// reference grid
int miny = ty1 ; // Vert. offset of the second precinct in the
// reference grid.
int maxx = tx0 ; // Max. horiz. offset of precincts in the ref. grid
int maxy = ty0 ; // Max. vert. offset of precincts in the ref. grid
//Coord numPrec;
for ( int c = comps ; c < compe ; c + + )
{
// components
for ( int r = ress ; r < rese ; r + + )
{
// resolution levels
if ( c > = mdl . Length )
continue ;
if ( r > mdl [ c ] )
continue ;
nextPrec [ c ] = new int [ mdl [ c ] + 1 ] ;
if ( lys [ c ] ! = null & & r < lys [ c ] . Length & & lys [ c ] [ r ] < minlys )
{
minlys = lys [ c ] [ r ] ;
}
p = pktDec . getNumPrecinct ( c , r ) - 1 ;
for ( ; p > = 0 ; p - - )
{
prec = pktDec . getPrecInfo ( c , r , p ) ;
if ( prec . rgulx ! = tx0 )
{
if ( prec . rgulx < minx )
minx = prec . rgulx ;
if ( prec . rgulx > maxx )
maxx = prec . rgulx ;
}
if ( prec . rguly ! = ty0 )
{
if ( prec . rguly < miny )
miny = prec . rguly ;
if ( prec . rguly > maxy )
maxy = prec . rguly ;
}
if ( nPrec = = 0 )
{
gcd_x = prec . rgw ;
gcd_y = prec . rgh ;
}
else
{
gcd_x = MathUtil . gcd ( gcd_x , prec . rgw ) ;
gcd_y = MathUtil . gcd ( gcd_y , prec . rgh ) ;
}
nPrec + + ;
} // precincts
} // resolution levels
} // components
if ( nPrec = = 0 )
{
throw new System . ApplicationException ( "Image cannot have no precinct" ) ;
}
int pyend = ( maxy - miny ) / gcd_y + 1 ;
int pxend = ( maxx - minx ) / gcd_x + 1 ;
int hlen , plen ;
int start ;
bool status = false ;
int lastByte = firstPackOff [ t ] [ curTilePart ] + tilePartLen [ t ] [ curTilePart ] - 1 - tilePartHeadLen [ t ] [ curTilePart ] ;
int numLayers = ( ( System . Int32 ) decSpec . nls . getTileDef ( t ) ) ;
bool pph = false ;
if ( ( ( System . Boolean ) decSpec . pphs . getTileDef ( t ) ) )
{
pph = true ;
}
int y = ty0 ;
int x = tx0 ;
for ( int py = 0 ; py < = pyend ; py + + )
{
// Vertical precincts
for ( int px = 0 ; px < = pxend ; px + + )
{
// Horiz. precincts
for ( int c = comps ; c < compe ; c + + )
{
// Components
if ( c > = mdl . Length )
continue ;
for ( int r = ress ; r < rese ; r + + )
{
// Resolution levels
if ( r > mdl [ c ] )
continue ;
if ( nextPrec [ c ] [ r ] > = pktDec . getNumPrecinct ( c , r ) )
{
continue ;
}
prec = pktDec . getPrecInfo ( c , r , nextPrec [ c ] [ r ] ) ;
if ( ( prec . rgulx ! = x ) | | ( prec . rguly ! = y ) )
{
continue ;
}
for ( int l = minlys ; l < lye ; l + + )
{
// Layers
if ( r > = lys [ c ] . Length )
continue ;
if ( l < lys [ c ] [ r ] | | l > = numLayers )
continue ;
start = in_Renamed . Pos ;
// If packed packet headers are used, there is no
// need to check that there are bytes enough to
// read header
if ( pph )
{
pktDec . readPktHead ( l , r , c , nextPrec [ c ] [ r ] , cbI [ c ] [ r ] , nBytes ) ;
}
// If we are about to read outside of tile-part,
// skip to next tile-part
if ( start > lastByte & & curTilePart < firstPackOff [ t ] . Length - 1 )
{
curTilePart + + ;
in_Renamed . seek ( firstPackOff [ t ] [ curTilePart ] ) ;
lastByte = in_Renamed . Pos + tilePartLen [ t ] [ curTilePart ] - 1 - tilePartHeadLen [ t ] [ curTilePart ] ;
}
// Read SOP marker segment if necessary
status = pktDec . readSOPMarker ( nBytes , nextPrec [ c ] [ r ] , c , r ) ;
if ( status )
{
if ( printInfo )
{
}
return true ;
}
if ( ! pph )
{
status = pktDec . readPktHead ( l , r , c , nextPrec [ c ] [ r ] , cbI [ c ] [ r ] , nBytes ) ;
}
if ( status )
{
if ( printInfo )
{
}
return true ;
}
// Store packet's head length
hlen = in_Renamed . Pos - start ;
pktHL . Add ( ( System . Int32 ) hlen ) ;
// Reads packet's body
status = pktDec . readPktBody ( l , r , c , nextPrec [ c ] [ r ] , cbI [ c ] [ r ] , nBytes ) ;
plen = in_Renamed . Pos - start ;
if ( status )
{
if ( printInfo )
{
}
return true ;
}
} // layers
nextPrec [ c ] [ r ] + + ;
} // Resolution levels
} // Components
if ( px ! = pxend )
{
x = minx + px * gcd_x ;
}
else
{
x = tx0 ;
}
} // Horizontal precincts
if ( py ! = pyend )
{
y = miny + py * gcd_y ;
}
else
{
y = ty0 ;
}
} // Vertical precincts
if ( printInfo )
{
}
return false ; // Decoding rate was not reached
}
/// <summary> Reads packets of the current tile according to the
/// component-position-resolution-layer progressiveness.
///
/// </summary>
/// <param name="lys">Index of the first layer for each component and resolution.
///
/// </param>
/// <param name="lye">Index of the last layer.
///
/// </param>
/// <param name="ress">Index of the first resolution level.
///
/// </param>
/// <param name="rese">Index of the last resolution level.
///
/// </param>
/// <param name="comps">Index of the first component.
///
/// </param>
/// <param name="compe">Index of the last component.
///
/// </param>
/// <returns> True if rate has been reached.
///
/// </returns>
private bool readCompPosResLy ( int [ ] [ ] lys , int lye , int ress , int rese , int comps , int compe )
{
Coord nTiles = getNumTiles ( null ) ;
Coord tileI = getTile ( null ) ;
int x0siz = hd . ImgULX ;
int y0siz = hd . ImgULY ;
int xsiz = x0siz + hd . ImgWidth ;
int ysiz = y0siz + hd . ImgHeight ;
int xt0siz = TilePartULX ;
int yt0siz = TilePartULY ;
int xtsiz = NomTileWidth ;
int ytsiz = NomTileHeight ;
int tx0 = ( tileI . x = = 0 ) ? x0siz : xt0siz + tileI . x * xtsiz ;
int ty0 = ( tileI . y = = 0 ) ? y0siz : yt0siz + tileI . y * ytsiz ;
int tx1 = ( tileI . x ! = nTiles . x - 1 ) ? xt0siz + ( tileI . x + 1 ) * xtsiz : xsiz ;
int ty1 = ( tileI . y ! = nTiles . y - 1 ) ? yt0siz + ( tileI . y + 1 ) * ytsiz : ysiz ;
// Get precinct information (number,distance between two consecutive
// precincts in the reference grid) in each component and resolution
// level
int t = TileIdx ; // Current tile index
PrecInfo prec ; // temporary variable
int p ; // Current precinct index
int gcd_x = 0 ; // Horiz. distance between 2 precincts in the ref. grid
int gcd_y = 0 ; // Vert. distance between 2 precincts in the ref. grid
int nPrec = 0 ; // Total number of found precincts
int [ ] [ ] nextPrec = new int [ compe ] [ ] ; // Next precinct index in each
// component and resolution level
int minlys = 100000 ; // minimum layer start index of each component
int minx = tx1 ; // Horiz. offset of the second precinct in the
// reference grid
int miny = ty1 ; // Vert. offset of the second precinct in the
// reference grid.
int maxx = tx0 ; // Max. horiz. offset of precincts in the ref. grid
int maxy = ty0 ; // Max. vert. offset of precincts in the ref. grid
//Coord numPrec;
for ( int c = comps ; c < compe ; c + + )
{
// components
for ( int r = ress ; r < rese ; r + + )
{
// resolution levels
if ( c > = mdl . Length )
continue ;
if ( r > mdl [ c ] )
continue ;
nextPrec [ c ] = new int [ mdl [ c ] + 1 ] ;
if ( lys [ c ] ! = null & & r < lys [ c ] . Length & & lys [ c ] [ r ] < minlys )
{
minlys = lys [ c ] [ r ] ;
}
p = pktDec . getNumPrecinct ( c , r ) - 1 ;
for ( ; p > = 0 ; p - - )
{
prec = pktDec . getPrecInfo ( c , r , p ) ;
if ( prec . rgulx ! = tx0 )
{
if ( prec . rgulx < minx )
minx = prec . rgulx ;
if ( prec . rgulx > maxx )
maxx = prec . rgulx ;
}
if ( prec . rguly ! = ty0 )
{
if ( prec . rguly < miny )
miny = prec . rguly ;
if ( prec . rguly > maxy )
maxy = prec . rguly ;
}
if ( nPrec = = 0 )
{
gcd_x = prec . rgw ;
gcd_y = prec . rgh ;
}
else
{
gcd_x = MathUtil . gcd ( gcd_x , prec . rgw ) ;
gcd_y = MathUtil . gcd ( gcd_y , prec . rgh ) ;
}
nPrec + + ;
} // precincts
} // resolution levels
} // components
if ( nPrec = = 0 )
{
throw new System . ApplicationException ( "Image cannot have no precinct" ) ;
}
int pyend = ( maxy - miny ) / gcd_y + 1 ;
int pxend = ( maxx - minx ) / gcd_x + 1 ;
int hlen , plen ;
int start ;
bool status = false ;
int lastByte = firstPackOff [ t ] [ curTilePart ] + tilePartLen [ t ] [ curTilePart ] - 1 - tilePartHeadLen [ t ] [ curTilePart ] ;
int numLayers = ( ( System . Int32 ) decSpec . nls . getTileDef ( t ) ) ;
bool pph = false ;
if ( ( ( System . Boolean ) decSpec . pphs . getTileDef ( t ) ) )
{
pph = true ;
}
int x , y ;
for ( int c = comps ; c < compe ; c + + )
{
// components
if ( c > = mdl . Length )
continue ;
y = ty0 ;
x = tx0 ;
for ( int py = 0 ; py < = pyend ; py + + )
{
// Vertical precincts
for ( int px = 0 ; px < = pxend ; px + + )
{
// Horiz. precincts
for ( int r = ress ; r < rese ; r + + )
{
// Resolution levels
if ( r > mdl [ c ] )
continue ;
if ( nextPrec [ c ] [ r ] > = pktDec . getNumPrecinct ( c , r ) )
{
continue ;
}
prec = pktDec . getPrecInfo ( c , r , nextPrec [ c ] [ r ] ) ;
if ( ( prec . rgulx ! = x ) | | ( prec . rguly ! = y ) )
{
continue ;
}
for ( int l = minlys ; l < lye ; l + + )
{
// Layers
if ( r > = lys [ c ] . Length )
continue ;
if ( l < lys [ c ] [ r ] )
continue ;
start = in_Renamed . Pos ;
// If packed packet headers are used, there is no
// need to check that there are bytes enough to
// read header
if ( pph )
{
pktDec . readPktHead ( l , r , c , nextPrec [ c ] [ r ] , cbI [ c ] [ r ] , nBytes ) ;
}
// If we are about to read outside of tile-part,
// skip to next tile-part
if ( start > lastByte & & curTilePart < firstPackOff [ t ] . Length - 1 )
{
curTilePart + + ;
in_Renamed . seek ( firstPackOff [ t ] [ curTilePart ] ) ;
lastByte = in_Renamed . Pos + tilePartLen [ t ] [ curTilePart ] - 1 - tilePartHeadLen [ t ] [ curTilePart ] ;
}
// Read SOP marker segment if necessary
status = pktDec . readSOPMarker ( nBytes , nextPrec [ c ] [ r ] , c , r ) ;
if ( status )
{
if ( printInfo )
{
}
return true ;
}
if ( ! pph )
{
status = pktDec . readPktHead ( l , r , c , nextPrec [ c ] [ r ] , cbI [ c ] [ r ] , nBytes ) ;
}
if ( status )
{
if ( printInfo )
{
}
return true ;
}
// Store packet's head length
hlen = in_Renamed . Pos - start ;
pktHL . Add ( ( System . Int32 ) hlen ) ;
// Reads packet's body
status = pktDec . readPktBody ( l , r , c , nextPrec [ c ] [ r ] , cbI [ c ] [ r ] , nBytes ) ;
plen = in_Renamed . Pos - start ;
if ( status )
{
if ( printInfo )
{
}
return true ;
}
} // layers
nextPrec [ c ] [ r ] + + ;
} // Resolution levels
if ( px ! = pxend )
{
x = minx + px * gcd_x ;
}
else
{
x = tx0 ;
}
} // Horizontal precincts
if ( py ! = pyend )
{
y = miny + py * gcd_y ;
}
else
{
y = ty0 ;
}
} // Vertical precincts
} // components
if ( printInfo )
{
}
return false ; // Decoding rate was not reached
}
/// <summary> Finish initialization of members for specified tile, reads packets head
/// of each tile and keeps location of each code-block's codewords. The
/// last 2 tasks are done by calling specific methods of PktDecoder.
///
/// <p>Then, if a parsing output rate is defined, it keeps information of
/// first layers only. This operation simulates a creation of a
/// layer-resolution-component progressive bit-stream which will be next
/// truncated and decoded.</p>
///
/// </summary>
/// <param name="t">Tile index
///
/// </param>
/// <seealso cref="PktDecoder">
///
/// </seealso>
private void readTilePkts ( int t )
{
pktHL = System . Collections . ArrayList . Synchronized ( new System . Collections . ArrayList ( 10 ) ) ;
2009-10-01 00:25:27 +00:00
layerStarts = new System . Collections . Generic . List < int > ( 5 ) ;
2009-09-30 23:50:03 +00:00
// Number of layers
int nl = ( ( System . Int32 ) decSpec . nls . getTileDef ( t ) ) ;
// If packed packet headers was used, get the packet headers for this
// tile
if ( ( ( System . Boolean ) decSpec . pphs . getTileDef ( t ) ) )
{
// Gets packed headers as separate input stream
System . IO . MemoryStream pphbais = hd . getPackedPktHead ( t ) ;
// Restarts PktDecoder instance
cbI = pktDec . restart ( this . nc , mdl , nl , cbI , true , pphbais ) ;
}
else
{
// Restarts PktDecoder instance
cbI = pktDec . restart ( this . nc , mdl , nl , cbI , false , null ) ;
}
// Reads packets of the tile according to the progression order
int [ ] [ ] pocSpec = ( ( int [ ] [ ] ) decSpec . pcs . getTileDef ( t ) ) ;
int nChg = ( pocSpec = = null ) ? 1 : pocSpec . Length ;
// Create an array containing information about changes (progression
// order type, layers index start, layer index end, resolution level
// start, resolution level end, component index start, component index
// end). There is one row per progresion order
int [ ] [ ] change = new int [ nChg ] [ ] ;
for ( int i = 0 ; i < nChg ; i + + )
{
change [ i ] = new int [ 6 ] ;
}
int idx = 0 ; // Index of the current progression order
change [ 0 ] [ 1 ] = 0 ; // layer start
if ( pocSpec = = null )
{
change [ idx ] [ 0 ] = ( ( System . Int32 ) decSpec . pos . getTileDef ( t ) ) ;
// Progression type found in COx marker segments
change [ idx ] [ 1 ] = nl ; // Layer index end
change [ idx ] [ 2 ] = 0 ; // resolution level start
change [ idx ] [ 3 ] = decSpec . dls . getMaxInTile ( t ) + 1 ; // res. level end
change [ idx ] [ 4 ] = 0 ; // Component index start
change [ idx ] [ 5 ] = this . nc ; // Component index end
}
else
{
for ( idx = 0 ; idx < nChg ; idx + + )
{
change [ idx ] [ 0 ] = pocSpec [ idx ] [ 5 ] ;
change [ idx ] [ 1 ] = pocSpec [ idx ] [ 2 ] ; // layer end
change [ idx ] [ 2 ] = pocSpec [ idx ] [ 0 ] ; // res. lev. start
change [ idx ] [ 3 ] = pocSpec [ idx ] [ 3 ] ; // res. lev. end
change [ idx ] [ 4 ] = pocSpec [ idx ] [ 1 ] ; // Comp. index start
change [ idx ] [ 5 ] = pocSpec [ idx ] [ 4 ] ; // Comp. index end
}
}
// Seeks to the first packet of the first tile-part
try
{
// If in truncation mode, the first tile-part may be beyond the
// target decoding rate. In this case, the offset of the first
// packet is not defined.
if ( isTruncMode & & firstPackOff = = null | | firstPackOff [ t ] = = null )
{
return ;
}
in_Renamed . seek ( firstPackOff [ t ] [ 0 ] ) ;
}
2009-10-01 00:19:01 +00:00
catch ( System . IO . EndOfStreamException )
2009-09-30 23:50:03 +00:00
{
FacilityManager . getMsgLogger ( ) . printmsg ( CSJ2K . j2k . util . MsgLogger_Fields . WARNING , "Codestream truncated in tile " + t ) ;
return ;
}
curTilePart = 0 ;
// Start and end indexes for layers, resolution levels and components.
int lye , ress , rese , comps , compe ;
bool status = false ;
int nb = nBytes [ t ] ;
int [ ] [ ] lys = new int [ this . nc ] [ ] ;
for ( int c = 0 ; c < this . nc ; c + + )
{
lys [ c ] = new int [ ( ( System . Int32 ) decSpec . dls . getTileCompVal ( t , c ) ) + 1 ] ;
}
try
{
for ( int chg = 0 ; chg < nChg ; chg + + )
{
lye = change [ chg ] [ 1 ] ;
ress = change [ chg ] [ 2 ] ;
rese = change [ chg ] [ 3 ] ;
comps = change [ chg ] [ 4 ] ;
compe = change [ chg ] [ 5 ] ;
switch ( change [ chg ] [ 0 ] )
{
case CSJ2K . j2k . codestream . ProgressionType . LY_RES_COMP_POS_PROG :
status = readLyResCompPos ( lys , lye , ress , rese , comps , compe ) ;
break ;
case CSJ2K . j2k . codestream . ProgressionType . RES_LY_COMP_POS_PROG :
status = readResLyCompPos ( lys , lye , ress , rese , comps , compe ) ;
break ;
case CSJ2K . j2k . codestream . ProgressionType . RES_POS_COMP_LY_PROG :
status = readResPosCompLy ( lys , lye , ress , rese , comps , compe ) ;
break ;
case CSJ2K . j2k . codestream . ProgressionType . POS_COMP_RES_LY_PROG :
status = readPosCompResLy ( lys , lye , ress , rese , comps , compe ) ;
break ;
case CSJ2K . j2k . codestream . ProgressionType . COMP_POS_RES_LY_PROG :
status = readCompPosResLy ( lys , lye , ress , rese , comps , compe ) ;
break ;
default :
throw new System . ArgumentException ( "Not recognized " + "progression type" ) ;
}
// Update next first layer index
for ( int c = comps ; c < compe ; c + + )
{
if ( c > = lys . Length )
continue ;
for ( int r = ress ; r < rese ; r + + )
{
if ( r > = lys [ c ] . Length )
continue ;
lys [ c ] [ r ] = lye ;
}
}
if ( status | | usePOCQuit )
{
break ;
}
}
}
catch ( System . IO . EndOfStreamException e )
{
// Should never happen. Truncated codestream are normally found by
// the class constructor
throw e ;
}
// In truncation mode, update the number of read bytes
if ( isTruncMode )
{
anbytes + = nb - nBytes [ t ] ;
// If truncation rate is reached
if ( status )
{
nBytes [ t ] = 0 ;
}
}
else if ( nBytes [ t ] < ( totTileLen [ t ] - totTileHeadLen [ t ] ) )
{
// In parsing mode, if there is not enough rate to entirely read the
// tile. Then, parses the bit stream so as to create a virtual
// layer-resolution-component progressive bit stream that will be
// truncated and decoded afterwards.
CBlkInfo cb ;
// Systematicaly reject all remaining code-blocks if one
// code-block, at least, is refused.
bool reject ;
// Stop reading any data from the bit stream
bool stopCount = false ;
// Length of each packet's head (in an array)
int [ ] pktHeadLen = new int [ pktHL . Count ] ;
for ( int i = pktHL . Count - 1 ; i > = 0 ; i - - )
{
pktHeadLen [ i ] = ( ( System . Int32 ) pktHL [ i ] ) ;
}
// Parse each code-block, layer per layer until nBytes[t] is
// reached
reject = false ;
for ( int l = 0 ; l < nl ; l + + )
{
// layers
if ( cbI = = null )
continue ;
int nc = cbI . Length ;
int mres = 0 ;
for ( int c = 0 ; c < nc ; c + + )
{
if ( cbI [ c ] ! = null & & cbI [ c ] . Length > mres )
mres = cbI [ c ] . Length ;
}
for ( int r = 0 ; r < mres ; r + + )
{
// resolutions
int msub = 0 ;
for ( int c = 0 ; c < nc ; c + + )
{
if ( cbI [ c ] ! = null & & cbI [ c ] [ r ] ! = null & & cbI [ c ] [ r ] . Length > msub )
msub = cbI [ c ] [ r ] . Length ;
}
for ( int s = 0 ; s < msub ; s + + )
{
// subbands
// Only LL subband resolution level 0
if ( r = = 0 & & s ! = 0 )
{
continue ;
}
else if ( r ! = 0 & & s = = 0 )
{
// No LL subband in resolution level > 0
continue ;
}
int mnby = 0 ;
for ( int c = 0 ; c < nc ; c + + )
{
if ( cbI [ c ] ! = null & & cbI [ c ] [ r ] ! = null & & cbI [ c ] [ r ] [ s ] ! = null & & cbI [ c ] [ r ] [ s ] . Length > mnby )
mnby = cbI [ c ] [ r ] [ s ] . Length ;
}
for ( int m = 0 ; m < mnby ; m + + )
{
int mnbx = 0 ;
for ( int c = 0 ; c < nc ; c + + )
{
if ( cbI [ c ] ! = null & & cbI [ c ] [ r ] ! = null & & cbI [ c ] [ r ] [ s ] ! = null & & cbI [ c ] [ r ] [ s ] [ m ] ! = null & & cbI [ c ] [ r ] [ s ] [ m ] . Length > mnbx )
mnbx = cbI [ c ] [ r ] [ s ] [ m ] . Length ;
}
for ( int n = 0 ; n < mnbx ; n + + )
{
for ( int c = 0 ; c < nc ; c + + )
{
if ( cbI [ c ] = = null | | cbI [ c ] [ r ] = = null | | cbI [ c ] [ r ] [ s ] = = null | | cbI [ c ] [ r ] [ s ] [ m ] = = null | | cbI [ c ] [ r ] [ s ] [ m ] [ n ] = = null )
{
continue ;
}
cb = cbI [ c ] [ r ] [ s ] [ m ] [ n ] ;
// If no code-block has been refused until
// now
if ( ! reject )
{
// Rate is to low to allow reading of
// packet's head
if ( nBytes [ t ] < pktHeadLen [ cb . pktIdx [ l ] ] )
{
// Stop parsing
stopCount = true ;
// Reject all next
// code-blocks
reject = true ;
}
else
{
// Rate is enough to read packet's
// head
if ( ! stopCount )
{
//If parsing was not stopped
//Takes into account packet's
//head length
nBytes [ t ] - = pktHeadLen [ cb . pktIdx [ l ] ] ;
anbytes + = pktHeadLen [ cb . pktIdx [ l ] ] ;
// Set packet's head length to
// 0, so that it won't be
// taken into account next
// time
pktHeadLen [ cb . pktIdx [ l ] ] = 0 ;
}
}
}
// Code-block has no data in this layer
if ( cb . len [ l ] = = 0 )
{
continue ;
}
// Accepts code-block if length is enough,
// if this code-block was not refused in a
// previous layer and if no code-block was
// refused in current component
if ( cb . len [ l ] < nBytes [ t ] & & ! reject )
{
nBytes [ t ] - = cb . len [ l ] ;
anbytes + = cb . len [ l ] ;
}
else
{
// Refuses code-block
// Forgets code-block's data
cb . len [ l ] = cb . off [ l ] = cb . ntp [ l ] = 0 ;
// Refuses all other code-block in
// current and next component
reject = true ;
}
} // End loop on components
} // End loop on horiz. code-blocks
} // End loop on vert. code-blocks
} // End loop on subbands
} // End loop on resolutions
} // End loop on layers
}
else
{
// No parsing for this tile, adds tile's body to the total
// number of read bytes.
anbytes + = totTileLen [ t ] - totTileHeadLen [ t ] ;
if ( t < getNumTiles ( ) - 1 )
{
nBytes [ t + 1 ] + = nBytes [ t ] - ( totTileLen [ t ] - totTileHeadLen [ t ] ) ;
}
}
}
/// <summary> Changes the current tile, given the new indexes. An
/// IllegalArgumentException is thrown if the indexes do not correspond to
/// a valid tile.
///
/// </summary>
/// <param name="x">The horizontal indexes the tile.
///
/// </param>
/// <param name="y">The vertical indexes of the new tile.
///
/// </param>
public override void setTile ( int x , int y )
{
int i ; // counter
// Check validity of tile indexes
if ( x < 0 | | y < 0 | | x > = ntX | | y > = ntY )
{
throw new System . ArgumentException ( ) ;
}
int t = ( y * ntX + x ) ;
// Reset number of read bytes if needed
if ( t = = 0 )
{
anbytes = headLen ;
if ( ! isTruncMode )
{
anbytes + = 2 ;
}
// Restore values of nBytes
for ( int tIdx = 0 ; tIdx < nt ; tIdx + + )
{
nBytes [ tIdx ] = baknBytes [ tIdx ] ;
}
}
// Set the new current tile
ctX = x ;
ctY = y ;
// Calculate tile relative points
int ctox = ( x = = 0 ) ? ax : px + x * ntW ;
int ctoy = ( y = = 0 ) ? ay : py + y * ntH ;
for ( i = nc - 1 ; i > = 0 ; i - - )
{
culx [ i ] = ( ctox + hd . getCompSubsX ( i ) - 1 ) / hd . getCompSubsX ( i ) ;
culy [ i ] = ( ctoy + hd . getCompSubsY ( i ) - 1 ) / hd . getCompSubsY ( i ) ;
offX [ i ] = ( px + x * ntW + hd . getCompSubsX ( i ) - 1 ) / hd . getCompSubsX ( i ) ;
offY [ i ] = ( py + y * ntH + hd . getCompSubsY ( i ) - 1 ) / hd . getCompSubsY ( i ) ;
}
// Initialize subband tree and number of resolution levels
subbTrees = new SubbandSyn [ nc ] ;
mdl = new int [ nc ] ;
derived = new bool [ nc ] ;
params_Renamed = new StdDequantizerParams [ nc ] ;
gb = new int [ nc ] ;
for ( int c = 0 ; c < nc ; c + + )
{
derived [ c ] = decSpec . qts . isDerived ( t , c ) ;
params_Renamed [ c ] = ( StdDequantizerParams ) decSpec . qsss . getTileCompVal ( t , c ) ;
gb [ c ] = ( ( System . Int32 ) decSpec . gbs . getTileCompVal ( t , c ) ) ;
mdl [ c ] = ( ( System . Int32 ) decSpec . dls . getTileCompVal ( t , c ) ) ;
subbTrees [ c ] = new SubbandSyn ( getTileCompWidth ( t , c , mdl [ c ] ) , getTileCompHeight ( t , c , mdl [ c ] ) , getResULX ( c , mdl [ c ] ) , getResULY ( c , mdl [ c ] ) , mdl [ c ] , decSpec . wfs . getHFilters ( t , c ) , decSpec . wfs . getVFilters ( t , c ) ) ;
initSubbandsFields ( c , subbTrees [ c ] ) ;
}
// Read tile's packets
try
{
readTilePkts ( t ) ;
}
catch ( System . IO . IOException e )
{
SupportClass . WriteStackTrace ( e , Console . Error ) ;
2010-08-06 03:11:08 +00:00
throw new System . ApplicationException ( "IO Error when reading tile " + x + " x " + y ) ;
2009-09-30 23:50:03 +00:00
}
}
/// <summary> Advances to the next tile, in standard scan-line order (by rows then
/// columns). A NoNextElementException is thrown if the current tile is the
/// last one (i.e. there is no next tile).
///
/// </summary>
public override void nextTile ( )
{
if ( ctX = = ntX - 1 & & ctY = = ntY - 1 )
{
// Already at last tile
throw new NoNextElementException ( ) ;
}
else if ( ctX < ntX - 1 )
{
// If not at end of current tile line
setTile ( ctX + 1 , ctY ) ;
}
else
{
// Go to first tile at next line
setTile ( 0 , ctY + 1 ) ;
}
}
/// <summary> Returns the specified coded code-block, for the specified component, in
/// the current tile. The first layer to return is indicated by 'fl'. The
/// number of layers that is returned depends on 'nl' and the amount of
/// available data.
///
/// <p>The argument 'fl' is to be used by subsequent calls to this method
/// for the same code-block. In this way supplemental data can be retrieved
/// at a later time. The fact that data from more than one layer can be
/// returned means that several packets from the same code-block, of the
/// same component, and the same tile, have been concatenated.</p>
///
/// <p>The returned compressed code-block can have its progressive
/// attribute set. If this attribute is set it means that more data can be
/// obtained by subsequent calls to this method (subject to transmission
/// delays, etc). If the progressive attribute is not set it means that the
/// returned data is all the data that can be obtained for the specified
/// code-block.</p>
///
/// <p>The compressed code-block is uniquely specified by the current tile,
/// the component (identified by 'c'), the subband (indentified by 'sb')
/// and the code-block vertical and horizontal indexes 'n' and 'm'.</p>
///
/// <p>The 'ulx' and 'uly' members of the returned 'DecLyrdCBlk' object
/// contain the coordinates of the top-left corner of the block, with
/// respect to the tile, not the subband.</p>
///
/// </summary>
/// <param name="c">The index of the component, from 0 to N-1.
///
/// </param>
/// <param name="m">The vertical index of the code-block to return, in the
/// specified subband.
///
/// </param>
/// <param name="n">The horizontal index of the code-block to return, in the
/// specified subband.
///
/// </param>
/// <param name="sb">The subband in whic the requested code-block is.
///
/// </param>
/// <param name="fl">The first layer to return.
///
/// </param>
/// <param name="nl">The number of layers to return, if negative all available
/// layers are returned, starting at 'fl'.
///
/// </param>
/// <param name="ccb">If not null this object is used to return the compressed
/// code-block. If null a new object is created and returned. If the data
/// array in ccb is not null then it can be reused to return the compressed
/// data.
///
/// </param>
/// <returns> The compressed code-block, with a certain number of layers
/// determined by the available data and 'nl'.
///
/// </returns>
public override DecLyrdCBlk getCodeBlock ( int c , int m , int n , SubbandSyn sb , int fl , int nl , DecLyrdCBlk ccb )
{
int t = TileIdx ;
CBlkInfo rcb ; // requested code-block
int r = sb . resLvl ; // Resolution level
int s = sb . sbandIdx ; // Subband index
int tpidx ;
int passtype ;
// Number of layers
int numLayers = ( ( System . Int32 ) decSpec . nls . getTileDef ( t ) ) ;
int options = ( ( System . Int32 ) decSpec . ecopts . getTileCompVal ( t , c ) ) ;
if ( nl < 0 )
{
nl = numLayers - fl + 1 ;
}
// If the l quit condition is used, Make sure that no layer
// after lquit is returned
if ( lQuit ! = - 1 & & fl + nl > lQuit )
{
nl = lQuit - fl ;
}
// Check validity of resquested resolution level (according to the
// "-res" option).
int maxdl = getSynSubbandTree ( t , c ) . resLvl ;
if ( r > targetRes + maxdl - decSpec . dls . Min )
{
throw new System . ApplicationException ( "JJ2000 error: requesting a code-block " + "disallowed by the '-res' option." ) ;
}
// Check validity of all the arguments
try
{
rcb = cbI [ c ] [ r ] [ s ] [ m ] [ n ] ;
if ( fl < 1 | | fl > numLayers | | fl + nl - 1 > numLayers )
{
throw new System . ArgumentException ( ) ;
}
}
2009-10-01 00:19:01 +00:00
catch ( System . IndexOutOfRangeException )
2009-09-30 23:50:03 +00:00
{
throw new System . ArgumentException ( "Code-block (t:" + t + ", c:" + c + ", r:" + r + ", s:" + s + ", " + m + "x" + ( + n ) + ") not found in codestream" ) ;
}
2009-10-01 00:19:01 +00:00
catch ( System . NullReferenceException )
2009-09-30 23:50:03 +00:00
{
throw new System . ArgumentException ( "Code-block (t:" + t + ", c:" + c + ", r:" + r + ", s:" + s + ", " + m + "x" + n + ") not found in bit stream" ) ;
}
// Create DecLyrdCBlk object if necessary
if ( ccb = = null )
{
ccb = new DecLyrdCBlk ( ) ;
}
ccb . m = m ;
ccb . n = n ;
ccb . nl = 0 ;
ccb . dl = 0 ;
ccb . nTrunc = 0 ;
if ( rcb = = null )
{
// This code-block was skipped when reading. Returns no data
ccb . skipMSBP = 0 ;
ccb . prog = false ;
ccb . w = ccb . h = ccb . ulx = ccb . uly = 0 ;
return ccb ;
}
// ccb initialization
ccb . skipMSBP = rcb . msbSkipped ;
ccb . ulx = rcb . ulx ;
ccb . uly = rcb . uly ;
ccb . w = rcb . w ;
ccb . h = rcb . h ;
ccb . ftpIdx = 0 ;
// Search for index of first truncation point (first layer where
// length of data is not zero)
int l = 0 ;
while ( ( l < rcb . len . Length ) & & ( rcb . len [ l ] = = 0 ) )
{
ccb . ftpIdx + = rcb . ntp [ l ] ;
l + + ;
}
// Calculate total length, number of included layer and number of
// truncation points
for ( l = fl - 1 ; l < fl + nl - 1 ; l + + )
{
ccb . nl + + ;
ccb . dl + = rcb . len [ l ] ;
ccb . nTrunc + = rcb . ntp [ l ] ;
}
// Calculate number of terminated segments
int nts ;
if ( ( options & CSJ2K . j2k . entropy . StdEntropyCoderOptions . OPT_TERM_PASS ) ! = 0 )
{
// Regular termination in use One segment per pass
// (i.e. truncation point)
nts = ccb . nTrunc - ccb . ftpIdx ;
}
else if ( ( options & CSJ2K . j2k . entropy . StdEntropyCoderOptions . OPT_BYPASS ) ! = 0 )
{
// Selective arithmetic coding bypass mode in use, but no regular
// termination: 1 segment upto the end of the last pass of the 4th
// most significant bit-plane, and, in each following bit-plane,
// one segment upto the end of the 2nd pass and one upto the end
// of the 3rd pass.
if ( ccb . nTrunc < = CSJ2K . j2k . entropy . StdEntropyCoderOptions . FIRST_BYPASS_PASS_IDX )
{
nts = 1 ;
}
else
{
nts = 1 ;
// Adds one for each terminated pass
for ( tpidx = ccb . ftpIdx ; tpidx < ccb . nTrunc ; tpidx + + )
{
if ( tpidx > = CSJ2K . j2k . entropy . StdEntropyCoderOptions . FIRST_BYPASS_PASS_IDX - 1 )
{
passtype = ( tpidx + CSJ2K . j2k . entropy . StdEntropyCoderOptions . NUM_EMPTY_PASSES_IN_MS_BP ) % CSJ2K . j2k . entropy . StdEntropyCoderOptions . NUM_PASSES ;
if ( passtype = = 1 | | passtype = = 2 )
{
// lazy pass just before MQ pass or MQ pass just
// before lazy pass => terminated
nts + + ;
}
}
}
}
}
else
{
// Nothing special in use, just one terminated segment
nts = 1 ;
}
// ccb.data creation
if ( ccb . data = = null | | ccb . data . Length < ccb . dl )
{
ccb . data = new byte [ ccb . dl ] ;
}
// ccb.tsLengths creation
if ( nts > 1 & & ( ccb . tsLengths = = null | | ccb . tsLengths . Length < nts ) )
{
ccb . tsLengths = new int [ nts ] ;
}
else if ( nts > 1 & & ( options & ( CSJ2K . j2k . entropy . StdEntropyCoderOptions . OPT_BYPASS | CSJ2K . j2k . entropy . StdEntropyCoderOptions . OPT_TERM_PASS ) ) = = CSJ2K . j2k . entropy . StdEntropyCoderOptions . OPT_BYPASS )
{
ArrayUtil . intArraySet ( ccb . tsLengths , 0 ) ;
}
// Fill ccb with compressed data
int dataIdx = - 1 ;
tpidx = ccb . ftpIdx ;
int ctp = ccb . ftpIdx ; // Cumulative number of truncation
// point for the current layer layer
int tsidx = 0 ;
int j ;
for ( l = fl - 1 ; l < fl + nl - 1 ; l + + )
{
ctp + = rcb . ntp [ l ] ;
// No data in this layer
if ( rcb . len [ l ] = = 0 )
continue ;
// Read data
// NOTE: we should never get an EOFException here since all
// data is checked to be within the file.
try
{
in_Renamed . seek ( rcb . off [ l ] ) ;
in_Renamed . readFully ( ccb . data , dataIdx + 1 , rcb . len [ l ] ) ;
dataIdx + = rcb . len [ l ] ;
}
catch ( System . IO . IOException e )
{
JJ2KExceptionHandler . handleException ( e ) ;
}
// Get the terminated segment lengths, if any
if ( nts = = 1 )
continue ;
if ( ( options & CSJ2K . j2k . entropy . StdEntropyCoderOptions . OPT_TERM_PASS ) ! = 0 )
{
// Regular termination => each pass is terminated
for ( j = 0 ; tpidx < ctp ; j + + , tpidx + + )
{
if ( rcb . segLen [ l ] ! = null )
{
ccb . tsLengths [ tsidx + + ] = rcb . segLen [ l ] [ j ] ;
}
else
{
// Only one terminated segment in packet
ccb . tsLengths [ tsidx + + ] = rcb . len [ l ] ;
}
}
}
else
{
// Lazy coding without regular termination
for ( j = 0 ; tpidx < ctp ; tpidx + + )
{
if ( tpidx > = CSJ2K . j2k . entropy . StdEntropyCoderOptions . FIRST_BYPASS_PASS_IDX - 1 )
{
passtype = ( tpidx + CSJ2K . j2k . entropy . StdEntropyCoderOptions . NUM_EMPTY_PASSES_IN_MS_BP ) % CSJ2K . j2k . entropy . StdEntropyCoderOptions . NUM_PASSES ;
if ( passtype ! = 0 )
{
// lazy pass just before MQ pass or MQ
// pass just before lazy pass =>
// terminated
if ( rcb . segLen [ l ] ! = null )
{
ccb . tsLengths [ tsidx + + ] + = rcb . segLen [ l ] [ j + + ] ;
rcb . len [ l ] - = rcb . segLen [ l ] [ j - 1 ] ;
}
else
{
// Only one terminated segment in packet
ccb . tsLengths [ tsidx + + ] + = rcb . len [ l ] ;
rcb . len [ l ] = 0 ;
}
}
}
}
// Last length in packet always in (either terminated segment
// or contribution to terminated segment)
if ( rcb . segLen [ l ] ! = null & & j < rcb . segLen [ l ] . Length )
{
ccb . tsLengths [ tsidx ] + = rcb . segLen [ l ] [ j ] ;
rcb . len [ l ] - = rcb . segLen [ l ] [ j ] ;
}
else
{
// Only one terminated segment in packet
if ( tsidx < nts )
{
ccb . tsLengths [ tsidx ] + = rcb . len [ l ] ;
rcb . len [ l ] = 0 ;
}
}
}
}
if ( nts = = 1 & & ccb . tsLengths ! = null )
{
ccb . tsLengths [ 0 ] = ccb . dl ;
}
// Set the progressive flag
int lastlayer = fl + nl - 1 ;
if ( lastlayer < numLayers - 1 )
{
for ( l = lastlayer + 1 ; l < numLayers ; l + + )
{
// It remains data for this code-block in the bit stream
if ( rcb . len [ l ] ! = 0 )
{
ccb . prog = true ;
}
}
}
return ccb ;
}
}
}