Ejemplo n.º 1
0
        /// <summary> Returns a block of image data containing the specifed rectangular area,
        /// in the specified component, as a reference to the internal buffer (see
        /// below). The rectangular area is specified by the coordinates and
        /// dimensions of the 'blk' object.
        ///
        /// <p>The area to return is specified by the 'ulx', 'uly', 'w' and 'h'
        /// members of the 'blk' argument. These members are not modified by this
        /// method.</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>
        ///
        /// <p>The returned data has its 'progressive' attribute unset
        /// (i.e. false).</p>
        ///
        /// </summary>
        /// <param name="blk">Its coordinates and dimensions specify the area to return.
        ///
        /// </param>
        /// <param name="c">The index of the component from which to get the data.
        ///
        /// </param>
        /// <returns> The requested DataBlk
        ///
        /// </returns>
        /// <seealso cref="getInternCompData">
        ///
        /// </seealso>
        public override DataBlk getInternCompData(DataBlk blk, int c)
        {
            int tIdx = TileIdx;

            if (src.getSynSubbandTree(tIdx, c).HorWFilter == null)
            {
                dtype = DataBlk.TYPE_INT;
            }
            else
            {
                dtype = src.getSynSubbandTree(tIdx, c).HorWFilter.DataType;
            }

            //If the source image has not been decomposed
            if (reconstructedComps[c] == null)
            {
                //Allocate component data buffer
                switch (dtype)
                {
                case DataBlk.TYPE_FLOAT:
                    reconstructedComps[c] = new DataBlkFloat(0, 0, getTileCompWidth(tIdx, c), getTileCompHeight(tIdx, c));
                    break;

                case DataBlk.TYPE_INT:
                    reconstructedComps[c] = new DataBlkInt(0, 0, getTileCompWidth(tIdx, c), getTileCompHeight(tIdx, c));
                    break;
                }
                //Reconstruct source image
                waveletTreeReconstruction(reconstructedComps[c], src.getSynSubbandTree(tIdx, c), c);
                if (pw != null && c == src.NumComps - 1)
                {
                    pw.terminateProgressWatch();
                }
            }

            if (blk.DataType != dtype)
            {
                if (dtype == DataBlk.TYPE_INT)
                {
                    blk = new DataBlkInt(blk.ulx, blk.uly, blk.w, blk.h);
                }
                else
                {
                    blk = new DataBlkFloat(blk.ulx, blk.uly, blk.w, blk.h);
                }
            }
            // Set the reference to the internal buffer
            blk.Data        = reconstructedComps[c].Data;
            blk.offset      = reconstructedComps[c].w * blk.uly + blk.ulx;
            blk.scanw       = reconstructedComps[c].w;
            blk.progressive = false;
            return(blk);
        }
Ejemplo n.º 2
0
        /// <summary>General utility used by ctors </summary>
        private void initialize()
        {
            tempInt   = new DataBlkInt[ncomps];
            tempFloat = new DataBlkFloat[ncomps];

            /* For each component, get the maximum data value, a reference
             * to the pixel data and set up working and temporary DataBlks
             * for both integer and float output.
             */
            for (int i = 0; i < ncomps; ++i)
            {
                tempInt[i]   = new DataBlkInt();
                tempFloat[i] = new DataBlkFloat();
            }
        }
