This abstract class represents a subband in a bidirectional tree structure that describes the subband decomposition for a wavelet transform. This class is implemented by the SubbandAn and SubbandSyn classes, which are for the analysis and synthesis sides respectively.

The element can be either a node or a leaf of the tree. If it is a node, it has 4 descendants (LL, HL, LH and HH). If it is a leaf, it has no descendant.

The tree is bidirectional. Each element in the tree structure has a "parent", which is the subband from which the element was obtained by decomposition. The only exception is the root element which, for obvious reasons, has no parent (i.e. it is null).

Esempio n. 1
0
        /// <summary> Initializes the childs of this node with the correct values. The sizes
        /// of the child subbands are calculated by taking into account the
        /// position of the subband in the canvas.
        ///
        /// <p>For the analysis subband gain calculation it is assumed that
        /// analysis filters are normalized with a DC gain of 1 and a Nyquist gain
        /// of 2.</p>
        ///
        /// </summary>
        protected internal virtual void  initChilds()
        {
            Subband subb_LL = LL;
            Subband subb_HL = HL;
            Subband subb_LH = LH;
            Subband subb_HH = HH;

            // LL subband
            subb_LL.level = level + 1;
            subb_LL.ulcx  = (ulcx + 1) >> 1;
            subb_LL.ulcy  = (ulcy + 1) >> 1;
            subb_LL.ulx   = ulx;
            subb_LL.uly   = uly;
            subb_LL.w     = ((ulcx + w + 1) >> 1) - subb_LL.ulcx;
            subb_LL.h     = ((ulcy + h + 1) >> 1) - subb_LL.ulcy;
            // If this subband in in the all LL path (i.e. it's global orientation
            // is LL) then child LL band contributes to a lower resolution level.
            subb_LL.resLvl    = (orientation == WT_ORIENT_LL)?resLvl - 1:resLvl;
            subb_LL.anGainExp = anGainExp;
            subb_LL.sbandIdx  = (sbandIdx << 2);
            // HL subband
            subb_HL.orientation = WT_ORIENT_HL;
            subb_HL.level       = subb_LL.level;
            subb_HL.ulcx        = ulcx >> 1;
            subb_HL.ulcy        = subb_LL.ulcy;
            subb_HL.ulx         = ulx + subb_LL.w;
            subb_HL.uly         = uly;
            subb_HL.w           = ((ulcx + w) >> 1) - subb_HL.ulcx;
            subb_HL.h           = subb_LL.h;
            subb_HL.resLvl      = resLvl;
            subb_HL.anGainExp   = anGainExp + 1;
            subb_HL.sbandIdx    = (sbandIdx << 2) + 1;
            // LH subband
            subb_LH.orientation = WT_ORIENT_LH;
            subb_LH.level       = subb_LL.level;
            subb_LH.ulcx        = subb_LL.ulcx;
            subb_LH.ulcy        = ulcy >> 1;
            subb_LH.ulx         = ulx;
            subb_LH.uly         = uly + subb_LL.h;
            subb_LH.w           = subb_LL.w;
            subb_LH.h           = ((ulcy + h) >> 1) - subb_LH.ulcy;
            subb_LH.resLvl      = resLvl;
            subb_LH.anGainExp   = anGainExp + 1;
            subb_LH.sbandIdx    = (sbandIdx << 2) + 2;
            // HH subband
            subb_HH.orientation = WT_ORIENT_HH;
            subb_HH.level       = subb_LL.level;
            subb_HH.ulcx        = subb_HL.ulcx;
            subb_HH.ulcy        = subb_LH.ulcy;
            subb_HH.ulx         = subb_HL.ulx;
            subb_HH.uly         = subb_LH.uly;
            subb_HH.w           = subb_HL.w;
            subb_HH.h           = subb_LH.h;
            subb_HH.resLvl      = resLvl;
            subb_HH.anGainExp   = anGainExp + 2;
            subb_HH.sbandIdx    = (sbandIdx << 2) + 3;
        }
