示例#1
0
        private static int GetLog2SubbandGain(Subband subband)
        {
            // See Table E.1 "Sub-band gains"

            if (subband.SubbandType == SubbandType.LL)
            {
                return(0);
            }
            else if (subband.SubbandType == SubbandType.LH)
            {
                return(1);
            }
            else if (subband.SubbandType == SubbandType.HL)
            {
                return(1);
            }
            else if (subband.SubbandType == SubbandType.HH)
            {
                return(2);
            }
            else
            {
                throw NotSupported(subband.SubbandType);
            }
        }
示例#2
0
        /// <summary> Returns the maximum number of magnitude bits in any subband of the
        /// current tile if reversible quantization is used
        ///
        /// </summary>
        /// <param name="sb">The root of the subband tree of the current tile
        ///
        /// </param>
        /// <param name="c">the component number
        ///
        /// </param>
        /// <returns> The highest number of magnitude bit-planes
        ///
        /// </returns>
        private int getMaxMagBitsRev(Subband sb, int c)
        {
            int tmp, max = 0;
            int g = ((System.Int32)gbs.getTileCompVal(tIdx, c));

            if (!sb.isNode)
            {
                return(g - 1 + src.getNomRangeBits(c) + sb.anGainExp);
            }

            max = getMaxMagBitsRev(sb.LL, c);
            tmp = getMaxMagBitsRev(sb.LH, c);
            if (tmp > max)
            {
                max = tmp;
            }
            tmp = getMaxMagBitsRev(sb.HL, c);
            if (tmp > max)
            {
                max = tmp;
            }
            tmp = getMaxMagBitsRev(sb.HH, c);
            if (tmp > max)
            {
                max = tmp;
            }

            return(max);
        }
示例#3
0
        /// <summary> Returns the maximum number of magnitude bits in any subband in the
        /// given tile-component if expounded quantization is used
        ///
        /// </summary>
        /// <param name="sb">The root of the subband tree of the tile-component
        ///
        /// </param>
        /// <param name="t">Tile index
        ///
        /// </param>
        /// <param name="c">Component index
        ///
        /// </param>
        /// <returns> The highest number of magnitude bit-planes
        ///
        /// </returns>
        private int getMaxMagBitsExpounded(Subband sb, int t, int c)
        {
            int tmp, max = 0;
            int g = ((System.Int32)gbs.getTileCompVal(t, c));

            if (!sb.isNode)
            {
                //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Float.floatValue' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
                float baseStep = (float)((System.Single)qsss.getTileCompVal(t, c));
                //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                return(g - 1 - (int)System.Math.Floor(System.Math.Log(baseStep / (((SubbandAn)sb).l2Norm * (1 << sb.anGainExp))) / log2));
            }

            max = getMaxMagBitsExpounded(sb.LL, t, c);
            tmp = getMaxMagBitsExpounded(sb.LH, t, c);
            if (tmp > max)
            {
                max = tmp;
            }
            tmp = getMaxMagBitsExpounded(sb.HL, t, c);
            if (tmp > max)
            {
                max = tmp;
            }
            tmp = getMaxMagBitsExpounded(sb.HH, t, c);
            if (tmp > max)
            {
                max = tmp;
            }

            return(max);
        }
 public int GetEb(Subband subband)
 {
     if (ReversibleStepSizes != null)
     {
         return(ReversibleStepSizes[subband.SubbandIndex].Exponent);
     }
     else if (QuantizationStepSizes != null)
     {
         return(QuantizationStepSizes[subband.SubbandIndex].Exponent);
     }
     else
     {
         throw new NotSupportedException();
     }
 }
示例#5
0
 /// <summary> Returns the reversibility of the current subband. It computes
 /// iteratively the reversibility of the child subbands. For each subband
 /// it tests the reversibility of the horizontal and vertical synthesis
 /// filters used to reconstruct this subband.
 ///
 /// </summary>
 /// <param name="subband">The current subband.
 ///
 /// </param>
 /// <returns> true if all the  filters used to reconstruct the current
 /// subband are reversible
 ///
 /// </returns>
 private bool isSubbandReversible(Subband subband)
 {
     if (subband.isNode)
     {
         // It's reversible if the filters to obtain the 4 subbands are
         // reversible and the ones for this one are reversible too.
         return(isSubbandReversible(subband.LL) && isSubbandReversible(subband.HL) && isSubbandReversible(subband.LH) && isSubbandReversible(subband.HH) && ((SubbandSyn)subband).hFilter.Reversible && ((SubbandSyn)subband).vFilter.Reversible);
     }
     else
     {
         // Leaf subband. Reversibility of data depends on source, so say
         // it's true
         return(true);
     }
 }