Ejemplo n.º 3
0
        /// <summary>General utility used by ctors </summary>
        private void initialize()
        {
            this.pl     = csMap.pl;
            this.ncomps = src.NumComps;

            shiftValueArray  = new int[ncomps];
            maxValueArray    = new int[ncomps];
            fixedPtBitsArray = new int[ncomps];

            srcBlk        = new DataBlk[ncomps];
            inInt         = new DataBlkInt[ncomps];
            inFloat       = new DataBlkFloat[ncomps];
            workInt       = new DataBlkInt[ncomps];
            workFloat     = new DataBlkFloat[ncomps];
            dataInt       = new int[ncomps][];
            dataFloat     = new float[ncomps][];
            workDataInt   = new int[ncomps][];
            workDataFloat = new float[ncomps][];
            dataInt       = new int[ncomps][];
            dataFloat     = new float[ncomps][];


            /* For each component, get a reference to the pixel data and
             * set up working DataBlks for both integer and float output.
             */
            for (int i = 0; i < ncomps; ++i)
            {
                shiftValueArray[i]  = 1 << (src.getNomRangeBits(i) - 1);
                maxValueArray[i]    = (1 << src.getNomRangeBits(i)) - 1;
                fixedPtBitsArray[i] = src.getFixedPoint(i);

                inInt[i]                 = new DataBlkInt();
                inFloat[i]               = new DataBlkFloat();
                workInt[i]               = new DataBlkInt();
                workInt[i].progressive   = inInt[i].progressive;
                workFloat[i]             = new DataBlkFloat();
                workFloat[i].progressive = inFloat[i].progressive;
            }
        }
Ejemplo n.º 4
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);
        }