Esempio n. 2
0
        /// <summary> Returns a subband element in the tree, given its resolution level and
        /// subband index. This method searches through the tree.
        ///
        /// </summary>
        /// <param name="rl">The resolution level.
        ///
        /// </param>
        /// <param name="sbi">The subband index, within the resolution level.
        ///
        /// </param>
        public virtual Subband getSubbandByIdx(int rl, int sbi)
        {
            Subband sb = this;

            // Find the root subband for the resolution level
            if (rl > sb.resLvl || rl < 0)
            {
                throw new System.ArgumentException("Resolution level index " + "out of range");
            }

            // Returns directly if it is itself
            if (rl == sb.resLvl && sbi == sb.sbandIdx)
            {
                return(sb);
            }

            if (sb.sbandIdx != 0)
            {
                sb = sb.Parent;
            }

            while (sb.resLvl > rl)
            {
                sb = sb.LL;
            }
            while (sb.resLvl < rl)
            {
                sb = sb.Parent;
            }

            switch (sbi)
            {
            case 0:
            default:
                return(sb);

            case 1:
                return(sb.HL);

            case 2:
                return(sb.LH);

            case 3:
                return(sb.HH);
            }
        }
		/// <summary> This function generates the ROI mask for the entire tile. The mask is
		/// generated for one component. This method is called once for each tile
		/// and component.
		/// 
		/// </summary>
		/// <param name="sb">The root of the subband tree used in the decomposition
		/// 
		/// </param>
		/// <param name="n">component number
		/// 
		/// </param>
		public override void  makeMask(Subband sb, int magbits, int n)
		{
			int nr = nrROIs[n];
			int r;
			int ulx, uly, lrx, lry;
			int tileulx = sb.ulcx;
			int tileuly = sb.ulcy;
			int tilew = sb.w;
			int tileh = sb.h;
			ROI[] ROIs = roi_array; // local copy
			
			ulxs = new int[nr];
			ulys = new int[nr];
			lrxs = new int[nr];
			lrys = new int[nr];
			
			nr = 0;
			
			for (r = ROIs.Length - 1; r >= 0; r--)
			{
				if (ROIs[r].comp == n)
				{
					ulx = ROIs[r].ulx;
					uly = ROIs[r].uly;
					lrx = ROIs[r].w + ulx - 1;
					lry = ROIs[r].h + uly - 1;
					
					if (ulx > (tileulx + tilew - 1) || uly > (tileuly + tileh - 1) || lrx < tileulx || lry < tileuly)
					// no part of ROI in tile
						continue;
					
					// Check bounds
					ulx -= tileulx;
					lrx -= tileulx;
					uly -= tileuly;
					lry -= tileuly;
					
					ulx = (ulx < 0)?0:ulx;
					uly = (uly < 0)?0:uly;
					lrx = (lrx > (tilew - 1))?tilew - 1:lrx;
					lry = (lry > (tileh - 1))?tileh - 1:lry;
					
					ulxs[nr] = ulx;
					ulys[nr] = uly;
					lrxs[nr] = lrx;
					lrys[nr] = lry;
					nr++;
				}
			}
			if (nr == 0)
			{
				roiInTile = false;
			}
			else
			{
				roiInTile = true;
			}
			sMasks[n] = new SubbandRectROIMask(sb, ulxs, ulys, lrxs, lrys, nr);
		}
		/// <summary> This functions gets a DataBlk the size of the current code-block and
		/// fills this block with the ROI mask.
		/// 
		/// <P> In order to get the mask for a particular Subband, the subband tree
		/// is traversed and at each decomposition, the ROI masks are computed. The
		/// roi bondaries for each subband are stored in the SubbandRectROIMask
		/// tree.
		/// 
		/// </summary>
		/// <param name="db">The data block that is to be filled with the mask
		/// 
		/// </param>
		/// <param name="sb">The root of the subband tree to which db belongs
		/// 
		/// </param>
		/// <param name="magbits">The max number of magnitude bits in any code-block
		/// 
		/// </param>
		/// <param name="c">The component for which to get the mask
		/// 
		/// </param>
		/// <returns> Whether or not a mask was needed for this tile
		/// 
		/// </returns>
		public override bool getROIMask(DataBlkInt db, Subband sb, int magbits, int c)
		{
			int x = db.ulx;
			int y = db.uly;
			int w = db.w;
			int h = db.h;
			int[] mask = db.DataInt;
            int i, j, k, r, maxk, maxj; // mink, minj removed
			int ulx = 0, uly = 0, lrx = 0, lry = 0;
			int wrap;
			int maxROI;
			int[] culxs;
			int[] culys;
			int[] clrxs;
			int[] clrys;
			SubbandRectROIMask srm;
			
			// If the ROI bounds have not been calculated for this tile and 
			// component, do so now.
			if (!tileMaskMade[c])
			{
				makeMask(sb, magbits, c);
				tileMaskMade[c] = true;
			}
			
			if (!roiInTile)
			{
				return false;
			}
			
			// Find relevant subband mask and get ROI bounds
			srm = (SubbandRectROIMask) sMasks[c].getSubbandRectROIMask(x, y);
			culxs = srm.ulxs;
			culys = srm.ulys;
			clrxs = srm.lrxs;
			clrys = srm.lrys;
			maxROI = culxs.Length - 1;
			// Make sure that only parts of ROIs within the code-block are used
			// and make the bounds local to this block the LR bounds are counted
			// as the distance from the lower right corner of the block
			x -= srm.ulx;
			y -= srm.uly;
			for (r = maxROI; r >= 0; r--)
			{
				ulx = culxs[r] - x;
				if (ulx < 0)
				{
					ulx = 0;
				}
				else if (ulx >= w)
				{
					ulx = w;
				}
				
				uly = culys[r] - y;
				if (uly < 0)
				{
					uly = 0;
				}
				else if (uly >= h)
				{
					uly = h;
				}
				
				lrx = clrxs[r] - x;
				if (lrx < 0)
				{
					lrx = - 1;
				}
				else if (lrx >= w)
				{
					lrx = w - 1;
				}
				
				lry = clrys[r] - y;
				if (lry < 0)
				{
					lry = - 1;
				}
				else if (lry >= h)
				{
					lry = h - 1;
				}
				
				// Add the masks of the ROI
				i = w * lry + lrx;
				maxj = (lrx - ulx);
				wrap = w - maxj - 1;
				maxk = lry - uly;
				
				for (k = maxk; k >= 0; k--)
				{
					for (j = maxj; j >= 0; j--, i--)
						mask[i] = magbits;
					i -= wrap;
				}
			}
			return true;
		}