示例#6
0
        /// <summary> Returns the maximum number of magnitude bits in any subband of the
        /// current tile.
        ///
        /// </summary>
        /// <param name="c">the component number
        ///
        /// </param>
        /// <returns> The maximum number of magnitude bits in all subbands of the
        /// current tile.
        ///
        /// </returns>
        public override int getMaxMagBits(int c)
        {
            Subband sb = getAnSubbandTree(tIdx, c);

            if (isReversible(tIdx, c))
            {
                return(getMaxMagBitsRev(sb, c));
            }
            else
            {
                if (isDerived(tIdx, c))
                {
                    return(getMaxMagBitsDerived(sb, tIdx, c));
                }
                else
                {
                    return(getMaxMagBitsExpounded(sb, tIdx, c));
                }
            }
        }
        /// <summary> This functions gets a DataBlk the size of the current code-block an
        /// fills this block with the ROI mask.
        ///
        /// <P> In order to get the mask for a particular Subband, the subband tree
        /// is traversed and at each decomposition, the ROI masks are computed.
        ///
        /// <P> The widths of the synthesis filters corresponding to the wavelet
        /// filters used in the wavelet transform are used to expand the ROI masks
        /// in the decompositions.
        ///
        /// </summary>
        /// <param name="db">The data block that is to be filled with the mask
        ///
        /// </param>
        /// <param name="sb">The root of the subband tree to which db belongs
        ///
        /// </param>
        /// <param name="magbits">The max number of magnitude bits in any code-block
        ///
        /// </param>
        /// <param name="c">The number of the component
        ///
        /// </param>
        /// <returns> Whether or not a mask was needed for this tile
        ///
        /// </returns>
        public override bool getROIMask(DataBlkInt db, Subband sb, int magbits, int c)
        {
            int x     = db.ulx;
            int y     = db.uly;
            int w     = db.w;
            int h     = db.h;
            int tilew = sb.w;
            int tileh = sb.h;

            int[] maskData = (int[])db.Data;
            int   i, j, k, bi, wrap;

            // If the ROI mask has not been calculated for this tile and
            // component, do so now.
            if (!tileMaskMade[c])
            {
                makeMask(sb, magbits, c);
                tileMaskMade[c] = true;
            }
            if (!roiInTile)
            {
                return(false);
            }

            int[] mask = roiMask[c];             // local copy

            // Copy relevant part of the ROI mask to the datablock
            i    = (y + h - 1) * tilew + x + w - 1;
            bi   = w * h - 1;
            wrap = tilew - w;
            for (j = h; j > 0; j--)
            {
                for (k = w; k > 0; k--, i--, bi--)
                {
                    maskData[bi] = mask[i];
                }
                i -= wrap;
            }
            return(true);
        }
示例#8
0
        private Subband[][][] CreateSubbands(int nComponents)
        {
            var subbands = new Subband[nComponents][][];

            for (var component = 0; component < nComponents; component++)
            {
                var nDecompositionLevels = COC[component].SP_NumberOfDecompositionLevels;

                var subbandIndex = 0;

                Subband NewSubband(int decompositionLevel, SubbandType subbandType)
                {
                    return(new Subband(subbandIndex++, decompositionLevel, subbandType));
                }

                subbands[component] = new Subband[nDecompositionLevels + 1][];
                for (var resolution = 0; resolution <= nDecompositionLevels; resolution++)
                {
                    if (resolution == 0)
                    {
                        var decompositionLevel = nDecompositionLevels - resolution;
                        subbands[component][resolution] = new[]
                        {
                            NewSubband(decompositionLevel, SubbandType.LL)
                        };
                    }
                    else
                    {
                        var decompositionLevel = nDecompositionLevels - (resolution - 1);
                        subbands[component][resolution] = new[]
                        {
                            NewSubband(decompositionLevel, SubbandType.HL),
                            NewSubband(decompositionLevel, SubbandType.LH),
                            NewSubband(decompositionLevel, SubbandType.HH)
                        };
                    }
                }
            }
            return(subbands);
        }
