Exemplo 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);
        }
 /// <summary> Constructor of the ROI scaler, takes a Quantizer as source of data to
 /// scale.
 ///
 /// </summary>
 /// <param name="src">The quantizer that is the source of data.
 ///
 /// </param>
 /// <param name="mg">The mask generator that will be used for all components
 ///
 /// </param>
 /// <param name="roi">Flag indicating whether there are rois specified.
 ///
 /// </param>
 /// <param name="sLev">The resolution levels that belong entirely to ROI
 ///
 /// </param>
 /// <param name="uba">Flag indicating whether block aligning is used.
 ///
 /// </param>
 /// <param name="encSpec">The encoder specifications for addition of roi specs
 ///
 /// </param>
 public ROIScaler(Quantizer src, ROIMaskGenerator mg, bool roi, int sLev, bool uba, EncoderSpecs encSpec) : base(src)
 {
     this.src           = src;
     this.roi           = roi;
     this.useStartLevel = sLev;
     if (roi)
     {
         // If there is no ROI, no need to do this
         this.mg = mg;
         roiMask = new DataBlkInt();
         calcMaxMagBits(encSpec);
         blockAligned = uba;
     }
 }
Exemplo n.º 3
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();
            }
        }
Exemplo n.º 4
0
        /// <summary> 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> After being read the coefficients are level shifted by subtracting
        /// 2^(nominal bit range - 1)
        ///
        /// <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 unset
        /// (i.e. false).
        ///
        /// <P>When an I/O exception is encountered the JJ2KExceptionHandler is
        /// used. The exception is passed to its handleException method. The action
        /// that is taken depends on the action that has been registered in
        /// JJ2KExceptionHandler. See JJ2KExceptionHandler for details.
        ///
        /// </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,1 and 2 are valid.
        ///
        /// </param>
        /// <returns> The requested DataBlk
        ///
        /// </returns>
        /// <seealso cref="getInternCompData">
        ///
        /// </seealso>
        /// <seealso cref="JJ2KExceptionHandler">
        ///
        /// </seealso>
        public override DataBlk getCompData(DataBlk blk, int c)
        {
            // NOTE: can not directly call getInterCompData since that returns
            // internally buffered data.
            int ulx, uly, w, h;

            // Check type of block provided as an argument
            if (blk.DataType != DataBlk.TYPE_INT)
            {
                DataBlkInt tmp = new DataBlkInt(blk.ulx, blk.uly, blk.w, blk.h);
                blk = tmp;
            }

            int[] bakarr = (int[])blk.Data;
            // Save requested block size
            ulx = blk.ulx;
            uly = blk.uly;
            w   = blk.w;
            h   = blk.h;
            // Force internal data buffer to be different from external
            blk.Data = null;
            getInternCompData(blk, c);
            // Copy the data
            if (bakarr == null)
            {
                bakarr = new int[w * h];
            }
            if (blk.offset == 0 && blk.scanw == w)
            {
                // Requested and returned block buffer are the same size
                // CONVERSION PROBLEM?
                Array.Copy((System.Array)blk.Data, 0, (System.Array)bakarr, 0, w * h);
            }
            else
            {
                // Requested and returned block are different
                for (int i = h - 1; i >= 0; i--)
                {
                    // copy line by line
                    // CONVERSION PROBLEM?
                    Array.Copy((System.Array)blk.Data, blk.offset + i * blk.scanw, (System.Array)bakarr, i * w, w);
                }
            }
            blk.Data   = bakarr;
            blk.offset = 0;
            blk.scanw  = blk.w;
            return(blk);
        }
Exemplo n.º 5
0
        /// <summary> Closes the underlying file or netwrok connection to where the data is
        /// written. Any call to other methods of the class become illegal after a
        /// call to this one.
        ///
        /// </summary>
        /// <exception cref="IOException">If an I/O error occurs.
        ///
        /// </exception>
        public override void  close()
        {
            int i;

            // Finish writing the file, writing 0s at the end if the data at end
            // has not been written.
            if (out_Renamed.Length != w * h * packBytes + offset)
            {
                // Goto end of file
                out_Renamed.Seek(out_Renamed.Length, System.IO.SeekOrigin.Begin);
                // Fill with 0s
                for (i = offset + w * h * packBytes - (int)out_Renamed.Length; i > 0; i--)
                {
                    out_Renamed.WriteByte((System.Byte) 0);
                }
            }
            out_Renamed.Close();
            src         = null;
            out_Renamed = null;
            db          = null;
        }
Exemplo n.º 6
0
        /// <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);
        }
Exemplo n.º 7
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;
            }
        }
        /// <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);
        }
Exemplo n.º 9
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);
Exemplo n.º 10
0
        /// <summary> Writes the data of the specified area to the file, coordinates are
        /// relative to the current tile of the source. Before writing, the
        /// coefficients are limited to the nominal range.
        ///
        /// <p>This method may not be called concurrently from different
        /// threads.</p>
        ///
        /// <p>If the data returned from the BlkImgDataSrc source is progressive,
        /// then it is requested over and over until it is not progressive
        /// anymore.</p>
        ///
        /// </summary>
        /// <param name="ulx">The horizontal coordinate of the upper-left corner of the
        /// area to write, relative to the current tile.
        ///
        /// </param>
        /// <param name="uly">The vertical coordinate of the upper-left corner of the area
        /// to write, relative to the current tile.
        ///
        /// </param>
        /// <param name="width">The width of the area to write.
        ///
        /// </param>
        /// <param name="height">The height of the area to write.
        ///
        /// </param>
        /// <exception cref="IOException">If an I/O error occurs.
        ///
        /// </exception>
        public override void  write(int ulx, int uly, int w, int h)
        {
            int k, j, i, c;
            // In local variables for faster access
            int fracbits;
            // variables used during coeff saturation
            int shift, tmp, maxVal;
            int tOffx, tOffy;             // Active tile offset in the X and Y direction

            // Active tiles in all components have same offset since they are at
            // same resolution (PPM does not support anything 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'"
            tOffx = src.getCompULX(cps[0]) - (int)System.Math.Ceiling(src.ImgULX / (double)src.getCompSubsX(cps[0]));
            //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'"
            tOffy = src.getCompULY(cps[0]) - (int)System.Math.Ceiling(src.ImgULY / (double)src.getCompSubsY(cps[0]));

            // Check the array size
            if (db.data_array != null && db.data_array.Length < w)
            {
                // A new one will be allocated by getInternCompData()
                db.data_array = null;
            }

            // Check the line buffer
            if (buf == null || buf.Length < 3 * w)
            {
                buf = new byte[3 * w];
            }

            // Write the data to the file
            // Write line by line
            for (i = 0; i < h; i++)
            {
                // Write into buffer first loop over the three components and
                // write for each
                for (c = 0; c < 3; c++)
                {
                    maxVal = (1 << src.getNomRangeBits(cps[c])) - 1;
                    shift  = levShift[c];

                    // Initialize db
                    db.ulx = ulx;
                    db.uly = uly + i;
                    db.w   = w;
                    db.h   = 1;

                    // Request the data and make sure it is not progressive
                    do
                    {
                        db = (DataBlkInt)src.getInternCompData(db, cps[c]);
                    }while (db.progressive);
                    // Get the fracbits value
                    fracbits = fb[c];
                    // Write all bytes in the line
                    if (fracbits == 0)
                    {
                        for (k = db.offset + w - 1, j = 3 * w - 1 + c - 2; j >= 0; k--)
                        {
                            tmp    = db.data_array[k] + shift;
                            buf[j] = (byte)((tmp < 0)?0:((tmp > maxVal)?maxVal:tmp));
                            j     -= 3;
                        }
                    }
                    else
                    {
                        for (k = db.offset + w - 1, j = 3 * w - 1 + c - 2; j >= 0; k--)
                        {
                            tmp    = (SupportClass.URShift(db.data_array[k], fracbits)) + shift;
                            buf[j] = (byte)((tmp < 0)?0:((tmp > maxVal)?maxVal:tmp));
                            j     -= 3;
                        }
                    }
                }
                // Write buffer into file
                out_Renamed.Seek(offset + 3 * (this.w * (uly + tOffy + i) + ulx + tOffx), System.IO.SeekOrigin.Begin);
                out_Renamed.Write(buf, 0, 3 * w);
            }
        }