Esempio n. 5
0
 /// <summary> Returns the reversibility of the current subband. It computes
 /// iteratively the reversibility of the child subbands. For each subband
 /// it tests the reversibility of the horizontal and vertical synthesis
 /// filters used to reconstruct this subband.
 /// 
 /// </summary>
 /// <param name="subband">The current subband.
 /// 
 /// </param>
 /// <returns> true if all the  filters used to reconstruct the current 
 /// subband are reversible
 /// 
 /// </returns>
 private bool isSubbandReversible(Subband subband)
 {
     if (subband.isNode)
     {
         // It's reversible if the filters to obtain the 4 subbands are
         // reversible and the ones for this one are reversible too.
         return isSubbandReversible(subband.LL) && isSubbandReversible(subband.HL) && isSubbandReversible(subband.LH) && isSubbandReversible(subband.HH) && ((SubbandSyn) subband).hFilter.Reversible && ((SubbandSyn) subband).vFilter.Reversible;
     }
     else
     {
         // Leaf subband. Reversibility of data depends on source, so say
         // it's true
         return true;
     }
 }
Esempio n. 6
0
		/// <summary> Initialises subbands fields, such as number of code-blocks and
		/// code-blocks dimension, in the subband tree. The nominal code-block
		/// width/height depends on the precincts dimensions if used.
		/// 
		/// </summary>
		/// <param name="t">The tile index of the subband
		/// 
		/// </param>
		/// <param name="c">The component index
		/// 
		/// </param>
		/// <param name="sb">The subband tree to be initialised.
		/// 
		/// </param>
		private void  initSubbandsFields(int t, int c, Subband sb)
		{
			int cbw = cblks.getCBlkWidth(ModuleSpec.SPEC_TILE_COMP, t, c);
			int cbh = cblks.getCBlkHeight(ModuleSpec.SPEC_TILE_COMP, t, c);
			
			if (!sb.isNode)
			{
				// Code-blocks dimension
				int ppx, ppy;
				int ppxExp, ppyExp, cbwExp, cbhExp;
				ppx = pss.getPPX(t, c, sb.resLvl);
				ppy = pss.getPPY(t, c, sb.resLvl);
				
				if (ppx != CSJ2K.j2k.codestream.Markers.PRECINCT_PARTITION_DEF_SIZE || ppy != CSJ2K.j2k.codestream.Markers.PRECINCT_PARTITION_DEF_SIZE)
				{
					
					ppxExp = MathUtil.log2(ppx);
					ppyExp = MathUtil.log2(ppy);
					cbwExp = MathUtil.log2(cbw);
					cbhExp = MathUtil.log2(cbh);
					
					// Precinct partition is used
					switch (sb.resLvl)
					{
						
						case 0: 
							sb.nomCBlkW = (cbwExp < ppxExp?(1 << cbwExp):(1 << ppxExp));
							sb.nomCBlkH = (cbhExp < ppyExp?(1 << cbhExp):(1 << ppyExp));
							break;
						
						
						default: 
							sb.nomCBlkW = (cbwExp < ppxExp - 1?(1 << cbwExp):(1 << (ppxExp - 1)));
							sb.nomCBlkH = (cbhExp < ppyExp - 1?(1 << cbhExp):(1 << (ppyExp - 1)));
							break;
						
					}
				}
				else
				{
					sb.nomCBlkW = cbw;
					sb.nomCBlkH = cbh;
				}
				
				// Number of code-blocks
				if (sb.numCb == null)
					sb.numCb = new Coord();
				if (sb.w != 0 && sb.h != 0)
				{
					int acb0x = cb0x;
					int acb0y = cb0y;
					int tmp;
					
					// Project code-block partition origin to subband. Since the
					// origin is always 0 or 1, it projects to the low-pass side
					// (throught the ceil operator) as itself (i.e. no change) and
					// to the high-pass side (through the floor operator) as 0,
					// always.
					switch (sb.sbandIdx)
					{
						
						case Subband.WT_ORIENT_LL: 
							// No need to project since all low-pass => nothing to do
							break;
						
						case Subband.WT_ORIENT_HL: 
							acb0x = 0;
							break;
						
						case Subband.WT_ORIENT_LH: 
							acb0y = 0;
							break;
						
						case Subband.WT_ORIENT_HH: 
							acb0x = 0;
							acb0y = 0;
							break;
						
						default: 
							throw new System.ApplicationException("Internal JJ2000 error");
						
					}
					if (sb.ulcx - acb0x < 0 || sb.ulcy - acb0y < 0)
					{
						throw new System.ArgumentException("Invalid code-blocks " + "partition origin or " + "image offset in the " + "reference grid.");
					}
					// NOTE: when calculating "floor()" by integer division the
					// dividend and divisor must be positive, we ensure that by
					// adding the divisor to the dividend and then substracting 1
					// to the result of the division
					tmp = sb.ulcx - acb0x + sb.nomCBlkW;
					sb.numCb.x = (tmp + sb.w - 1) / sb.nomCBlkW - (tmp / sb.nomCBlkW - 1);
					tmp = sb.ulcy - acb0y + sb.nomCBlkH;
					sb.numCb.y = (tmp + sb.h - 1) / sb.nomCBlkH - (tmp / sb.nomCBlkH - 1);
				}
				else
				{
					sb.numCb.x = sb.numCb.y = 0;
				}
			}
			else
			{
				initSubbandsFields(t, c, sb.LL);
				initSubbandsFields(t, c, sb.HL);
				initSubbandsFields(t, c, sb.LH);
				initSubbandsFields(t, c, sb.HH);
			}
		}