示例#9
0
        private void ReadSubBand(BitReader bitReader, Subband subband)
        {
            var subbandPrecinct = ResolutionLevel.GetSubbandPrecinct(subband);

            var nCodeBlocksX = subbandPrecinct.NCodeBlocksX;
            var nCodeBlocksY = subbandPrecinct.NCodeBlocksY;

            var codeBlockInclusionTagTree = subbandPrecinct.CodeBlockInclusionTagTree;

            for (var y = 0; y < nCodeBlocksY; y++)
            {
                for (var x = 0; x < nCodeBlocksX; x++)
                {
                    var codeBlockFirstIncludedInLayerIsValid = codeBlockInclusionTagTree.TryGetValue((uint)x, (uint)y,
                                                                                                     (uint)Layer, bitReader, out uint codeBlockFirstIncludedInLayer);

                    var codeBlockIsIncludedInPacket = false;

                    if (codeBlockFirstIncludedInLayerIsValid)
                    {
                        if (codeBlockFirstIncludedInLayer < Layer)
                        {
                            codeBlockIsIncludedInPacket = (bitReader.ReadBit() == 1);
                        }
                        else
                        {
                            codeBlockIsIncludedInPacket = codeBlockFirstIncludedInLayer == Layer;
                        }
                    }

                    if (codeBlockIsIncludedInPacket)
                    {
                        var codeBlock = subbandPrecinct.AddCodeBlock(x, y);

                        if (codeBlockFirstIncludedInLayer == Layer)
                        {
                            var zeroBitPlaneTagTree      = subbandPrecinct.ZeroBitPlaneTagTree;
                            var nAllZeroBitPlanesIsValid = zeroBitPlaneTagTree.TryGetValue((uint)x, (uint)y, uint.MaxValue,
                                                                                           bitReader, out uint nAllZeroBitPlanes);
                            Debug.Assert(nAllZeroBitPlanesIsValid); // must be true since limit == uint.MaxValue
                            codeBlock.NAllZeroBitPlanes_P = (int)nAllZeroBitPlanes;
                        }

                        codeBlock.NCodingPasses = (ushort)ReadNumberOfCodingPasses(bitReader);

                        ThrowIf(ResolutionLevel.TilePartComponent.COC.SP_CodeBlockCodingPassStyle != 0);

                        var codeBlockLengthIndicator = 3; // TODO: Get from and update in layer for this code block
                        while (bitReader.ReadBit() != 0)
                        {
                            codeBlockLengthIndicator++;
                        }

                        var nBitsUsedToStoreCodeBlockLength = codeBlockLengthIndicator + StaticInclude.FloorLog2(codeBlock.NCodingPasses);

                        codeBlock.LengthInBytes = bitReader.ReadBits(nBitsUsedToStoreCodeBlockLength);

                        IncludedCodeBlocks.Add(codeBlock);
                    }
                }
            }
        }
        /// <summary> This function generates the ROI mask for the entire tile. The mask is
        /// generated for one component. This method is called once for each tile
        /// and component.
        ///
        /// </summary>
        /// <param name="sb">The root of the subband tree used in the decomposition
        ///
        /// </param>
        /// <param name="n">component number
        ///
        /// </param>
        public override void  makeMask(Subband sb, int magbits, int n)
        {
            int nr = nrROIs[n];
            int r;
            int ulx, uly, lrx, lry;
            int tileulx = sb.ulcx;
            int tileuly = sb.ulcy;
            int tilew   = sb.w;
            int tileh   = sb.h;

            ROI[] ROIs = roi_array;             // local copy

            ulxs = new int[nr];
            ulys = new int[nr];
            lrxs = new int[nr];
            lrys = new int[nr];

            nr = 0;

            for (r = ROIs.Length - 1; r >= 0; r--)
            {
                if (ROIs[r].comp == n)
                {
                    ulx = ROIs[r].ulx;
                    uly = ROIs[r].uly;
                    lrx = ROIs[r].w + ulx - 1;
                    lry = ROIs[r].h + uly - 1;

                    if (ulx > (tileulx + tilew - 1) || uly > (tileuly + tileh - 1) || lrx < tileulx || lry < tileuly)
                    {
                        // no part of ROI in tile
                        continue;
                    }

                    // Check bounds
                    ulx -= tileulx;
                    lrx -= tileulx;
                    uly -= tileuly;
                    lry -= tileuly;

                    ulx = (ulx < 0)?0:ulx;
                    uly = (uly < 0)?0:uly;
                    lrx = (lrx > (tilew - 1))?tilew - 1:lrx;
                    lry = (lry > (tileh - 1))?tileh - 1:lry;

                    ulxs[nr] = ulx;
                    ulys[nr] = uly;
                    lrxs[nr] = lrx;
                    lrys[nr] = lry;
                    nr++;
                }
            }
            if (nr == 0)
            {
                roiInTile = false;
            }
            else
            {
                roiInTile = true;
            }
            sMasks[n] = new SubbandRectROIMask(sb, ulxs, ulys, lrxs, lrys, nr);
        }
        /// <summary> This functions gets a DataBlk the size of the current code-block and
        /// fills this block with the ROI mask.
        ///
        /// <P> In order to get the mask for a particular Subband, the subband tree
        /// is traversed and at each decomposition, the ROI masks are computed. The
        /// roi bondaries for each subband are stored in the SubbandRectROIMask
        /// tree.
        ///
        /// </summary>
        /// <param name="db">The data block that is to be filled with the mask
        ///
        /// </param>
        /// <param name="sb">The root of the subband tree to which db belongs
        ///
        /// </param>
        /// <param name="magbits">The max number of magnitude bits in any code-block
        ///
        /// </param>
        /// <param name="c">The component for which to get the mask
        ///
        /// </param>
        /// <returns> Whether or not a mask was needed for this tile
        ///
        /// </returns>
        public override bool getROIMask(DataBlkInt db, Subband sb, int magbits, int c)
        {
            int x = db.ulx;
            int y = db.uly;
            int w = db.w;
            int h = db.h;

            int[] mask = db.DataInt;
            int   i, j, k, r, maxk, maxj; // mink, minj removed
            int   ulx = 0, uly = 0, lrx = 0, lry = 0;
            int   wrap;
            int   maxROI;

            int[] culxs;
            int[] culys;
            int[] clrxs;
            int[] clrys;
            SubbandRectROIMask srm;

            // If the ROI bounds have not been calculated for this tile and
            // component, do so now.
            if (!tileMaskMade[c])
            {
                makeMask(sb, magbits, c);
                tileMaskMade[c] = true;
            }

            if (!roiInTile)
            {
                return(false);
            }

            // Find relevant subband mask and get ROI bounds
            srm    = (SubbandRectROIMask)sMasks[c].getSubbandRectROIMask(x, y);
            culxs  = srm.ulxs;
            culys  = srm.ulys;
            clrxs  = srm.lrxs;
            clrys  = srm.lrys;
            maxROI = culxs.Length - 1;
            // Make sure that only parts of ROIs within the code-block are used
            // and make the bounds local to this block the LR bounds are counted
            // as the distance from the lower right corner of the block
            x -= srm.ulx;
            y -= srm.uly;
            for (r = maxROI; r >= 0; r--)
            {
                ulx = culxs[r] - x;
                if (ulx < 0)
                {
                    ulx = 0;
                }
                else if (ulx >= w)
                {
                    ulx = w;
                }

                uly = culys[r] - y;
                if (uly < 0)
                {
                    uly = 0;
                }
                else if (uly >= h)
                {
                    uly = h;
                }

                lrx = clrxs[r] - x;
                if (lrx < 0)
                {
                    lrx = -1;
                }
                else if (lrx >= w)
                {
                    lrx = w - 1;
                }

                lry = clrys[r] - y;
                if (lry < 0)
                {
                    lry = -1;
                }
                else if (lry >= h)
                {
                    lry = h - 1;
                }

                // Add the masks of the ROI
                i    = w * lry + lrx;
                maxj = (lrx - ulx);
                wrap = w - maxj - 1;
                maxk = lry - uly;

                for (k = maxk; k >= 0; k--)
                {
                    for (j = maxj; j >= 0; j--, i--)
                    {
                        mask[i] = magbits;
                    }
                    i -= wrap;
                }
            }
            return(true);
        }