Exemplo n.º 11
0
        /// <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);
                }
            }
        }
Exemplo n.º 12
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);
        }
Exemplo n.º 13
0
        public static Image FromStream(Stream stream)
        {
            RandomAccessIO in_stream = new ISRandomAccessIO(stream);

            // Initialize default parameters
            ParameterList defpl = GetDefaultParameterList(decoder_pinfo);

            // Create parameter list using defaults
            ParameterList pl = new ParameterList(defpl);

            // **** File Format ****
            // If the codestream is wrapped in the jp2 fileformat, Read the
            // file format wrapper
            FileFormatReader ff = new FileFormatReader(in_stream);

            ff.readFileFormat();
            if (ff.JP2FFUsed)
            {
                in_stream.seek(ff.FirstCodeStreamPos);
            }

            // +----------------------------+
            // | Instantiate decoding chain |
            // +----------------------------+

            // **** Header decoder ****
            // Instantiate header decoder and read main header
            HeaderInfo    hi = new HeaderInfo();
            HeaderDecoder hd;

            try
            {
                hd = new HeaderDecoder(in_stream, pl, hi);
            }
            catch (EndOfStreamException e)
            {
                throw new ApplicationException("Codestream too short or bad header, unable to decode.", e);
            }

            int          nCompCod = hd.NumComps;
            int          nTiles   = hi.sizValue.NumTiles;
            DecoderSpecs decSpec  = hd.DecoderSpecs;

            // Get demixed bitdepths
            int[] depth = new int[nCompCod];
            for (int i = 0; i < nCompCod; i++)
            {
                depth[i] = hd.getOriginalBitDepth(i);
            }

            // **** Bit stream reader ****
            BitstreamReaderAgent breader;

            try
            {
                breader = BitstreamReaderAgent.
                          createInstance(in_stream, hd, pl, decSpec,
                                         false, hi);
            }
            catch (IOException e)
            {
                throw new ApplicationException("Error while reading bit stream header or parsing packets.", e);
            }
            catch (ArgumentException e)
            {
                throw new ApplicationException("Cannot instantiate bit stream reader.", e);
            }

            // **** Entropy decoder ****
            EntropyDecoder entdec;

            try
            {
                entdec = hd.createEntropyDecoder(breader, pl);
            }
            catch (ArgumentException e)
            {
                throw new ApplicationException("Cannot instantiate entropy decoder.", e);
            }

            // **** ROI de-scaler ****
            ROIDeScaler roids;

            try
            {
                roids = hd.createROIDeScaler(entdec, pl, decSpec);
            }
            catch (ArgumentException e)
            {
                throw new ApplicationException("Cannot instantiate roi de-scaler.", e);
            }

            // **** Dequantizer ****
            Dequantizer deq;

            try
            {
                deq = hd.createDequantizer(roids, depth, decSpec);
            }
            catch (ArgumentException e)
            {
                throw new ApplicationException("Cannot instantiate dequantizer.", e);
            }

            // **** Inverse wavelet transform ***
            InverseWT invWT;

            try
            {
                // full page inverse wavelet transform
                invWT = InverseWT.createInstance(deq, decSpec);
            }
            catch (ArgumentException e)
            {
                throw new ApplicationException("Cannot instantiate inverse wavelet transform.", e);
            }

            int res = breader.ImgRes;

            invWT.ImgResLevel = res;

            // **** Data converter **** (after inverse transform module)
            ImgDataConverter converter = new ImgDataConverter(invWT, 0);

            // **** Inverse component transformation ****
            InvCompTransf ictransf = new InvCompTransf(converter, decSpec, depth, pl);

            // **** Color space mapping ****
            BlkImgDataSrc color;

            if (ff.JP2FFUsed && pl.getParameter("nocolorspace").Equals("off"))
            {
                try
                {
                    ColorSpace    csMap      = new ColorSpace(in_stream, hd, pl);
                    BlkImgDataSrc channels   = hd.createChannelDefinitionMapper(ictransf, csMap);
                    BlkImgDataSrc resampled  = hd.createResampler(channels, csMap);
                    BlkImgDataSrc palettized = hd.createPalettizedColorSpaceMapper(resampled, csMap);
                    color = hd.createColorSpaceMapper(palettized, csMap);
                }
                catch (ArgumentException e)
                {
                    throw new ApplicationException("Could not instantiate ICC profiler.", e);
                }
                catch (ColorSpaceException e)
                {
                    throw new ApplicationException("Error processing ColorSpace information.", e);
                }
            }
            else
            { // Skip colorspace mapping
                color = ictransf;
            }

            // This is the last image in the decoding chain and should be
            // assigned by the last transformation:
            BlkImgDataSrc decodedImage = color;

            if (color == null)
            {
                decodedImage = ictransf;
            }
            int numComps      = decodedImage.NumComps;
            int bytesPerPixel = numComps; // Assuming 8-bit components

            // **** Copy to Bitmap ****
            PixelFormat pixelFormat;

            switch (numComps)
            {
            case 1:
                pixelFormat = PixelFormat.Format24bppRgb; break;

            case 3:
                pixelFormat = PixelFormat.Format24bppRgb; break;

            case 4:
            case 5:
                pixelFormat = PixelFormat.Format32bppArgb; break;

            default:
                throw new ApplicationException("Unsupported PixelFormat.  " + numComps + " components.");
            }

            Bitmap dst = new Bitmap(decodedImage.ImgWidth, decodedImage.ImgHeight, pixelFormat);

            Coord numTiles = decodedImage.getNumTiles(null);

            int tIdx = 0;

            for (int y = 0; y < numTiles.y; y++)
            {
                // Loop on horizontal tiles
                for (int x = 0; x < numTiles.x; x++, tIdx++)
                {
                    decodedImage.setTile(x, y);

                    int height = decodedImage.getTileCompHeight(tIdx, 0);
                    int width  = decodedImage.getTileCompWidth(tIdx, 0);

                    int tOffx = decodedImage.getCompULX(0) -
                                (int)Math.Ceiling(decodedImage.ImgULX /
                                                  (double)decodedImage.getCompSubsX(0));

                    int tOffy = decodedImage.getCompULY(0) -
                                (int)Math.Ceiling(decodedImage.ImgULY /
                                                  (double)decodedImage.getCompSubsY(0));

                    DataBlkInt[] db = new DataBlkInt[numComps];
                    int[]        ls = new int[numComps];
                    int[]        mv = new int[numComps];
                    int[]        fb = new int[numComps];
                    for (int i = 0; i < numComps; i++)
                    {
                        db[i] = new DataBlkInt();
                        ls[i] = 1 << (decodedImage.getNomRangeBits(0) - 1);
                        mv[i] = (1 << decodedImage.getNomRangeBits(0)) - 1;
                        fb[i] = decodedImage.getFixedPoint(0);
                    }
                    for (int l = 0; l < height; l++)
                    {
                        for (int i = numComps - 1; i >= 0; i--)
                        {
                            db[i].ulx = 0;
                            db[i].uly = l;
                            db[i].w   = width;
                            db[i].h   = 1;
                            decodedImage.getInternCompData(db[i], i);
                        }
                        int[] k = new int[numComps];
                        for (int i = numComps - 1; i >= 0; i--)
                        {
                            k[i] = db[i].offset + width - 1;
                        }

                        int    outputBytesPerPixel = Math.Max(3, Math.Min(4, bytesPerPixel));
                        byte[] rowvalues           = new byte[width * outputBytesPerPixel];

                        for (int i = width - 1; i >= 0; i--)
                        {
                            int[] tmp = new int[numComps];
                            for (int j = numComps - 1; j >= 0; j--)
                            {
                                tmp[j] = (db[j].data_array[k[j]--] >> fb[j]) + ls[j];
                                tmp[j] = (tmp[j] < 0) ? 0 : ((tmp[j] > mv[j]) ? mv[j] : tmp[j]);

                                if (decodedImage.getNomRangeBits(j) != 8)
                                {
                                    tmp[j] = (int)Math.Round(((double)tmp[j] / Math.Pow(2D, (double)decodedImage.getNomRangeBits(j))) * 255D);
                                }
                            }
                            int offset = i * outputBytesPerPixel;
                            switch (numComps)
                            {
                            case 1:
                                rowvalues[offset + 0] = (byte)tmp[0];
                                rowvalues[offset + 1] = (byte)tmp[0];
                                rowvalues[offset + 2] = (byte)tmp[0];
                                break;

                            case 3:
                                rowvalues[offset + 0] = (byte)tmp[2];
                                rowvalues[offset + 1] = (byte)tmp[1];
                                rowvalues[offset + 2] = (byte)tmp[0];
                                break;

                            case 4:
                            case 5:
                                rowvalues[offset + 0] = (byte)tmp[2];
                                rowvalues[offset + 1] = (byte)tmp[1];
                                rowvalues[offset + 2] = (byte)tmp[0];
                                rowvalues[offset + 3] = (byte)tmp[3];
                                break;
                            }
                        }

                        BitmapData dstdata = dst.LockBits(
                            new System.Drawing.Rectangle(tOffx, tOffy + l, width, 1),
                            ImageLockMode.WriteOnly, pixelFormat);

                        IntPtr ptr = dstdata.Scan0;
                        System.Runtime.InteropServices.Marshal.Copy(rowvalues, 0, ptr, rowvalues.Length);
                        dst.UnlockBits(dstdata);
                    }
                }
            }
            return(dst);
        }