Esempio n. 7
0
		/// <summary> This function decomposes the mask for a node in the subband tree.
		/// after the mask is decomposed for a node, this function is called for 
		/// the children of the subband. The decomposition is done line by line
		/// and column by column
		/// 
		/// </summary>
		/// <param name="sb">The subband that is to be used for the decomposition
		/// 
		/// </param>
		/// <param name="tilew">The width of the current tile
		/// 
		/// </param>
		/// <param name="tileh">The height of the current tile
		/// 
		/// </param>
		/// <param name="c">component number
		/// </param>
		private void  decomp(Subband sb, int tilew, int tileh, int c)
		{
			int ulx = sb.ulx;
			int uly = sb.uly;
			int w = sb.w;
			int h = sb.h;
			int scalVal, maxVal = 0;
			int j, k, s, mi = 0, pin; // i, hi, li removed
			int hmax, lmax; // smax removed
			int lineoffs; // wrap, lastlow removed
			int[] mask = roiMask[c]; // local copy
			int[] low = maskLineLow; // local copy
			int[] high = maskLineHigh; // local copy
			int[] padLine = paddedMaskLine; // local copy
			int highFirst = 0;
			int lastpin;
			
			
			if (!sb.isNode)
				return ;
			
			// HORIZONTAL DECOMPOSITION
			
			// Calculate number of high and low samples after decomposition
			// and get support for low and high filters
			WaveletFilter filter = sb.HorWFilter;
			int lnSup = filter.SynLowNegSupport;
			int hnSup = filter.SynHighNegSupport;
			int lpSup = filter.SynLowPosSupport;
			int hpSup = filter.SynHighPosSupport;
			int lsup = lnSup + lpSup + 1;
			int hsup = hnSup + hpSup + 1;
			
			// Calculate number of high/low coeffis in subbands
			highFirst = sb.ulcx % 2;
			if (sb.w % 2 == 0)
			{
				lmax = w / 2 - 1;
				hmax = lmax;
			}
			else
			{
				if (highFirst == 0)
				{
					lmax = (w + 1) / 2 - 1;
					hmax = w / 2 - 1;
				}
				else
				{
					hmax = (w + 1) / 2 - 1;
					lmax = w / 2 - 1;
				}
			}
			
			int maxnSup = (lnSup > hnSup)?lnSup:hnSup; // Maximum negative support
			int maxpSup = (lpSup > hpSup)?lpSup:hpSup; // Maximum positive support
			
			
			// Set padding to 0
			for (pin = maxnSup - 1; pin >= 0; pin--)
				padLine[pin] = 0;
			for (pin = maxnSup + w - 1 + maxpSup; pin >= w; pin--)
				padLine[pin] = 0;
			
			// Do decomposition of all lines 
			lineoffs = (uly + h) * tilew + ulx + w - 1;
			for (j = h - 1; j >= 0; j--)
			{
				lineoffs -= tilew;
				// Get the line to transform from the mask
				mi = lineoffs;
				for (k = w, pin = w - 1 + maxnSup; k > 0; k--, mi--, pin--)
				{
					padLine[pin] = mask[mi];
				}
				
				lastpin = maxnSup + highFirst + 2 * lmax + lpSup;
				for (k = lmax; k >= 0; k--, lastpin -= 2)
				{
					// Low frequency samples
					pin = lastpin;
					for (s = lsup; s > 0; s--, pin--)
					{
						scalVal = padLine[pin];
						if (scalVal > maxVal)
							maxVal = scalVal;
					}
					low[k] = maxVal;
					maxVal = 0;
				}
				lastpin = maxnSup - highFirst + 2 * hmax + 1 + hpSup;
				for (k = hmax; k >= 0; k--, lastpin -= 2)
				{
					// High frequency samples
					pin = lastpin;
					for (s = hsup; s > 0; s--, pin--)
					{
						scalVal = padLine[pin];
						if (scalVal > maxVal)
							maxVal = scalVal;
					}
					high[k] = maxVal;
					maxVal = 0;
				}
				// Put the lows and highs back
				mi = lineoffs;
				for (k = hmax; k >= 0; k--, mi--)
				{
					mask[mi] = high[k];
				}
				for (k = lmax; k >= 0; k--, mi--)
				{
					mask[mi] = low[k];
				}
			}
			
			// VERTICAL DECOMPOSITION
			
			// Calculate number of high and low samples after decomposition
			// and get support for low and high filters
			filter = sb.VerWFilter;
			lnSup = filter.SynLowNegSupport;
			hnSup = filter.SynHighNegSupport;
			lpSup = filter.SynLowPosSupport;
			hpSup = filter.SynHighPosSupport;
			lsup = lnSup + lpSup + 1;
			hsup = hnSup + hpSup + 1;
			
			// Calculate number of high/low coeffs in subbands
			highFirst = sb.ulcy % 2;
			if (sb.h % 2 == 0)
			{
				lmax = h / 2 - 1;
				hmax = lmax;
			}
			else
			{
				if (sb.ulcy % 2 == 0)
				{
					lmax = (h + 1) / 2 - 1;
					hmax = h / 2 - 1;
				}
				else
				{
					hmax = (h + 1) / 2 - 1;
					lmax = h / 2 - 1;
				}
			}
			
			maxnSup = (lnSup > hnSup)?lnSup:hnSup; // Maximum negative support
			maxpSup = (lpSup > hpSup)?lpSup:hpSup; // Maximum positive support
			
			// Set padding to 0
			for (pin = maxnSup - 1; pin >= 0; pin--)
				padLine[pin] = 0;
			for (pin = maxnSup + h - 1 + maxpSup; pin >= h; pin--)
				padLine[pin] = 0;
			
			// Do decomposition of all columns 
			lineoffs = (uly + h - 1) * tilew + ulx + w;
			for (j = w - 1; j >= 0; j--)
			{
				lineoffs--;
				// Get the line to transform from the mask
				mi = lineoffs;
				for (k = h, pin = k - 1 + maxnSup; k > 0; k--, mi -= tilew, pin--)
				{
					padLine[pin] = mask[mi];
				}
				lastpin = maxnSup + highFirst + 2 * lmax + lpSup;
				for (k = lmax; k >= 0; k--, lastpin -= 2)
				{
					// Low frequency samples
					pin = lastpin;
					for (s = lsup; s > 0; s--, pin--)
					{
						scalVal = padLine[pin];
						if (scalVal > maxVal)
							maxVal = scalVal;
					}
					low[k] = maxVal;
					maxVal = 0;
				}
				lastpin = maxnSup - highFirst + 2 * hmax + 1 + hpSup;
				for (k = hmax; k >= 0; k--, lastpin -= 2)
				{
					// High frequency samples
					pin = lastpin;
					for (s = hsup; s > 0; s--, pin--)
					{
						scalVal = padLine[pin];
						if (scalVal > maxVal)
							maxVal = scalVal;
					}
					high[k] = maxVal;
					maxVal = 0;
				}
				// Put the lows and highs back
				mi = lineoffs;
				for (k = hmax; k >= 0; k--, mi -= tilew)
				{
					mask[mi] = high[k];
				}
				for (k = lmax; k >= 0; k--, mi -= tilew)
				{
					mask[mi] = low[k];
				}
			}
			
			if (sb.isNode)
			{
				decomp(sb.HH, tilew, tileh, c);
				decomp(sb.LH, tilew, tileh, c);
				decomp(sb.HL, tilew, tileh, c);
				decomp(sb.LL, tilew, tileh, c);
			}
		}