Ejemplo n.º 5
0
        /// <summary> Return a DataBlk containing the requested component
        /// upsampled by the scale factor applied to the particular
        /// scaling direction
        ///
        /// Returns, in the blk argument, a block of image data containing the
        /// specifed rectangular area, in the specified component. The data is
        /// returned, as a copy of the internal data, therefore the returned data
        /// can be modified "in place".
        ///
        /// <P>The rectangular area to return is specified by the 'ulx', 'uly', 'w'
        /// and 'h' members of the 'blk' argument, relative to the current
        /// tile. These members are not modified by this method. The 'offset' of
        /// the returned data is 0, and the 'scanw' is the same as the block's
        /// width. See the 'DataBlk' class.
        ///
        /// <P>If the data array in 'blk' is 'null', then a new one is created. If
        /// the data array is not 'null' then it is reused, and it must be large
        /// enough to contain the block's data. Otherwise an 'ArrayStoreException'
        /// or an 'IndexOutOfBoundsException' is thrown by the Java system.
        ///
        /// <P>The returned data has its 'progressive' attribute set to that of the
        /// input data.
        ///
        /// </summary>
        /// <param name="blk">Its coordinates and dimensions specify the area to
        /// return. If it contains a non-null data array, then it must have the
        /// correct dimensions. If it contains a null data array a new one is
        /// created. The fields in this object are modified to return the data.
        ///
        /// </param>
        /// <param name="c">The index of the component from which to get the data. Only 0
        /// and 3 are valid.
        ///
        /// </param>
        /// <returns> The requested DataBlk
        ///
        /// </returns>
        /// <seealso cref="getCompData">
        /// </seealso>
        public override DataBlk getInternCompData(DataBlk outblk, int c)
        {
            // If the scaling factor of this channel is 1 in both
            // directions, simply return the source DataBlk.

            if (src.getCompSubsX(c) == 1 && src.getCompSubsY(c) == 1)
            {
                return(src.getInternCompData(outblk, c));
            }

            int wfactor = src.getCompSubsX(c);
            int hfactor = src.getCompSubsY(c);

            if ((wfactor != 2 && wfactor != 1) || (hfactor != 2 && hfactor != 1))
            {
                throw new System.ArgumentException("Upsampling by other than 2:1" + " not supported");
            }

            int leftedgeOut  = -1;            // offset to the start of the output scanline
            int rightedgeOut = -1;            // offset to the end of the output
            // scanline + 1
            int leftedgeIn  = -1;             // offset to the start of the input scanline
            int rightedgeIn = -1;             // offset to the end of the input scanline + 1


            int y0In, y1In, y0Out, y1Out;
            int x0In, x1In, x0Out, x1Out;

            y0Out = outblk.uly;
            y1Out = y0Out + outblk.h - 1;

            x0Out = outblk.ulx;
            x1Out = x0Out + outblk.w - 1;

            y0In = y0Out / hfactor;
            y1In = y1Out / hfactor;

            x0In = x0Out / wfactor;
            x1In = x1Out / wfactor;


            // Calculate the requested height and width, requesting an extra
            // row and or for upsampled channels.
            int reqW = x1In - x0In + 1;
            int reqH = y1In - y0In + 1;

            // Initialize general input and output indexes
            int kOut = -1;
            int kIn  = -1;
            int yIn;

            switch (outblk.DataType)
            {
            case DataBlk.TYPE_INT:

                DataBlkInt inblkInt = new DataBlkInt(x0In, y0In, reqW, reqH);
                inblkInt   = (DataBlkInt)src.getInternCompData(inblkInt, c);
                dataInt[c] = inblkInt.DataInt;

                // Reference the working array
                int[] outdataInt = (int[])outblk.Data;

                // Create data array if necessary
                if (outdataInt == null || outdataInt.Length != outblk.w * outblk.h)
                {
                    outdataInt  = new int[outblk.h * outblk.w];
                    outblk.Data = outdataInt;
                }

                // The nitty-gritty.

                for (int yOut = y0Out; yOut <= y1Out; ++yOut)
                {
                    yIn = yOut / hfactor;


                    leftedgeIn   = inblkInt.offset + (yIn - y0In) * inblkInt.scanw;
                    rightedgeIn  = leftedgeIn + inblkInt.w;
                    leftedgeOut  = outblk.offset + (yOut - y0Out) * outblk.scanw;
                    rightedgeOut = leftedgeOut + outblk.w;

                    kIn  = leftedgeIn;
                    kOut = leftedgeOut;

                    if ((x0Out & 0x1) == 1)
                    {
                        // first is odd do the pixel once.
                        outdataInt[kOut++] = dataInt[c][kIn++];
                    }

                    if ((x1Out & 0x1) == 0)
                    {
                        // last is even adjust loop bounds
                        rightedgeOut--;
                    }

                    while (kOut < rightedgeOut)
                    {
                        outdataInt[kOut++] = dataInt[c][kIn];
                        outdataInt[kOut++] = dataInt[c][kIn++];
                    }

                    if ((x1Out & 0x1) == 0)
                    {
                        // last is even do the pixel once.
                        outdataInt[kOut++] = dataInt[c][kIn];
                    }
                }

                outblk.progressive = inblkInt.progressive;
                break;


            case DataBlk.TYPE_FLOAT:

                DataBlkFloat inblkFloat = new DataBlkFloat(x0In, y0In, reqW, reqH);
                inblkFloat   = (DataBlkFloat)src.getInternCompData(inblkFloat, c);
                dataFloat[c] = inblkFloat.DataFloat;

                // Reference the working array
                float[] outdataFloat = (float[])outblk.Data;

                // Create data array if necessary
                if (outdataFloat == null || outdataFloat.Length != outblk.w * outblk.h)
                {
                    outdataFloat = new float[outblk.h * outblk.w];
                    outblk.Data  = outdataFloat;
                }

                // The nitty-gritty.

                for (int yOut = y0Out; yOut <= y1Out; ++yOut)
                {
                    yIn = yOut / hfactor;


                    leftedgeIn   = inblkFloat.offset + (yIn - y0In) * inblkFloat.scanw;
                    rightedgeIn  = leftedgeIn + inblkFloat.w;
                    leftedgeOut  = outblk.offset + (yOut - y0Out) * outblk.scanw;
                    rightedgeOut = leftedgeOut + outblk.w;

                    kIn  = leftedgeIn;
                    kOut = leftedgeOut;

                    if ((x0Out & 0x1) == 1)
                    {
                        // first is odd do the pixel once.
                        outdataFloat[kOut++] = dataFloat[c][kIn++];
                    }

                    if ((x1Out & 0x1) == 0)
                    {
                        // last is even adjust loop bounds
                        rightedgeOut--;
                    }

                    while (kOut < rightedgeOut)
                    {
                        outdataFloat[kOut++] = dataFloat[c][kIn];
                        outdataFloat[kOut++] = dataFloat[c][kIn++];
                    }

                    if ((x1Out & 0x1) == 0)
                    {
                        // last is even do the pixel once.
                        outdataFloat[kOut++] = dataFloat[c][kIn];
                    }
                }

                outblk.progressive = inblkFloat.progressive;
                break;


            case DataBlk.TYPE_SHORT:
            case DataBlk.TYPE_BYTE:
            default:
                // Unsupported output type.
                throw new System.ArgumentException("invalid source datablock " + "type");
            }

            return(outblk);
        }