Exemplo n.º 14
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);
        }
Exemplo n.º 15
0
        /// <summary> Apply forward component transformation to obtain requested component
        /// from specified block of data. Whatever the type of requested DataBlk,
        /// it always returns a DataBlkInt.
        ///
        /// </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 forwRCT(DataBlk blk, int c)
        {
            int k, k0, k1, k2, mink, i;
            int w = blk.w;             //width of output block
            int h = blk.h;             //height of ouput block

            int[] outdata;             //array of output data

            //If asking for Yr, Ur or Vr do transform
            if (c >= 0 && c <= 2)
            {
                // Check that request data type is int
                if (blk.DataType != DataBlk.TYPE_INT)
                {
                    if (outBlk == null || outBlk.DataType != DataBlk.TYPE_INT)
                    {
                        outBlk = new DataBlkInt();
                    }
                    outBlk.w   = w;
                    outBlk.h   = h;
                    outBlk.ulx = blk.ulx;
                    outBlk.uly = blk.uly;
                    blk        = outBlk;
                }

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

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

                // Block buffers for input RGB data
                int[] data0, data1, bdata;                 // input data arrays

                if (block0 == null)
                {
                    block0 = new DataBlkInt();
                }
                if (block1 == null)
                {
                    block1 = new DataBlkInt();
                }
                if (block2 == null)
                {
                    block2 = new DataBlkInt();
                }
                block0.w   = block1.w = block2.w = blk.w;
                block0.h   = block1.h = block2.h = blk.h;
                block0.ulx = block1.ulx = block2.ulx = blk.ulx;
                block0.uly = block1.uly = block2.uly = blk.uly;

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

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

                //Perform conversion

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

                switch (c)
                {
                case 0:                          //RGB to Yr conversion
                    for (i = h - 1; i >= 0; i--)
                    {
                        for (mink = k - w; k > mink; k--, k0--, k1--, k2--)
                        {
                            // Use int arithmetic with 12 fractional bits
                            // and rounding
                            outdata[k] = (data0[k] + 2 * data1[k] + bdata[k]) >> 2;                                     // Same as / 4
                        }
                        // Jump to beggining of previous line in input
                        k0 -= (block0.scanw - w);
                        k1 -= (block1.scanw - w);
                        k2 -= (block2.scanw - w);
                    }
                    break;


                case 1:                          //RGB to Ur conversion
                    for (i = h - 1; i >= 0; i--)
                    {
                        for (mink = k - w; k > mink; k--, k1--, k2--)
                        {
                            // Use int arithmetic with 12 fractional bits
                            // and rounding
                            outdata[k] = bdata[k2] - data1[k1];
                        }
                        // Jump to beggining of previous line in input
                        k1 -= (block1.scanw - w);
                        k2 -= (block2.scanw - w);
                    }
                    break;


                case 2:                          //RGB to Vr conversion
                    for (i = h - 1; i >= 0; i--)
                    {
                        for (mink = k - w; k > mink; k--, k0--, k1--)
                        {
                            // Use int arithmetic with 12 fractional bits
                            // and rounding
                            outdata[k] = data0[k0] - data1[k1];
                        }
                        // Jump to beggining of previous line in input
                        k0 -= (block0.scanw - w);
                        k1 -= (block1.scanw - w);
                    }
                    break;
                }
            }
            else if (c >= 3)
            {
                // Requesting a component which is not Y, Ur or Vr =>
                // just pass the data
                return(src.getInternCompData(blk, c));
            }
            else
            {
                // Requesting a non valid component index
                throw new System.ArgumentException();
            }
            return(blk);
        }
Exemplo n.º 16
0
        /// <summary> Writes the data of the specified area to the file, coordinates are
        /// relative to the current tile of the source. Before writing, the
        /// coefficients are limited to the nominal range.
        ///
        /// <p>This method may not be called concurrently from different
        /// threads.</p>
        ///
        /// <p>If the data returned from the BlkImgDataSrc source is progressive,
        /// then it is requested over and over until it is not progressive
        /// anymore.</p>
        ///
        /// </summary>
        /// <param name="ulx">The horizontal coordinate of the upper-left corner of the
        /// area to write, relative to the current tile.
        ///
        /// </param>
        /// <param name="uly">The vertical coordinate of the upper-left corner of the area
        /// to write, relative to the current tile.
        ///
        /// </param>
        /// <param name="width">The width of the area to write.
        ///
        /// </param>
        /// <param name="height">The height of the area to write.
        ///
        /// </param>
        /// <exception cref="IOException">If an I/O error occurs.
        ///
        /// </exception>
        public override void  write(int ulx, int uly, int w, int h)
        {
            int k, i, j;
            int fracbits = fb;            // In local variable for faster access
            int tOffx, tOffy;             // Active tile offset in the X and Y direction

            // Initialize db
            db.ulx = ulx;
            db.uly = uly;
            db.w   = w;
            db.h   = h;
            // Get the current active tile offset
            //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'"
            tOffx = src.getCompULX(c) - (int)System.Math.Ceiling(src.ImgULX / (double)src.getCompSubsX(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'"
            tOffy = src.getCompULY(c) - (int)System.Math.Ceiling(src.ImgULY / (double)src.getCompSubsY(c));
            // Check the array size
            if (db.data_array != null && db.data_array.Length < w * h)
            {
                // A new one will be allocated by getInternCompData()
                db.data_array = null;
            }
            // Request the data and make sure it is not
            // progressive
            do
            {
                db = (DataBlkInt)src.getInternCompData(db, c);
            }while (db.progressive);

            // variables used during coeff saturation
            int tmp, maxVal = (1 << src.getNomRangeBits(c)) - 1;

            // If nominal bitdepth greater than 8, calculate down shift
            int downShift = src.getNomRangeBits(c) - 8;

            if (downShift < 0)
            {
                downShift = 0;
            }

            // Check line buffer
            if (buf == null || buf.Length < w)
            {
                buf = new byte[w];                 // Expand buffer
            }

            // Write line by line
            for (i = 0; i < h; i++)
            {
                // Skip to beggining of line in file
                out_Renamed.Seek(this.offset + this.w * (uly + tOffy + i) + ulx + tOffx, System.IO.SeekOrigin.Begin);
                // Write all bytes in the line
                if (fracbits == 0)
                {
                    for (k = db.offset + i * db.scanw + w - 1, j = w - 1; j >= 0; j--, k--)
                    {
                        tmp    = db.data_array[k] + levShift;
                        buf[j] = (byte)(((tmp < 0)?0:((tmp > maxVal)?maxVal:tmp)) >> downShift);
                    }
                }
                else
                {
                    for (k = db.offset + i * db.scanw + w - 1, j = w - 1; j >= 0; j--, k--)
                    {
                        tmp    = (db.data_array[k] >> fracbits) + levShift;
                        buf[j] = (byte)(((tmp < 0)?0:((tmp > maxVal)?maxVal:tmp)) >> downShift);
                    }
                }
                out_Renamed.Write(buf, 0, w);
            }
        }
Exemplo n.º 17
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);
        }