Esempio n. 8
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);
			}
		}
Esempio n. 9
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;
		}
Esempio n. 10
0
		/// <summary> This function generates the ROI mask for the entire tile. The mask is
		/// generated for one component. This method is called once for each tile
		/// and component.
		/// 
		/// </summary>
		/// <param name="sb">The root of the subband tree used in the decomposition
		/// 
		/// </param>
		/// <param name="magbits">The max number of magnitude bits in any code-block
		/// 
		/// </param>
		/// <param name="n">component number
		/// </param>
		public abstract void  makeMask(Subband sb, int magbits, int n);
Esempio n. 11
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);
Esempio n. 12
0
		/// <summary> The constructor of the SubbandROIMask takes the dimensions of the
		/// subband as parameters. A tree of masks is generated from the subband
		/// sb. Each Subband contains the boundaries of each ROI.
		/// 
		/// </summary>
		/// <param name="sb">The subband corresponding to this Subband Mask
		/// 
		/// </param>
		/// <param name="ulxs">The upper left x coordinates of the ROIs
		/// 
		/// </param>
		/// <param name="ulys">The upper left y coordinates of the ROIs
		/// 
		/// </param>
		/// <param name="lrxs">The lower right x coordinates of the ROIs
		/// 
		/// </param>
		/// <param name="lrys">The lower right y coordinates of the ROIs
		/// 
		/// </param>
		/// <param name="lrys">The lower right y coordinates of the ROIs
		/// 
		/// </param>
		/// <param name="nr">Number of ROIs that affect this tile
		/// 
		/// </param>
		public SubbandRectROIMask(Subband sb, int[] ulxs, int[] ulys, int[] lrxs, int[] lrys, int nr):base(sb.ulx, sb.uly, sb.w, sb.h)
		{
			this.ulxs = ulxs;
			this.ulys = ulys;
			this.lrxs = lrxs;
			this.lrys = lrys;
			int r;
			
			if (sb.isNode)
			{
				isNode = true;
				// determine odd/even - high/low filters
				int horEvenLow = sb.ulcx % 2;
				int verEvenLow = sb.ulcy % 2;
				
				// Get filter support lengths
				WaveletFilter hFilter = sb.HorWFilter;
				WaveletFilter vFilter = sb.VerWFilter;
				int hlnSup = hFilter.SynLowNegSupport;
				int hhnSup = hFilter.SynHighNegSupport;
				int hlpSup = hFilter.SynLowPosSupport;
				int hhpSup = hFilter.SynHighPosSupport;
				int vlnSup = vFilter.SynLowNegSupport;
				int vhnSup = vFilter.SynHighNegSupport;
				int vlpSup = vFilter.SynLowPosSupport;
				int vhpSup = vFilter.SynHighPosSupport;
				
				// Generate arrays for children
				int x, y;
				int[] lulxs = new int[nr];
				int[] lulys = new int[nr];
				int[] llrxs = new int[nr];
				int[] llrys = new int[nr];
				int[] hulxs = new int[nr];
				int[] hulys = new int[nr];
				int[] hlrxs = new int[nr];
				int[] hlrys = new int[nr];
				for (r = nr - 1; r >= 0; r--)
				{
					// For all ROI calculate ...
					// Upper left x for all children
					x = ulxs[r];
					if (horEvenLow == 0)
					{
						lulxs[r] = (x + 1 - hlnSup) / 2;
						hulxs[r] = (x - hhnSup) / 2;
					}
					else
					{
						lulxs[r] = (x - hlnSup) / 2;
						hulxs[r] = (x + 1 - hhnSup) / 2;
					}
					// Upper left y for all children
					y = ulys[r];
					if (verEvenLow == 0)
					{
						lulys[r] = (y + 1 - vlnSup) / 2;
						hulys[r] = (y - vhnSup) / 2;
					}
					else
					{
						lulys[r] = (y - vlnSup) / 2;
						hulys[r] = (y + 1 - vhnSup) / 2;
					}
					// lower right x for all children
					x = lrxs[r];
					if (horEvenLow == 0)
					{
						llrxs[r] = (x + hlpSup) / 2;
						hlrxs[r] = (x - 1 + hhpSup) / 2;
					}
					else
					{
						llrxs[r] = (x - 1 + hlpSup) / 2;
						hlrxs[r] = (x + hhpSup) / 2;
					}
					// lower right y for all children
					y = lrys[r];
					if (verEvenLow == 0)
					{
						llrys[r] = (y + vlpSup) / 2;
						hlrys[r] = (y - 1 + vhpSup) / 2;
					}
					else
					{
						llrys[r] = (y - 1 + vlpSup) / 2;
						hlrys[r] = (y + vhpSup) / 2;
					}
				}
				// Create children
				hh = new SubbandRectROIMask(sb.HH, hulxs, hulys, hlrxs, hlrys, nr);
				lh = new SubbandRectROIMask(sb.LH, lulxs, hulys, llrxs, hlrys, nr);
				hl = new SubbandRectROIMask(sb.HL, hulxs, lulys, hlrxs, llrys, nr);
				ll = new SubbandRectROIMask(sb.LL, lulxs, lulys, llrxs, llrys, nr);
			}
		}
