001/*
002 * $RCSfile: PktDecoder.java,v $
003 * $Revision: 1.1 $
004 * $Date: 2005/02/11 05:02:01 $
005 * $State: Exp $
006 *
007 * Class:                   PktDecoder
008 *
009 * Description:             Reads packets heads and keeps location of
010 *                          code-blocks' codewords
011 *
012 *
013 *
014 * COPYRIGHT:
015 *
016 * This software module was originally developed by Raphaël Grosbois and
017 * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel
018 * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David
019 * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research
020 * Centre France S.A) in the course of development of the JPEG2000
021 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This
022 * software module is an implementation of a part of the JPEG 2000
023 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio
024 * Systems AB and Canon Research Centre France S.A (collectively JJ2000
025 * Partners) agree not to assert against ISO/IEC and users of the JPEG
026 * 2000 Standard (Users) any of their rights under the copyright, not
027 * including other intellectual property rights, for this software module
028 * with respect to the usage by ISO/IEC and Users of this software module
029 * or modifications thereof for use in hardware or software products
030 * claiming conformance to the JPEG 2000 Standard. Those intending to use
031 * this software module in hardware or software products are advised that
032 * their use may infringe existing patents. The original developers of
033 * this software module, JJ2000 Partners and ISO/IEC assume no liability
034 * for use of this software module or modifications thereof. No license
035 * or right to this software module is granted for non JPEG 2000 Standard
036 * conforming products. JJ2000 Partners have full right to use this
037 * software module for his/her own purpose, assign or donate this
038 * software module to any third party and to inhibit third parties from
039 * using this software module for non JPEG 2000 Standard conforming
040 * products. This copyright notice must be included in all copies or
041 * derivative works of this software module.
042 *
043 * Copyright (c) 1999/2000 JJ2000 Partners.
044 * */
045package jj2000.j2k.codestream.reader;
046import java.awt.Point;
047
048import jj2000.j2k.wavelet.synthesis.*;
049import jj2000.j2k.codestream.*;
050import jj2000.j2k.entropy.*;
051import jj2000.j2k.wavelet.*;
052import jj2000.j2k.decoder.*;
053import jj2000.j2k.image.*;
054import jj2000.j2k.util.*;
055import jj2000.j2k.io.*;
056
057import java.util.*;
058import java.io.*;
059
060/**
061 * This class is used to read packet's head and body. All the members must be
062 * re-initialized at the beginning of each tile thanks to the restart()
063 * method.
064 * */
065public class PktDecoder implements StdEntropyCoderOptions{
066
067    /** Reference to the codestream reader agent */
068    private BitstreamReaderAgent src;
069
070    /** Flag indicating whether packed packet header was used for this tile*/
071    private boolean pph=false;
072
073    /** The packed packet header if it was used */
074    private ByteArrayInputStream pphbais;
075
076    /** Reference to decoder specifications */
077    private DecoderSpecs decSpec;
078
079    /** Reference to the HeaderDecoder */
080    private HeaderDecoder hd;
081
082    /** Initial value of the state variable associated with code-block
083     * length. */
084    private final int INIT_LBLOCK = 3;
085
086    /** The wrapper to read bits for the packet heads */
087    private PktHeaderBitReader bin;
088
089    /** Reference to the stream where to read from */
090    private RandomAccessIO ehs;
091
092    /**
093     * Maximum number of precincts :
094     *
095     * <ul>
096     * <li> 1st dim: component index.</li>
097     * <li> 2nd dim: resolution level index.</li>
098     * </ul>
099     * */
100    private Point[][] numPrec;
101
102    /** Index of the current tile */
103    private int tIdx;
104
105    /** 
106     * Array containing the coordinates, width, height, indexes, ... of the
107     * precincts in the current tile:
108     * 
109     * <ul>
110     * <li> 1st dim: component index.</li>
111     * <li> 2nd dim: resolution level index.</li>
112     * <li> 3rd dim: precinct index.</li>
113     * </ul>
114     * */
115    private PrecInfo[][][] ppinfo;
116
117    /**
118     * Lblock value used to read code size information in each packet head:
119     *
120     * <ul>
121     * <li> 1st dim: component index.</li>
122     * <li> 2nd dim: resolution level index.</li>
123     * <li> 3rd dim: subband index.</li>
124     * <li> 4th/5th dim: code-block index (vert. and horiz.).</li>
125     * </ul>
126     * */
127    private int[][][][][] lblock;
128
129    /** 
130     * Tag tree used to read inclusion informations in packet's head:
131     *
132     * <ul>   
133     * <li> 1st dim: component index.</li>
134     * <li> 2nd dim: resolution level index.</li>
135     * <li> 3rd dim: precinct index.</li> 
136     * <li> 4th dim: subband index.</li>
137     * */
138    private TagTreeDecoder[][][][] ttIncl;
139
140    /** 
141     * Tag tree used to read bit-depth information in packet's head:
142     * 
143     * <ul>
144     * <li> 1st dim: component index.</li>
145     * <li> 2nd dim: resolution level index.</li>
146     * <li> 3rd dim: precinct index.</li>
147     * <li> 4th dim: subband index.</li>
148     * </ul>
149     * */
150    private TagTreeDecoder[][][][] ttMaxBP;
151
152    /** Number of layers in t he current tile */
153    private int nl = 0;
154
155    /** The number of components */
156    private int nc;
157
158    /** Whether or not SOP marker segment are used */
159    private boolean sopUsed = false;
160
161    /** Whether or not EPH marker are used */
162    private boolean ephUsed = false;
163
164    /** Index of the current packet in the tile. Used with SOP marker
165        segment*/
166    private int pktIdx;
167
168    /** List of code-blocks found in last read packet head (one list
169     * per subband) */
170    private Vector[] cblks;
171
172    /** Number of codeblocks encountered. used for ncb quit condition*/
173    private int ncb;
174
175    /** Maximum number of codeblocks to read before ncb quit condition is
176     * reached */
177    private int maxCB;
178
179    /** Flag indicating whether ncb quit condition has been reached */
180    private boolean ncbQuit;
181
182    /** The tile in which the ncb quit condition was reached */
183    private int tQuit;
184
185    /** The component in which the ncb quit condition was reached */
186    private int cQuit;
187
188    /** The subband in which the ncb quit condition was reached */
189    private int sQuit;
190
191    /** The resolution in which the ncb quit condition was reached */
192    private int rQuit;
193
194    /** The x position of the last code block before ncb quit reached */
195    private int xQuit;
196
197    /** The y position of the last code block before ncb quit reached  */
198    private int yQuit;
199
200    /** True if truncation mode is used. False if it is parsing mode */
201    private boolean isTruncMode;
202
203    /** 
204     * Creates an empty PktDecoder object associated with given decoder
205     * specifications and HeaderDecoder. This object must be initialized
206     * thanks to the restart method before being used.
207     *
208     * @param decSpec The decoder specifications.
209     *
210     * @param hd The HeaderDecoder instance.
211     *
212     * @param ehs The stream where to read data from.
213     *
214     * @param src The bit stream reader agent.
215     *
216     * @param isTruncMode Whether or not truncation mode is required.
217     *
218     * @param maxCB The maximum number of code-blocks to read before ncbquit
219     *
220     * */
221    public PktDecoder(DecoderSpecs decSpec,HeaderDecoder hd,
222                      RandomAccessIO ehs,BitstreamReaderAgent src,
223                      boolean isTruncMode, int maxCB) {
224        this.decSpec = decSpec;
225        this.hd = hd;
226        this.ehs = ehs;
227        this.isTruncMode = isTruncMode;
228        bin = new PktHeaderBitReader(ehs);
229        this.src = src;
230        ncb = 0;
231        ncbQuit = false;
232        this.maxCB = maxCB;
233    }
234
235    /** 
236     * Re-initialize the PktDecoder instance at the beginning of a new tile.
237     * 
238     * @param nc The number of components in this tile
239     *
240     * @param mdl The maximum number of decomposition level in each component
241     * of this tile
242     *
243     * @param nl The number of layers in  this tile
244     *
245     * @param cbI The code-blocks array
246     *
247     * @param pph Flag indicating whether packed packet headers was used
248     *
249     * @param pphbais Stream containing the packed packet headers
250     * */
251    public CBlkInfo[][][][][] restart(int nc,int[] mdl,int nl,
252                                      CBlkInfo[][][][][] cbI, boolean pph,
253                                      ByteArrayInputStream pphbais) {
254        this.nc = nc;
255        this.nl = nl;
256        this.tIdx = src.getTileIdx();
257        this.pph = pph;
258        this.pphbais = pphbais;
259
260        sopUsed = ((Boolean)decSpec.sops.getTileDef(tIdx)).booleanValue();
261        pktIdx = 0;
262        ephUsed = ((Boolean)decSpec.ephs.getTileDef(tIdx)).booleanValue();
263
264        cbI = new CBlkInfo[nc][][][][];
265        lblock = new int[nc][][][][];
266        ttIncl = new TagTreeDecoder[nc][][][];
267        ttMaxBP = new TagTreeDecoder[nc][][][];
268        numPrec = new Point[nc][];
269        ppinfo = new PrecInfo[nc][][];
270
271        // Used to compute the maximum number of precincts for each resolution
272        // level
273        int tcx0, tcy0, tcx1, tcy1; // Current tile position in the domain of
274        // the image component
275        int trx0, try0, trx1, try1; // Current tile position in the reduced
276        // resolution image domain
277        int xrsiz, yrsiz; // Component sub-sampling factors
278
279        SubbandSyn root,sb;
280        int mins,maxs;
281        Point nBlk = null;
282        int cb0x = src.getCbULX();
283        int cb0y = src.getCbULY();
284
285        for(int c=0; c<nc; c++) {
286            cbI[c] = new CBlkInfo[mdl[c]+1][][][];
287            lblock[c] = new int[mdl[c]+1][][][];
288            ttIncl[c] = new TagTreeDecoder[mdl[c]+1][][];
289            ttMaxBP[c] = new TagTreeDecoder[mdl[c]+1][][];
290            numPrec[c] = new Point[mdl[c]+1];
291            ppinfo[c] = new PrecInfo[mdl[c]+1][];
292
293            // Get the tile-component coordinates on the reference grid
294            tcx0 = src.getResULX(c,mdl[c]);
295            tcy0 = src.getResULY(c,mdl[c]);
296            tcx1 = tcx0 + src.getTileCompWidth(tIdx,c,mdl[c]);
297            tcy1 = tcy0 + src.getTileCompHeight(tIdx,c,mdl[c]);
298
299            for(int r=0; r<=mdl[c]; r++) {
300
301                // Tile's coordinates in the reduced resolution image domain
302                trx0 = (int)Math.ceil(tcx0/(double)(1<<(mdl[c]-r)));
303                try0 = (int)Math.ceil(tcy0/(double)(1<<(mdl[c]-r)));
304                trx1 = (int)Math.ceil(tcx1/(double)(1<<(mdl[c]-r)));
305                try1 = (int)Math.ceil(tcy1/(double)(1<<(mdl[c]-r)));
306
307                // Calculate the maximum number of precincts for each
308                // resolution level taking into account tile specific options.
309                double twoppx = (double)getPPX(tIdx,c,r);
310                double twoppy = (double)getPPY(tIdx,c,r);
311                numPrec[c][r] = new Point();
312                if (trx1>trx0) {
313                    numPrec[c][r].x = (int)Math.ceil((trx1-cb0x)/twoppx)
314                        - (int)Math.floor((trx0-cb0x)/twoppx);
315                } else {
316                    numPrec[c][r].x = 0;
317                }
318                if (try1>try0) {
319                    numPrec[c][r].y = (int)Math.ceil((try1-cb0y)/twoppy)
320                        - (int)Math.floor((try0-cb0y)/twoppy);
321                } else {
322                    numPrec[c][r].y = 0;
323                }
324
325                // First and last subbands indexes
326                mins = (r==0) ? 0 : 1;
327                maxs = (r==0) ? 1 : 4;
328
329                int maxPrec = numPrec[c][r].x * numPrec[c][r].y;
330
331                ttIncl[c][r] = new TagTreeDecoder[maxPrec][maxs+1];
332                ttMaxBP[c][r] = new TagTreeDecoder[maxPrec][maxs+1];
333                cbI[c][r] = new CBlkInfo[maxs+1][][];
334                lblock[c][r] = new int[maxs+1][][];
335
336                ppinfo[c][r] = new PrecInfo[maxPrec];
337                fillPrecInfo(c,r,mdl[c]);
338
339                root = (SubbandSyn)src.getSynSubbandTree(tIdx,c);
340                for(int s=mins; s<maxs; s++){
341                    sb = (SubbandSyn)root.getSubbandByIdx(r,s);
342                    nBlk = sb.numCb;
343
344                    cbI[c][r][s] = new CBlkInfo[nBlk.y][nBlk.x];
345                    lblock[c][r][s] = new int[nBlk.y][nBlk.x];
346
347                    for(int i=nBlk.y-1;i>=0;i--) {
348                        ArrayUtil.intArraySet(lblock[c][r][s][i],INIT_LBLOCK);
349                    }
350                } // loop on subbands
351            } // End loop on resolution levels
352        } // End loop on components
353
354        return cbI;
355    }
356
357    /** 
358     * Retrives precincts and code-blocks coordinates in the given resolution,
359     * level and component. Finishes TagTreeEncoder initialization as well.
360     *
361     * @param c Component index.
362     *
363     * @param r Resolution level index.
364     *
365     * @param mdl Number of decomposition level in component <tt>c</tt>.
366     * */
367    private void fillPrecInfo(int c,int r,int mdl) {
368        if(ppinfo[c][r].length==0) return; // No precinct in this
369        // resolution level
370
371        Point tileI = src.getTile(null);
372        Point nTiles = src.getNumTiles(null);
373
374        int xsiz,ysiz,x0siz,y0siz;
375        int xt0siz,yt0siz;
376        int xtsiz,ytsiz;
377
378        xt0siz = src.getTilePartULX();
379        yt0siz = src.getTilePartULY();
380        xtsiz = src.getNomTileWidth();
381        ytsiz = src.getNomTileHeight();
382        x0siz = hd.getImgULX();
383        y0siz = hd.getImgULY();
384        xsiz = hd.getImgWidth();
385        ysiz = hd.getImgHeight();
386
387        int tx0 = (tileI.x==0) ? x0siz : xt0siz+tileI.x*xtsiz;
388        int ty0 = (tileI.y==0) ? y0siz : yt0siz+tileI.y*ytsiz;
389        int tx1 = (tileI.x!=nTiles.x-1) ? xt0siz+(tileI.x+1)*xtsiz : xsiz;
390        int ty1 = (tileI.y!=nTiles.y-1) ? yt0siz+(tileI.y+1)*ytsiz : ysiz;
391
392        int xrsiz = hd.getCompSubsX(c);
393        int yrsiz = hd.getCompSubsY(c);
394
395        int tcx0 = src.getResULX(c,mdl);
396        int tcy0 = src.getResULY(c,mdl);
397        int tcx1 = tcx0 + src.getTileCompWidth(tIdx,c,mdl);
398        int tcy1 = tcy0 + src.getTileCompHeight(tIdx,c,mdl);
399
400        int ndl = mdl-r;
401        int trx0 = (int)Math.ceil(tcx0/(double)(1<<ndl));
402        int try0 = (int)Math.ceil(tcy0/(double)(1<<ndl));
403        int trx1 = (int)Math.ceil(tcx1/(double)(1<<ndl));
404        int try1 = (int)Math.ceil(tcy1/(double)(1<<ndl));
405
406        int cb0x = src.getCbULX();
407        int cb0y = src.getCbULY();
408
409        double twoppx = (double)getPPX(tIdx,c,r);
410        double twoppy = (double)getPPY(tIdx,c,r);
411        int twoppx2 = (int)(twoppx/2);
412        int twoppy2 = (int)(twoppy/2);
413
414        // Precincts are located at (cb0x+i*twoppx,cb0y+j*twoppy)
415        // Valid precincts are those which intersect with the current
416        // resolution level
417        int maxPrec = ppinfo[c][r].length;
418        int nPrec = 0;
419
420        int istart = (int)Math.floor((try0-cb0y)/twoppy);
421        int iend = (int)Math.floor((try1-1-cb0y)/twoppy);
422        int jstart = (int)Math.floor((trx0-cb0x)/twoppx);
423        int jend = (int)Math.floor((trx1-1-cb0x)/twoppx);
424
425        int acb0x,acb0y;
426
427        SubbandSyn root = src.getSynSubbandTree(tIdx,c);
428        SubbandSyn sb = null;
429
430        int p0x,p0y,p1x,p1y; // Precinct projection in subband
431        int s0x,s0y,s1x,s1y; // Active subband portion
432        int cw,ch;
433        int kstart,kend,lstart,lend,k0,l0;
434        int prg_ulx,prg_uly;
435        int prg_w = (int)twoppx<<ndl;
436        int prg_h = (int)twoppy<<ndl;
437        int tmp1,tmp2;
438
439        CBlkCoordInfo cb;
440
441        for(int i=istart; i<=iend; i++) { // Vertical precincts
442            for(int j=jstart; j<=jend; j++,nPrec++) { // Horizontal precincts
443                if(j==jstart && (trx0-cb0x)%(xrsiz*((int)twoppx))!=0) {
444                    prg_ulx = tx0;
445                } else {
446                    prg_ulx = cb0x+j*xrsiz*((int)twoppx<<ndl);
447                }
448                if(i==istart && (try0-cb0y)%(yrsiz*((int)twoppy))!=0) {
449                    prg_uly = ty0;
450                } else {
451                    prg_uly = cb0y+i*yrsiz*((int)twoppy<<ndl);
452                }
453
454                ppinfo[c][r][nPrec] =
455                    new PrecInfo(r,(int)(cb0x+j*twoppx),(int)(cb0y+i*twoppy),
456                                 (int)twoppx,(int)twoppy,
457                                 prg_ulx,prg_uly,prg_w,prg_h);
458
459                if(r==0) { // LL subband
460                    acb0x = cb0x;
461                    acb0y = cb0y;
462
463                    p0x = acb0x+j*(int)twoppx;
464                    p1x = p0x + (int)twoppx;
465                    p0y = acb0y+i*(int)twoppy;
466                    p1y = p0y + (int)twoppy;
467
468                    sb = (SubbandSyn)root.getSubbandByIdx(0,0);
469                    s0x = (p0x<sb.ulcx) ? sb.ulcx : p0x;
470                    s1x = (p1x>sb.ulcx+sb.w) ? sb.ulcx+sb.w : p1x;
471                    s0y = (p0y<sb.ulcy) ? sb.ulcy : p0y;
472                    s1y = (p1y>sb.ulcy+sb.h) ? sb.ulcy+sb.h : p1y;
473
474                    // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch)
475                    cw = sb.nomCBlkW;
476                    ch = sb.nomCBlkH;
477                    k0 = (int)Math.floor((sb.ulcy-acb0y)/(double)ch);
478                    kstart = (int)Math.floor((s0y-acb0y)/(double)ch);
479                    kend = (int)Math.floor((s1y-1-acb0y)/(double)ch);
480                    l0 = (int)Math.floor((sb.ulcx-acb0x)/(double)cw);
481                    lstart = (int)Math.floor((s0x-acb0x)/(double)cw);
482                    lend = (int)Math.floor((s1x-1-acb0x)/(double)cw);
483
484                    if(s1x-s0x<=0 || s1y-s0y<=0) {
485                        ppinfo[c][r][nPrec].nblk[0] = 0;
486                        ttIncl[c][r][nPrec][0] = new TagTreeDecoder(0,0);
487                        ttMaxBP[c][r][nPrec][0] = new TagTreeDecoder(0,0);
488                    } else {
489                        ttIncl[c][r][nPrec][0] =
490                            new TagTreeDecoder(kend-kstart+1,lend-lstart+1);
491                        ttMaxBP[c][r][nPrec][0] =
492                            new TagTreeDecoder(kend-kstart+1,lend-lstart+1);
493                        ppinfo[c][r][nPrec].cblk[0] =
494                            new CBlkCoordInfo[kend-kstart+1][lend-lstart+1];
495                        ppinfo[c][r][nPrec].
496                            nblk[0] = (kend-kstart+1)*(lend-lstart+1);
497
498                        for(int k=kstart; k<=kend; k++) { // Vertical cblks
499                            for(int l=lstart; l<=lend; l++) { // Horiz. cblks
500                                cb = new CBlkCoordInfo(k-k0,l-l0);
501                                if(l==l0) {
502                                    cb.ulx = sb.ulx;
503                                } else {
504                                    cb.ulx = sb.ulx+l*cw-(sb.ulcx-acb0x);
505                                }
506                                if(k==k0) {
507                                    cb.uly = sb.uly;
508                                } else {
509                                    cb.uly = sb.uly+k*ch-(sb.ulcy-acb0y);
510                                }
511                                tmp1 = acb0x+l*cw;
512                                tmp1 = (tmp1>sb.ulcx) ? tmp1 : sb.ulcx;
513                                tmp2 = acb0x+(l+1)*cw;
514                                tmp2 = (tmp2>sb.ulcx+sb.w) ?
515                                    sb.ulcx+sb.w : tmp2;
516                                cb.w = tmp2-tmp1;
517                                tmp1 = acb0y+k*ch;
518                                tmp1 = (tmp1>sb.ulcy) ? tmp1 : sb.ulcy;
519                                tmp2 = acb0y+(k+1)*ch;
520                                tmp2 = (tmp2>sb.ulcy+sb.h) ?
521                                    sb.ulcy+sb.h : tmp2;
522                                cb.h = tmp2-tmp1;
523                                ppinfo[c][r][nPrec].
524                                    cblk[0][k-kstart][l-lstart] = cb;
525                            } // Horizontal code-blocks
526                        } // Vertical code-blocks
527                    }
528                } else { // HL, LH and HH subbands
529                    // HL subband
530                    acb0x = 0;
531                    acb0y = cb0y;
532
533                    p0x = acb0x+j*twoppx2;
534                    p1x = p0x + twoppx2;
535                    p0y = acb0y+i*twoppy2;
536                    p1y = p0y + twoppy2;
537
538                    sb = (SubbandSyn)root.getSubbandByIdx(r,1);
539                    s0x = (p0x<sb.ulcx) ? sb.ulcx : p0x;
540                    s1x = (p1x>sb.ulcx+sb.w) ? sb.ulcx+sb.w : p1x;
541                    s0y = (p0y<sb.ulcy) ? sb.ulcy : p0y;
542                    s1y = (p1y>sb.ulcy+sb.h) ? sb.ulcy+sb.h : p1y;
543
544                    // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch)
545                    cw = sb.nomCBlkW;
546                    ch = sb.nomCBlkH;
547                    k0 = (int)Math.floor((sb.ulcy-acb0y)/(double)ch);
548                    kstart = (int)Math.floor((s0y-acb0y)/(double)ch);
549                    kend = (int)Math.floor((s1y-1-acb0y)/(double)ch);
550                    l0 = (int)Math.floor((sb.ulcx-acb0x)/(double)cw);
551                    lstart = (int)Math.floor((s0x-acb0x)/(double)cw);
552                    lend = (int)Math.floor((s1x-1-acb0x)/(double)cw);
553
554                    if(s1x-s0x<=0 || s1y-s0y<=0) {
555                        ppinfo[c][r][nPrec].nblk[1] = 0;
556                        ttIncl[c][r][nPrec][1] = new TagTreeDecoder(0,0);
557                        ttMaxBP[c][r][nPrec][1] = new TagTreeDecoder(0,0);
558                    } else {
559                        ttIncl[c][r][nPrec][1] =
560                            new TagTreeDecoder(kend-kstart+1,lend-lstart+1);
561                        ttMaxBP[c][r][nPrec][1] =
562                            new TagTreeDecoder(kend-kstart+1,lend-lstart+1);
563                        ppinfo[c][r][nPrec].cblk[1] =
564                            new CBlkCoordInfo[kend-kstart+1][lend-lstart+1];
565                        ppinfo[c][r][nPrec].
566                            nblk[1] = (kend-kstart+1)*(lend-lstart+1);
567
568                        for(int k=kstart; k<=kend; k++) { // Vertical cblks
569                            for(int l=lstart; l<=lend; l++) { // Horiz. cblks
570                                cb = new CBlkCoordInfo(k-k0,l-l0);
571                                if(l==l0) {
572                                    cb.ulx = sb.ulx;
573                                } else {
574                                    cb.ulx = sb.ulx+l*cw-(sb.ulcx-acb0x);
575                                }
576                                if(k==k0) {
577                                    cb.uly = sb.uly;
578                                } else {
579                                    cb.uly = sb.uly+k*ch-(sb.ulcy-acb0y);
580                                }
581                                tmp1 = acb0x+l*cw;
582                                tmp1 = (tmp1>sb.ulcx) ? tmp1 : sb.ulcx;
583                                tmp2 = acb0x+(l+1)*cw;
584                                tmp2 = (tmp2>sb.ulcx+sb.w) ?
585                                    sb.ulcx+sb.w : tmp2;
586                                cb.w = tmp2-tmp1;
587                                tmp1 = acb0y+k*ch;
588                                tmp1 = (tmp1>sb.ulcy) ? tmp1 : sb.ulcy;
589                                tmp2 = acb0y+(k+1)*ch;
590                                tmp2 = (tmp2>sb.ulcy+sb.h) ?
591                                    sb.ulcy+sb.h : tmp2;
592                                cb.h = tmp2-tmp1;
593                                ppinfo[c][r][nPrec].
594                                    cblk[1][k-kstart][l-lstart] = cb;
595                            } // Horizontal code-blocks
596                        } // Vertical code-blocks
597                    }
598
599                    // LH subband
600                    acb0x = cb0x;
601                    acb0y = 0;
602
603                    p0x = acb0x+j*twoppx2;
604                    p1x = p0x + twoppx2;
605                    p0y = acb0y+i*twoppy2;
606                    p1y = p0y + twoppy2;
607
608                    sb = (SubbandSyn)root.getSubbandByIdx(r,2);
609                    s0x = (p0x<sb.ulcx) ? sb.ulcx : p0x;
610                    s1x = (p1x>sb.ulcx+sb.w) ? sb.ulcx+sb.w : p1x;
611                    s0y = (p0y<sb.ulcy) ? sb.ulcy : p0y;
612                    s1y = (p1y>sb.ulcy+sb.h) ? sb.ulcy+sb.h : p1y;
613
614                    // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch)
615                    cw = sb.nomCBlkW;
616                    ch = sb.nomCBlkH;
617                    k0 = (int)Math.floor((sb.ulcy-acb0y)/(double)ch);
618                    kstart = (int)Math.floor((s0y-acb0y)/(double)ch);
619                    kend = (int)Math.floor((s1y-1-acb0y)/(double)ch);
620                    l0 = (int)Math.floor((sb.ulcx-acb0x)/(double)cw);
621                    lstart = (int)Math.floor((s0x-acb0x)/(double)cw);
622                    lend = (int)Math.floor((s1x-1-acb0x)/(double)cw);
623
624                    if(s1x-s0x<=0 || s1y-s0y<=0) {
625                        ppinfo[c][r][nPrec].nblk[2] = 0;
626                        ttIncl[c][r][nPrec][2] = new TagTreeDecoder(0,0);
627                        ttMaxBP[c][r][nPrec][2] = new TagTreeDecoder(0,0);
628                    } else {
629                        ttIncl[c][r][nPrec][2] =
630                            new TagTreeDecoder(kend-kstart+1,lend-lstart+1);
631                        ttMaxBP[c][r][nPrec][2] =
632                            new TagTreeDecoder(kend-kstart+1,lend-lstart+1);
633                        ppinfo[c][r][nPrec].cblk[2] =
634                            new CBlkCoordInfo[kend-kstart+1][lend-lstart+1];
635                        ppinfo[c][r][nPrec].
636                            nblk[2] = (kend-kstart+1)*(lend-lstart+1);
637
638                        for(int k=kstart; k<=kend; k++) { // Vertical cblks
639                            for(int l=lstart; l<=lend; l++) { // Horiz cblks
640                                cb = new CBlkCoordInfo(k-k0,l-l0);
641                                if(l==l0) {
642                                    cb.ulx = sb.ulx;
643                                } else {
644                                    cb.ulx = sb.ulx+l*cw-(sb.ulcx-acb0x);
645                                }
646                                if(k==k0) {
647                                    cb.uly = sb.uly;
648                                } else {
649                                    cb.uly = sb.uly+k*ch-(sb.ulcy-acb0y);
650                                }
651                                tmp1 = acb0x+l*cw;
652                                tmp1 = (tmp1>sb.ulcx) ? tmp1 : sb.ulcx;
653                                tmp2 = acb0x+(l+1)*cw;
654                                tmp2 = (tmp2>sb.ulcx+sb.w) ?
655                                    sb.ulcx+sb.w : tmp2;
656                                cb.w = tmp2-tmp1;
657                                tmp1 = acb0y+k*ch;
658                                tmp1 = (tmp1>sb.ulcy) ? tmp1 : sb.ulcy;
659                                tmp2 = acb0y+(k+1)*ch;
660                                tmp2 = (tmp2>sb.ulcy+sb.h) ?
661                                    sb.ulcy+sb.h : tmp2;
662                                cb.h = tmp2-tmp1;
663                                ppinfo[c][r][nPrec].
664                                    cblk[2][k-kstart][l-lstart] = cb;
665                            } // Horizontal code-blocks
666                        } // Vertical code-blocks
667                    }
668
669                    // HH subband
670                    acb0x = 0;
671                    acb0y = 0;
672
673                    p0x = acb0x+j*twoppx2;
674                    p1x = p0x + twoppx2;
675                    p0y = acb0y+i*twoppy2;
676                    p1y = p0y + twoppy2;
677
678                    sb = (SubbandSyn)root.getSubbandByIdx(r,3);
679                    s0x = (p0x<sb.ulcx) ? sb.ulcx : p0x;
680                    s1x = (p1x>sb.ulcx+sb.w) ? sb.ulcx+sb.w : p1x;
681                    s0y = (p0y<sb.ulcy) ? sb.ulcy : p0y;
682                    s1y = (p1y>sb.ulcy+sb.h) ? sb.ulcy+sb.h : p1y;
683
684                    // Code-blocks are located at (acb0x+k*cw,acb0y+l*ch)
685                    cw = sb.nomCBlkW;
686                    ch = sb.nomCBlkH;
687                    k0 = (int)Math.floor((sb.ulcy-acb0y)/(double)ch);
688                    kstart = (int)Math.floor((s0y-acb0y)/(double)ch);
689                    kend = (int)Math.floor((s1y-1-acb0y)/(double)ch);
690                    l0 = (int)Math.floor((sb.ulcx-acb0x)/(double)cw);
691                    lstart = (int)Math.floor((s0x-acb0x)/(double)cw);
692                    lend = (int)Math.floor((s1x-1-acb0x)/(double)cw);
693
694                    if(s1x-s0x<=0 || s1y-s0y<=0) {
695                        ppinfo[c][r][nPrec].nblk[3] = 0;
696                        ttIncl[c][r][nPrec][3] = new TagTreeDecoder(0,0);
697                        ttMaxBP[c][r][nPrec][3] = new TagTreeDecoder(0,0);
698                    } else {
699                        ttIncl[c][r][nPrec][3] =
700                            new TagTreeDecoder(kend-kstart+1,lend-lstart+1);
701                        ttMaxBP[c][r][nPrec][3] =
702                            new TagTreeDecoder(kend-kstart+1,lend-lstart+1);
703                        ppinfo[c][r][nPrec].cblk[3] =
704                            new CBlkCoordInfo[kend-kstart+1][lend-lstart+1];
705                        ppinfo[c][r][nPrec].
706                            nblk[3] = (kend-kstart+1)*(lend-lstart+1);
707
708                        for(int k=kstart; k<=kend; k++) { // Vertical cblks
709                            for(int l=lstart; l<=lend; l++) { // Horiz cblks
710                                cb = new CBlkCoordInfo(k-k0,l-l0);
711                                if(l==l0) {
712                                    cb.ulx = sb.ulx;
713                                } else {
714                                    cb.ulx = sb.ulx+l*cw-(sb.ulcx-acb0x);
715                                }
716                                if(k==k0) {
717                                    cb.uly = sb.uly;
718                                } else {
719                                    cb.uly = sb.uly+k*ch-(sb.ulcy-acb0y);
720                                }
721                                tmp1 = acb0x+l*cw;
722                                tmp1 = (tmp1>sb.ulcx) ? tmp1 : sb.ulcx;
723                                tmp2 = acb0x+(l+1)*cw;
724                                tmp2 = (tmp2>sb.ulcx+sb.w) ?
725                                    sb.ulcx+sb.w : tmp2;
726                                cb.w = tmp2-tmp1;
727                                tmp1 = acb0y+k*ch;
728                                tmp1 = (tmp1>sb.ulcy) ? tmp1 : sb.ulcy;
729                                tmp2 = acb0y+(k+1)*ch;
730                                tmp2 = (tmp2>sb.ulcy+sb.h) ?
731                                    sb.ulcy+sb.h : tmp2;
732                                cb.h = tmp2-tmp1;
733                                ppinfo[c][r][nPrec].
734                                    cblk[3][k-kstart][l-lstart] = cb;
735                            } // Horizontal code-blocks
736                        } // Vertical code-blocks
737                    }
738
739                }
740            } // Horizontal precincts
741        } // Vertical precincts
742   }
743
744   /** 
745     * Gets the number of precincts in a given component and resolution level.
746     *
747     * @param c Component index
748     *
749     * @param r Resolution index
750     * */
751    public int getNumPrecinct(int c,int r) {
752        return numPrec[c][r].x*numPrec[c][r].y;
753    }
754
755    /** 
756     * Read specified packet head and found length of each code-block's piece
757     * of codewords as well as number of skipped most significant bit-planes.
758     *
759     * @param l layer index
760     *
761     * @param r Resolution level index
762     *
763     * @param c Component index
764     *
765     * @param p Precinct index
766     *
767     * @param cbI CBlkInfo array of relevant component and resolution
768     * level.
769     *
770     * @param nb The number of bytes to read in each tile before reaching
771     * output rate (used by truncation mode)
772     *
773     * @return True if specified output rate or EOF is reached.
774     * */
775    public boolean readPktHead(int l,int r,int c,int p,CBlkInfo[][][] cbI,
776                               int[] nb) throws IOException {
777
778        CBlkInfo ccb;
779        int nSeg;                   // number of segment to read
780        int cbLen;                  // Length of cblk's code-words
781        int ltp;                    // last truncation point index
782        int passtype;               // coding pass type
783        TagTreeDecoder tdIncl,tdBD;
784        int tmp,tmp2,totnewtp,lblockCur,tpidx;
785        int sumtotnewtp = 0;
786        Point cbc;
787        int startPktHead = ehs.getPos();
788        if(startPktHead>=ehs.length()) {
789            // EOF reached at the beginning of this packet head
790            return true;
791        }
792        int tIdx = src.getTileIdx();
793        PktHeaderBitReader bin;
794        int mend,nend;
795        int b;
796        SubbandSyn sb;
797        SubbandSyn root = src.getSynSubbandTree(tIdx,c);
798
799        // If packed packet headers was used, use separate stream for reading
800        // of packet headers
801        if(pph) {
802            bin = new PktHeaderBitReader(pphbais);
803        } else {
804            bin = this.bin;
805        }
806
807        int mins = (r==0) ? 0 : 1;
808        int maxs = (r==0) ? 1 : 4;
809
810        boolean precFound = false;
811        for(int s=mins; s<maxs; s++) {
812            if(p<ppinfo[c][r].length) {
813                precFound = true;
814            }
815        }
816        if(!precFound) {
817            return false;
818        }
819
820        PrecInfo prec = ppinfo[c][r][p];
821
822        // Synchronize for bit reading
823        bin.sync();
824
825        // If packet is empty there is no info in it (i.e. no code-blocks)
826        if(bin.readBit()==0) {
827            // No code-block is included
828            cblks = new Vector[maxs+1];
829            for(int s=mins; s<maxs; s++){
830                cblks[s] = new Vector();
831            }
832            pktIdx++;
833
834            // If truncation mode, checks if output rate is reached
835            // unless ncb quit condition is used in which case headers
836            // are not counted
837            if(isTruncMode && maxCB == -1) {
838                tmp = ehs.getPos()-startPktHead;
839                if(tmp>nb[tIdx]) {
840                    nb[tIdx] = 0;
841                    return true;
842                } else {
843                    nb[tIdx] -= tmp;
844                }
845            }
846
847            // Read EPH marker if needed
848            if(ephUsed) {
849                readEPHMarker(bin);
850            }
851            return false;
852        }
853
854        // Packet is not empty => decode info
855        // Loop on each subband in this resolution level
856        if(cblks==null || cblks.length<maxs+1) {
857            cblks = new Vector[maxs+1];
858        }
859
860        for(int s=mins; s<maxs; s++) {
861            if(cblks[s]==null) {
862                cblks[s] = new Vector();
863            } else {
864                cblks[s].removeAllElements();
865            }
866            sb = (SubbandSyn)root.getSubbandByIdx(r,s);
867            // No code-block in this precinct
868            if(prec.nblk[s]==0) {
869                // Go to next subband
870                continue;
871            }
872
873            tdIncl = ttIncl[c][r][p][s];
874            tdBD = ttMaxBP[c][r][p][s];
875
876            mend = (prec.cblk[s]==null) ? 0 : prec.cblk[s].length;
877            for(int m=0; m<mend; m++) { // Vertical code-blocks
878                nend = (prec.cblk[s][m]==null) ? 0 : prec.cblk[s][m].length;
879                for (int n=0; n<nend; n++) { // Horizontal code-blocks
880                    cbc = prec.cblk[s][m][n].idx;
881                    b = cbc.x+cbc.y*sb.numCb.x;
882
883                    ccb = cbI[s][cbc.y][cbc.x];
884
885                    try {
886                        // If code-block not included in previous layer(s)
887                        if(ccb==null || ccb.ctp==0) {
888                            if(ccb==null) {
889                                ccb = cbI[s][cbc.y][cbc.x] =
890                                    new CBlkInfo(prec.cblk[s][m][n].ulx,
891                                                 prec.cblk[s][m][n].uly,
892                                                 prec.cblk[s][m][n].w,
893                                                 prec.cblk[s][m][n].h,nl);
894                            }
895                            ccb.pktIdx[l] = pktIdx;
896
897                            // Read inclusion using tag-tree
898                            tmp = tdIncl.update(m,n,l+1,bin);
899                            if(tmp>l) { // Not included
900                                continue;
901                            }
902
903                            // Read bitdepth using tag-tree
904                            tmp = 1;// initialization
905                            for(tmp2=1; tmp>=tmp2; tmp2++) {
906                                tmp = tdBD.update(m,n,tmp2,bin);
907                            }
908                            ccb.msbSkipped = tmp2-2;
909
910                            // New code-block => at least one truncation point
911                            totnewtp = 1;
912                            ccb.addNTP(l,0);
913
914                            // Check whether ncb quit condition is reached
915                            ncb++;
916                            if(maxCB != -1 && !ncbQuit && ncb == maxCB){
917                                // ncb quit contidion reached
918                                ncbQuit = true;
919                                tQuit = tIdx;
920                                cQuit = c;
921                                sQuit = s;
922                                rQuit = r;
923                                xQuit = cbc.x;
924                                yQuit = cbc.y;
925                           }
926
927                        } else { // If code-block already included in one of
928                            // the previous layers.
929
930                            ccb.pktIdx[l] = pktIdx;
931
932                            // If not inclused
933                            if(bin.readBit()!=1) {
934                                continue;
935                            }
936
937                            // At least 1 more truncation point than
938                            // prev. packet
939                            totnewtp = 1;
940                        }
941
942                        // Read new truncation points
943                        if(bin.readBit()==1) {// if bit is 1
944                            totnewtp++;
945
946                            // if next bit is 0 do nothing
947                            if(bin.readBit()==1) {//if is 1
948                                totnewtp++;
949
950                                tmp = bin.readBits(2);
951                                totnewtp += tmp;
952                                // If next 2 bits are not 11 do nothing
953                                if(tmp==0x3) { //if 11
954                                    tmp = bin.readBits(5);
955                                    totnewtp += tmp;
956
957                                // If next 5 bits are not 11111 do nothing
958                                    if(tmp==0x1F) { //if 11111
959                                        totnewtp += bin.readBits(7);
960                                    }
961                                }
962                            }
963                        }
964                        ccb.addNTP(l,totnewtp);
965                        sumtotnewtp += totnewtp;
966                        cblks[s].addElement(prec.cblk[s][m][n]);
967
968                        // Code-block length
969
970                        // -- Compute the number of bit to read to obtain
971                        // code-block length.  
972                        // numBits = betaLamda + log2(totnewtp);
973
974                        // The length is signalled for each segment in
975                        // addition to the final one. The total length is the
976                        // sum of all segment lengths.
977
978                        // If regular termination in use, then there is one
979                        // segment per truncation point present. Otherwise, if
980                        // selective arithmetic bypass coding mode is present,
981                        // then there is one termination per bypass/MQ and
982                        // MQ/bypass transition. Otherwise the only
983                        // termination is at the end of the code-block.
984                        int options =
985                            ((Integer)decSpec.ecopts.getTileCompVal(tIdx,c)).
986                            intValue();
987
988                        if( (options&OPT_TERM_PASS) != 0) {
989                            // Regular termination in use, one segment per new
990                            // pass (i.e. truncation point)
991                            nSeg = totnewtp;
992                        } else if( (options&OPT_BYPASS) != 0) {
993                            // Selective arithmetic coding bypass coding mode
994                            // in use, but no regular termination 1 segment up
995                            // to the end of the last pass of the 4th most
996                            // significant bit-plane, and, in each following
997                            // bit-plane, one segment upto the end of the 2nd
998                            // pass and one upto the end of the 3rd pass.
999
1000                            if(ccb.ctp<=FIRST_BYPASS_PASS_IDX) {
1001                                nSeg = 1;
1002                            } else {
1003                                nSeg = 1; // One at least for last pass
1004                                // And one for each other terminated pass
1005                                for(tpidx = ccb.ctp-totnewtp;
1006                                    tpidx < ccb.ctp-1; tpidx++) {
1007                                    if(tpidx >= FIRST_BYPASS_PASS_IDX-1) {
1008                                        passtype =
1009                                            (tpidx+NUM_EMPTY_PASSES_IN_MS_BP)%
1010                                            NUM_PASSES;
1011                                        if (passtype==1 || passtype==2) {
1012                                            // bypass coding just before MQ
1013                                            // pass or MQ pass just before
1014                                            // bypass coding => terminated
1015                                            nSeg++;
1016                                        }
1017                                    }
1018                                }
1019                            }
1020                        } else {
1021                            // Nothing special in use, just one segment
1022                            nSeg = 1;
1023                        }
1024
1025                        // Reads lblock increment (common to all segments)
1026                        while(bin.readBit()!=0) {
1027                            lblock[c][r][s][cbc.y][cbc.x]++;
1028                        }
1029
1030                        if(nSeg==1) { // Only one segment in packet
1031                            cbLen = bin.readBits(lblock[c][r][s][cbc.y][cbc.x]+
1032                                                 MathUtil.log2(totnewtp));
1033                        } else {
1034                            // We must read one length per segment
1035                            ccb.segLen[l] = new int[nSeg];
1036                            cbLen = 0;
1037                            int j;
1038                            if((options&OPT_TERM_PASS) != 0) {
1039                                // Regular termination: each pass is terminated
1040                                for(tpidx=ccb.ctp-totnewtp,j=0;
1041                                    tpidx<ccb.ctp;tpidx++,j++) {
1042
1043                                    lblockCur = lblock[c][r][s][cbc.y][cbc.x];
1044
1045                                    tmp = bin.readBits(lblockCur);
1046                                    ccb.segLen[l][j] = tmp;
1047                                    cbLen += tmp;
1048                                }
1049                            } else {
1050                                // Bypass coding: only some passes are
1051                                // terminated
1052                                ltp = ccb.ctp-totnewtp-1;
1053                                for(tpidx = ccb.ctp-totnewtp, j=0;
1054                                    tpidx<ccb.ctp-1;tpidx++) {
1055                                    if(tpidx >= FIRST_BYPASS_PASS_IDX-1) {
1056                                        passtype =
1057                                            (tpidx+NUM_EMPTY_PASSES_IN_MS_BP)%
1058                                            NUM_PASSES;
1059                                        if (passtype==0) continue;
1060
1061                                        lblockCur =
1062                                            lblock[c][r][s][cbc.y][cbc.x];
1063                                        tmp =
1064                                            bin.
1065                                            readBits(lblockCur+
1066                                                     MathUtil.log2(tpidx-ltp));
1067                                        ccb.segLen[l][j] = tmp;
1068                                        cbLen += tmp;
1069                                        ltp = tpidx;
1070                                        j++;
1071                                    }
1072                                }
1073                                // Last pass has always the length sent
1074                                lblockCur = lblock[c][r][s][cbc.y][cbc.x];
1075                                tmp = bin.readBits(lblockCur+
1076                                                   MathUtil.log2(tpidx-ltp));
1077                                cbLen += tmp;
1078                                ccb.segLen[l][j] = tmp;
1079                            }
1080                        }
1081                        ccb.len[l] = cbLen;
1082
1083                        // If truncation mode, checks if output rate is reached
1084                        // unless ncb and lbody quit contitions used.
1085                        if(isTruncMode && maxCB==-1) {
1086                            tmp = ehs.getPos()-startPktHead;
1087                            if(tmp>nb[tIdx]) {
1088                                nb[tIdx] = 0;
1089                                // Remove found information in this code-block
1090                                if(l==0) {
1091                                    cbI[s][cbc.y][cbc.x] = null;
1092                                } else {
1093                                    ccb.off[l]=ccb.len[l]=0;
1094                                    ccb.ctp -= ccb.ntp[l];
1095                                    ccb.ntp[l] = 0;
1096                                    ccb.pktIdx[l] = -1;
1097                                }
1098                                return true;
1099                            }
1100                        }
1101
1102                    } catch(EOFException e) {
1103                        // Remove found information in this code-block
1104                        if(l==0) {
1105                            cbI[s][cbc.y][cbc.x] = null;
1106                        } else {
1107                            ccb.off[l]=ccb.len[l]=0;
1108                            ccb.ctp -= ccb.ntp[l];
1109                            ccb.ntp[l] = 0;
1110                            ccb.pktIdx[l] = -1;
1111                        }
1112//                         throw new EOFException();
1113                        return true;
1114                    }
1115                } // End loop on horizontal code-blocks
1116            } // End loop on vertical code-blocks
1117        } // End loop on subbands
1118
1119        // Read EPH marker if needed
1120        if(ephUsed) {
1121            readEPHMarker(bin);
1122        }
1123
1124        pktIdx++;
1125
1126        // If truncation mode, checks if output rate is reached
1127        if(isTruncMode && maxCB == -1) {
1128            tmp = ehs.getPos()-startPktHead;
1129            if(tmp>nb[tIdx]) {
1130                nb[tIdx] = 0;
1131                return true;
1132            } else {
1133                nb[tIdx] -= tmp;
1134            }
1135        }
1136        return false;
1137    }
1138
1139    /** 
1140     * Reads specificied packet body in order to find offset of each
1141     * code-block's piece of codeword. This use the list of found code-blocks
1142     * in previous red packet head.
1143     *
1144     * @param l layer index
1145     *
1146     * @param r Resolution level index
1147     *
1148     * @param c Component index
1149     *
1150     * @param p Precinct index
1151     *
1152     * @param cbI CBlkInfo array of relevant component and resolution
1153     * level.
1154     *
1155     * @param nb The remainding number of bytes to read from the bit stream in
1156     * each tile before reaching the decoding rate (in truncation mode)
1157     *
1158     * @return True if decoding rate is reached 
1159     * */
1160    public boolean readPktBody(int l,int r,int c,int p,CBlkInfo[][][] cbI,
1161                               int[] nb) throws IOException {
1162        int curOff = ehs.getPos();
1163        Point curCB;
1164        CBlkInfo ccb;
1165        boolean stopRead = false;
1166        int tIdx = src.getTileIdx();
1167        Point cbc;
1168
1169        boolean precFound = false;
1170        int mins = (r==0) ? 0 : 1;
1171        int maxs = (r==0) ? 1 : 4;
1172        for(int s=mins; s<maxs; s++) {
1173            if(p<ppinfo[c][r].length) {
1174                precFound = true;
1175            }
1176        }
1177        if(!precFound) {
1178            return false;
1179        }
1180
1181        for(int s=mins; s<maxs; s++) {
1182            for(int numCB=0; numCB<cblks[s].size(); numCB++) {
1183                cbc = ((CBlkCoordInfo)cblks[s].elementAt(numCB)).idx;
1184                ccb = cbI[s][cbc.y][cbc.x];
1185                ccb.off[l] = curOff;
1186                curOff += ccb.len[l];
1187                try {
1188                    ehs.seek(curOff);
1189                } catch(EOFException e) {
1190                    if(l==0) {
1191                        cbI[s][cbc.y][cbc.x] = null;
1192                    } else {
1193                        ccb.off[l] = ccb.len[l]=0;
1194                        ccb.ctp -= ccb.ntp[l];
1195                        ccb.ntp[l] = 0;
1196                        ccb.pktIdx[l] = -1;
1197                    }
1198                    throw new EOFException();
1199                }
1200
1201                // If truncation mode
1202                if(isTruncMode) {
1203                    if(stopRead || ccb.len[l]>nb[tIdx]) {
1204                        // Remove found information in this code-block
1205                        if(l==0) {
1206                            cbI[s][cbc.y][cbc.x] = null;
1207                        } else {
1208                            ccb.off[l] = ccb.len[l] = 0;
1209                            ccb.ctp -= ccb.ntp[l];
1210                            ccb.ntp[l] = 0;
1211                            ccb.pktIdx[l] = -1;
1212                        }
1213                        stopRead = true;
1214                    }
1215                    if(!stopRead) {
1216                        nb[tIdx] -= ccb.len[l];
1217                    }
1218                }
1219                // If ncb quit condition reached
1220                if(ncbQuit && r == rQuit && s == sQuit && cbc.x == xQuit &&
1221                   cbc.y == yQuit && tIdx == tQuit && c == cQuit) {
1222                    cbI[s][cbc.y][cbc.x] = null;
1223                    stopRead = true;
1224                }
1225            } // Loop on code-blocks
1226        } // End loop on subbands
1227
1228        // Seek to the end of the packet
1229        ehs.seek(curOff);
1230
1231        if(stopRead) {
1232            return true;
1233        } else {
1234            return false;
1235        }
1236    }
1237
1238    /**
1239     * Returns the precinct partition width for the specified component,
1240     * resolution level and tile.
1241     *
1242     * @param t the tile index
1243     *
1244     * @param c The index of the component (between 0 and C-1)
1245     *
1246     * @param r The resolution level, from 0 to L.
1247     *
1248     * @return the precinct partition width for the specified component,
1249     * resolution level and tile.
1250     * */
1251    public final int getPPX(int t,int c,int r){
1252        return decSpec.pss.getPPX(t,c,r);
1253    }
1254
1255    /**
1256     * Returns the precinct partition height for the specified component,
1257     * resolution level and tile.
1258     *
1259     * @param t the tile index
1260     *
1261     * @param c The index of the component (between 0 and C-1)
1262     *
1263     * @param rl The resolution level, from 0 to L.
1264     *
1265     * @return the precinct partition height in the specified component, for
1266     * the specified resolution level, for the current tile.
1267     * */
1268    public final int getPPY(int t,int c,int rl) {
1269        return decSpec.pss.getPPY(t,c,rl);
1270    }
1271
1272    /**
1273     * Try to read a SOP marker and check that its sequence number if not out
1274     * of sequence. If so, an error is thrown.
1275     *
1276     * @param nBytes The number of bytes left to read from each tile
1277     *
1278     * @param p Precinct index
1279     *
1280     * @param r Resolution level index
1281     *
1282     * @param c Component index
1283     * */
1284    public boolean readSOPMarker(int[] nBytes,int p,int c,int r)
1285        throws IOException {
1286        int val;
1287        byte sopArray[] = new byte[6];
1288        int tIdx = src.getTileIdx();
1289        int mins = (r==0) ? 0 : 1;
1290        int maxs = (r==0) ? 1 : 4;
1291        boolean precFound = false;
1292        for(int s=mins; s<maxs; s++) {
1293            if(p<ppinfo[c][r].length) {
1294                precFound = true;
1295            }
1296        }
1297        if(!precFound) {
1298            return false;
1299        }
1300
1301        // If SOP markers are not used, return
1302        if(!sopUsed) {
1303            return false;
1304        }
1305
1306        // Check if SOP is used for this packet
1307        int pos = ehs.getPos();
1308        if( (short)((ehs.read()<<8) | ehs.read()) != Markers.SOP ) {
1309            ehs.seek(pos);
1310            return false;
1311        }
1312        ehs.seek(pos);
1313
1314        // If length of SOP marker greater than remaining bytes to read for
1315        // this tile return true
1316        if(nBytes[tIdx]<6) {
1317            return true;
1318        }
1319        nBytes[tIdx] -= 6;
1320
1321        // Read marker into array 'sopArray'
1322        ehs.readFully(sopArray,0,Markers.SOP_LENGTH);
1323
1324        // Check if this is the correct marker
1325        val = sopArray[0];
1326        val <<= 8;
1327        val |= sopArray[1];
1328        if(val!=Markers.SOP) {
1329            throw new Error("Corrupted Bitstream: Could not parse SOP "+
1330                            "marker !");
1331        }
1332
1333        // Check if length is correct
1334        val = (sopArray[2]&0xff);
1335        val <<= 8;
1336        val |= (sopArray[3]&0xff);
1337        if(val!=4) {
1338            throw new Error("Corrupted Bitstream: Corrupted SOP marker !");
1339        }
1340
1341        // Check if sequence number if ok
1342        val = (sopArray[4]&0xff);
1343        val <<= 8;
1344        val |= (sopArray[5]&0xff);
1345
1346        if(!pph && val!=pktIdx) {
1347            throw new Error("Corrupted Bitstream: SOP marker out of "
1348                            +"sequence !");
1349        }
1350        if(pph && val!=pktIdx-1) {
1351            // if packed packet headers are used, packet header was read
1352            // before SOP marker segment
1353            throw new Error("Corrupted Bitstream: SOP marker out of "
1354                            +"sequence !");
1355        }
1356        return false;
1357    }
1358
1359    /**
1360     * Try to read an EPH marker. If it is not possible then an Error is
1361     * thrown.
1362     *
1363     * @param bin The packet header reader to read the EPH marker from
1364     * */
1365    public void readEPHMarker(PktHeaderBitReader bin) throws IOException {
1366        int val;
1367        byte ephArray[] = new byte[2];
1368
1369        if(bin.usebais) {
1370            bin.bais.read(ephArray,0,Markers.EPH_LENGTH);
1371        } else {
1372            bin.in.readFully(ephArray,0,Markers.EPH_LENGTH);
1373        }
1374
1375        // Check if this is the correct marker
1376        val = ephArray[0];
1377        val <<= 8;
1378        val |= ephArray[1];
1379        if (val!=Markers.EPH) {
1380            throw new Error("Corrupted Bitstream: Could not parse EPH "
1381                            +"marker ! ");
1382        }
1383    }
1384
1385    /** 
1386     * Get PrecInfo instance of the specified resolution level, component and
1387     * precinct.
1388     *
1389     * @param c Component index.
1390     *
1391     * @param r Resolution level index.
1392     *
1393     * @param p Precinct index.
1394     * */
1395    public PrecInfo getPrecInfo(int c,int r,int p) {
1396        return ppinfo[c][r][p];
1397    }
1398
1399}