示例#12
0
 /// <summary> This function generates the ROI mask for the entire tile. The mask is
 /// generated for one component. This method is called once for each tile
 /// and component.
 ///
 /// </summary>
 /// <param name="sb">The root of the subband tree used in the decomposition
 ///
 /// </param>
 /// <param name="magbits">The max number of magnitude bits in any code-block
 ///
 /// </param>
 /// <param name="n">component number
 /// </param>
 public abstract void  makeMask(Subband sb, int magbits, int n);
示例#13
0
 /// <summary> This functions gets a DataBlk with the size of the current code-block
 /// and fills it with the ROI mask. The lowest scaling value in the mask
 /// for this code-block is returned by the function to be used for
 /// modifying the rate distortion estimations.
 ///
 /// </summary>
 /// <param name="db">The data block that is to be filled with the mask
 ///
 /// </param>
 /// <param name="sb">The root of the current subband tree
 ///
 /// </param>
 /// <param name="magbits">The number of magnitude bits in this code-block
 ///
 /// </param>
 /// <param name="c">Component number
 ///
 /// </param>
 /// <returns> Whether or not a mask was needed for this tile
 /// </returns>
 public abstract bool getROIMask(DataBlkInt db, Subband sb, int magbits, int c);
示例#14
0
 public abstract void Dequantisize(Signal2D transformCoefficientValues, TilePartComponent tilePartComponent, Subband subband);
        /// <summary> This function generates the ROI mask for one tile-component.
        ///
        /// <P> Once the mask is generated in the pixel domain. it is decomposed
        /// following the same decomposition scheme as the wavelet transform.
        ///
        /// </summary>
        /// <param name="sb">The root of the subband tree used in the decomposition
        ///
        /// </param>
        /// <param name="magbits">The max number of magnitude bits in any code-block
        ///
        /// </param>
        /// <param name="c">component number
        /// </param>
        public override void  makeMask(Subband sb, int magbits, int c)
        {
            int[] mask;                  // local copy
            ROI[] rois = this.roi_array; // local copy
            int   i, j, k, r, maxj;      // mink, minj removed
            int   lrx, lry;
            int   x, y, w, h;
            int   cx, cy, rad;
            int   wrap;
            int   curScalVal;
            int   tileulx = sb.ulcx;
            int   tileuly = sb.ulcy;
            int   tilew   = sb.w;
            int   tileh   = sb.h;
            int   lineLen = (tilew > tileh)?tilew:tileh;

            // Make sure there is a sufficiently large mask buffer
            if (roiMask[c] == null || (roiMask[c].Length < (tilew * tileh)))
            {
                roiMask[c] = new int[tilew * tileh];
                mask       = roiMask[c];
            }
            else
            {
                mask = roiMask[c];
                for (i = tilew * tileh - 1; i >= 0; i--)
                {
                    mask[i] = 0;
                }
            }

            // Make sure there are sufficiently large line buffers
            if (maskLineLow == null || (maskLineLow.Length < (lineLen + 1) / 2))
            {
                maskLineLow = new int[(lineLen + 1) / 2];
            }
            if (maskLineHigh == null || (maskLineHigh.Length < (lineLen + 1) / 2))
            {
                maskLineHigh = new int[(lineLen + 1) / 2];
            }

            roiInTile = false;
            // Generate ROIs in pixel domain:
            for (r = rois.Length - 1; r >= 0; r--)
            {
                if (rois[r].comp == c)
                {
                    curScalVal = magbits;

                    if (rois[r].arbShape)
                    {
                        ImgReaderPGM maskPGM = rois[r].maskPGM;                         // Local copy

                        if ((src.ImgWidth != maskPGM.ImgWidth) || (src.ImgHeight != maskPGM.ImgHeight))
                        {
                            throw new System.ArgumentException("Input image and" + " ROI mask must " + "have the same " + "size");
                        }
                        x   = src.ImgULX;
                        y   = src.ImgULY;
                        lrx = x + src.ImgWidth - 1;
                        lry = y + src.ImgHeight - 1;
                        if ((x > tileulx + tilew) || (y > tileuly + tileh) || (lrx < tileulx) || (lry < tileuly))
                        {
                            // Roi not in tile
                            continue;
                        }

                        // Check bounds
                        x   -= tileulx;
                        lrx -= tileulx;
                        y   -= tileuly;
                        lry -= tileuly;

                        int offx = 0;
                        int offy = 0;
                        if (x < 0)
                        {
                            offx = -x;
                            x    = 0;
                        }
                        if (y < 0)
                        {
                            offy = -y;
                            y    = 0;
                        }
                        w = (lrx > (tilew - 1))?tilew - x:lrx + 1 - x;
                        h = (lry > (tileh - 1))?tileh - y:lry + 1 - y;


                        // Get shape line by line to reduce memory
                        DataBlkInt srcblk    = new DataBlkInt();
                        int        mDcOff    = -ImgReaderPGM.DC_OFFSET;
                        int        nROIcoeff = 0;
                        int[]      src_data;
                        srcblk.ulx = offx;
                        srcblk.w   = w;
                        srcblk.h   = 1;

                        i    = (y + h - 1) * tilew + x + w - 1;
                        maxj = w;
                        wrap = tilew - maxj;
                        for (k = h; k > 0; k--)
                        {
                            srcblk.uly = offy + k - 1;
                            srcblk     = (DataBlkInt)maskPGM.getInternCompData(srcblk, 0);
                            src_data   = srcblk.DataInt;

                            for (j = maxj; j > 0; j--, i--)
                            {
                                if (src_data[j - 1] != mDcOff)
                                {
                                    mask[i] = curScalVal;
                                    nROIcoeff++;
                                }
                            }
                            i -= wrap;
                        }

                        if (nROIcoeff != 0)
                        {
                            roiInTile = true;
                        }
                    }
                    else if (rois[r].rect)
                    {
                        // Rectangular ROI
                        x   = rois[r].ulx;
                        y   = rois[r].uly;
                        lrx = rois[r].w + x - 1;
                        lry = rois[r].h + y - 1;

                        if ((x > tileulx + tilew) || (y > tileuly + tileh) || (lrx < tileulx) || (lry < tileuly))
                        {
                            // Roi not in tile
                            continue;
                        }

                        roiInTile = true;

                        // Check bounds
                        x   -= tileulx;
                        lrx -= tileulx;
                        y   -= tileuly;
                        lry -= tileuly;

                        x = (x < 0)?0:x;
                        y = (y < 0)?0:y;
                        w = (lrx > (tilew - 1))?tilew - x:lrx + 1 - x;
                        h = (lry > (tileh - 1))?tileh - y:lry + 1 - y;

                        i    = (y + h - 1) * tilew + x + w - 1;
                        maxj = w;
                        wrap = tilew - maxj;
                        for (k = h; k > 0; k--)
                        {
                            for (j = maxj; j > 0; j--, i--)
                            {
                                mask[i] = curScalVal;
                            }
                            i -= wrap;
                        }
                    }
                    else
                    {
                        // Non-rectangular ROI. So far only circular case
                        cx  = rois[r].x - tileulx;
                        cy  = rois[r].y - tileuly;
                        rad = rois[r].r;
                        i   = tileh * tilew - 1;
                        for (k = tileh - 1; k >= 0; k--)
                        {
                            for (j = tilew - 1; j >= 0; j--, i--)
                            {
                                if (((j - cx) * (j - cx) + (k - cy) * (k - cy) < rad * rad))
                                {
                                    mask[i]   = curScalVal;
                                    roiInTile = true;
                                }
                            }
                        }
                    }
                }
            }

            // If wavelet transform is used
            if (sb.isNode)
            {
                // Decompose the mask according to the subband tree
                // Calculate size of padded line buffer
                WaveletFilter vFilter = sb.VerWFilter;
                WaveletFilter hFilter = sb.HorWFilter;
                int           lvsup   = vFilter.SynLowNegSupport + vFilter.SynLowPosSupport;
                int           hvsup   = vFilter.SynHighNegSupport + vFilter.SynHighPosSupport;
                int           lhsup   = hFilter.SynLowNegSupport + hFilter.SynLowPosSupport;
                int           hhsup   = hFilter.SynHighNegSupport + hFilter.SynHighPosSupport;
                lvsup          = (lvsup > hvsup)?lvsup:hvsup;
                lhsup          = (lhsup > hhsup)?lhsup:hhsup;
                lvsup          = (lvsup > lhsup)?lvsup:lhsup;
                paddedMaskLine = new int[lineLen + lvsup];

                if (roiInTile)
                {
                    decomp(sb, tilew, tileh, c);
                }
            }
        }
