CSJ2K.j2k.codestream.reader.FileBitstreamReaderAgent.getCodeBlock C# (CSharp) Метод

getCodeBlock() публичный Метод

Returns the specified coded code-block, for the specified component, in the current tile. The first layer to return is indicated by 'fl'. The number of layers that is returned depends on 'nl' and the amount of available data.

The argument 'fl' is to be used by subsequent calls to this method for the same code-block. In this way supplemental data can be retrieved at a later time. The fact that data from more than one layer can be returned means that several packets from the same code-block, of the same component, and the same tile, have been concatenated.

The returned compressed code-block can have its progressive attribute set. If this attribute is set it means that more data can be obtained by subsequent calls to this method (subject to transmission delays, etc). If the progressive attribute is not set it means that the returned data is all the data that can be obtained for the specified code-block.

The compressed code-block is uniquely specified by the current tile, the component (identified by 'c'), the subband (indentified by 'sb') and the code-block vertical and horizontal indexes 'n' and 'm'.

The 'ulx' and 'uly' members of the returned 'DecLyrdCBlk' object contain the coordinates of the top-left corner of the block, with respect to the tile, not the subband.

public getCodeBlock ( int c, int m, int n, CSJ2K.j2k.wavelet.synthesis.SubbandSyn sb, int fl, int nl, CSJ2K.j2k.entropy.decoder.DecLyrdCBlk ccb ) : CSJ2K.j2k.entropy.decoder.DecLyrdCBlk
c int The index of the component, from 0 to N-1. /// ///
m int The vertical index of the code-block to return, in the /// specified subband. /// ///
n int The horizontal index of the code-block to return, in the /// specified subband. /// ///
sb CSJ2K.j2k.wavelet.synthesis.SubbandSyn The subband in whic the requested code-block is. /// ///
fl int The first layer to return. /// ///
nl int The number of layers to return, if negative all available /// layers are returned, starting at 'fl'. /// ///
ccb CSJ2K.j2k.entropy.decoder.DecLyrdCBlk If not null this object is used to return the compressed /// code-block. If null a new object is created and returned. If the data /// array in ccb is not null then it can be reused to return the compressed /// data. /// ///
Результат CSJ2K.j2k.entropy.decoder.DecLyrdCBlk
        public override DecLyrdCBlk getCodeBlock(int c, int m, int n, SubbandSyn sb, int fl, int nl, DecLyrdCBlk ccb)
        {
            int t = TileIdx;
            CBlkInfo rcb; // requested code-block
            int r = sb.resLvl; // Resolution level
            int s = sb.sbandIdx; // Subband index
            int tpidx;
            int passtype;

            // Number of layers
            int numLayers = ((System.Int32) decSpec.nls.getTileDef(t));
            int options = ((System.Int32) decSpec.ecopts.getTileCompVal(t, c));
            if (nl < 0)
            {
                nl = numLayers - fl + 1;
            }

            // If the l quit condition is used, Make sure that no layer
            // after lquit is returned
            if (lQuit != - 1 && fl + nl > lQuit)
            {
                nl = lQuit - fl;
            }

            // Check validity of resquested resolution level (according to the
            // "-res" option).
            int maxdl = getSynSubbandTree(t, c).resLvl;
            if (r > targetRes + maxdl - decSpec.dls.Min)
            {
                throw new System.InvalidOperationException("JJ2000 error: requesting a code-block " + "disallowed by the '-res' option.");
            }

            // Check validity of all the arguments
            try
            {
                rcb = cbI[c][r][s][m][n];

                if (fl < 1 || fl > numLayers || fl + nl - 1 > numLayers)
                {
                    throw new System.ArgumentException();
                }
            }
            catch (System.IndexOutOfRangeException e)
            {
                throw new System.ArgumentException("Code-block (t:" + t + ", c:" + c + ", r:" + r + ", s:" + s + ", " + m + "x" + (+ n) + ") not found in codestream");
            }
            catch (System.NullReferenceException e)
            {
                throw new System.ArgumentException("Code-block (t:" + t + ", c:" + c + ", r:" + r + ", s:" + s + ", " + m + "x" + n + ") not found in bit stream");
            }

            // Create DecLyrdCBlk object if necessary
            if (ccb == null)
            {
                ccb = new DecLyrdCBlk();
            }
            ccb.m = m;
            ccb.n = n;
            ccb.nl = 0;
            ccb.dl = 0;
            ccb.nTrunc = 0;

            if (rcb == null)
            {
                // This code-block was skipped when reading. Returns no data
                ccb.skipMSBP = 0;
                ccb.prog = false;
                ccb.w = ccb.h = ccb.ulx = ccb.uly = 0;
                return ccb;
            }

            // ccb initialization
            ccb.skipMSBP = rcb.msbSkipped;
            ccb.ulx = rcb.ulx;
            ccb.uly = rcb.uly;
            ccb.w = rcb.w;
            ccb.h = rcb.h;
            ccb.ftpIdx = 0;

            // Search for index of first truncation point (first layer where
            // length of data is not zero)
            int l = 0;
            while ((l < rcb.len.Length) && (rcb.len[l] == 0))
            {
                ccb.ftpIdx += rcb.ntp[l];
                l++;
            }

            // Calculate total length, number of included layer and number of
            // truncation points
            for (l = fl - 1; l < fl + nl - 1; l++)
            {
                ccb.nl++;
                ccb.dl += rcb.len[l];
                ccb.nTrunc += rcb.ntp[l];
            }

            // Calculate number of terminated segments
            int nts;
            if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0)
            {
                // Regular termination in use One segment per pass
                // (i.e. truncation point)
                nts = ccb.nTrunc - ccb.ftpIdx;
            }
            else if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0)
            {
                // Selective arithmetic coding bypass mode in use, but no regular
                // termination: 1 segment upto the end of the last pass of the 4th
                // most significant bit-plane, and, in each following bit-plane,
                // one segment upto the end of the 2nd pass and one upto the end
                // of the 3rd pass.

                if (ccb.nTrunc <= CSJ2K.j2k.entropy.StdEntropyCoderOptions.FIRST_BYPASS_PASS_IDX)
                {
                    nts = 1;
                }
                else
                {
                    nts = 1;
                    // Adds one for each terminated pass
                    for (tpidx = ccb.ftpIdx; tpidx < ccb.nTrunc; tpidx++)
                    {
                        if (tpidx >= CSJ2K.j2k.entropy.StdEntropyCoderOptions.FIRST_BYPASS_PASS_IDX - 1)
                        {
                            passtype = (tpidx + CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_EMPTY_PASSES_IN_MS_BP) % CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES;
                            if (passtype == 1 || passtype == 2)
                            {
                                // lazy pass just before MQ pass or MQ pass just
                                // before lazy pass => terminated
                                nts++;
                            }
                        }
                    }
                }
            }
            else
            {
                // Nothing special in use, just one terminated segment
                nts = 1;
            }

            // ccb.data creation
            if (ccb.data == null || ccb.data.Length < ccb.dl)
            {
                ccb.data = new byte[ccb.dl];
            }

            // ccb.tsLengths creation
            if (nts > 1 && (ccb.tsLengths == null || ccb.tsLengths.Length < nts))
            {
                ccb.tsLengths = new int[nts];
            }
            else if (nts > 1 && (options & (CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS | CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS)) == CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS)
            {
                ArrayUtil.intArraySet(ccb.tsLengths, 0);
            }

            // Fill ccb with compressed data
            int dataIdx = - 1;
            tpidx = ccb.ftpIdx;
            int ctp = ccb.ftpIdx; // Cumulative number of truncation
            // point for the current layer layer
            int tsidx = 0;
            int j;

            for (l = fl - 1; l < fl + nl - 1; l++)
            {
                ctp += rcb.ntp[l];
                // No data in this layer
                if (rcb.len[l] == 0)
                    continue;

                // Read data
                // NOTE: we should never get an EOFException here since all
                // data is checked to be within the file.
                try
                {
                    in_Renamed.seek(rcb.off[l]);
                    in_Renamed.readFully(ccb.data, dataIdx + 1, rcb.len[l]);
                    dataIdx += rcb.len[l];
                }
                catch (System.IO.IOException e)
                {
                    JJ2KExceptionHandler.handleException(e);
                }

                // Get the terminated segment lengths, if any
                if (nts == 1)
                    continue;
                if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0)
                {
                    // Regular termination => each pass is terminated
                    for (j = 0; tpidx < ctp; j++, tpidx++)
                    {
                        if (rcb.segLen[l] != null)
                        {
                            ccb.tsLengths[tsidx++] = rcb.segLen[l][j];
                        }
                        else
                        {
                            // Only one terminated segment in packet
                            ccb.tsLengths[tsidx++] = rcb.len[l];
                        }
                    }
                }
                else
                {
                    // Lazy coding without regular termination
                    for (j = 0; tpidx < ctp; tpidx++)
                    {
                        if (tpidx >= CSJ2K.j2k.entropy.StdEntropyCoderOptions.FIRST_BYPASS_PASS_IDX - 1)
                        {
                            passtype = (tpidx + CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_EMPTY_PASSES_IN_MS_BP) % CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_PASSES;
                            if (passtype != 0)
                            {
                                // lazy pass just before MQ pass or MQ
                                // pass just before lazy pass =>
                                // terminated
                                if (rcb.segLen[l] != null)
                                {
                                    ccb.tsLengths[tsidx++] += rcb.segLen[l][j++];
                                    rcb.len[l] -= rcb.segLen[l][j - 1];
                                }
                                else
                                {
                                    // Only one terminated segment in packet
                                    ccb.tsLengths[tsidx++] += rcb.len[l];
                                    rcb.len[l] = 0;
                                }
                            }
                        }
                    }

                    // Last length in packet always in (either terminated segment
                    // or contribution to terminated segment)
                    if (rcb.segLen[l] != null && j < rcb.segLen[l].Length)
                    {
                        ccb.tsLengths[tsidx] += rcb.segLen[l][j];
                        rcb.len[l] -= rcb.segLen[l][j];
                    }
                    else
                    {
                        // Only one terminated segment in packet
                        if (tsidx < nts)
                        {
                            ccb.tsLengths[tsidx] += rcb.len[l];
                            rcb.len[l] = 0;
                        }
                    }
                }
            }
            if (nts == 1 && ccb.tsLengths != null)
            {
                ccb.tsLengths[0] = ccb.dl;
            }

            // Set the progressive flag
            int lastlayer = fl + nl - 1;
            if (lastlayer < numLayers - 1)
            {
                for (l = lastlayer + 1; l < numLayers; l++)
                {
                    // It remains data for this code-block in the bit stream
                    if (rcb.len[l] != 0)
                    {
                        ccb.prog = true;
                    }
                }
            }

            return ccb;
        }