Ejemplo n.º 6
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 is the data in the internal buffer
        /// of this object, and thus can not be modified by the caller. The
        /// 'offset' and 'scanw' of the returned data have, in general, some
        /// non-zero value. The 'magbits' of the returned data is not set by this
        /// method and should be ignored. 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.
        ///
        /// </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)
        {
            int       cbm, cbn, cn, cm;
            int       acb0x, acb0y;
            SubbandAn sb;

            intData = (filters.getWTDataType(tIdx, c) == DataBlk.TYPE_INT);

            //If the source image has not been decomposed
            if (decomposedComps[c] == null)
            {
                int           k, w, h;
                DataBlk       bufblk;
                System.Object dst_data;

                w = getTileCompWidth(tIdx, c);
                h = getTileCompHeight(tIdx, c);

                //Get the source image data
                if (intData)
                {
                    decomposedComps[c] = new DataBlkInt(0, 0, w, h);
                    bufblk             = new DataBlkInt();
                }
                else
                {
                    decomposedComps[c] = new DataBlkFloat(0, 0, w, h);
                    bufblk             = new DataBlkFloat();
                }

                // Get data from source line by line (this diminishes the memory
                // requirements on the data source)
                dst_data = decomposedComps[c].Data;
                int lstart = getCompULX(c);
                bufblk.ulx = lstart;
                bufblk.w   = w;
                bufblk.h   = 1;
                int kk = getCompULY(c);
                for (k = 0; k < h; k++, kk++)
                {
                    bufblk.uly = kk;
                    bufblk.ulx = lstart;
                    bufblk     = src.getInternCompData(bufblk, c);
                    // CONVERSION PROBLEM?
                    Array.Copy((System.Array)bufblk.Data, bufblk.offset, (System.Array)dst_data, k * w, w);
                }

                //Decompose source image
                waveletTreeDecomposition(decomposedComps[c], getAnSubbandTree(tIdx, c), c);

                // Make the first subband the current one
                currentSubband[c] = getNextSubband(c);

                lastn[c] = -1;
                lastm[c] = 0;
            }

            // Get the next code-block to "send"
            do
            {
                // Calculate number of code-blocks in current subband
                ncblks = currentSubband[c].numCb;
                // Goto next code-block
                lastn[c]++;
                if (lastn[c] == ncblks.x)
                {
                    // Got to end of this row of
                    // code-blocks
                    lastn[c] = 0;
                    lastm[c]++;
                }
                if (lastm[c] < ncblks.y)
                {
                    // Not past the last code-block in the subband, we can return
                    // this code-block
                    break;
                }
                // If we get here we already sent all code-blocks in this subband,
                // goto next subband
                currentSubband[c] = getNextSubband(c);
                lastn[c]          = -1;
                lastm[c]          = 0;
                if (currentSubband[c] == null)
                {
                    // We don't need the transformed data any more (a priori)
                    decomposedComps[c] = null;
                    // All code-blocks from all subbands in the current
                    // tile have been returned so we return a null
                    // reference
                    return(null);
                }
                // Loop to find the next code-block
            }while (true);


            // 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.
            acb0x = cb0x;
            acb0y = cb0y;
            switch (currentSubband[c].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");
            }

            // Initialize output code-block
            if (cblk == null)
            {
                if (intData)
                {
                    cblk = new CBlkWTDataInt();
                }
                else
                {
                    cblk = new CBlkWTDataFloat();
                }
            }
            cbn     = lastn[c];
            cbm     = lastm[c];
            sb      = currentSubband[c];
            cblk.n  = cbn;
            cblk.m  = cbm;
            cblk.sb = sb;
            // Calculate the indexes of first code-block in subband with respect
            // to the partitioning origin, to then calculate the position and size
            // 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
            cn = (sb.ulcx - acb0x + sb.nomCBlkW) / sb.nomCBlkW - 1;
            cm = (sb.ulcy - acb0y + sb.nomCBlkH) / sb.nomCBlkH - 1;
            if (cbn == 0)
            {
                // Left-most code-block, starts where subband starts
                cblk.ulx = sb.ulx;
            }
            else
            {
                // Calculate starting canvas coordinate and convert to subb. coords
                cblk.ulx = (cn + cbn) * sb.nomCBlkW - (sb.ulcx - acb0x) + sb.ulx;
            }
            if (cbm == 0)
            {
                // Bottom-most code-block, starts where subband starts
                cblk.uly = sb.uly;
            }
            else
            {
                cblk.uly = (cm + cbm) * sb.nomCBlkH - (sb.ulcy - acb0y) + sb.uly;
            }
            if (cbn < ncblks.x - 1)
            {
                // Calculate where next code-block starts => width
                cblk.w = (cn + cbn + 1) * sb.nomCBlkW - (sb.ulcx - acb0x) + sb.ulx - cblk.ulx;
            }
            else
            {
                // Right-most code-block, ends where subband ends
                cblk.w = sb.ulx + sb.w - cblk.ulx;
            }
            if (cbm < ncblks.y - 1)
            {
                // Calculate where next code-block starts => height
                cblk.h = (cm + cbm + 1) * sb.nomCBlkH - (sb.ulcy - acb0y) + sb.uly - cblk.uly;
            }
            else
            {
                // Bottom-most code-block, ends where subband ends
                cblk.h = sb.uly + sb.h - cblk.uly;
            }
            cblk.wmseScaling = 1f;

            // Since we are in getNextInternCodeBlock() we can return a
            // reference to the internal buffer, no need to copy. Just initialize
            // the 'offset' and 'scanw'
            cblk.offset = cblk.uly * decomposedComps[c].w + cblk.ulx;
            cblk.scanw  = decomposedComps[c].w;

            // For the data just put a reference to our buffer
            cblk.Data = decomposedComps[c].Data;
            // Return code-block
            return(cblk);
        }