示例#16
0
        protected sealed override void Dequantisize(Signal2D <T> transformCoefficientValues, TilePartComponent component, Subband subband)
        {
            var quantizationStepSize = GetQuantizationStepSize(component, subband);

            if (quantizationStepSize != 1)
            {
                transformCoefficientValues.URange.GetBounds(out int u0, out int u1);
                transformCoefficientValues.VRange.GetBounds(out int v0, out int v1);

                Parallel.For(v0, v1, v =>
                {
                    for (var u = u0; u < u1; u++)
                    {
                        ApplyQuantizationStepSize(transformCoefficientValues, u, v, quantizationStepSize);
                    }
                });
            }
        }
 public int GetMb(Subband subband)
 {
     return(NGuardBits_G + GetEb(subband) - 1);
 }
示例#18
0
        private static double GetQuantizationStepSize(TilePartComponent tilePartComponent, Subband subband)
        {
            var qcc = tilePartComponent.QCC;

            ThrowIf(qcc.QuantizationStyle == QuantizationStyle.NoQuantization);

            // See E.1.1.1 "Determination of the quantization step size"

            var ri = tilePartComponent.TileComponent.Component.ComponentSampleBitDepth;

            var rb = ri + GetLog2SubbandGain(subband);

            if (qcc.QuantizationStyle == QuantizationStyle.ScalarExpounded)
            {
                var qss = qcc.QuantizationStepSizes[subband.SubbandIndex];
                return(Math.Pow(2, rb - qss.Exponent) * (1 + qss.Mantissa / Math.Pow(2, 11)));
            }
            else
            {
                throw NotSupported(qcc.QuantizationStyle);
            }
        }
示例#19
0
 protected sealed override void Dequantisize(Signal2D <T> transformCoefficientValues, TilePartComponent tilePartComponent, Subband subband)
 {
     // Nothing to do
 }