Exemplo n.º 18
0
        /// <summary> Returns, in the blk argument, the block of image data containing the
        /// specifed rectangular area, in the specified component. The data is
        /// returned, as a reference to the internal data, if any, instead of as a
        /// copy, therefore the returned data should not be modified.
        ///
        /// <P> After being read the coefficients are level shifted by subtracting
        /// 2^(nominal bit range - 1)
        ///
        /// <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' and
        /// 'scanw' of the returned data can be arbitrary. See the 'DataBlk' class.
        ///
        /// <P>If the data array in <tt>blk</tt> is <tt>null</tt>, then a new one
        /// is created if necessary. The implementation of this interface may
        /// choose to return the same array or a new one, depending on what is more
        /// efficient. Therefore, the data array in <tt>blk</tt> prior to the
        /// method call should not be considered to contain the returned data, a
        /// new array may have been created. Instead, get the array from
        /// <tt>blk</tt> after the method has returned.
        ///
        /// <P>The returned data always has its 'progressive' attribute unset
        /// (i.e. false).
        ///
        /// <P>When an I/O exception is encountered the JJ2KExceptionHandler is
        /// used. The exception is passed to its handleException method. The action
        /// that is taken depends on the action that has been registered in
        /// JJ2KExceptionHandler. See JJ2KExceptionHandler for details.
        ///
        /// <P>This method implements buffering for the 3 components: When the
        /// first one is asked, all the 3 components are read and stored until they
        /// are needed.
        ///
        /// </summary>
        /// <param name="blk">Its coordinates and dimensions specify the area to
        /// return. Some 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,
        /// 1 and 3 are valid.
        ///
        /// </param>
        /// <returns> The requested DataBlk
        ///
        /// </returns>
        /// <seealso cref="getCompData">
        ///
        /// </seealso>
        /// <seealso cref="JJ2KExceptionHandler">
        ///
        /// </seealso>
        public override DataBlk getInternCompData(DataBlk blk, int c)
        {
            // Check component index
            if (c < 0 || c > 2)
            {
                throw new System.ArgumentException();
            }

            // Check type of block provided as an argument
            if (blk.DataType != DataBlk.TYPE_INT)
            {
                if (intBlk == null)
                {
                    intBlk = new DataBlkInt(blk.ulx, blk.uly, blk.w, blk.h);
                }
                else
                {
                    intBlk.ulx = blk.ulx;
                    intBlk.uly = blk.uly;
                    intBlk.w   = blk.w;
                    intBlk.h   = blk.h;
                }
                blk = intBlk;
            }

            // If asking a component for the first time for this block, read all of the components
            if ((barr == 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   i;
                int[] red, green, blue, alpha;
                int   componentCount = (image.PixelFormat == PixelFormat.Format32bppArgb) ? 4 : 3;

                barr = new int[componentCount][];

                // Reset data arrays if needed
                if (barr[c] == null || barr[c].Length < blk.w * blk.h)
                {
                    barr[c] = new int[blk.w * blk.h];
                }
                blk.Data = barr[c];

                i = (c + 1) % 3;
                if (barr[i] == null || barr[i].Length < blk.w * blk.h)
                {
                    barr[i] = new int[blk.w * blk.h];
                }
                i = (c + 2) % 3;
                if (barr[i] == null || barr[i].Length < blk.w * blk.h)
                {
                    barr[i] = new int[blk.w * blk.h];
                }

                if (componentCount == 4)
                {
                    if (barr[3] == null || barr[3].Length < blk.w * blk.h)
                    {
                        barr[3] = new int[blk.w * blk.h];
                    }
                }

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

                red   = barr[0];
                green = barr[1];
                blue  = barr[2];
                alpha = (componentCount == 4) ? barr[3] : null;

                Bitmap     bitmap = (Bitmap)image;
                BitmapData data   = bitmap.LockBits(new Rectangle(blk.ulx, blk.uly, blk.w, blk.h), ImageLockMode.ReadOnly,
                                                    (componentCount == 3) ? PixelFormat.Format24bppRgb : PixelFormat.Format32bppArgb);
                unsafe
                {
                    byte *ptr = (byte *)data.Scan0.ToPointer();

                    int k = 0;
                    for (int j = 0; j < blk.w * blk.h; j++)
                    {
                        blue[k]  = ((byte)*(ptr + 0) & 0xFF) - 128;
                        green[k] = ((byte)*(ptr + 1) & 0xFF) - 128;
                        red[k]   = ((byte)*(ptr + 2) & 0xFF) - 128;
                        if (componentCount == 4)
                        {
                            alpha[k] = ((byte)*(ptr + 3) & 0xFF) - 128;
                        }

                        ++k;
                        ptr += 3;
                    }
                }
                bitmap.UnlockBits(data);

                barr[0] = red;
                barr[1] = green;
                barr[2] = blue;
                if (componentCount == 4)
                {
                    barr[3] = alpha;
                }

                // Set buffer attributes
                blk.Data   = barr[c];
                blk.offset = 0;
                blk.scanw  = blk.w;
            }
            else
            {
                //Asking for the 2nd or 3rd (or 4th) block component
                blk.Data   = barr[c];
                blk.offset = (blk.ulx - dbi.ulx) * dbi.w + blk.ulx - dbi.ulx;
                blk.scanw  = dbi.scanw;
            }

            // Turn off the progressive attribute
            blk.progressive = false;
            return(blk);
        }
Exemplo n.º 19
0
        /// <summary> Returns, in the blk argument, the block of image data containing the
        /// specifed rectangular area, in the specified component. The data is
        /// returned, as a reference to the internal data, if any, instead of as a
        /// copy, therefore the returned data should not be modified.
        ///
        /// <P> After being read the coefficients are level shifted by subtracting
        /// 2^(nominal bit range - 1)
        ///
        /// <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' and
        /// 'scanw' of the returned data can be arbitrary. See the 'DataBlk' class.
        ///
        /// <P>If the data array in <tt>blk</tt> is <tt>null</tt>, then a new one
        /// is created if necessary. The implementation of this interface may
        /// choose to return the same array or a new one, depending on what is more
        /// efficient. Therefore, the data array in <tt>blk</tt> prior to the
        /// method call should not be considered to contain the returned data, a
        /// new array may have been created. Instead, get the array from
        /// <tt>blk</tt> after the method has returned.
        ///
        /// <P>The returned data always has its 'progressive' attribute unset
        /// (i.e. false).
        ///
        /// <P>When an I/O exception is encountered the JJ2KExceptionHandler is
        /// used. The exception is passed to its handleException method. The action
        /// that is taken depends on the action that has been registered in
        /// JJ2KExceptionHandler. See JJ2KExceptionHandler for details.
        ///
        /// <P>This method implements buffering for the 3 components: When the
        /// first one is asked, all the 3 components are read and stored until they
        /// are needed.
        ///
        /// </summary>
        /// <param name="blk">Its coordinates and dimensions specify the area to
        /// return. Some 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,
        /// 1 and 3 are valid.
        ///
        /// </param>
        /// <returns> The requested DataBlk
        ///
        /// </returns>
        /// <seealso cref="getCompData">
        ///
        /// </seealso>
        /// <seealso cref="JJ2KExceptionHandler">
        ///
        /// </seealso>
        public override DataBlk getInternCompData(DataBlk blk, int c)
        {
            // Check component index
            if (c < 0 || c > 2)
            {
                throw new System.ArgumentException();
            }

            // Check type of block provided as an argument
            if (blk.DataType != DataBlk.TYPE_INT)
            {
                if (intBlk == null)
                {
                    intBlk = new DataBlkInt(blk.ulx, blk.uly, blk.w, blk.h);
                }
                else
                {
                    intBlk.ulx = blk.ulx;
                    intBlk.uly = blk.uly;
                    intBlk.w   = blk.w;
                    intBlk.h   = blk.h;
                }
                blk = intBlk;
            }

            // If asking a component for the first time for this block, read the 3
            // components
            if ((barr[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, j, i, mi;
                int[] red, green, blue;

                // Reset data arrays if needed
                if (barr[c] == null || barr[c].Length < blk.w * blk.h)
                {
                    barr[c] = new int[blk.w * blk.h];
                }
                blk.Data = barr[c];

                i = (c + 1) % 3;
                if (barr[i] == null || barr[i].Length < blk.w * blk.h)
                {
                    barr[i] = new int[blk.w * blk.h];
                }
                i = (c + 2) % 3;
                if (barr[i] == null || barr[i].Length < blk.w * blk.h)
                {
                    barr[i] = new int[blk.w * blk.h];
                }

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

                // Check line buffer
                if (buf == null || buf.Length < 3 * blk.w)
                {
                    buf = new byte[3 * blk.w];
                }

                red   = barr[0];
                green = barr[1];
                blue  = barr[2];

                try
                {
                    // Read line by line
                    mi = blk.uly + blk.h;
                    for (i = blk.uly; i < mi; i++)
                    {
                        // Reposition in input offset takes care of
                        // header offset
                        in_Renamed.Seek(offset + i * 3 * w + 3 * blk.ulx, System.IO.SeekOrigin.Begin);
                        in_Renamed.Read(buf, 0, 3 * blk.w);

                        for (k = (i - blk.uly) * blk.w + blk.w - 1, j = 3 * blk.w - 1; j >= 0; k--)
                        {
                            // Read every third sample
                            blue[k]  = (((byte)buf[j--]) & 0xFF) - DC_OFFSET;
                            green[k] = (((byte)buf[j--]) & 0xFF) - DC_OFFSET;
                            red[k]   = (((byte)buf[j--]) & 0xFF) - DC_OFFSET;
                        }
                    }
                }
                catch (System.IO.IOException e)
                {
                    JJ2KExceptionHandler.handleException(e);
                }
                barr[0] = red;
                barr[1] = green;
                barr[2] = blue;

                // Set buffer attributes
                blk.Data   = barr[c];
                blk.offset = 0;
                blk.scanw  = blk.w;
            }
            else
            {
                //Asking for the 2nd or 3rd block component
                blk.Data   = barr[c];
                blk.offset = (blk.ulx - dbi.ulx) * dbi.w + blk.ulx - dbi.ulx;
                blk.scanw  = dbi.scanw;
            }

            // Turn off the progressive attribute
            blk.progressive = false;
            return(blk);
        }
Exemplo n.º 20
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);
                }
            }
        }