Ejemplo n.º 7
0
        /// <summary> Performs the inverse wavelet transform on the whole component. It
        /// iteratively reconstructs the subbands from leaves up to the root
        /// node. This method is recursive, the first call to it the 'sb' must be
        /// the root of the subband tree. The method will then process the entire
        /// subband tree by calling itslef recursively.
        ///
        /// </summary>
        /// <param name="img">The buffer for the image/wavelet data.
        ///
        /// </param>
        /// <param name="sb">The subband to reconstruct.
        ///
        /// </param>
        /// <param name="c">The index of the component to reconstruct
        ///
        /// </param>
        private void waveletTreeReconstruction(DataBlk img, SubbandSyn sb, int c)
        {
            DataBlk subbData;

            // If the current subband is a leaf then get the data from the source
            if (!sb.isNode)
            {
                int           i, m, n;
                System.Object src_data, dst_data;
                Coord         ncblks;

                if (sb.w == 0 || sb.h == 0)
                {
                    return; // If empty subband do nothing
                }

                // Get all code-blocks in subband
                if (dtype == DataBlk.TYPE_INT)
                {
                    subbData = new DataBlkInt();
                }
                else
                {
                    subbData = new DataBlkFloat();
                }
                ncblks   = sb.numCb;
                dst_data = img.Data;
                for (m = 0; m < ncblks.y; m++)
                {
                    for (n = 0; n < ncblks.x; n++)
                    {
                        subbData = src.getInternCodeBlock(c, m, n, sb, subbData);
                        src_data = subbData.Data;
                        if (pw != null)
                        {
                            nDecCblk++;
                            pw.updateProgressWatch(nDecCblk, null);
                        }
                        // Copy the data line by line
                        for (i = subbData.h - 1; i >= 0; i--)
                        {
                            // CONVERSION PROBLEM
                            Array.Copy((System.Array)src_data, subbData.offset + i * subbData.scanw, (System.Array)dst_data, (subbData.uly + i) * img.w + subbData.ulx, subbData.w);
                        }
                    }
                }
            }
            else if (sb.isNode)
            {
                // Reconstruct the lower resolution levels if the current subbands
                // is a node

                //Perform the reconstruction of the LL subband
                waveletTreeReconstruction(img, (SubbandSyn)sb.LL, c);

                if (sb.resLvl <= reslvl - maxImgRes + ndl[c])
                {
                    //Reconstruct the other subbands
                    waveletTreeReconstruction(img, (SubbandSyn)sb.HL, c);
                    waveletTreeReconstruction(img, (SubbandSyn)sb.LH, c);
                    waveletTreeReconstruction(img, (SubbandSyn)sb.HH, c);

                    //Perform the 2D wavelet decomposition of the current subband
                    wavelet2DReconstruction(img, (SubbandSyn)sb, c);
                }
            }
        }