示例#20
0
        /// <summary> Initialises subbands fields, such as number of code-blocks and
        /// code-blocks dimension, in the subband tree. The nominal code-block
        /// width/height depends on the precincts dimensions if used.
        ///
        /// </summary>
        /// <param name="t">The tile index of the subband
        ///
        /// </param>
        /// <param name="c">The component index
        ///
        /// </param>
        /// <param name="sb">The subband tree to be initialised.
        ///
        /// </param>
        private void initSubbandsFields(int t, int c, Subband sb)
        {
            int cbw = cblks.getCBlkWidth(ModuleSpec.SPEC_TILE_COMP, t, c);
            int cbh = cblks.getCBlkHeight(ModuleSpec.SPEC_TILE_COMP, t, c);

            if (!sb.isNode)
            {
                // Code-blocks dimension
                int ppx, ppy;
                int ppxExp, ppyExp, cbwExp, cbhExp;
                ppx = pss.getPPX(t, c, sb.resLvl);
                ppy = pss.getPPY(t, c, sb.resLvl);

                if (ppx != CSJ2K.j2k.codestream.Markers.PRECINCT_PARTITION_DEF_SIZE || ppy != CSJ2K.j2k.codestream.Markers.PRECINCT_PARTITION_DEF_SIZE)
                {
                    ppxExp = MathUtil.log2(ppx);
                    ppyExp = MathUtil.log2(ppy);
                    cbwExp = MathUtil.log2(cbw);
                    cbhExp = MathUtil.log2(cbh);

                    // Precinct partition is used
                    switch (sb.resLvl)
                    {
                    case 0:
                        sb.nomCBlkW = (cbwExp < ppxExp ? (1 << cbwExp) : (1 << ppxExp));
                        sb.nomCBlkH = (cbhExp < ppyExp ? (1 << cbhExp) : (1 << ppyExp));
                        break;


                    default:
                        sb.nomCBlkW = (cbwExp < ppxExp - 1 ? (1 << cbwExp) : (1 << (ppxExp - 1)));
                        sb.nomCBlkH = (cbhExp < ppyExp - 1 ? (1 << cbhExp) : (1 << (ppyExp - 1)));
                        break;
                    }
                }
                else
                {
                    sb.nomCBlkW = cbw;
                    sb.nomCBlkH = cbh;
                }

                // Number of code-blocks
                if (sb.numCb == null)
                {
                    sb.numCb = new Coord();
                }
                if (sb.w != 0 && sb.h != 0)
                {
                    int acb0x = cb0x;
                    int acb0y = cb0y;
                    int tmp;

                    // Project code-block partition origin to subband. Since the
                    // origin is always 0 or 1, it projects to the low-pass side
                    // (throught the ceil operator) as itself (i.e. no change) and
                    // to the high-pass side (through the floor operator) as 0,
                    // always.
                    switch (sb.sbandIdx)
                    {
                    case Subband.WT_ORIENT_LL:
                        // No need to project since all low-pass => nothing to do
                        break;

                    case Subband.WT_ORIENT_HL:
                        acb0x = 0;
                        break;

                    case Subband.WT_ORIENT_LH:
                        acb0y = 0;
                        break;

                    case Subband.WT_ORIENT_HH:
                        acb0x = 0;
                        acb0y = 0;
                        break;

                    default:
                        throw new System.ApplicationException("Internal JJ2000 error");
                    }
                    if (sb.ulcx - acb0x < 0 || sb.ulcy - acb0y < 0)
                    {
                        throw new System.ArgumentException("Invalid code-blocks " + "partition origin or " + "image offset in the " + "reference grid.");
                    }
                    // NOTE: when calculating "floor()" by integer division the
                    // dividend and divisor must be positive, we ensure that by
                    // adding the divisor to the dividend and then substracting 1
                    // to the result of the division
                    tmp        = sb.ulcx - acb0x + sb.nomCBlkW;
                    sb.numCb.x = (tmp + sb.w - 1) / sb.nomCBlkW - (tmp / sb.nomCBlkW - 1);
                    tmp        = sb.ulcy - acb0y + sb.nomCBlkH;
                    sb.numCb.y = (tmp + sb.h - 1) / sb.nomCBlkH - (tmp / sb.nomCBlkH - 1);
                }
                else
                {
                    sb.numCb.x = sb.numCb.y = 0;
                }
            }
            else
            {
                initSubbandsFields(t, c, sb.LL);
                initSubbandsFields(t, c, sb.HL);
                initSubbandsFields(t, c, sb.LH);
                initSubbandsFields(t, c, sb.HH);
            }
        }
        /// <summary> This function decomposes the mask for a node in the subband tree.
        /// after the mask is decomposed for a node, this function is called for
        /// the children of the subband. The decomposition is done line by line
        /// and column by column
        ///
        /// </summary>
        /// <param name="sb">The subband that is to be used for the decomposition
        ///
        /// </param>
        /// <param name="tilew">The width of the current tile
        ///
        /// </param>
        /// <param name="tileh">The height of the current tile
        ///
        /// </param>
        /// <param name="c">component number
        /// </param>
        private void  decomp(Subband sb, int tilew, int tileh, int c)
        {
            int ulx = sb.ulx;
            int uly = sb.uly;
            int w = sb.w;
            int h = sb.h;
            int scalVal, maxVal = 0;
            int j, k, s, mi = 0, pin;         // i, hi, li removed
            int hmax, lmax;                   // smax removed
            int lineoffs;                     // wrap, lastlow removed

            int[] mask      = roiMask[c];     // local copy
            int[] low       = maskLineLow;    // local copy
            int[] high      = maskLineHigh;   // local copy
            int[] padLine   = paddedMaskLine; // local copy
            int   highFirst = 0;
            int   lastpin;


            if (!sb.isNode)
            {
                return;
            }

            // HORIZONTAL DECOMPOSITION

            // Calculate number of high and low samples after decomposition
            // and get support for low and high filters
            WaveletFilter filter = sb.HorWFilter;
            int           lnSup  = filter.SynLowNegSupport;
            int           hnSup  = filter.SynHighNegSupport;
            int           lpSup  = filter.SynLowPosSupport;
            int           hpSup  = filter.SynHighPosSupport;
            int           lsup   = lnSup + lpSup + 1;
            int           hsup   = hnSup + hpSup + 1;

            // Calculate number of high/low coeffis in subbands
            highFirst = sb.ulcx % 2;
            if (sb.w % 2 == 0)
            {
                lmax = w / 2 - 1;
                hmax = lmax;
            }
            else
            {
                if (highFirst == 0)
                {
                    lmax = (w + 1) / 2 - 1;
                    hmax = w / 2 - 1;
                }
                else
                {
                    hmax = (w + 1) / 2 - 1;
                    lmax = w / 2 - 1;
                }
            }

            int maxnSup = (lnSup > hnSup)?lnSup:hnSup;             // Maximum negative support
            int maxpSup = (lpSup > hpSup)?lpSup:hpSup;             // Maximum positive support


            // Set padding to 0
            for (pin = maxnSup - 1; pin >= 0; pin--)
            {
                padLine[pin] = 0;
            }
            for (pin = maxnSup + w - 1 + maxpSup; pin >= w; pin--)
            {
                padLine[pin] = 0;
            }

            // Do decomposition of all lines
            lineoffs = (uly + h) * tilew + ulx + w - 1;
            for (j = h - 1; j >= 0; j--)
            {
                lineoffs -= tilew;
                // Get the line to transform from the mask
                mi = lineoffs;
                for (k = w, pin = w - 1 + maxnSup; k > 0; k--, mi--, pin--)
                {
                    padLine[pin] = mask[mi];
                }

                lastpin = maxnSup + highFirst + 2 * lmax + lpSup;
                for (k = lmax; k >= 0; k--, lastpin -= 2)
                {
                    // Low frequency samples
                    pin = lastpin;
                    for (s = lsup; s > 0; s--, pin--)
                    {
                        scalVal = padLine[pin];
                        if (scalVal > maxVal)
                        {
                            maxVal = scalVal;
                        }
                    }
                    low[k] = maxVal;
                    maxVal = 0;
                }
                lastpin = maxnSup - highFirst + 2 * hmax + 1 + hpSup;
                for (k = hmax; k >= 0; k--, lastpin -= 2)
                {
                    // High frequency samples
                    pin = lastpin;
                    for (s = hsup; s > 0; s--, pin--)
                    {
                        scalVal = padLine[pin];
                        if (scalVal > maxVal)
                        {
                            maxVal = scalVal;
                        }
                    }
                    high[k] = maxVal;
                    maxVal  = 0;
                }
                // Put the lows and highs back
                mi = lineoffs;
                for (k = hmax; k >= 0; k--, mi--)
                {
                    mask[mi] = high[k];
                }
                for (k = lmax; k >= 0; k--, mi--)
                {
                    mask[mi] = low[k];
                }
            }

            // VERTICAL DECOMPOSITION

            // Calculate number of high and low samples after decomposition
            // and get support for low and high filters
            filter = sb.VerWFilter;
            lnSup  = filter.SynLowNegSupport;
            hnSup  = filter.SynHighNegSupport;
            lpSup  = filter.SynLowPosSupport;
            hpSup  = filter.SynHighPosSupport;
            lsup   = lnSup + lpSup + 1;
            hsup   = hnSup + hpSup + 1;

            // Calculate number of high/low coeffs in subbands
            highFirst = sb.ulcy % 2;
            if (sb.h % 2 == 0)
            {
                lmax = h / 2 - 1;
                hmax = lmax;
            }
            else
            {
                if (sb.ulcy % 2 == 0)
                {
                    lmax = (h + 1) / 2 - 1;
                    hmax = h / 2 - 1;
                }
                else
                {
                    hmax = (h + 1) / 2 - 1;
                    lmax = h / 2 - 1;
                }
            }

            maxnSup = (lnSup > hnSup)?lnSup:hnSup;             // Maximum negative support
            maxpSup = (lpSup > hpSup)?lpSup:hpSup;             // Maximum positive support

            // Set padding to 0
            for (pin = maxnSup - 1; pin >= 0; pin--)
            {
                padLine[pin] = 0;
            }
            for (pin = maxnSup + h - 1 + maxpSup; pin >= h; pin--)
            {
                padLine[pin] = 0;
            }

            // Do decomposition of all columns
            lineoffs = (uly + h - 1) * tilew + ulx + w;
            for (j = w - 1; j >= 0; j--)
            {
                lineoffs--;
                // Get the line to transform from the mask
                mi = lineoffs;
                for (k = h, pin = k - 1 + maxnSup; k > 0; k--, mi -= tilew, pin--)
                {
                    padLine[pin] = mask[mi];
                }
                lastpin = maxnSup + highFirst + 2 * lmax + lpSup;
                for (k = lmax; k >= 0; k--, lastpin -= 2)
                {
                    // Low frequency samples
                    pin = lastpin;
                    for (s = lsup; s > 0; s--, pin--)
                    {
                        scalVal = padLine[pin];
                        if (scalVal > maxVal)
                        {
                            maxVal = scalVal;
                        }
                    }
                    low[k] = maxVal;
                    maxVal = 0;
                }
                lastpin = maxnSup - highFirst + 2 * hmax + 1 + hpSup;
                for (k = hmax; k >= 0; k--, lastpin -= 2)
                {
                    // High frequency samples
                    pin = lastpin;
                    for (s = hsup; s > 0; s--, pin--)
                    {
                        scalVal = padLine[pin];
                        if (scalVal > maxVal)
                        {
                            maxVal = scalVal;
                        }
                    }
                    high[k] = maxVal;
                    maxVal  = 0;
                }
                // Put the lows and highs back
                mi = lineoffs;
                for (k = hmax; k >= 0; k--, mi -= tilew)
                {
                    mask[mi] = high[k];
                }
                for (k = lmax; k >= 0; k--, mi -= tilew)
                {
                    mask[mi] = low[k];
                }
            }

            if (sb.isNode)
            {
                decomp(sb.HH, tilew, tileh, c);
                decomp(sb.LH, tilew, tileh, c);
                decomp(sb.HL, tilew, tileh, c);
                decomp(sb.LL, tilew, tileh, c);
            }
        }
        /// <summary> The constructor of the SubbandROIMask takes the dimensions of the
        /// subband as parameters. A tree of masks is generated from the subband
        /// sb. Each Subband contains the boundaries of each ROI.
        ///
        /// </summary>
        /// <param name="sb">The subband corresponding to this Subband Mask
        ///
        /// </param>
        /// <param name="ulxs">The upper left x coordinates of the ROIs
        ///
        /// </param>
        /// <param name="ulys">The upper left y coordinates of the ROIs
        ///
        /// </param>
        /// <param name="lrxs">The lower right x coordinates of the ROIs
        ///
        /// </param>
        /// <param name="lrys">The lower right y coordinates of the ROIs
        ///
        /// </param>
        /// <param name="lrys">The lower right y coordinates of the ROIs
        ///
        /// </param>
        /// <param name="nr">Number of ROIs that affect this tile
        ///
        /// </param>
        public SubbandRectROIMask(Subband sb, int[] ulxs, int[] ulys, int[] lrxs, int[] lrys, int nr) : base(sb.ulx, sb.uly, sb.w, sb.h)
        {
            this.ulxs = ulxs;
            this.ulys = ulys;
            this.lrxs = lrxs;
            this.lrys = lrys;
            int r;

            if (sb.isNode)
            {
                isNode = true;
                // determine odd/even - high/low filters
                int horEvenLow = sb.ulcx % 2;
                int verEvenLow = sb.ulcy % 2;

                // Get filter support lengths
                WaveletFilter hFilter = sb.HorWFilter;
                WaveletFilter vFilter = sb.VerWFilter;
                int           hlnSup  = hFilter.SynLowNegSupport;
                int           hhnSup  = hFilter.SynHighNegSupport;
                int           hlpSup  = hFilter.SynLowPosSupport;
                int           hhpSup  = hFilter.SynHighPosSupport;
                int           vlnSup  = vFilter.SynLowNegSupport;
                int           vhnSup  = vFilter.SynHighNegSupport;
                int           vlpSup  = vFilter.SynLowPosSupport;
                int           vhpSup  = vFilter.SynHighPosSupport;

                // Generate arrays for children
                int   x, y;
                int[] lulxs = new int[nr];
                int[] lulys = new int[nr];
                int[] llrxs = new int[nr];
                int[] llrys = new int[nr];
                int[] hulxs = new int[nr];
                int[] hulys = new int[nr];
                int[] hlrxs = new int[nr];
                int[] hlrys = new int[nr];
                for (r = nr - 1; r >= 0; r--)
                {
                    // For all ROI calculate ...
                    // Upper left x for all children
                    x = ulxs[r];
                    if (horEvenLow == 0)
                    {
                        lulxs[r] = (x + 1 - hlnSup) / 2;
                        hulxs[r] = (x - hhnSup) / 2;
                    }
                    else
                    {
                        lulxs[r] = (x - hlnSup) / 2;
                        hulxs[r] = (x + 1 - hhnSup) / 2;
                    }
                    // Upper left y for all children
                    y = ulys[r];
                    if (verEvenLow == 0)
                    {
                        lulys[r] = (y + 1 - vlnSup) / 2;
                        hulys[r] = (y - vhnSup) / 2;
                    }
                    else
                    {
                        lulys[r] = (y - vlnSup) / 2;
                        hulys[r] = (y + 1 - vhnSup) / 2;
                    }
                    // lower right x for all children
                    x = lrxs[r];
                    if (horEvenLow == 0)
                    {
                        llrxs[r] = (x + hlpSup) / 2;
                        hlrxs[r] = (x - 1 + hhpSup) / 2;
                    }
                    else
                    {
                        llrxs[r] = (x - 1 + hlpSup) / 2;
                        hlrxs[r] = (x + hhpSup) / 2;
                    }
                    // lower right y for all children
                    y = lrys[r];
                    if (verEvenLow == 0)
                    {
                        llrys[r] = (y + vlpSup) / 2;
                        hlrys[r] = (y - 1 + vhpSup) / 2;
                    }
                    else
                    {
                        llrys[r] = (y - 1 + vlpSup) / 2;
                        hlrys[r] = (y + vhpSup) / 2;
                    }
                }
                // Create children
                hh = new SubbandRectROIMask(sb.HH, hulxs, hulys, hlrxs, hlrys, nr);
                lh = new SubbandRectROIMask(sb.LH, lulxs, hulys, llrxs, hlrys, nr);
                hl = new SubbandRectROIMask(sb.HL, hulxs, lulys, hlrxs, llrys, nr);
                ll = new SubbandRectROIMask(sb.LL, lulxs, lulys, llrxs, llrys, nr);
            }
        }