Exemplo n.º 21
0
        /// <summary> Apply forward 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 forwICT(DataBlk blk, int c)
        {
            int k, k0, k1, k2, mink, i;
            int w = blk.w;             //width of output block
            int h = blk.h;             //height of ouput block

            float[] outdata;           //array of output data

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

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

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

            //If asking for Y, Cb or Cr do transform
            if (c >= 0 && c <= 2)
            {
                int[] data0, data1, data2;                 // input data arrays

                if (block0 == null)
                {
                    block0 = new DataBlkInt();
                }
                if (block1 == null)
                {
                    block1 = new DataBlkInt();
                }
                if (block2 == null)
                {
                    block2 = new DataBlkInt();
                }
                block0.w   = block1.w = block2.w = blk.w;
                block0.h   = block1.h = block2.h = blk.h;
                block0.ulx = block1.ulx = block2.ulx = blk.ulx;
                block0.uly = block1.uly = block2.uly = blk.uly;

                // Returned blocks may have different size and position
                block0 = (DataBlkInt)src.getInternCompData(block0, 0);
                data0  = (int[])block0.Data;
                block1 = (DataBlkInt)src.getInternCompData(block1, 1);
                data1  = (int[])block1.Data;
                block2 = (DataBlkInt)src.getInternCompData(block2, 2);
                data2  = (int[])block2.Data;

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

                //Perform conversion

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

                switch (c)
                {
                case 0:
                    //RGB to Y conversion
                    for (i = h - 1; i >= 0; i--)
                    {
                        for (mink = k - w; k > mink; k--, k0--, k1--, k2--)
                        {
                            outdata[k] = 0.299f * data0[k0] + 0.587f * data1[k1] + 0.114f * data2[k2];
                        }
                        // Jump to beggining of previous line in input
                        k0 -= (block0.scanw - w);
                        k1 -= (block1.scanw - w);
                        k2 -= (block2.scanw - w);
                    }
                    break;


                case 1:
                    //RGB to Cb conversion
                    for (i = h - 1; i >= 0; i--)
                    {
                        for (mink = k - w; k > mink; k--, k0--, k1--, k2--)
                        {
                            outdata[k] = (-0.16875f) * data0[k0] - 0.33126f * data1[k1] + 0.5f * data2[k2];
                        }
                        // Jump to beggining of previous line in input
                        k0 -= (block0.scanw - w);
                        k1 -= (block1.scanw - w);
                        k2 -= (block2.scanw - w);
                    }
                    break;


                case 2:
                    //RGB to Cr conversion
                    for (i = h - 1; i >= 0; i--)
                    {
                        for (mink = k - w; k > mink; k--, k0--, k1--, k2--)
                        {
                            outdata[k] = 0.5f * data0[k0] - 0.41869f * data1[k1] - 0.08131f * data2[k2];
                        }
                        // Jump to beggining of previous line in input
                        k0 -= (block0.scanw - w);
                        k1 -= (block1.scanw - w);
                        k2 -= (block2.scanw - w);
                    }
                    break;
                }
            }
            else if (c >= 3)
            {
                // Requesting a component which is not Y, Cb or Cr =>
                // just pass the data

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

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

                // Copy the data converting from int to float
                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'"
                        outdata[k] = (float)indata[k0];
                    }
                    // Jump to beggining of next line in input
                    k0 += indb.w - w;
                }

                // Set the progressivity
                blk.progressive = indb.progressive;
                blk.offset      = 0;
                blk.scanw       = w;
                return(blk);
            }
            else
            {
                // Requesting a non valid component index
                throw new System.ArgumentException();
            }
            return(blk);
        }