Esempio n. 13
0
		/// <summary> Returns the maximum number of magnitude bits in any subband in the
		/// given tile-component if expounded quantization is used
		/// 
		/// </summary>
		/// <param name="sb">The root of the subband tree of the tile-component
		/// 
		/// </param>
		/// <param name="t">Tile index
		/// 
		/// </param>
		/// <param name="c">Component index
		/// 
		/// </param>
		/// <returns> The highest number of magnitude bit-planes
		/// 
		/// </returns>
		private int getMaxMagBitsExpounded(Subband sb, int t, int c)
		{
			int tmp, max = 0;
			int g = ((System.Int32) gbs.getTileCompVal(t, c));
			
			if (!sb.isNode)
			{
				//UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Float.floatValue' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'"
				float baseStep = (float) ((System.Single) qsss.getTileCompVal(t, c));
				//UPGRADE_WARNING: Data types in Visual C# might be different.  Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'"
				return g - 1 - (int) System.Math.Floor(System.Math.Log(baseStep / (((SubbandAn) sb).l2Norm * (1 << sb.anGainExp))) / log2);
			}
			
			max = getMaxMagBitsExpounded(sb.LL, t, c);
			tmp = getMaxMagBitsExpounded(sb.LH, t, c);
			if (tmp > max)
				max = tmp;
			tmp = getMaxMagBitsExpounded(sb.HL, t, c);
			if (tmp > max)
				max = tmp;
			tmp = getMaxMagBitsExpounded(sb.HH, t, c);
			if (tmp > max)
				max = tmp;
			
			return max;
		}
Esempio n. 14
0
		/// <summary> Returns the maximum number of magnitude bits in any subband of the
		/// current tile if reversible quantization is used
		/// 
		/// </summary>
		/// <param name="sb">The root of the subband tree of the current tile
		/// 
		/// </param>
		/// <param name="c">the component number
		/// 
		/// </param>
		/// <returns> The highest number of magnitude bit-planes
		/// 
		/// </returns>
		private int getMaxMagBitsRev(Subband sb, int c)
		{
			int tmp, max = 0;
			int g = ((System.Int32) gbs.getTileCompVal(tIdx, c));
			
			if (!sb.isNode)
				return g - 1 + src.getNomRangeBits(c) + sb.anGainExp;
			
			max = getMaxMagBitsRev(sb.LL, c);
			tmp = getMaxMagBitsRev(sb.LH, c);
			if (tmp > max)
				max = tmp;
			tmp = getMaxMagBitsRev(sb.HL, c);
			if (tmp > max)
				max = tmp;
			tmp = getMaxMagBitsRev(sb.HH, c);
			if (tmp > max)
				max = tmp;
			
			return max;
		}