Ejemplo n.º 8
0
        /// <summary> Apply inverse irreversible component transformation to obtain requested
        /// component from specified block of data. Whatever the type of requested
        /// DataBlk, it always returns a DataBlkFloat.
        ///
        /// </summary>
        /// <param name="blk">Determine the rectangular area to return
        ///
        /// </param>
        /// <param name="c">The index of the requested component
        ///
        /// </param>
        /// <returns> Data of requested component
        ///
        /// </returns>
        private DataBlk invICT(DataBlk blk, int c)
        {
            if (c >= 3 && c < NumComps)
            {
                // Requesting a component whose index is greater than 3
                int k, k0, mink, i; //  k1, k2 removed
                int w = blk.w;      //width of output block
                int h = blk.h;      //height of ouput block

                int[] out_data;     // array of output data

                //Reference to output block data array
                out_data = (int[])blk.Data;

                //Create data array of blk if necessary
                if (out_data == null)
                {
                    out_data = new int[h * w];
                    blk.Data = out_data;
                }

                // Variables
                DataBlkFloat indb = new DataBlkFloat(blk.ulx, blk.uly, w, h);
                float[]      indata;            // input data array

                // Get the input data
                // (returned block may be larger than requested one)
                src.getInternCompData(indb, c);
                indata = (float[])indb.Data;

                // Copy the data converting from int to int
                k  = w * h - 1;
                k0 = indb.offset + (h - 1) * indb.scanw + w - 1;
                for (i = h - 1; i >= 0; i--)
                {
                    for (mink = k - w; k > mink; k--, k0--)
                    {
                        //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'"
                        out_data[k] = (int)(indata[k0]);
                    }
                    // Jump to beggining of previous line in input
                    k0 -= (indb.scanw - w);
                }

                // Set the progressivity and offset
                blk.progressive = indb.progressive;
                blk.offset      = 0;
                blk.scanw       = w;
            }
            // If asking a component for the first time for this block,
            // do transform for the 3 components
            else if ((outdata[c] == null) || (dbi.ulx > blk.ulx) || (dbi.uly > blk.uly) || (dbi.ulx + dbi.w < blk.ulx + blk.w) || (dbi.uly + dbi.h < blk.uly + blk.h))
            {
                int k, k0, k1, k2, mink, i;
                int w = blk.w;                 //width of output block
                int h = blk.h;                 //height of ouput block

                //Reference to output block data array
                outdata[c] = (int[])blk.Data;

                //Create data array of blk if necessary
                if (outdata[c] == null || outdata[c].Length != w * h)
                {
                    outdata[c] = new int[h * w];
                    blk.Data   = outdata[c];
                }

                outdata[(c + 1) % 3] = new int[outdata[c].Length];
                outdata[(c + 2) % 3] = new int[outdata[c].Length];

                if (block0 == null || block0.DataType != DataBlk.TYPE_FLOAT)
                {
                    block0 = new DataBlkFloat();
                }
                if (block2 == null || block2.DataType != DataBlk.TYPE_FLOAT)
                {
                    block2 = new DataBlkFloat();
                }
                if (block1 == null || block1.DataType != DataBlk.TYPE_FLOAT)
                {
                    block1 = new DataBlkFloat();
                }
                block0.w   = block2.w = block1.w = blk.w;
                block0.h   = block2.h = block1.h = blk.h;
                block0.ulx = block2.ulx = block1.ulx = blk.ulx;
                block0.uly = block2.uly = block1.uly = blk.uly;

                float[] data0, data1, data2;                 // input data arrays

                // Fill in buffer blocks (to be read only)
                // Returned blocks may have different size and position
                block0 = (DataBlkFloat)src.getInternCompData(block0, 0);
                data0  = (float[])block0.Data;
                block2 = (DataBlkFloat)src.getInternCompData(block2, 1);
                data2  = (float[])block2.Data;
                block1 = (DataBlkFloat)src.getInternCompData(block1, 2);
                data1  = (float[])block1.Data;

                // Set the progressiveness of the output data
                blk.progressive = block0.progressive || block1.progressive || block2.progressive;
                blk.offset      = 0;
                blk.scanw       = w;

                // set attributes of the DataBlk used for buffering
                dbi.progressive = blk.progressive;
                dbi.ulx         = blk.ulx;
                dbi.uly         = blk.uly;
                dbi.w           = blk.w;
                dbi.h           = blk.h;

                //Perform conversion

                // Initialize general indexes
                k  = w * h - 1;
                k0 = block0.offset + (h - 1) * block0.scanw + w - 1;
                k2 = block2.offset + (h - 1) * block2.scanw + w - 1;
                k1 = block1.offset + (h - 1) * block1.scanw + w - 1;

                for (i = h - 1; i >= 0; i--)
                {
                    for (mink = k - w; k > mink; k--, k0--, k2--, k1--)
                    {
                        //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'"
                        outdata[0][k] = (int)(data0[k0] + 1.402f * data1[k1] + 0.5f);
                        //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'"
                        outdata[1][k] = (int)(data0[k0] - 0.34413f * data2[k2] - 0.71414f * data1[k1] + 0.5f);
                        //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'"
                        outdata[2][k] = (int)(data0[k0] + 1.772f * data2[k2] + 0.5f);
                    }
                    // Jump to beggining of previous line in input
                    k0 -= (block0.scanw - w);
                    k2 -= (block2.scanw - w);
                    k1 -= (block1.scanw - w);
                }
                outdata[c] = null;
            }
            else if ((c >= 0) && (c <= 3))
            {
                //Asking for the 2nd or 3rd block component
                blk.Data        = outdata[c];
                blk.progressive = dbi.progressive;
                blk.offset      = (blk.uly - dbi.uly) * dbi.w + blk.ulx - dbi.ulx;
                blk.scanw       = dbi.w;
                outdata[c]      = null;
            }
            else
            {
                // Requesting a non valid component index
                throw new System.ArgumentException();
            }
            return(blk);
        }