Exemplo n.º 22
0
        /// <summary> This function gets a datablk from the entropy coder. The sample sin the
        /// block, which consists of  the quantized coefficients from the quantizer,
        /// are scaled by the values given for any ROIs specified.
        ///
        /// <p>The function calls on a ROIMaskGenerator to get the mask for scaling
        /// the coefficients in the current block.</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 virtual CBlkWTData getNextInternCodeBlock(int c, CBlkWTData cblk)
        {
            int        mi, i, j, k, wrap;
            int        ulx, uly, w, h;
            DataBlkInt mask = roiMask; // local copy of mask

            int[]     maskData;        // local copy of mask data
            int[]     data;            // local copy of quantized data
            int       tmp;
            int       bitMask = 0x7FFFFFFF;
            SubbandAn root, sb;
            int       maxBits = 0;       // local copy
            bool      roiInTile;
            bool      sbInMask;
            int       nROIcoeff = 0;

            // Get codeblock's data from quantizer
            cblk = src.getNextCodeBlock(c, cblk);

            // If there is no ROI in the image, or if we already got all
            // code-blocks
            if (!roi || cblk == null)
            {
                return(cblk);
            }

            data     = (int[])cblk.Data;
            sb       = cblk.sb;
            ulx      = cblk.ulx;
            uly      = cblk.uly;
            w        = cblk.w;
            h        = cblk.h;
            sbInMask = (sb.resLvl <= useStartLevel);

            // Check that there is an array for the mask and set it to zero
            maskData = mask.DataInt;             // local copy of mask data
            if (maskData == null || w * h > maskData.Length)
            {
                maskData     = new int[w * h];
                mask.DataInt = maskData;
            }
            else
            {
                for (i = w * h - 1; i >= 0; i--)
                {
                    maskData[i] = 0;
                }
            }
            mask.ulx = ulx;
            mask.uly = uly;
            mask.w   = w;
            mask.h   = h;

            // Get ROI mask from generator
            root      = src.getAnSubbandTree(tIdx, c);
            maxBits   = maxMagBits[tIdx][c];
            roiInTile = mg.getROIMask(mask, root, maxBits, c);

            // If there is no ROI in this tile, return the code-block untouched
            if (!roiInTile && (!sbInMask))
            {
                cblk.nROIbp = 0;
                return(cblk);
            }

            // Update field containing the number of ROI magnitude bit-planes
            cblk.nROIbp = cblk.magbits;

            // If the entire subband belongs to the ROI mask, The code-block is
            // set to belong entirely to the ROI with the highest scaling value
            if (sbInMask)
            {
                // Scale the wmse so that instead of scaling the coefficients, the
                // wmse is scaled.
                //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.wmseScaling *= (float)(1 << (maxBits << 1));
                cblk.nROIcoeff    = w * h;
                return(cblk);
            }

            // In 'block aligned' mode, the code-block is set to belong entirely
            // to the ROI with the highest scaling value if one coefficient, at
            // least, belongs to the ROI
            if (blockAligned)
            {
                wrap = cblk.scanw - w;
                mi   = h * w - 1;
                i    = cblk.offset + cblk.scanw * (h - 1) + w - 1;
                int nroicoeff = 0;
                for (j = h; j > 0; j--)
                {
                    for (k = w - 1; k >= 0; k--, i--, mi--)
                    {
                        if (maskData[mi] != 0)
                        {
                            nroicoeff++;
                        }
                    }
                    i -= wrap;
                }
                if (nroicoeff != 0)
                {
                    // Include the subband
                    //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.wmseScaling *= (float)(1 << (maxBits << 1));
                    cblk.nROIcoeff    = w * h;
                }
                return(cblk);
            }

            // Scale background coefficients
            bitMask = (((1 << cblk.magbits) - 1) << (31 - cblk.magbits));
            wrap    = cblk.scanw - w;
            mi      = h * w - 1;
            i       = cblk.offset + cblk.scanw * (h - 1) + w - 1;
            for (j = h; j > 0; j--)
            {
                for (k = w; k > 0; k--, i--, mi--)
                {
                    tmp = data[i];
                    if (maskData[mi] != 0)
                    {
                        // ROI coeff. We need to erase fractional bits to ensure
                        // that they do not conflict with BG coeffs. This is only
                        // strictly necessary for ROI coeffs. which non-fractional
                        // magnitude is zero, but much better BG quality can be
                        // achieved if done if reset to zero since coding zeros is
                        // much more efficient (the entropy coder knows nothing
                        // about ROI and cannot avoid coding the ROI fractional
                        // bits, otherwise this would not be necessary).
                        data[i] = (unchecked ((int)0x80000000) & tmp) | (tmp & bitMask);
                        nROIcoeff++;
                    }
                    else
                    {
                        // BG coeff. it is not necessary to erase fractional bits
                        data[i] = (unchecked ((int)0x80000000) & tmp) | ((tmp & 0x7FFFFFFF) >> maxBits);
                    }
                }
                i -= wrap;
            }

            // Modify the number of significant bit-planes in the code-block
            cblk.magbits += maxBits;

            // Store the number of ROI coefficients present in the code-block
            cblk.nROIcoeff = nROIcoeff;

            return(cblk);
        }
