jj2000.j2k.codestream.reader.HeaderDecoder Maven / Gradle / Ivy
Show all versions of jai-imageio-jpeg2000 Show documentation
/*
* $RCSfile: HeaderDecoder.java,v $
* $Revision: 1.2 $
* $Date: 2006/09/28 00:55:20 $
* $State: Exp $
*
* Class: HeaderDecoder
*
* Description: Reads main and tile-part headers.
*
*
*
* COPYRIGHT:
*
* This software module was originally developed by Raphaël Grosbois and
* Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
* Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
* Bouchard, Fé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.
* */
package jj2000.j2k.codestream.reader;
import java.awt.Point;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Vector;
import jj2000.j2k.ModuleSpec;
import jj2000.j2k.NotImplementedError;
import jj2000.j2k.codestream.CorruptedCodestreamException;
import jj2000.j2k.codestream.HeaderInfo;
import jj2000.j2k.codestream.Markers;
import jj2000.j2k.codestream.ProgressionType;
import jj2000.j2k.decoder.DecoderSpecs;
import jj2000.j2k.entropy.StdEntropyCoderOptions;
import jj2000.j2k.entropy.decoder.CodedCBlkDataSrcDec;
import jj2000.j2k.entropy.decoder.EntropyDecoder;
import jj2000.j2k.entropy.decoder.StdEntropyDecoder;
import jj2000.j2k.io.RandomAccessIO;
import jj2000.j2k.quantization.dequantizer.CBlkQuantDataSrcDec;
import jj2000.j2k.quantization.dequantizer.Dequantizer;
import jj2000.j2k.quantization.dequantizer.StdDequantizer;
import jj2000.j2k.quantization.dequantizer.StdDequantizerParams;
import jj2000.j2k.roi.MaxShiftSpec;
import jj2000.j2k.roi.ROIDeScaler;
import jj2000.j2k.util.FacilityManager;
import jj2000.j2k.util.MsgLogger;
import jj2000.j2k.wavelet.FilterTypes;
import jj2000.j2k.wavelet.synthesis.SynWTFilter;
import jj2000.j2k.wavelet.synthesis.SynWTFilterFloatLift9x7;
import jj2000.j2k.wavelet.synthesis.SynWTFilterIntLift5x3;
import com.github.jaiimageio.jpeg2000.impl.J2KImageReadParamJava;
/**
* This class reads Main and Tile-part headers from the codestream. It is
* created by the run() method of the Decoder instance.
*
* A marker segment includes a marker and eventually marker segment
* parameters. It is designed by the three letters code of the marker
* associated with the marker segment. JPEG 2000 part 1 defines 6 types of
* markers:
*
*
* - Delimiting : SOC,SOT (read in FileBitstreamReaderAgent),SOD,EOC
* (read in FileBitstreamReaderAgent).
- Fixed information: SIZ.
*
* - Functional: COD,COC,RGN,QCD,QCC,POC.
- In bit-stream:
* SOP,EPH.
*
* - Pointer: TLM,PLM,PLT,PPM,PPT.
*
* - Informational: CRG,COM.
*
*
* The main header is read when the constructor is called whereas tile-part
* headers are read when the FileBitstreamReaderAgent instance is created. The
* reading is done in 2 passes:
*
*
* - All marker segments are buffered and their corresponding flag is
* activated (extractMainMarkSeg and extractTilePartMarkSeg methods).
*
* - Buffered marker segment are analyzed in a logical way and
* specifications are stored in appropriate member of DecoderSpecs instance
* (readFoundMainMarkSeg and readFoundTilePartMarkSeg methods).
*
*
* Whenever a marker segment is not recognized a warning message is
* displayed and its length parameter is used to skip it.
*
* @see DecoderSpecs
* @see Decoder
* @see FileBitstreamReaderAgent
* */
public class HeaderDecoder implements ProgressionType, Markers,
StdEntropyCoderOptions {
/** The prefix for header decoder options: 'H' */
public final static char OPT_PREFIX = 'H';
/** The list of parameters that is accepted for quantization. Options
* for quantization start with 'Q'. */
private final static String [][] pinfo = null;
/** The reference to the HeaderInfo instance holding the information found
* in headers */
private HeaderInfo hi;
/** Current header information in a string */
private String hdStr = "";
/** The J2KImageReadParamJava instance of the decoder */
private J2KImageReadParamJava j2krparam;
/** The number of tiles within the image */
private int nTiles;
/** The number of tile parts per tile */
public int[] nTileParts;
/** Used to store which markers have been already read, by using flag
* bits. The different markers are marked with XXX_FOUND flags, such as
* SIZ_FOUND */
private int nfMarkSeg = 0;
/** Counts number of COC markers found in the header */
private int nCOCMarkSeg = 0;
/** Counts number of QCC markers found in the header */
private int nQCCMarkSeg = 0;
/** Counts number of COM markers found in the header */
private int nCOMMarkSeg = 0;
/** Counts number of RGN markers found in the header */
private int nRGNMarkSeg = 0;
/** Counts number of PPM markers found in the header */
private int nPPMMarkSeg = 0;
/** Counts number of PPT markers found in the header */
private int[][] nPPTMarkSeg = null;
/** Flag bit for SIZ marker segment found */
private static final int SIZ_FOUND = 1;
/** Flag bit for COD marker segment found */
private static final int COD_FOUND = 1<<1;
/** Flag bit for COC marker segment found */
private static final int COC_FOUND = 1<<2;
/** Flag bit for QCD marker segment found */
private static final int QCD_FOUND = 1<<3;
/** Flag bit for TLM marker segment found */
private static final int TLM_FOUND = 1<<4;
/** Flag bit for PLM marker segment found */
private static final int PLM_FOUND = 1<<5;
/** Flag bit for SOT marker segment found */
private static final int SOT_FOUND = 1<<6;
/** Flag bit for PLT marker segment found */
private static final int PLT_FOUND = 1<<7;
/** Flag bit for QCC marker segment found */
private static final int QCC_FOUND = 1<<8;
/** Flag bit for RGN marker segment found */
private static final int RGN_FOUND = 1<<9;
/** Flag bit for POC marker segment found */
private static final int POC_FOUND = 1<<10;
/** Flag bit for COM marker segment found */
private static final int COM_FOUND = 1<<11;
/** Flag bit for SOD marker segment found */
public static final int SOD_FOUND = 1<<13;
/** Flag bit for SOD marker segment found */
public static final int PPM_FOUND = 1<<14;
/** Flag bit for SOD marker segment found */
public static final int PPT_FOUND = 1<<15;
/** Flag bit for CRG marker segment found */
public static final int CRG_FOUND = 1<<16;
/** The reset mask for new tiles */
private static final int TILE_RESET = ~(PLM_FOUND|SIZ_FOUND|RGN_FOUND);
/** HashTable used to store marker segment byte buffers */
private Hashtable ht = null;
/** The number of components in the image */
private int nComp;
/** The horizontal code-block partition origin */
private int cb0x = -1;
/** The vertical code-block partition origin */
private int cb0y = -1;
/** The decoder specifications */
private DecoderSpecs decSpec;
/** Is the precinct partition used */
boolean precinctPartitionIsUsed;
/** The offset of the main header in the input stream */
public int mainHeadOff;
/** Vector containing info as to which tile each tilepart belong */
public Vector tileOfTileParts;
/** Array containing the Nppm and Ippm fields of the PPM marker segments*/
private byte[][] pPMMarkerData;
/** Array containing the Ippm fields of the PPT marker segments */
private byte[][][][] tilePartPkdPktHeaders;
/** The packed packet headers if the PPM or PPT markers are used */
private ByteArrayOutputStream[] pkdPktHeaders;
/**
* Return the maximum height among all components
*
* @return Maximum component height
* */
public int getMaxCompImgHeight() { return hi.siz.getMaxCompHeight(); }
/**
* Return the maximum width among all components
*
* @return Maximum component width
* */
public int getMaxCompImgWidth() { return hi.siz.getMaxCompWidth(); }
/**
* Returns the image width in the reference grid.
*
* @return The image width in the reference grid
* */
public final int getImgWidth() { return hi.siz.xsiz-hi.siz.x0siz; }
/**
* Returns the image height in the reference grid.
*
* @return The image height in the reference grid
* */
public final int getImgHeight() { return hi.siz.ysiz-hi.siz.y0siz; }
/**
* Return the horizontal upper-left coordinate of the image in the
* reference grid.
*
* @return The horizontal coordinate of the image origin.
* */
public final int getImgULX() { return hi.siz.x0siz; }
/**
* Return the vertical upper-left coordinate of the image in the reference
* grid.
*
* @return The vertical coordinate of the image origin.
* */
public final int getImgULY() { return hi.siz.y0siz; }
/**
* Returns the nominal width of the tiles in the reference grid.
*
* @return The nominal tile width, in the reference grid.
* */
public final int getNomTileWidth() { return hi.siz.xtsiz; }
/**
* Returns the nominal width of the tiles in the reference grid.
*
* @return The nominal tile width, in the reference grid.
* */
public final int getNomTileHeight() { return hi.siz.ytsiz; }
/**
* Returns the tiling origin, referred to as '(Px,Py)' in the 'ImgData'
* interface.
*
* @param co If not null this object is used to return the information. If
* null a new one is created and returned.
*
* @return The coordinate of the tiling origin, in the canvas system, on
* the reference grid.
*
* @see jj2000.j2k.image.ImgData
* */
public final Point getTilingOrigin(Point co) {
if (co != null) {
co.x = hi.siz.xt0siz;
co.y = hi.siz.yt0siz;
return co;
}
else {
return new Point(hi.siz.xt0siz,hi.siz.yt0siz);
}
}
/**
* Returns true if the original data of the specified component was
* signed. If the data was not signed a level shift has to be applied at
* the end of the decompression chain.
*
* @param c The index of the component
*
* @return True if the original image component was signed.
* */
public final boolean isOriginalSigned(int c) {
return hi.siz.isOrigSigned(c);
}
/**
* Returns the original bitdepth of the specified component.
*
* @param c The index of the component
*
* @return The bitdepth of the component
* */
public final int getOriginalBitDepth(int c) {
return hi.siz.getOrigBitDepth(c);
}
/**
* Returns the number of components in the image.
*
* @return The number of components in the image.
* */
public final int getNumComps() {
return nComp;
}
/**
* Returns the component sub-sampling factor, with respect to the
* reference grid, along the horizontal direction for the specified
* component.
*
* @param c The index of the component
*
* @return The component sub-sampling factor X-wise.
* */
public final int getCompSubsX(int c) { return hi.siz.xrsiz[c]; }
/**
* Returns the component sub-sampling factor, with respect to the
* reference grid, along the vertical direction for the specified
* component.
*
* @param c The index of the component
*
* @return The component sub-sampling factor Y-wise.
* */
public final int getCompSubsY(int c) { return hi.siz.yrsiz[c]; }
/**
* Returns the dequantizer parameters. Dequantizer parameters normally are
* the quantization step sizes, see DequantizerParams.
*
* @param src The source of data for the dequantizer.
*
* @param rb The number of range bits for each component. Must be
* the number of range bits of the mixed components.
*
* @param decSpec2 The DecoderSpecs instance after any image manipulation.
*
* @return The dequantizer
* */
public final Dequantizer createDequantizer(CBlkQuantDataSrcDec src,
int rb[],
DecoderSpecs decSpec2) {
return new StdDequantizer(src,rb,decSpec2);
}
/**
* Returns the horizontal code-block partition origin.Allowable values are
* 0 and 1, nothing else.
* */
public final int getCbULX() {
return cb0x;
}
/**
* Returns the vertical code-block partition origin. Allowable values are
* 0 and 1, nothing else.
* */
public final int getCbULY() {
return cb0y;
}
/**
* Returns the precinct partition width for the specified tile-component
* and resolution level.
*
* @param c the component index
*
* @param t the tile index
*
* @param rl the resolution level
*
* @return The precinct partition width for the specified tile-component
* and resolution level
* */
public final int getPPX(int t,int c,int rl) {
return decSpec.pss.getPPX(t,c,rl);
}
/**
* Returns the precinct partition height for the specified component, tile
* and resolution level.
*
* @param c the component
*
* @param t the tile index
*
* @param rl the resolution level
*
* @return The precinct partition height for the specified component,
* tile and resolution level
* */
public final int getPPY(int t, int c, int rl) {
return decSpec.pss.getPPY(t, c, rl);
}
/**
* Returns the boolean used to know if the precinct partition is used
**/
public final boolean precinctPartitionUsed() {
return precinctPartitionIsUsed;
}
/**
* Reads a wavelet filter from the codestream and returns the filter
* object that implements it.
*
* @param ehs The encoded header stream from where to read the info
*
* @param filtIdx Int array of one element to return the type of the
* wavelet filter.
* */
private SynWTFilter readFilter(DataInputStream ehs,int[] filtIdx)
throws IOException {
int kid; // the filter id
kid = filtIdx[0] = ehs.readUnsignedByte();
if (kid >= (1<<7)) {
throw new NotImplementedError("Custom filters not supported");
}
// Return filter based on ID
switch (kid) {
case FilterTypes.W9X7:
return new SynWTFilterFloatLift9x7();
case FilterTypes.W5X3:
return new SynWTFilterIntLift5x3();
default:
throw new CorruptedCodestreamException("Specified wavelet filter "+
"not"+
" JPEG 2000 part I "+
"compliant");
}
}
/**
* Checks that the marker segment length is correct.
*
* @param ehs The encoded header stream
*
* @param str The string identifying the marker, such as "SIZ marker"
*
* @exception IOException If an I/O error occurs
* */
public void checkMarkerLength(DataInputStream ehs, String str)
throws IOException {
if (ehs.available()!=0) {
FacilityManager.getMsgLogger().
printmsg(MsgLogger.WARNING,
str+" length was short, attempting to resync.");
}
}
/**
* Reads the SIZ marker segment and realigns the codestream at the point
* where the next marker segment should be found.
*
*
SIZ is a fixed information marker segment containing informations
* about image and tile sizes. It is required in the main header
* immediately after SOC.
*
* @param ehs The encoded header stream
*
* @exception IOException If an I/O error occurs while reading from the
* encoded header stream
* */
private void readSIZ (DataInputStream ehs) throws IOException {
HeaderInfo.SIZ ms = hi.getNewSIZ();
hi.siz = ms;
// Read the length of SIZ marker segment (Lsiz)
ms.lsiz = ehs.readUnsignedShort();
// Read the capability of the codestream (Rsiz)
ms.rsiz = ehs.readUnsignedShort();
if (ms.rsiz > 2) {
throw new Error("Codestream capabiities not JPEG 2000 - Part I"+
" compliant");
}
// Read image size
ms.xsiz = ehs.readInt();
ms.ysiz = ehs.readInt();
if ( ms.xsiz<=0 || ms.ysiz<=0 ) {
throw new IOException("JJ2000 does not support images whose "+
"width and/or height not in the "+
"range: 1 -- (2^31)-1");
}
// Read image offset
ms.x0siz = ehs.readInt();
ms.y0siz = ehs.readInt();
if ( ms.x0siz<0 || ms.y0siz<0 ) {
throw new IOException("JJ2000 does not support images offset "+
"not in the range: 0 -- (2^31)-1");
}
// Read size of tile
ms.xtsiz = ehs.readInt();
ms.ytsiz = ehs.readInt();
if ( ms.xtsiz<=0 || ms.ytsiz<=0 ) {
throw new IOException("JJ2000 does not support tiles whose "+
"width and/or height are not in "+
"the range: 1 -- (2^31)-1");
}
// Read upper-left tile offset
ms.xt0siz = ehs.readInt();
ms.yt0siz = ehs.readInt();
if ( ms.xt0siz<0 || ms.yt0siz<0 ){
throw new IOException("JJ2000 does not support tiles whose "+
"offset is not in "+
"the range: 0 -- (2^31)-1");
}
// Read number of components and initialize related arrays
nComp = ms.csiz = ehs.readUnsignedShort();
if (nComp<1 || nComp>16384) {
throw new IllegalArgumentException("Number of component out of "+
"range 1--16384: "+nComp);
}
ms.ssiz = new int[nComp];
ms.xrsiz = new int[nComp];
ms.yrsiz = new int[nComp];
// Read bit-depth and down-sampling factors of each component
for(int i = 0; i maxrl-rl) {
hpd -= maxrl-rl;
}
else {
hpd = 1;
}
// Determine max and min subband index
minb = 1<<((hpd-1)<<1); // minb = 4^(hpd-1)
maxb = 1<<(hpd<<1); // maxb = 4^hpd
}
// Allocate array for subbands in resolution level
exp[rl] = new int[maxb];
for(j=minb; j>SQCX_EXP_SHIFT)&SQCX_EXP_MASK;
}
}// end for rl
} else {
int maxrl = (qType == SQCX_SCALAR_DERIVED) ? 0 :
( mainh ?
((Integer)decSpec.dls.getDefault()).intValue() :
((Integer)decSpec.dls.getTileDef(tileIdx)).intValue());
int i,j,rl;
int minb,maxb,hpd;
int tmp;
exp = qParms.exp = new int[maxrl+1][];
nStep = qParms.nStep = new float[maxrl+1][];
ms.spqcd = new int[maxrl+1][4];
for (rl=0; rl <= maxrl; rl++) { // Loop on resolution levels
// Find the number of subbands in the resolution level
if (rl == 0) { // Only the LL subband
minb = 0;
maxb = 1;
} else {
// Dyadic decomposition
hpd = 1;
// Adapt hpd to resolution level
if (hpd > maxrl-rl) {
hpd -= maxrl-rl;
} else {
hpd = 1;
}
// Determine max and min subband index
minb = 1<<((hpd-1)<<1); // minb = 4^(hpd-1)
maxb = 1<<(hpd<<1); // maxb = 4^hpd
}
// Allocate array for subbands in resolution level
exp[rl] = new int[maxb];
nStep[rl] = new float[maxb];
for(j=minb; j>11) & 0x1f;
// NOTE: the formula below does not support more than 5
// bits for the exponent, otherwise (-1<= nComp) {
throw new CorruptedCodestreamException("Invalid component "+
"index in QCC marker");
}
// Sqcc (quantization style)
ms.sqcc = ehs.readUnsignedByte();
int guardBits = ms.getNumGuardBits();
int qType = ms.getQuantType();
if(mainh) {
hi.qcc.put("main_c"+cComp,ms);
// If main header is being read, set default for component in all
// tiles
switch (qType) {
case SQCX_NO_QUANTIZATION:
decSpec.qts.setCompDef(cComp,"reversible");
break;
case SQCX_SCALAR_DERIVED:
decSpec.qts.setCompDef(cComp,"derived");
break;
case SQCX_SCALAR_EXPOUNDED:
decSpec.qts.setCompDef(cComp,"expounded");
break;
default:
throw new CorruptedCodestreamException("Unknown or "+
"unsupported "+
"quantization style "+
"in Sqcd field, QCD "+
"marker, main header");
}
} else {
hi.qcc.put("t"+tileIdx+"_c"+cComp,ms);
// If tile header is being read, set value for component in
// this tiles
switch (qType) {
case SQCX_NO_QUANTIZATION:
decSpec.qts.setTileCompVal(tileIdx, cComp,"reversible");
break;
case SQCX_SCALAR_DERIVED:
decSpec.qts.setTileCompVal(tileIdx, cComp,"derived");
break;
case SQCX_SCALAR_EXPOUNDED:
decSpec.qts.setTileCompVal(tileIdx, cComp,"expounded");
break;
default:
throw new CorruptedCodestreamException("Unknown or "+
"unsupported "+
"quantization style "+
"in Sqcd field, QCD "+
"marker, main header");
}
}
// Decode all dequantizer params
qParms = new StdDequantizerParams();
if (qType == SQCX_NO_QUANTIZATION) {
int maxrl = ( mainh ?
((Integer)decSpec.dls.getCompDef(cComp)).intValue() :
((Integer)decSpec.dls.getTileCompVal(tileIdx,cComp)).
intValue());
int i,j,rl;
int minb,maxb,hpd;
expC = qParms.exp = new int[maxrl+1][];
ms.spqcc = new int[maxrl+1][4];
for (rl=0; rl <= maxrl; rl++) { // Loop on resolution levels
// Find the number of subbands in the resolution level
if (rl == 0) { // Only the LL subband
minb = 0;
maxb = 1;
} else {
// Dyadic decomposition
hpd = 1;
// Adapt hpd to resolution level
if (hpd > maxrl-rl) {
hpd -= maxrl-rl;
} else {
hpd = 1;
}
// Determine max and min subband index
minb = 1<<((hpd-1)<<1); // minb = 4^(hpd-1)
maxb = 1<<(hpd<<1); // maxb = 4^hpd
}
// Allocate array for subbands in resolution level
expC[rl] = new int[maxb];
for(j=minb; j>SQCX_EXP_SHIFT)&SQCX_EXP_MASK;
}
}// end for rl
} else {
int maxrl = (qType == SQCX_SCALAR_DERIVED) ? 0 :
( mainh ?
((Integer)decSpec.dls.getCompDef(cComp)).intValue() :
((Integer)decSpec.dls.getTileCompVal(tileIdx,cComp)).
intValue());
int i,j,rl;
int minb,maxb,hpd;
nStepC = qParms.nStep = new float[maxrl+1][];
expC = qParms.exp = new int[maxrl+1][];
ms.spqcc = new int[maxrl+1][4];
for (rl=0; rl <= maxrl; rl++) { // Loop on resolution levels
// Find the number of subbands in the resolution level
if (rl == 0) { // Only the LL subband
minb = 0;
maxb = 1;
} else {
// Dyadic decomposition
hpd = 1;
// Adapt hpd to resolution level
if (hpd > maxrl-rl) {
hpd -= maxrl-rl;
} else {
hpd = 1;
}
// Determine max and min subband index
minb = 1<<((hpd-1)<<1); // minb = 4^(hpd-1)
maxb = 1<<(hpd<<1); // maxb = 4^hpd
}
// Allocate array for subbands in resolution level
expC[rl] = new int[maxb];
nStepC[rl] = new float[maxb];
for(j=minb; j>11) & 0x1f;
// NOTE: the formula below does not support more than 5
// bits for the exponent, otherwise (-1<65535 ) {
throw new CorruptedCodestreamException("Number of layers out of "+
"range: 1--65535");
}
// Multiple component transform
ms.sgcod_mct = ehs.readUnsignedByte();
// SPcod
// decomposition levels
int mrl = ms.spcod_ndl = ehs.readUnsignedByte();
if( mrl>32 ){
throw new CorruptedCodestreamException("Number of decomposition "+
"levels out of range: "+
"0--32");
}
// Read the code-blocks dimensions
cblk = new Integer[2];
ms.spcod_cw = ehs.readUnsignedByte();
cblk[0] = new Integer(1<<(ms.spcod_cw+2));
if ( cblk[0].intValue() < StdEntropyCoderOptions.MIN_CB_DIM ||
cblk[0].intValue() > StdEntropyCoderOptions.MAX_CB_DIM ) {
errMsg = "Non-valid code-block width in SPcod field, "+
"COD marker";
throw new CorruptedCodestreamException(errMsg);
}
ms.spcod_ch = ehs.readUnsignedByte();
cblk[1] = new Integer(1<<(ms.spcod_ch+2));
if ( cblk[1].intValue() < StdEntropyCoderOptions.MIN_CB_DIM ||
cblk[1].intValue() > StdEntropyCoderOptions.MAX_CB_DIM ) {
errMsg = "Non-valid code-block height in SPcod field, "+
"COD marker";
throw new CorruptedCodestreamException(errMsg);
}
if ( (cblk[0].intValue()*cblk[1].intValue()) >
StdEntropyCoderOptions.MAX_CB_AREA ) {
errMsg = "Non-valid code-block area in SPcod field, "+
"COD marker";
throw new CorruptedCodestreamException(errMsg);
}
if ( mainh ) {
decSpec.cblks.setDefault(cblk);
}
else {
decSpec.cblks.setTileDef(tileIdx, cblk);
}
// Style of the code-block coding passes
int ecOptions = ms.spcod_cs = ehs.readUnsignedByte();
if ((ecOptions &
~(OPT_BYPASS|OPT_RESET_MQ|OPT_TERM_PASS|
OPT_VERT_STR_CAUSAL|OPT_PRED_TERM | OPT_SEG_SYMBOLS)) != 0){
throw
new CorruptedCodestreamException("Unknown \"code-block "+
"style\" in SPcod field, "+
"COD marker: 0x"+
Integer.
toHexString(ecOptions));
}
// Read wavelet filter for tile or image
hfilters = new SynWTFilter[1];
vfilters = new SynWTFilter[1];
hfilters[0] = readFilter(ehs,ms.spcod_t);
vfilters[0] = hfilters[0];
// Fill the filter spec
// If this is the main header, set the default value, if it is the
// tile header, set default for this tile
SynWTFilter[][] hvfilters = new SynWTFilter[2][];
hvfilters[0]=hfilters;
hvfilters[1]=vfilters;
// Get precinct partition sizes
Vector v[] = new Vector[2];
v[0] = new Vector();
v[1] = new Vector();
int val = PRECINCT_PARTITION_DEF_SIZE;
if ( !precinctPartitionIsUsed ) {
Integer w, h;
w = new Integer(1<<(val & 0x000F));
v[0].addElement(w);
h = new Integer(1<<(((val & 0x00F0)>>4)));
v[1].addElement(h);
} else {
ms.spcod_ps = new int[mrl+1];
for (int rl=mrl ;rl>=0 ;rl--) {
Integer w, h;
val = ms.spcod_ps[mrl-rl] = ehs.readUnsignedByte();
w = new Integer(1<<(val & 0x000F));
v[0].insertElementAt(w,0);
h = new Integer(1<<(((val & 0x00F0)>>4)));
v[1].insertElementAt(h,0);
}
}
if (mainh) {
decSpec.pss.setDefault(v);
} else {
decSpec.pss.setTileDef(tileIdx, v);
}
precinctPartitionIsUsed = true;
// Check marker length
checkMarkerLength(ehs,"COD marker");
// Store specifications in decSpec
if(mainh){
decSpec.wfs.setDefault(hvfilters);
decSpec.dls.setDefault(new Integer(mrl));
decSpec.ecopts.setDefault(new Integer(ecOptions));
decSpec.cts.setDefault(new Integer(ms.sgcod_mct));
decSpec.nls.setDefault(new Integer(ms.sgcod_nl));
decSpec.pos.setDefault(new Integer(ms.sgcod_po));
}
else{
decSpec.wfs.setTileDef(tileIdx, hvfilters);
decSpec.dls.setTileDef(tileIdx,new Integer(mrl));
decSpec.ecopts.setTileDef(tileIdx,new Integer(ecOptions));
decSpec.cts.setTileDef(tileIdx,new Integer(ms.sgcod_mct));
decSpec.nls.setTileDef(tileIdx,new Integer(ms.sgcod_nl));
decSpec.pos.setTileDef(tileIdx,new Integer(ms.sgcod_po));
}
}
/**
* Reads the COC marker segment and realigns the codestream where the next
* marker should be found.
*
* @param ehs The encoder header stream.
*
* @param mainh Flag indicating whether or not this marker segment is read
* from the main header.
*
* @param tileIdx The index of the current tile
*
* @param tpIdx Tile-part index
*
* @exception IOException If an I/O error occurs while reading from the
* encoder header stream
* */
private void readCOC (DataInputStream ehs, boolean mainh, int tileIdx,
int tpIdx) throws IOException {
int cComp; // current component
SynWTFilter hfilters[],vfilters[];
int tmp,l;
int ecOptions;
Integer cblk[];
String errMsg;
HeaderInfo.COC ms = hi.getNewCOC();
// Lcoc (marker length)
ms.lcoc = ehs.readUnsignedShort();
// Ccoc
if (nComp < 257) {
cComp = ms.ccoc = ehs.readUnsignedByte();
} else {
cComp = ms.ccoc = ehs.readUnsignedShort();
}
if (cComp >= nComp) {
throw new CorruptedCodestreamException("Invalid component index "+
"in QCC marker");
}
// Scoc (block style)
int cstyle = ms.scoc = ehs.readUnsignedByte();
if( (cstyle&SCOX_PRECINCT_PARTITION) != 0 ){
precinctPartitionIsUsed = true;
// Remove flag
cstyle &= ~(SCOX_PRECINCT_PARTITION);
} else {
precinctPartitionIsUsed = false;
}
// SPcoc
// decomposition levels
int mrl = ms.spcoc_ndl = ehs.readUnsignedByte();
// Read the code-blocks dimensions
cblk = new Integer[2];
ms.spcoc_cw = ehs.readUnsignedByte();
cblk[0] = new Integer(1<<(ms.spcoc_cw+2));
if ( cblk[0].intValue() < StdEntropyCoderOptions.MIN_CB_DIM ||
cblk[0].intValue() > StdEntropyCoderOptions.MAX_CB_DIM ) {
errMsg = "Non-valid code-block width in SPcod field, "+
"COC marker";
throw new CorruptedCodestreamException(errMsg);
}
ms.spcoc_ch = ehs.readUnsignedByte();
cblk[1] = new Integer(1<<(ms.spcoc_ch+2));
if ( cblk[1].intValue() < StdEntropyCoderOptions.MIN_CB_DIM ||
cblk[1].intValue() > StdEntropyCoderOptions.MAX_CB_DIM ) {
errMsg = "Non-valid code-block height in SPcod field, "+
"COC marker";
throw new CorruptedCodestreamException(errMsg);
}
if ( (cblk[0].intValue()*cblk[1].intValue()) >
StdEntropyCoderOptions.MAX_CB_AREA ) {
errMsg = "Non-valid code-block area in SPcod field, "+
"COC marker";
throw new CorruptedCodestreamException(errMsg);
}
if ( mainh ) {
decSpec.cblks.setCompDef(cComp,cblk);
} else {
decSpec.cblks.setTileCompVal(tileIdx,cComp,cblk);
}
// Read entropy block mode options
// NOTE: currently OPT_SEG_SYMBOLS is not included here
ecOptions = ms.spcoc_cs = ehs.readUnsignedByte();
if ((ecOptions &
~(OPT_BYPASS|OPT_RESET_MQ|OPT_TERM_PASS|
OPT_VERT_STR_CAUSAL|OPT_PRED_TERM|OPT_SEG_SYMBOLS)) != 0){
throw
new CorruptedCodestreamException("Unknown \"code-block "+
"context\" in SPcoc field, "+
"COC marker: 0x"+
Integer.
toHexString(ecOptions));
}
// Read wavelet filter for tile or image
hfilters = new SynWTFilter[1];
vfilters = new SynWTFilter[1];
hfilters[0] = readFilter(ehs,ms.spcoc_t);
vfilters[0] = hfilters[0];
// Fill the filter spec
// If this is the main header, set the default value, if it is the
// tile header, set default for this tile
SynWTFilter[][] hvfilters = new SynWTFilter[2][];
hvfilters[0]=hfilters;
hvfilters[1]=vfilters;
// Get precinct partition sizes
Vector v[] = new Vector[2];
v[0] = new Vector();
v[1] = new Vector();
int val = PRECINCT_PARTITION_DEF_SIZE;
if ( !precinctPartitionIsUsed ) {
Integer w, h;
w = new Integer(1<<(val & 0x000F));
v[0].addElement(w);
h = new Integer(1<<(((val & 0x00F0)>>4)));
v[1].addElement(h);
} else {
ms.spcoc_ps = new int[mrl+1];
for ( int rl=mrl ; rl>=0 ; rl-- ) {
Integer w, h;
val = ms.spcoc_ps[rl] = ehs.readUnsignedByte();
w = new Integer(1<<(val & 0x000F));
v[0].insertElementAt(w,0);
h = new Integer(1<<(((val & 0x00F0)>>4)));
v[1].insertElementAt(h,0);
}
}
if (mainh) {
decSpec.pss.setCompDef(cComp,v);
} else {
decSpec.pss.setTileCompVal(tileIdx,cComp,v);
}
precinctPartitionIsUsed = true;
// Check marker length
checkMarkerLength(ehs,"COD marker");
if(mainh){
hi.coc.put("main_c"+cComp,ms);
decSpec.wfs.setCompDef(cComp,hvfilters);
decSpec.dls.setCompDef(cComp,new Integer(mrl));
decSpec.ecopts.setCompDef(cComp,new Integer(ecOptions));
} else {
hi.coc.put("t"+tileIdx+"_c"+cComp,ms);
decSpec.wfs.setTileCompVal(tileIdx,cComp,hvfilters);
decSpec.dls.setTileCompVal(tileIdx,cComp,new Integer(mrl));
decSpec.ecopts.setTileCompVal(tileIdx,cComp,
new Integer(ecOptions));
}
}
/**
* Reads the POC marker segment and realigns the codestream where the next
* marker should be found.
*
* @param ehs The encoder header stream.
*
* @param mainh Flag indicating whether or not this marker segment is read
* from the main header.
*
* @param t The index of the current tile
*
* @param tpIdx Tile-part index
*
* @exception IOException If an I/O error occurs while reading from the
* encoder header stream
* */
private void readPOC(DataInputStream ehs,boolean mainh,int t,int tpIdx)
throws IOException {
boolean useShort = (nComp>=256) ? true : false;
int tmp;
int nOldChg = 0;
HeaderInfo.POC ms;
if(mainh || hi.poc.get("t"+t)==null) {
ms = hi.getNewPOC();
} else {
ms = (HeaderInfo.POC)hi.poc.get("t"+t);
nOldChg = ms.rspoc.length;
}
// Lpoc
ms.lpoc = ehs.readUnsignedShort();
// Compute the number of new progression changes
// newChg = (lpoc - Lpoc(2)) / (RSpoc(1) + CSpoc(2) +
// LYEpoc(2) + REpoc(1) + CEpoc(2) + Ppoc (1) )
int newChg = (ms.lpoc-2)/(5+ (useShort?4:2));
int ntotChg = nOldChg+newChg;
int[][] change;
if(nOldChg!=0) {
// Creates new arrays
change = new int[ntotChg][6];
int[] tmprspoc = new int[ntotChg];
int[] tmpcspoc = new int[ntotChg];
int[] tmplyepoc = new int[ntotChg];
int[] tmprepoc = new int[ntotChg];
int[] tmpcepoc = new int[ntotChg];
int[] tmpppoc = new int[ntotChg];
// Copy old values
int[][] prevChg = (int[][])decSpec.pcs.getTileDef(t);
for(int chg=0; chgMay be used in tile or main header. If used in main header, it
* refers to the maxshift value of a component in all tiles. When used in
* tile header, only the particular tile-component is affected.
*
* @param ehs The encoder header stream.
*
* @param mainh Flag indicating whether or not this marker segment is read
* from the main header.
*
* @param tileIdx The index of the current tile
*
* @param tpIdx Tile-part index
*
* @exception IOException If an I/O error occurs while reading from the
* encoder header stream
* */
private void readRGN(DataInputStream ehs, boolean mainh, int tileIdx,
int tpIdx) throws IOException {
int comp; // ROI component
int i; // loop variable
int tempComp; // Component for
HeaderInfo.RGN ms = hi.getNewRGN();
// Lrgn (marker length)
ms.lrgn = ehs.readUnsignedShort();
// Read component
ms.crgn = comp = (nComp < 257) ? ehs.readUnsignedByte():
ehs.readUnsignedShort();
if (comp >= nComp) {
throw new CorruptedCodestreamException("Invalid component "+
"index in RGN marker"+
comp);
}
// Read type of RGN.(Srgn)
ms.srgn = ehs.readUnsignedByte();
// Check that we can handle it.
if(ms.srgn != SRGN_IMPLICIT)
throw new CorruptedCodestreamException("Unknown or unsupported "+
"Srgn parameter in ROI "+
"marker");
if(decSpec.rois==null) { // No maxshift spec defined
// Create needed ModuleSpec
decSpec.rois=new MaxShiftSpec(nTiles,nComp,
ModuleSpec.SPEC_TYPE_TILE_COMP, "null");
}
// SPrgn
ms.sprgn = ehs.readUnsignedByte();
if(mainh) {
hi.rgn.put("main_c"+comp,ms);
decSpec.rois.setCompDef(comp, new Integer(ms.sprgn));
} else {
hi.rgn.put("t"+tileIdx+"_c"+comp,ms);
decSpec.rois.setTileCompVal(tileIdx,comp,new Integer(ms.sprgn));
}
// Check marker length
checkMarkerLength(ehs,"RGN marker");
}
/**
* Reads the PPM marker segment of the main header.
*
* @param ehs The encoder header stream.
*
* @exception IOException If an I/O error occurs while reading from the
* encoder header stream
* */
private void readPPM(DataInputStream ehs) throws IOException {
int curMarkSegLen;
int i,indx,len,off;
int remSegLen;
byte[] b;
// If first time readPPM method is called allocate arrays for packed
// packet data
if(pPMMarkerData==null) {
pPMMarkerData = new byte[nPPMMarkSeg][];
tileOfTileParts = new Vector();
decSpec.pphs.setDefault(new Boolean(true));
}
// Lppm (marker length)
curMarkSegLen = ehs.readUnsignedShort();
remSegLen = curMarkSegLen - 3;
// Zppm (index of PPM marker)
indx = ehs.readUnsignedByte();
// Read Nppm and Ippm data
pPMMarkerData[indx] = new byte[remSegLen];
ehs.read(pPMMarkerData[indx],0,remSegLen);
// Check marker length
checkMarkerLength(ehs,"PPM marker");
}
/**
* Teads the PPT marker segment of the main header.
*
* @param ehs The encoder header stream.
*
* @param tile The tile to which the current tile part belongs
*
* @param tpIdx Tile-part index
*
* @exception IOException If an I/O error occurs while reading from the
* encoder header stream
* */
private void readPPT(DataInputStream ehs,int tile,int tpIdx)
throws IOException {
int curMarkSegLen;
int indx,len=0;
byte[] temp;
if(tilePartPkdPktHeaders == null){
tilePartPkdPktHeaders = new byte[nTiles][][][];
}
if(tilePartPkdPktHeaders[tile] == null){
tilePartPkdPktHeaders[tile] = new byte[nTileParts[tile]][][];
}
if(tilePartPkdPktHeaders[tile][tpIdx] == null){
tilePartPkdPktHeaders[tile][tpIdx] =
new byte[nPPTMarkSeg[tile][tpIdx]][];
}
// Lppt (marker length)
curMarkSegLen = ehs.readUnsignedShort();
// Zppt (index of PPT marker)
indx = ehs.readUnsignedByte();
// Ippt (packed packet headers)
temp = new byte[curMarkSegLen-3];
ehs.read(temp);
tilePartPkdPktHeaders[tile][tpIdx][indx]=temp;
// Check marker length
checkMarkerLength(ehs,"PPT marker");
decSpec.pphs.setTileDef(tile, new Boolean(true));
}
/**
* This method extract a marker segment from the main header and stores it
* into a byte buffer for the second pass. The marker segment is first
* identified. Then its flag is activated. Finally, its content is
* buffered into a byte array stored in an hashTable.
*
* If the marker is not recognized, it prints a warning and skips it
* according to its length.
*
* SIZ marker segment shall be the first encountered marker segment.
*
* @param marker The marker segment to process
*
* @param ehs The encoded header stream
* */
private void extractMainMarkSeg(short marker,RandomAccessIO ehs)
throws IOException {
if(nfMarkSeg == 0) { // First non-delimiting marker of the header
// JPEG 2000 part 1 specify that it must be SIZ
if(marker != SIZ) {
throw new CorruptedCodestreamException("First marker after "+
"SOC "+
"must be SIZ "+
Integer.
toHexString(marker));
}
}
String htKey=""; // Name used as a key for the hash-table
if(ht==null) {
ht = new Hashtable();
}
switch(marker){
case SIZ:
if ((nfMarkSeg & SIZ_FOUND) != 0) {
throw
new CorruptedCodestreamException("More than one SIZ marker "+
"segment found in main "+
"header");
}
nfMarkSeg |= SIZ_FOUND;
htKey = "SIZ";
break;
case SOD:
throw new CorruptedCodestreamException("SOD found in main header");
case EOC:
throw new CorruptedCodestreamException("EOC found in main header");
case SOT:
if ((nfMarkSeg & SOT_FOUND) != 0) {
throw new CorruptedCodestreamException("More than one SOT "+
"marker "+
"found right after "+
"main "+
"or tile header");
}
nfMarkSeg |= SOT_FOUND;
return;
case COD:
if((nfMarkSeg & COD_FOUND) != 0) {
throw new CorruptedCodestreamException("More than one COD "+
"marker "+
"found in main header");
}
nfMarkSeg |= COD_FOUND;
htKey = "COD";
break;
case COC:
nfMarkSeg |= COC_FOUND;
htKey = "COC"+(nCOCMarkSeg++);
break;
case QCD:
if((nfMarkSeg & QCD_FOUND) != 0) {
throw new CorruptedCodestreamException("More than one QCD "+
"marker "+
"found in main header");
}
nfMarkSeg |= QCD_FOUND;
htKey = "QCD";
break;
case QCC:
nfMarkSeg |= QCC_FOUND;
htKey = "QCC"+(nQCCMarkSeg++);
break;
case RGN:
nfMarkSeg |= RGN_FOUND;
htKey = "RGN"+(nRGNMarkSeg++);
break;
case COM:
nfMarkSeg |= COM_FOUND;
htKey = "COM"+(nCOMMarkSeg++);
break;
case CRG:
if((nfMarkSeg & CRG_FOUND) != 0) {
throw new CorruptedCodestreamException("More than one CRG "+
"marker "+
"found in main header");
}
nfMarkSeg |= CRG_FOUND;
htKey = "CRG";
break;
case PPM:
nfMarkSeg |= PPM_FOUND;
htKey = "PPM"+(nPPMMarkSeg++);
break;
case TLM:
if((nfMarkSeg & TLM_FOUND) != 0) {
FacilityManager.getMsgLogger().
printmsg(MsgLogger.INFO,
"More than one TLM "+
"marker "+
"found in main header");
/** XXX It is legal to have multiple TLM segments.
throw new CorruptedCodestreamException("More than one TLM "+
"marker "+
"found in main header");
*/
}
nfMarkSeg |= TLM_FOUND;
break;
case PLM:
if((nfMarkSeg & PLM_FOUND) != 0) {
throw new CorruptedCodestreamException("More than one PLM "+
"marker "+
"found in main header");
}
FacilityManager.getMsgLogger().
printmsg(MsgLogger.WARNING,"PLM marker segment found but "+
"not used by by JJ2000 decoder.");
nfMarkSeg |= PLM_FOUND;
htKey = "PLM";
break;
case POC:
if( (nfMarkSeg&POC_FOUND)!=0) {
throw new CorruptedCodestreamException("More than one POC "+
"marker segment found "+
"in main header");
}
nfMarkSeg |= POC_FOUND;
htKey = "POC";
break;
case PLT:
throw new CorruptedCodestreamException("PLT found in main header");
case PPT:
throw new CorruptedCodestreamException("PPT found in main header");
default:
htKey = "UNKNOWN";
FacilityManager.getMsgLogger().
printmsg(MsgLogger.WARNING,"Non recognized marker segment (0x"+
Integer.toHexString(marker)+") in main header!");
break;
}
if(marker < 0xffffff30 || marker > 0xffffff3f){
// Read marker segment length and create corresponding byte buffer
int markSegLen = ehs.readUnsignedShort();
byte[] buf = new byte[markSegLen];
// Copy data (after re-insertion of the marker segment length);
buf[0]= (byte)((markSegLen>>8) & 0xFF);
buf[1]= (byte)(markSegLen & 0xFF);
ehs.readFully(buf,2,markSegLen-2);
if(!htKey.equals("UNKNOWN")) {
// Store array in hashTable
ht.put(htKey,buf);
}
}
}
/**
* This method extracts a marker segment in a tile-part header and stores
* it into a byte buffer for the second pass. The marker is first
* recognized, then its flag is activated and, finally, its content is
* buffered in an element of byte arrays accessible thanks to a hashTable.
* If a marker segment is not recognized, it prints a warning and skip it
* according to its length.
*
* @param marker The marker to process
*
* @param ehs The encoded header stream
*
* @param tileIdx The index of the current tile
*
* @param tilePartIdx The index of the current tile part
* */
public void extractTilePartMarkSeg(short marker, RandomAccessIO ehs,
int tileIdx, int tilePartIdx)
throws IOException {
String htKey=""; // Name used as a hash-table key
if(ht==null) {
ht = new Hashtable();
}
switch(marker) {
case SOT:
throw new CorruptedCodestreamException("Second SOT marker "+
"segment found in tile-"+
"part header");
case SIZ:
throw new CorruptedCodestreamException("SIZ found in tile-part"+
" header");
case EOC:
throw new CorruptedCodestreamException("EOC found in tile-part"+
" header");
case TLM:
throw new CorruptedCodestreamException("TLM found in tile-part"+
" header");
case PPM:
throw new CorruptedCodestreamException("PPM found in tile-part"+
" header");
case COD:
if((nfMarkSeg & COD_FOUND) != 0) {
throw new CorruptedCodestreamException("More than one COD "+
"marker "+
"found in tile-part"+
" header");
}
nfMarkSeg |= COD_FOUND;
htKey = "COD";
break;
case COC:
nfMarkSeg |= COC_FOUND;
htKey = "COC"+(nCOCMarkSeg++);
break;
case QCD:
if((nfMarkSeg & QCD_FOUND) != 0) {
throw new CorruptedCodestreamException("More than one QCD "+
"marker "+
"found in tile-part"+
" header");
}
nfMarkSeg |= QCD_FOUND;
htKey = "QCD";
break;
case QCC:
nfMarkSeg |= QCC_FOUND;
htKey = "QCC"+(nQCCMarkSeg++);
break;
case RGN:
nfMarkSeg |= RGN_FOUND;
htKey = "RGN"+(nRGNMarkSeg++);
break;
case COM:
nfMarkSeg |= COM_FOUND;
htKey = "COM"+(nCOMMarkSeg++);
break;
case CRG:
throw new CorruptedCodestreamException("CRG marker found in "+
"tile-part header");
case PPT:
nfMarkSeg |= PPT_FOUND;
if(nPPTMarkSeg == null){
nPPTMarkSeg = new int[nTiles][];
}
if(nPPTMarkSeg[tileIdx] == null){
nPPTMarkSeg[tileIdx] = new int[nTileParts[tileIdx]];
}
htKey = "PPT"+(nPPTMarkSeg[tileIdx][tilePartIdx]++);
break;
case SOD:
nfMarkSeg |= SOD_FOUND;
return;
case POC:
if( (nfMarkSeg&POC_FOUND) != 0)
throw new CorruptedCodestreamException("More than one POC "+
"marker segment found "+
"in tile-part"+
" header");
nfMarkSeg |= POC_FOUND;
htKey = "POC";
break;
case PLT:
if((nfMarkSeg & PLM_FOUND) != 0) {
throw new CorruptedCodestreamException("PLT marker found even"+
"though PLM marker "+
"found in main header");
}
FacilityManager.getMsgLogger().
printmsg(MsgLogger.WARNING,"PLT marker segment found but "+
"not used by JJ2000 decoder.");
htKey = "UNKNOWN";
break;
default:
htKey = "UNKNOWN";
FacilityManager.getMsgLogger().
printmsg(MsgLogger.WARNING,"Non recognized marker segment (0x"+
Integer.toHexString(marker)+") in tile-part header"+
" of tile "+tileIdx+" !");
break;
}
// Read marker segment length and create corresponding byte buffer
int markSegLen = ehs.readUnsignedShort();
byte[] buf = new byte[markSegLen];
// Copy data (after re-insertion of marker segment length);
buf[0]= (byte)((markSegLen>>8) & 0xFF);
buf[1]= (byte)(markSegLen & 0xFF);
ehs.readFully(buf,2,markSegLen-2);
if(!htKey.equals("UNKNOWN")) {
// Store array in hashTable
ht.put(htKey,buf);
}
}
/**
* Retrieves and reads all marker segments found in the main header during
* the first pass.
* */
private void readFoundMainMarkSeg() throws IOException {
DataInputStream dis;
ByteArrayInputStream bais;
// SIZ marker segment
if((nfMarkSeg&SIZ_FOUND) != 0) {
bais = new ByteArrayInputStream( (byte[])(ht.get("SIZ")));
readSIZ(new DataInputStream(bais));
}
// COM marker segments
if((nfMarkSeg&COM_FOUND) != 0) {
for(int i=0; i=0; i--) {
pkdPktHeaders[i] = new ByteArrayOutputStream();
}
if(nPPMMarkSeg!=0) {
// If this is first time packed packet headers are requested,
// create packed packet headers from Nppm and Ippm fields
int nppm;
int nTileParts = tileOfTileParts.size();
byte[] temp;
ByteArrayInputStream pph;
ByteArrayOutputStream allNppmIppm =
new ByteArrayOutputStream();
// Concatenate all Nppm and Ippm fields
for(i=0 ; i=0; t--) {
for(tp=0; tp