Ejemplo n.º 1
0
        /// <summary> Returns the next code-block in the current tile for the specified
        /// component. The order in which code-blocks are returned is not
        /// specified. However each code-block is returned only once and all
        /// code-blocks will be returned if the method is called 'N' times, where
        /// 'N' is the number of code-blocks in the tile. After all the code-blocks
        /// have been returned for the current tile calls to this method will
        /// return 'null'.
        ///
        /// <p>When changing the current tile (through 'setTile()' or 'nextTile()')
        /// this method will always return the first code-block, as if this method
        /// was never called before for the new current tile.</p>
        ///
        /// <p>The data returned by this method can be the data in the internal
        /// buffer of this object, if any, and thus can not be modified by the
        /// caller. The 'offset' and 'scanw' of the returned data can be
        /// arbitrary. See the 'CBlkWTData' class.</p>
        ///
        /// <p>The 'ulx' and 'uly' members of the returned 'CBlkWTData' object
        /// contain the coordinates of the top-left corner of the block, with
        /// respect to the tile, not the subband.</p>
        ///
        /// </summary>
        /// <param name="c">The component for which to return the next code-block.
        ///
        /// </param>
        /// <param name="cblk">If non-null this object will be used to return the new
        /// code-block. If null a new one will be allocated and returned. If the
        /// "data" array of the object is non-null it will be reused, if possible,
        /// to return the data.
        ///
        /// </param>
        /// <returns> The next code-block in the current tile for component 'n', or
        /// null if all code-blocks for the current tile have been returned.
        ///
        /// </returns>
        /// <seealso cref="CBlkWTData">
        ///
        /// </seealso>
        public override CBlkWTData getNextInternCodeBlock(int c, CBlkWTData cblk)
        {
            // NOTE: this method is declared final since getNextCodeBlock() relies
            // on this particular implementation
            int k, j;
            int tmp, shiftBits, jmin;
            int w, h;

            int[]           outarr;
            float[]         infarr = null;
            CBlkWTDataFloat infblk;
            float           invstep; // The inverse of the quantization step size
            bool            intq;    // flag for quantizig ints
            SubbandAn       sb;
            float           stepUDR; // The quantization step size (for a dynamic
            // range of 1, or unit)
            int g = ((System.Int32)gbs.getTileCompVal(tIdx, c));

            // Are we quantizing ints or floats?
            intq = (src.getDataType(tIdx, c) == DataBlk.TYPE_INT);

            // Check that we have an output object
            if (cblk == null)
            {
                cblk = new CBlkWTDataInt();
            }

            // Cache input float code-block
            infblk = this.infblk;

            // Get data to quantize. When quantizing int data 'cblk' is used to
            // get the data to quantize and to return the quantized data as well,
            // that's why 'getNextCodeBlock()' is used. This can not be done when
            // quantizing float data because of the different data types, that's
            // why 'getNextInternCodeBlock()' is used in that case.
            if (intq)
            {
                // Source data is int
                cblk = src.getNextCodeBlock(c, cblk);
                if (cblk == null)
                {
                    return(null);                    // No more code-blocks in current tile for comp.
                }
                // Input and output arrays are the same (for "in place" quant.)
                outarr = (int[])cblk.Data;
            }
            else
            {
                // Source data is float
                // Can not use 'cblk' to get float data, use 'infblk'
                infblk = (CBlkWTDataFloat)src.getNextInternCodeBlock(c, infblk);
                if (infblk == null)
                {
                    // Release buffer from infblk: this enables to garbage collect
                    // the big buffer when we are done with last code-block of
                    // component.
                    this.infblk.Data = null;
                    return(null);                    // No more code-blocks in current tile for comp.
                }
                this.infblk = infblk;                // Save local cache
                infarr      = (float[])infblk.Data;
                // Get output data array and check that there is memory to put the
                // quantized coeffs in
                outarr = (int[])cblk.Data;
                if (outarr == null || outarr.Length < infblk.w * infblk.h)
                {
                    outarr    = new int[infblk.w * infblk.h];
                    cblk.Data = outarr;
                }
                cblk.m           = infblk.m;
                cblk.n           = infblk.n;
                cblk.sb          = infblk.sb;
                cblk.ulx         = infblk.ulx;
                cblk.uly         = infblk.uly;
                cblk.w           = infblk.w;
                cblk.h           = infblk.h;
                cblk.wmseScaling = infblk.wmseScaling;
                cblk.offset      = 0;
                cblk.scanw       = cblk.w;
            }

            // Cache width, height and subband of code-block
            w  = cblk.w;
            h  = cblk.h;
            sb = cblk.sb;

            if (isReversible(tIdx, c))
            {
                // Reversible only for int data
                cblk.magbits = g - 1 + src.getNomRangeBits(c) + sb.anGainExp;
                shiftBits    = 31 - cblk.magbits;

                // Update the convertFactor field
                cblk.convertFactor = (1 << shiftBits);

                // Since we used getNextCodeBlock() to get the int data then
                // 'offset' is 0 and 'scanw' is the width of the code-block The
                // input and output arrays are the same (i.e. "in place")
                for (j = w * h - 1; j >= 0; j--)
                {
                    tmp       = (outarr[j] << shiftBits);
                    outarr[j] = ((tmp < 0)?(1 << 31) | (-tmp):tmp);
                }
            }
            else
            {
                // Non-reversible, use step size
                //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(tIdx, c));

                // Calculate magnitude bits and quantization step size
                if (isDerived(tIdx, 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'"
                    cblk.magbits = g - 1 + sb.level - (int)System.Math.Floor(System.Math.Log(baseStep) / log2);
                    stepUDR      = baseStep / (1 << sb.level);
                }
                else
                {
                    //UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
                    cblk.magbits = g - 1 - (int)System.Math.Floor(System.Math.Log(baseStep / (sb.l2Norm * (1 << sb.anGainExp))) / log2);
                    stepUDR      = baseStep / (sb.l2Norm * (1 << sb.anGainExp));
                }
                shiftBits = 31 - cblk.magbits;
                // Calculate step that decoder will get and use that one.
                stepUDR = convertFromExpMantissa(convertToExpMantissa(stepUDR));
                invstep = 1.0f / ((1L << (src.getNomRangeBits(c) + sb.anGainExp)) * stepUDR);
                // Normalize to magnitude bits (output fractional point)
                invstep *= (1 << (shiftBits - src.getFixedPoint(c)));

                // Update convertFactor and stepSize fields
                cblk.convertFactor = invstep;
                cblk.stepSize      = ((1L << (src.getNomRangeBits(c) + sb.anGainExp)) * stepUDR);

                if (intq)
                {
                    // Quantizing int data
                    // Since we used getNextCodeBlock() to get the int data then
                    // 'offset' is 0 and 'scanw' is the width of the code-block
                    // The input and output arrays are the same (i.e. "in place")
                    for (j = w * h - 1; j >= 0; j--)
                    {
                        //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'"
                        tmp       = (int)(outarr[j] * invstep);
                        outarr[j] = ((tmp < 0)?(1 << 31) | (-tmp):tmp);
                    }
                }
                else
                {
                    // Quantizing float data
                    for (j = w * h - 1, k = infblk.offset + (h - 1) * infblk.scanw + w - 1, jmin = w * (h - 1); j >= 0; jmin -= w)
                    {
                        for (; j >= jmin; k--, j--)
                        {
                            //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'"
                            tmp       = (int)(infarr[k] * invstep);
                            outarr[j] = ((tmp < 0)?(1 << 31) | (-tmp):tmp);
                        }
                        // Jump to beggining of previous line in input
                        k -= (infblk.scanw - w);
                    }
                }
            }
            // Return the quantized code-block
            return(cblk);
        }
Ejemplo n.º 2
0
        /// <summary> Returns the specified code-block in the current tile for the specified
        /// component (as a reference or copy).
        ///
        /// <p>The returned code-block may be progressive, which is indicated by
        /// the 'progressive' variable of the returned 'DataBlk'
        /// object. If a code-block is progressive it means that in a later request
        /// to this method for the same code-block it is possible to retrieve data
        /// which is a better approximation, since meanwhile more data to decode
        /// for the code-block could have been received. If the code-block is not
        /// progressive then later calls to this method for the same code-block
        /// will return the exact same data values.</p>
        ///
        /// <p>The data returned by this method can be the data in the internal
        /// buffer of this object, if any, and thus can not be modified by the
        /// caller. The 'offset' and 'scanw' of the returned data can be
        /// arbitrary. See the 'DataBlk' class.</p>
        ///
        /// </summary>
        /// <param name="c">The component for which to return the next code-block.
        ///
        /// </param>
        /// <param name="m">The vertical index of the code-block to return, in the
        /// specified subband.
        ///
        /// </param>
        /// <param name="n">The horizontal index of the code-block to return, in the
        /// specified subband.
        ///
        /// </param>
        /// <param name="sb">The subband in which the code-block to return is.
        ///
        /// </param>
        /// <param name="cblk">If non-null this object will be used to return the new
        /// code-block. If null a new one will be allocated and returned. If the
        /// "data" array of the object is non-null it will be reused, if possible,
        /// to return the data.
        ///
        /// </param>
        /// <returns> The next code-block in the current tile for component 'n', or
        /// null if all code-blocks for the current tile have been returned.
        ///
        /// </returns>
        /// <seealso cref="DataBlk">
        ///
        /// </seealso>
        public override DataBlk getInternCodeBlock(int c, int m, int n, SubbandSyn sb, DataBlk cblk)
        {
            // This method is declared final since getNextCodeBlock() relies on
            // the actual implementation of this method.
            int   j, jmin, k;
            int   temp;
            float step;
            int   shiftBits;
            int   magBits;

            int[]   outiarr, inarr;
            float[] outfarr;
            int     w, h;
            bool    reversible = qts.isReversible(tIdx, c);
            bool    derived    = qts.isDerived(tIdx, c);
            StdDequantizerParams params_Renamed = (StdDequantizerParams)qsss.getTileCompVal(tIdx, c);
            int G = ((System.Int32)gbs.getTileCompVal(tIdx, c));

            outdtype = cblk.DataType;

            if (reversible && outdtype != DataBlk.TYPE_INT)
            {
                throw new System.ArgumentException("Reversible quantizations " + "must use int data");
            }

            // To get compiler happy
            outiarr = null;
            outfarr = null;
            inarr   = null;

            // Get source data and initialize output DataBlk object.
            switch (outdtype)
            {
            case DataBlk.TYPE_INT:
                // With int data we can use the same DataBlk object to get the
                // data from the source and return the dequantized data, and we
                // can also work "in place" (i.e. same buffer).
                cblk = src.getCodeBlock(c, m, n, sb, cblk);
                // Input and output arrays are the same
                outiarr = (int[])cblk.Data;
                break;

            case DataBlk.TYPE_FLOAT:
                // With float data we must use a different DataBlk objects to get
                // the data from the source and to return the dequantized data.
                inblk = (DataBlkInt)src.getInternCodeBlock(c, m, n, sb, inblk);
                inarr = inblk.DataInt;
                if (cblk == null)
                {
                    cblk = new DataBlkFloat();
                }
                // Copy the attributes of the CodeBlock object
                cblk.ulx         = inblk.ulx;
                cblk.uly         = inblk.uly;
                cblk.w           = inblk.w;
                cblk.h           = inblk.h;
                cblk.offset      = 0;
                cblk.scanw       = cblk.w;
                cblk.progressive = inblk.progressive;
                // Get output data array and check its size
                outfarr = (float[])cblk.Data;
                if (outfarr == null || outfarr.Length < cblk.w * cblk.h)
                {
                    outfarr   = new float[cblk.w * cblk.h];
                    cblk.Data = outfarr;
                }
                break;
            }

            magBits = sb.magbits;

            // Calculate quantization step and number of magnitude bits
            // depending on reversibility and derivedness and perform
            // inverse quantization
            if (reversible)
            {
                shiftBits = 31 - magBits;
                // For int data Inverse quantization happens "in-place". The input
                // array has an offset of 0 and scan width equal to the code-block
                // width.
                for (j = outiarr.Length - 1; j >= 0; j--)
                {
                    temp       = outiarr[j]; // input array is same as output one
                    outiarr[j] = (temp >= 0) ? (temp >> shiftBits) : -((temp & 0x7FFFFFFF) >> shiftBits);
                }
            }
            else
            {
                // Not reversible
                if (derived)
                {
                    // Max resolution level
                    int mrl = src.getSynSubbandTree(TileIdx, c).resLvl;
                    step = params_Renamed.nStep[0][0] * (1L << (rb[c] + sb.anGainExp + mrl - sb.level));
                }
                else
                {
                    step = params_Renamed.nStep[sb.resLvl][sb.sbandIdx] * (1L << (rb[c] + sb.anGainExp));
                }
                shiftBits = 31 - magBits;

                // Adjust step to the number of shiftBits
                step /= (1 << shiftBits);

                switch (outdtype)
                {
                case DataBlk.TYPE_INT:
                    // For int data Inverse quantization happens "in-place". The
                    // input array has an offset of 0 and scan width equal to the
                    // code-block width.
                    for (j = outiarr.Length - 1; j >= 0; j--)
                    {
                        temp = outiarr[j];     // input array is same as output one
                                               //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'"
                        outiarr[j] = (int)(((float)((temp >= 0) ? temp : -(temp & 0x7FFFFFFF))) * step);
                    }
                    break;

                case DataBlk.TYPE_FLOAT:
                    // For float data the inverse quantization can not happen
                    // "in-place".
                    w = cblk.w;
                    h = cblk.h;
                    for (j = w * h - 1, k = inblk.offset + (h - 1) * inblk.scanw + w - 1, jmin = w * (h - 1); j >= 0; jmin -= w)
                    {
                        for (; j >= jmin; k--, j--)
                        {
                            temp = inarr[k];
                            //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'"
                            outfarr[j] = ((float)((temp >= 0) ? temp : -(temp & 0x7FFFFFFF))) * step;
                        }
                        // Jump to beggining of previous line in input
                        k -= (inblk.scanw - w);
                    }
                    break;
                }
            }
            // Return the output code-block
            return(cblk);
        }