Exemplo n.º 23
0
        /// <summary> Writes the data of the specified area to the file, coordinates are
        /// relative to the current tile of the source. Before writing, the
        /// coefficients are limited to the nominal range and packed into 1,2 or 4
        /// bytes (according to the bit-depth).
        ///
        /// <p>If the data is unisigned, level shifting is applied adding 2^(bit
        /// depth - 1)</p>
        ///
        /// <p>This method may not be called concurrently from different
        /// threads.</p>
        ///
        /// <p>If the data returned from the BlkImgDataSrc source is progressive,
        /// then it is requested over and over until it is not progressive
        /// anymore.</p>
        ///
        /// </summary>
        /// <param name="ulx">The horizontal coordinate of the upper-left corner of the
        /// area to write, relative to the current tile.
        ///
        /// </param>
        /// <param name="uly">The vertical coordinate of the upper-left corner of the area
        /// to write, relative to the current tile.
        ///
        /// </param>
        /// <param name="width">The width of the area to write.
        ///
        /// </param>
        /// <param name="height">The height of the area to write.
        ///
        /// </param>
        /// <exception cref="IOException">If an I/O error occurs.
        ///
        /// </exception>
        public override void  write(int ulx, int uly, int w, int h)
        {
            int k, i, j;
            int fracbits = fb;            // In local variable for faster access
            int tOffx, tOffy;             // Active tile offset in the X and Y direction

            // Initialize db
            db.ulx = ulx;
            db.uly = uly;
            db.w   = w;
            db.h   = h;
            // Get the current active tile offset
            //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'"
            tOffx = src.getCompULX(c) - (int)System.Math.Ceiling(src.ImgULX / (double)src.getCompSubsX(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'"
            tOffy = src.getCompULY(c) - (int)System.Math.Ceiling(src.ImgULY / (double)src.getCompSubsY(c));
            // Check the array size
            if (db.data_array != null && db.data_array.Length < w * h)
            {
                // A new one will be allocated by getInternCompData()
                db.data_array = null;
            }
            // Request the data and make sure it is not
            // progressive
            do
            {
                db = (DataBlkInt)src.getInternCompData(db, c);
            }while (db.progressive);

            int tmp;


            // Check line buffer
            if (buf == null || buf.Length < packBytes * w)
            {
                buf = new byte[packBytes * w];                 // Expand buffer
            }

            switch (packBytes)
            {
            case 1:                      // Samples packed into 1 byte
                // Write line by line
                for (i = 0; i < h; i++)
                {
                    // Skip to beggining of line in file
                    out_Renamed.Seek(offset + this.w * (uly + tOffy + i) + ulx + tOffx, System.IO.SeekOrigin.Begin);
                    // Write all bytes in the line
                    if (fracbits == 0)
                    {
                        for (k = db.offset + i * db.scanw + w - 1, j = w - 1; j >= 0; k--)
                        {
                            tmp      = db.data_array[k] + levShift;
                            buf[j--] = (byte)((tmp < minVal)?minVal:((tmp > maxVal)?maxVal:tmp));
                        }
                    }
                    else
                    {
                        for (k = db.offset + i * db.scanw + w - 1, j = w - 1; j >= 0; k--)
                        {
                            tmp      = (SupportClass.URShift(db.data_array[k], fracbits)) + levShift;
                            buf[j--] = (byte)((tmp < minVal)?minVal:((tmp > maxVal)?maxVal:tmp));
                        }
                    }
                    out_Renamed.Write(buf, 0, w);
                }
                break;


            case 2:                      // Samples packed in to 2 bytes (short)
                // Write line by line
                for (i = 0; i < h; i++)
                {
                    // Skip to beggining of line in file
                    out_Renamed.Seek(offset + 2 * (this.w * (uly + tOffy + i) + ulx + tOffx), System.IO.SeekOrigin.Begin);
                    // Write all bytes in the line
                    if (fracbits == 0)
                    {
                        for (k = db.offset + i * db.scanw + w - 1, j = (w << 1) - 1; j >= 0; k--)
                        {
                            tmp      = db.data_array[k] + levShift;
                            tmp      = (tmp < minVal)?minVal:((tmp > maxVal)?maxVal:tmp);
                            buf[j--] = (byte)tmp;                                      // no need for 0xFF mask since
                            // truncation will do it already
                            buf[j--] = (byte)(SupportClass.URShift(tmp, 8));
                        }
                    }
                    else
                    {
                        for (k = db.offset + i * db.scanw + w - 1, j = (w << 1) - 1; j >= 0; k--)
                        {
                            tmp      = (SupportClass.URShift(db.data_array[k], fracbits)) + levShift;
                            tmp      = (tmp < minVal)?minVal:((tmp > maxVal)?maxVal:tmp);
                            buf[j--] = (byte)tmp;                                      // no need for 0xFF mask since
                            // truncation will do it already
                            buf[j--] = (byte)(SupportClass.URShift(tmp, 8));
                        }
                    }
                    out_Renamed.Write(buf, 0, w << 1);
                }
                break;


            case 4:
                // Write line by line
                for (i = 0; i < h; i++)
                {
                    // Skip to beggining of line in file
                    out_Renamed.Seek(offset + 4 * (this.w * (uly + tOffy + i) + ulx + tOffx), System.IO.SeekOrigin.Begin);
                    // Write all bytes in the line
                    if (fracbits == 0)
                    {
                        for (k = db.offset + i * db.scanw + w - 1, j = (w << 2) - 1; j >= 0; k--)
                        {
                            tmp      = db.data_array[k] + levShift;
                            tmp      = (tmp < minVal)?minVal:((tmp > maxVal)?maxVal:tmp);
                            buf[j--] = (byte)tmp;                                      // No need to use 0xFF
                            buf[j--] = (byte)(SupportClass.URShift(tmp, 8));           // masks since truncation
                            buf[j--] = (byte)(SupportClass.URShift(tmp, 16));          // will have already the
                            buf[j--] = (byte)(SupportClass.URShift(tmp, 24));          // same effect
                        }
                    }
                    else
                    {
                        for (k = db.offset + i * db.scanw + w - 1, j = (w << 2) - 1; j >= 0; k--)
                        {
                            tmp      = (SupportClass.URShift(db.data_array[k], fracbits)) + levShift;
                            tmp      = (tmp < minVal)?minVal:((tmp > maxVal)?maxVal:tmp);
                            buf[j--] = (byte)tmp;                                      // No need to use 0xFF
                            buf[j--] = (byte)(SupportClass.URShift(tmp, 8));           // masks since truncation
                            buf[j--] = (byte)(SupportClass.URShift(tmp, 16));          // will have already the
                            buf[j--] = (byte)(SupportClass.URShift(tmp, 24));          // same effect
                        }
                    }
                    out_Renamed.Write(buf, 0, w << 2);
                }
                break;


            default:
                throw new System.IO.IOException("PGX supports only bit-depth between " + "1 and 31");
            }
        }
Exemplo n.º 24
0
        /// <summary> Returns, in the blk argument, the block of image data containing the
        /// specifed rectangular area, in the specified component. The data is
        /// returned, as a reference to the internal data, if any, instead of as a
        /// copy, therefore the returned data should not be modified.
        ///
        /// <P> After being read the coefficients are level shifted by subtracting
        /// 2^(nominal bit range - 1)
        ///
        /// <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' and
        /// 'scanw' of the returned data can be arbitrary. See the 'DataBlk' class.
        ///
        /// <P>If the data array in <tt>blk</tt> is <tt>null</tt>, then a new one
        /// is created if necessary. The implementation of this interface may
        /// choose to return the same array or a new one, depending on what is more
        /// efficient. Therefore, the data array in <tt>blk</tt> prior to the
        /// method call should not be considered to contain the returned data, a
        /// new array may have been created. Instead, get the array from
        /// <tt>blk</tt> after the method has returned.
        ///
        /// <P>The returned data always has its 'progressive' attribute unset
        /// (i.e. false).
        ///
        /// <P>When an I/O exception is encountered the JJ2KExceptionHandler is
        /// used. The exception is passed to its handleException method. The action
        /// that is taken depends on the action that has been registered in
        /// JJ2KExceptionHandler. See JJ2KExceptionHandler for details.
        ///
        /// </summary>
        /// <param name="blk">Its coordinates and dimensions specify the area to
        /// return. Some 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
        /// is valid.
        ///
        /// </param>
        /// <returns> The requested DataBlk
        ///
        /// </returns>
        /// <seealso cref="getCompData">
        ///
        /// </seealso>
        /// <seealso cref="JJ2KExceptionHandler">
        ///
        /// </seealso>
        public override DataBlk getInternCompData(DataBlk blk, int c)
        {
            int k, j, i, mi;

            int[] barr;

            // Check component index
            if (c != 0)
            {
                throw new System.ArgumentException();
            }

            // Check type of block provided as an argument
            if (blk.DataType != DataBlk.TYPE_INT)
            {
                if (intBlk == null)
                {
                    intBlk = new DataBlkInt(blk.ulx, blk.uly, blk.w, blk.h);
                }
                else
                {
                    intBlk.ulx = blk.ulx;
                    intBlk.uly = blk.uly;
                    intBlk.w   = blk.w;
                    intBlk.h   = blk.h;
                }
                blk = intBlk;
            }

            // Get data array
            barr = (int[])blk.Data;
            if (barr == null || barr.Length < blk.w * blk.h)
            {
                barr     = new int[blk.w * blk.h];
                blk.Data = barr;
            }

            // Check line buffer
            if (buf == null || buf.Length < blk.w)
            {
                buf = new byte[blk.w];
            }

            try
            {
                // Read line by line
                mi = blk.uly + blk.h;
                for (i = blk.uly; i < mi; i++)
                {
                    // Reposition in input
                    in_Renamed.Seek(offset + i * w + blk.ulx, System.IO.SeekOrigin.Begin);
                    in_Renamed.Read(buf, 0, blk.w);
                    for (k = (i - blk.uly) * blk.w + blk.w - 1, j = blk.w - 1; j >= 0; j--, k--)
                    {
                        barr[k] = (((int)buf[j]) & 0xFF) - DC_OFFSET;
                    }
                }
            }
            catch (System.IO.IOException e)
            {
                JJ2KExceptionHandler.handleException(e);
            }

            // Turn off the progressive attribute
            blk.progressive = false;
            // Set buffer attributes
            blk.offset = 0;
            blk.scanw  = blk.w;
            return(blk);
        }
        /// <summary> Returns, in the blk argument, the block of image data containing the
        /// specifed rectangular area, in the specified component. The data is
        /// returned, as a reference to the internal data, if any, instead of as a
        /// copy, therefore the returned data should not be modified.
        ///
        /// <p>After being read the coefficients are level shifted by subtracting
        /// 2^(nominal bit range - 1)<p>
        ///
        /// <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' and
        /// 'scanw' of the returned data can be arbitrary. See the 'DataBlk'
        /// class.</p>
        ///
        /// <p>If the data array in <tt>blk</tt> is <tt>null</tt>, then a new one
        /// is created if necessary. The implementation of this interface may
        /// choose to return the same array or a new one, depending on what is more
        /// efficient. Therefore, the data array in <tt>blk</tt> prior to the
        /// method call should not be considered to contain the returned data, a
        /// new array may have been created. Instead, get the array from
        /// <tt>blk</tt> after the method has returned.</p>
        ///
        /// <p>The returned data always has its 'progressive' attribute unset
        /// (i.e. false).</p>
        ///
        /// <p>When an I/O exception is encountered the JJ2KExceptionHandler is
        /// used. The exception is passed to its handleException method. The action
        /// that is taken depends on the action that has been registered in
        /// JJ2KExceptionHandler. See JJ2KExceptionHandler for details.</p>
        ///
        /// </summary>
        /// <param name="blk">Its coordinates and dimensions specify the area to
        /// return. Some 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
        /// is valid.
        ///
        /// </param>
        /// <returns> The requested DataBlk
        ///
        /// </returns>
        /// <seealso cref="getCompData">
        /// </seealso>
        /// <seealso cref="JJ2KExceptionHandler">
        ///
        /// </seealso>
        public override DataBlk getInternCompData(DataBlk blk, int c)
        {
            int k, j, i, mi;             // counters
            int levShift = 1 << (bitDepth - 1);

            // Check component index
            if (c != 0)
            {
                throw new System.ArgumentException();
            }

            // Check type of block provided as an argument
            if (blk.DataType != DataBlk.TYPE_INT)
            {
                if (intBlk == null)
                {
                    intBlk = new DataBlkInt(blk.ulx, blk.uly, blk.w, blk.h);
                }
                else
                {
                    intBlk.ulx = blk.ulx;
                    intBlk.uly = blk.uly;
                    intBlk.w   = blk.w;
                    intBlk.h   = blk.h;
                }
                blk = intBlk;
            }

            // Get data array
            int[] barr = (int[])blk.Data;
            if (barr == null || barr.Length < blk.w * blk.h * packBytes)
            {
                barr     = new int[blk.w * blk.h];
                blk.Data = barr;
            }

            int paddingLength = (32 - bitDepth);

            if (buf == null || buf.Length < packBytes * blk.w)
            {
                buf = new byte[packBytes * blk.w];
            }
            try
            {
                switch (packBytes)
                {
                // Switch between one of the 3 byte packet type
                case 1:                          // Samples packed into 1 byte
                    // Read line by line
                    mi = blk.uly + blk.h;
                    if (isSigned)
                    {
                        for (i = blk.uly; i < mi; i++)
                        {
                            // Reposition in input
                            in_Renamed.Seek(offset + i * w + blk.ulx, System.IO.SeekOrigin.Begin);
                            in_Renamed.Read(buf, 0, blk.w);
                            for (k = (i - blk.uly) * blk.w + blk.w - 1, j = blk.w - 1; j >= 0; k--)
                            {
                                barr[k] = (((buf[j--] & 0xFF) << paddingLength) >> paddingLength);
                            }
                        }
                    }
                    else
                    {
                        // Not signed
                        for (i = blk.uly; i < mi; i++)
                        {
                            // Reposition in input
                            in_Renamed.Seek(offset + i * w + blk.ulx, System.IO.SeekOrigin.Begin);
                            in_Renamed.Read(buf, 0, blk.w);
                            for (k = (i - blk.uly) * blk.w + blk.w - 1, j = blk.w - 1; j >= 0; k--)
                            {
                                barr[k] = (SupportClass.URShift(((buf[j--] & 0xFF) << paddingLength), paddingLength)) - levShift;
                            }
                        }
                    }
                    break;


                case 2:                          // Samples packed into 2 bytes
                    // Read line by line
                    mi = blk.uly + blk.h;
                    if (isSigned)
                    {
                        for (i = blk.uly; i < mi; i++)
                        {
                            // Reposition in input
                            in_Renamed.Seek(offset + 2 * (i * w + blk.ulx), System.IO.SeekOrigin.Begin);
                            in_Renamed.Read(buf, 0, blk.w << 1);
                            switch (byteOrder)
                            {
                            case CSJ2K.j2k.io.EndianType_Fields.LITTLE_ENDIAN:
                                for (k = (i - blk.uly) * blk.w + blk.w - 1, j = (blk.w << 1) - 1; j >= 0; k--)
                                {
                                    barr[k] = ((((buf[j--] & 0xFF) << 8) | (buf[j--] & 0xFF)) << paddingLength) >> paddingLength;
                                }
                                break;

                            case CSJ2K.j2k.io.EndianType_Fields.BIG_ENDIAN:
                                for (k = (i - blk.uly) * blk.w + blk.w - 1, j = (blk.w << 1) - 1; j >= 0; k--)
                                {
                                    barr[k] = (((buf[j--] & 0xFF) | ((buf[j--] & 0xFF) << 8)) << paddingLength) >> paddingLength;
                                }
                                break;

                            default:
                                throw new System.ApplicationException("Internal JJ2000 bug");
                            }
                        }
                    }
                    else
                    {
                        // If not signed
                        for (i = blk.uly; i < mi; i++)
                        {
                            // Reposition in input
                            in_Renamed.Seek(offset + 2 * (i * w + blk.ulx), System.IO.SeekOrigin.Begin);
                            in_Renamed.Read(buf, 0, blk.w << 1);
                            switch (byteOrder)
                            {
                            case CSJ2K.j2k.io.EndianType_Fields.LITTLE_ENDIAN:
                                for (k = (i - blk.uly) * blk.w + blk.w - 1, j = (blk.w << 1) - 1; j >= 0; k--)
                                {
                                    barr[k] = (SupportClass.URShift(((((buf[j--] & 0xFF) << 8) | (buf[j--] & 0xFF)) << paddingLength), paddingLength)) - levShift;
                                }
                                break;

                            case CSJ2K.j2k.io.EndianType_Fields.BIG_ENDIAN:
                                for (k = (i - blk.uly) * blk.w + blk.w - 1, j = (blk.w << 1) - 1; j >= 0; k--)
                                {
                                    barr[k] = (SupportClass.URShift((((buf[j--] & 0xFF) | ((buf[j--] & 0xFF) << 8)) << paddingLength), paddingLength)) - levShift;
                                }
                                break;

                            default:
                                throw new System.ApplicationException("Internal JJ2000 bug");
                            }
                        }
                    }
                    break;


                case 4:                          // Samples packed into 4 bytes
                    // Read line by line
                    mi = blk.uly + blk.h;
                    if (isSigned)
                    {
                        for (i = blk.uly; i < mi; i++)
                        {
                            // Reposition in input
                            in_Renamed.Seek(offset + 4 * (i * w + blk.ulx), System.IO.SeekOrigin.Begin);
                            in_Renamed.Read(buf, 0, blk.w << 2);
                            switch (byteOrder)
                            {
                            case CSJ2K.j2k.io.EndianType_Fields.LITTLE_ENDIAN:
                                for (k = (i - blk.uly) * blk.w + blk.w - 1, j = (blk.w << 2) - 1; j >= 0; k--)
                                {
                                    barr[k] = ((((buf[j--] & 0xFF) << 24) | ((buf[j--] & 0xFF) << 16) | ((buf[j--] & 0xFF) << 8) | (buf[j--] & 0xFF)) << paddingLength) >> paddingLength;
                                }
                                break;

                            case CSJ2K.j2k.io.EndianType_Fields.BIG_ENDIAN:
                                for (k = (i - blk.uly) * blk.w + blk.w - 1, j = (blk.w << 2) - 1; j >= 0; k--)
                                {
                                    barr[k] = (((buf[j--] & 0xFF) | ((buf[j--] & 0xFF) << 8) | ((buf[j--] & 0xFF) << 16) | ((buf[j--] & 0xFF) << 24)) << paddingLength) >> paddingLength;
                                }
                                break;

                            default:
                                throw new System.ApplicationException("Internal JJ2000 bug");
                            }
                        }
                    }
                    else
                    {
                        for (i = blk.uly; i < mi; i++)
                        {
                            // Reposition in input
                            in_Renamed.Seek(offset + 4 * (i * w + blk.ulx), System.IO.SeekOrigin.Begin);
                            in_Renamed.Read(buf, 0, blk.w << 2);
                            switch (byteOrder)
                            {
                            case CSJ2K.j2k.io.EndianType_Fields.LITTLE_ENDIAN:
                                for (k = (i - blk.uly) * blk.w + blk.w - 1, j = (blk.w << 2) - 1; j >= 0; k--)
                                {
                                    barr[k] = (SupportClass.URShift(((((buf[j--] & 0xFF) << 24) | ((buf[j--] & 0xFF) << 16) | ((buf[j--] & 0xFF) << 8) | (buf[j--] & 0xFF)) << paddingLength), paddingLength)) - levShift;
                                }
                                break;

                            case CSJ2K.j2k.io.EndianType_Fields.BIG_ENDIAN:
                                for (k = (i - blk.uly) * blk.w + blk.w - 1, j = (blk.w << 2) - 1; j >= 0; k--)
                                {
                                    barr[k] = (SupportClass.URShift((((buf[j--] & 0xFF) | ((buf[j--] & 0xFF) << 8) | ((buf[j--] & 0xFF) << 16) | ((buf[j--] & 0xFF) << 24)) << paddingLength), paddingLength)) - levShift;
                                }
                                break;

                            default:
                                throw new System.ApplicationException("Internal JJ2000 bug");
                            }
                        }
                    }
                    break;


                default:
                    throw new System.IO.IOException("PGX supports only bit-depth between" + " 1 and 31");
                }
            }
            catch (System.IO.IOException e)
            {
                JJ2KExceptionHandler.handleException(e);
            }

            // Turn off the progressive attribute
            blk.progressive = false;
            // Set buffer attributes
            blk.offset = 0;
            blk.scanw  = blk.w;
            return(blk);
        }
Exemplo n.º 26
0
        public override DataBlk getCompData(DataBlk blk, int c)
        {
            var newBlk = new DataBlkInt(blk.ulx, blk.uly, blk.w, blk.h);

            return(this.getInternCompData(newBlk, c));
        }