private static int GetLog2SubbandGain(Subband subband) { // See Table E.1 "Sub-band gains" if (subband.SubbandType == SubbandType.LL) { return(0); } else if (subband.SubbandType == SubbandType.LH) { return(1); } else if (subband.SubbandType == SubbandType.HL) { return(1); } else if (subband.SubbandType == SubbandType.HH) { return(2); } else { throw NotSupported(subband.SubbandType); } }
/// <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); }
/// <summary> Returns the maximum number of magnitude bits in any subband in the /// given tile-component if expounded quantization is used /// /// </summary> /// <param name="sb">The root of the subband tree of the tile-component /// /// </param> /// <param name="t">Tile index /// /// </param> /// <param name="c">Component index /// /// </param> /// <returns> The highest number of magnitude bit-planes /// /// </returns> private int getMaxMagBitsExpounded(Subband sb, int t, int c) { int tmp, max = 0; int g = ((System.Int32)gbs.getTileCompVal(t, c)); if (!sb.isNode) { //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Float.floatValue' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'" float baseStep = (float)((System.Single)qsss.getTileCompVal(t, c)); //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" return(g - 1 - (int)System.Math.Floor(System.Math.Log(baseStep / (((SubbandAn)sb).l2Norm * (1 << sb.anGainExp))) / log2)); } max = getMaxMagBitsExpounded(sb.LL, t, c); tmp = getMaxMagBitsExpounded(sb.LH, t, c); if (tmp > max) { max = tmp; } tmp = getMaxMagBitsExpounded(sb.HL, t, c); if (tmp > max) { max = tmp; } tmp = getMaxMagBitsExpounded(sb.HH, t, c); if (tmp > max) { max = tmp; } return(max); }
public int GetEb(Subband subband) { if (ReversibleStepSizes != null) { return(ReversibleStepSizes[subband.SubbandIndex].Exponent); } else if (QuantizationStepSizes != null) { return(QuantizationStepSizes[subband.SubbandIndex].Exponent); } else { throw new NotSupportedException(); } }
/// <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); } }
/// <summary> Returns the maximum number of magnitude bits in any subband of the /// current tile. /// /// </summary> /// <param name="c">the component number /// /// </param> /// <returns> The maximum number of magnitude bits in all subbands of the /// current tile. /// /// </returns> public override int getMaxMagBits(int c) { Subband sb = getAnSubbandTree(tIdx, c); if (isReversible(tIdx, c)) { return(getMaxMagBitsRev(sb, c)); } else { if (isDerived(tIdx, c)) { return(getMaxMagBitsDerived(sb, tIdx, c)); } else { return(getMaxMagBitsExpounded(sb, tIdx, c)); } } }
/// <summary> This functions gets a DataBlk the size of the current code-block an /// fills this block with the ROI mask. /// /// <P> In order to get the mask for a particular Subband, the subband tree /// is traversed and at each decomposition, the ROI masks are computed. /// /// <P> The widths of the synthesis filters corresponding to the wavelet /// filters used in the wavelet transform are used to expand the ROI masks /// in the decompositions. /// /// </summary> /// <param name="db">The data block that is to be filled with the mask /// /// </param> /// <param name="sb">The root of the subband tree to which db belongs /// /// </param> /// <param name="magbits">The max number of magnitude bits in any code-block /// /// </param> /// <param name="c">The number of the component /// /// </param> /// <returns> Whether or not a mask was needed for this tile /// /// </returns> public override bool getROIMask(DataBlkInt db, Subband sb, int magbits, int c) { int x = db.ulx; int y = db.uly; int w = db.w; int h = db.h; int tilew = sb.w; int tileh = sb.h; int[] maskData = (int[])db.Data; int i, j, k, bi, wrap; // If the ROI mask has not been calculated for this tile and // component, do so now. if (!tileMaskMade[c]) { makeMask(sb, magbits, c); tileMaskMade[c] = true; } if (!roiInTile) { return(false); } int[] mask = roiMask[c]; // local copy // Copy relevant part of the ROI mask to the datablock i = (y + h - 1) * tilew + x + w - 1; bi = w * h - 1; wrap = tilew - w; for (j = h; j > 0; j--) { for (k = w; k > 0; k--, i--, bi--) { maskData[bi] = mask[i]; } i -= wrap; } return(true); }
private Subband[][][] CreateSubbands(int nComponents) { var subbands = new Subband[nComponents][][]; for (var component = 0; component < nComponents; component++) { var nDecompositionLevels = COC[component].SP_NumberOfDecompositionLevels; var subbandIndex = 0; Subband NewSubband(int decompositionLevel, SubbandType subbandType) { return(new Subband(subbandIndex++, decompositionLevel, subbandType)); } subbands[component] = new Subband[nDecompositionLevels + 1][]; for (var resolution = 0; resolution <= nDecompositionLevels; resolution++) { if (resolution == 0) { var decompositionLevel = nDecompositionLevels - resolution; subbands[component][resolution] = new[] { NewSubband(decompositionLevel, SubbandType.LL) }; } else { var decompositionLevel = nDecompositionLevels - (resolution - 1); subbands[component][resolution] = new[] { NewSubband(decompositionLevel, SubbandType.HL), NewSubband(decompositionLevel, SubbandType.LH), NewSubband(decompositionLevel, SubbandType.HH) }; } } } return(subbands); }
private void ReadSubBand(BitReader bitReader, Subband subband) { var subbandPrecinct = ResolutionLevel.GetSubbandPrecinct(subband); var nCodeBlocksX = subbandPrecinct.NCodeBlocksX; var nCodeBlocksY = subbandPrecinct.NCodeBlocksY; var codeBlockInclusionTagTree = subbandPrecinct.CodeBlockInclusionTagTree; for (var y = 0; y < nCodeBlocksY; y++) { for (var x = 0; x < nCodeBlocksX; x++) { var codeBlockFirstIncludedInLayerIsValid = codeBlockInclusionTagTree.TryGetValue((uint)x, (uint)y, (uint)Layer, bitReader, out uint codeBlockFirstIncludedInLayer); var codeBlockIsIncludedInPacket = false; if (codeBlockFirstIncludedInLayerIsValid) { if (codeBlockFirstIncludedInLayer < Layer) { codeBlockIsIncludedInPacket = (bitReader.ReadBit() == 1); } else { codeBlockIsIncludedInPacket = codeBlockFirstIncludedInLayer == Layer; } } if (codeBlockIsIncludedInPacket) { var codeBlock = subbandPrecinct.AddCodeBlock(x, y); if (codeBlockFirstIncludedInLayer == Layer) { var zeroBitPlaneTagTree = subbandPrecinct.ZeroBitPlaneTagTree; var nAllZeroBitPlanesIsValid = zeroBitPlaneTagTree.TryGetValue((uint)x, (uint)y, uint.MaxValue, bitReader, out uint nAllZeroBitPlanes); Debug.Assert(nAllZeroBitPlanesIsValid); // must be true since limit == uint.MaxValue codeBlock.NAllZeroBitPlanes_P = (int)nAllZeroBitPlanes; } codeBlock.NCodingPasses = (ushort)ReadNumberOfCodingPasses(bitReader); ThrowIf(ResolutionLevel.TilePartComponent.COC.SP_CodeBlockCodingPassStyle != 0); var codeBlockLengthIndicator = 3; // TODO: Get from and update in layer for this code block while (bitReader.ReadBit() != 0) { codeBlockLengthIndicator++; } var nBitsUsedToStoreCodeBlockLength = codeBlockLengthIndicator + StaticInclude.FloorLog2(codeBlock.NCodingPasses); codeBlock.LengthInBytes = bitReader.ReadBits(nBitsUsedToStoreCodeBlockLength); IncludedCodeBlocks.Add(codeBlock); } } } }
/// <summary> This function generates the ROI mask for the entire tile. The mask is /// generated for one component. This method is called once for each tile /// and component. /// /// </summary> /// <param name="sb">The root of the subband tree used in the decomposition /// /// </param> /// <param name="n">component number /// /// </param> public override void makeMask(Subband sb, int magbits, int n) { int nr = nrROIs[n]; int r; int ulx, uly, lrx, lry; int tileulx = sb.ulcx; int tileuly = sb.ulcy; int tilew = sb.w; int tileh = sb.h; ROI[] ROIs = roi_array; // local copy ulxs = new int[nr]; ulys = new int[nr]; lrxs = new int[nr]; lrys = new int[nr]; nr = 0; for (r = ROIs.Length - 1; r >= 0; r--) { if (ROIs[r].comp == n) { ulx = ROIs[r].ulx; uly = ROIs[r].uly; lrx = ROIs[r].w + ulx - 1; lry = ROIs[r].h + uly - 1; if (ulx > (tileulx + tilew - 1) || uly > (tileuly + tileh - 1) || lrx < tileulx || lry < tileuly) { // no part of ROI in tile continue; } // Check bounds ulx -= tileulx; lrx -= tileulx; uly -= tileuly; lry -= tileuly; ulx = (ulx < 0)?0:ulx; uly = (uly < 0)?0:uly; lrx = (lrx > (tilew - 1))?tilew - 1:lrx; lry = (lry > (tileh - 1))?tileh - 1:lry; ulxs[nr] = ulx; ulys[nr] = uly; lrxs[nr] = lrx; lrys[nr] = lry; nr++; } } if (nr == 0) { roiInTile = false; } else { roiInTile = true; } sMasks[n] = new SubbandRectROIMask(sb, ulxs, ulys, lrxs, lrys, nr); }
/// <summary> This functions gets a DataBlk the size of the current code-block and /// fills this block with the ROI mask. /// /// <P> In order to get the mask for a particular Subband, the subband tree /// is traversed and at each decomposition, the ROI masks are computed. The /// roi bondaries for each subband are stored in the SubbandRectROIMask /// tree. /// /// </summary> /// <param name="db">The data block that is to be filled with the mask /// /// </param> /// <param name="sb">The root of the subband tree to which db belongs /// /// </param> /// <param name="magbits">The max number of magnitude bits in any code-block /// /// </param> /// <param name="c">The component for which to get the mask /// /// </param> /// <returns> Whether or not a mask was needed for this tile /// /// </returns> public override bool getROIMask(DataBlkInt db, Subband sb, int magbits, int c) { int x = db.ulx; int y = db.uly; int w = db.w; int h = db.h; int[] mask = db.DataInt; int i, j, k, r, maxk, maxj; // mink, minj removed int ulx = 0, uly = 0, lrx = 0, lry = 0; int wrap; int maxROI; int[] culxs; int[] culys; int[] clrxs; int[] clrys; SubbandRectROIMask srm; // If the ROI bounds have not been calculated for this tile and // component, do so now. if (!tileMaskMade[c]) { makeMask(sb, magbits, c); tileMaskMade[c] = true; } if (!roiInTile) { return(false); } // Find relevant subband mask and get ROI bounds srm = (SubbandRectROIMask)sMasks[c].getSubbandRectROIMask(x, y); culxs = srm.ulxs; culys = srm.ulys; clrxs = srm.lrxs; clrys = srm.lrys; maxROI = culxs.Length - 1; // Make sure that only parts of ROIs within the code-block are used // and make the bounds local to this block the LR bounds are counted // as the distance from the lower right corner of the block x -= srm.ulx; y -= srm.uly; for (r = maxROI; r >= 0; r--) { ulx = culxs[r] - x; if (ulx < 0) { ulx = 0; } else if (ulx >= w) { ulx = w; } uly = culys[r] - y; if (uly < 0) { uly = 0; } else if (uly >= h) { uly = h; } lrx = clrxs[r] - x; if (lrx < 0) { lrx = -1; } else if (lrx >= w) { lrx = w - 1; } lry = clrys[r] - y; if (lry < 0) { lry = -1; } else if (lry >= h) { lry = h - 1; } // Add the masks of the ROI i = w * lry + lrx; maxj = (lrx - ulx); wrap = w - maxj - 1; maxk = lry - uly; for (k = maxk; k >= 0; k--) { for (j = maxj; j >= 0; j--, i--) { mask[i] = magbits; } i -= wrap; } } return(true); }
/// <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);
/// <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);
public abstract void Dequantisize(Signal2D transformCoefficientValues, TilePartComponent tilePartComponent, Subband subband);
/// <summary> This function generates the ROI mask for one tile-component. /// /// <P> Once the mask is generated in the pixel domain. it is decomposed /// following the same decomposition scheme as the wavelet transform. /// /// </summary> /// <param name="sb">The root of the subband tree used in the decomposition /// /// </param> /// <param name="magbits">The max number of magnitude bits in any code-block /// /// </param> /// <param name="c">component number /// </param> public override void makeMask(Subband sb, int magbits, int c) { int[] mask; // local copy ROI[] rois = this.roi_array; // local copy int i, j, k, r, maxj; // mink, minj removed int lrx, lry; int x, y, w, h; int cx, cy, rad; int wrap; int curScalVal; int tileulx = sb.ulcx; int tileuly = sb.ulcy; int tilew = sb.w; int tileh = sb.h; int lineLen = (tilew > tileh)?tilew:tileh; // Make sure there is a sufficiently large mask buffer if (roiMask[c] == null || (roiMask[c].Length < (tilew * tileh))) { roiMask[c] = new int[tilew * tileh]; mask = roiMask[c]; } else { mask = roiMask[c]; for (i = tilew * tileh - 1; i >= 0; i--) { mask[i] = 0; } } // Make sure there are sufficiently large line buffers if (maskLineLow == null || (maskLineLow.Length < (lineLen + 1) / 2)) { maskLineLow = new int[(lineLen + 1) / 2]; } if (maskLineHigh == null || (maskLineHigh.Length < (lineLen + 1) / 2)) { maskLineHigh = new int[(lineLen + 1) / 2]; } roiInTile = false; // Generate ROIs in pixel domain: for (r = rois.Length - 1; r >= 0; r--) { if (rois[r].comp == c) { curScalVal = magbits; if (rois[r].arbShape) { ImgReaderPGM maskPGM = rois[r].maskPGM; // Local copy if ((src.ImgWidth != maskPGM.ImgWidth) || (src.ImgHeight != maskPGM.ImgHeight)) { throw new System.ArgumentException("Input image and" + " ROI mask must " + "have the same " + "size"); } x = src.ImgULX; y = src.ImgULY; lrx = x + src.ImgWidth - 1; lry = y + src.ImgHeight - 1; if ((x > tileulx + tilew) || (y > tileuly + tileh) || (lrx < tileulx) || (lry < tileuly)) { // Roi not in tile continue; } // Check bounds x -= tileulx; lrx -= tileulx; y -= tileuly; lry -= tileuly; int offx = 0; int offy = 0; if (x < 0) { offx = -x; x = 0; } if (y < 0) { offy = -y; y = 0; } w = (lrx > (tilew - 1))?tilew - x:lrx + 1 - x; h = (lry > (tileh - 1))?tileh - y:lry + 1 - y; // Get shape line by line to reduce memory DataBlkInt srcblk = new DataBlkInt(); int mDcOff = -ImgReaderPGM.DC_OFFSET; int nROIcoeff = 0; int[] src_data; srcblk.ulx = offx; srcblk.w = w; srcblk.h = 1; i = (y + h - 1) * tilew + x + w - 1; maxj = w; wrap = tilew - maxj; for (k = h; k > 0; k--) { srcblk.uly = offy + k - 1; srcblk = (DataBlkInt)maskPGM.getInternCompData(srcblk, 0); src_data = srcblk.DataInt; for (j = maxj; j > 0; j--, i--) { if (src_data[j - 1] != mDcOff) { mask[i] = curScalVal; nROIcoeff++; } } i -= wrap; } if (nROIcoeff != 0) { roiInTile = true; } } else if (rois[r].rect) { // Rectangular ROI x = rois[r].ulx; y = rois[r].uly; lrx = rois[r].w + x - 1; lry = rois[r].h + y - 1; if ((x > tileulx + tilew) || (y > tileuly + tileh) || (lrx < tileulx) || (lry < tileuly)) { // Roi not in tile continue; } roiInTile = true; // Check bounds x -= tileulx; lrx -= tileulx; y -= tileuly; lry -= tileuly; x = (x < 0)?0:x; y = (y < 0)?0:y; w = (lrx > (tilew - 1))?tilew - x:lrx + 1 - x; h = (lry > (tileh - 1))?tileh - y:lry + 1 - y; i = (y + h - 1) * tilew + x + w - 1; maxj = w; wrap = tilew - maxj; for (k = h; k > 0; k--) { for (j = maxj; j > 0; j--, i--) { mask[i] = curScalVal; } i -= wrap; } } else { // Non-rectangular ROI. So far only circular case cx = rois[r].x - tileulx; cy = rois[r].y - tileuly; rad = rois[r].r; i = tileh * tilew - 1; for (k = tileh - 1; k >= 0; k--) { for (j = tilew - 1; j >= 0; j--, i--) { if (((j - cx) * (j - cx) + (k - cy) * (k - cy) < rad * rad)) { mask[i] = curScalVal; roiInTile = true; } } } } } } // If wavelet transform is used if (sb.isNode) { // Decompose the mask according to the subband tree // Calculate size of padded line buffer WaveletFilter vFilter = sb.VerWFilter; WaveletFilter hFilter = sb.HorWFilter; int lvsup = vFilter.SynLowNegSupport + vFilter.SynLowPosSupport; int hvsup = vFilter.SynHighNegSupport + vFilter.SynHighPosSupport; int lhsup = hFilter.SynLowNegSupport + hFilter.SynLowPosSupport; int hhsup = hFilter.SynHighNegSupport + hFilter.SynHighPosSupport; lvsup = (lvsup > hvsup)?lvsup:hvsup; lhsup = (lhsup > hhsup)?lhsup:hhsup; lvsup = (lvsup > lhsup)?lvsup:lhsup; paddedMaskLine = new int[lineLen + lvsup]; if (roiInTile) { decomp(sb, tilew, tileh, c); } } }
protected sealed override void Dequantisize(Signal2D <T> transformCoefficientValues, TilePartComponent component, Subband subband) { var quantizationStepSize = GetQuantizationStepSize(component, subband); if (quantizationStepSize != 1) { transformCoefficientValues.URange.GetBounds(out int u0, out int u1); transformCoefficientValues.VRange.GetBounds(out int v0, out int v1); Parallel.For(v0, v1, v => { for (var u = u0; u < u1; u++) { ApplyQuantizationStepSize(transformCoefficientValues, u, v, quantizationStepSize); } }); } }
public int GetMb(Subband subband) { return(NGuardBits_G + GetEb(subband) - 1); }
private static double GetQuantizationStepSize(TilePartComponent tilePartComponent, Subband subband) { var qcc = tilePartComponent.QCC; ThrowIf(qcc.QuantizationStyle == QuantizationStyle.NoQuantization); // See E.1.1.1 "Determination of the quantization step size" var ri = tilePartComponent.TileComponent.Component.ComponentSampleBitDepth; var rb = ri + GetLog2SubbandGain(subband); if (qcc.QuantizationStyle == QuantizationStyle.ScalarExpounded) { var qss = qcc.QuantizationStepSizes[subband.SubbandIndex]; return(Math.Pow(2, rb - qss.Exponent) * (1 + qss.Mantissa / Math.Pow(2, 11))); } else { throw NotSupported(qcc.QuantizationStyle); } }
protected sealed override void Dequantisize(Signal2D <T> transformCoefficientValues, TilePartComponent tilePartComponent, Subband subband) { // Nothing to do }
/// <summary> Initialises subbands fields, such as number of code-blocks and /// code-blocks dimension, in the subband tree. The nominal code-block /// width/height depends on the precincts dimensions if used. /// /// </summary> /// <param name="t">The tile index of the subband /// /// </param> /// <param name="c">The component index /// /// </param> /// <param name="sb">The subband tree to be initialised. /// /// </param> private void initSubbandsFields(int t, int c, Subband sb) { int cbw = cblks.getCBlkWidth(ModuleSpec.SPEC_TILE_COMP, t, c); int cbh = cblks.getCBlkHeight(ModuleSpec.SPEC_TILE_COMP, t, c); if (!sb.isNode) { // Code-blocks dimension int ppx, ppy; int ppxExp, ppyExp, cbwExp, cbhExp; ppx = pss.getPPX(t, c, sb.resLvl); ppy = pss.getPPY(t, c, sb.resLvl); if (ppx != CSJ2K.j2k.codestream.Markers.PRECINCT_PARTITION_DEF_SIZE || ppy != CSJ2K.j2k.codestream.Markers.PRECINCT_PARTITION_DEF_SIZE) { ppxExp = MathUtil.log2(ppx); ppyExp = MathUtil.log2(ppy); cbwExp = MathUtil.log2(cbw); cbhExp = MathUtil.log2(cbh); // Precinct partition is used switch (sb.resLvl) { case 0: sb.nomCBlkW = (cbwExp < ppxExp ? (1 << cbwExp) : (1 << ppxExp)); sb.nomCBlkH = (cbhExp < ppyExp ? (1 << cbhExp) : (1 << ppyExp)); break; default: sb.nomCBlkW = (cbwExp < ppxExp - 1 ? (1 << cbwExp) : (1 << (ppxExp - 1))); sb.nomCBlkH = (cbhExp < ppyExp - 1 ? (1 << cbhExp) : (1 << (ppyExp - 1))); break; } } else { sb.nomCBlkW = cbw; sb.nomCBlkH = cbh; } // Number of code-blocks if (sb.numCb == null) { sb.numCb = new Coord(); } if (sb.w != 0 && sb.h != 0) { int acb0x = cb0x; int acb0y = cb0y; int tmp; // Project code-block partition origin to subband. Since the // origin is always 0 or 1, it projects to the low-pass side // (throught the ceil operator) as itself (i.e. no change) and // to the high-pass side (through the floor operator) as 0, // always. switch (sb.sbandIdx) { case Subband.WT_ORIENT_LL: // No need to project since all low-pass => nothing to do break; case Subband.WT_ORIENT_HL: acb0x = 0; break; case Subband.WT_ORIENT_LH: acb0y = 0; break; case Subband.WT_ORIENT_HH: acb0x = 0; acb0y = 0; break; default: throw new System.ApplicationException("Internal JJ2000 error"); } if (sb.ulcx - acb0x < 0 || sb.ulcy - acb0y < 0) { throw new System.ArgumentException("Invalid code-blocks " + "partition origin or " + "image offset in the " + "reference grid."); } // NOTE: when calculating "floor()" by integer division the // dividend and divisor must be positive, we ensure that by // adding the divisor to the dividend and then substracting 1 // to the result of the division tmp = sb.ulcx - acb0x + sb.nomCBlkW; sb.numCb.x = (tmp + sb.w - 1) / sb.nomCBlkW - (tmp / sb.nomCBlkW - 1); tmp = sb.ulcy - acb0y + sb.nomCBlkH; sb.numCb.y = (tmp + sb.h - 1) / sb.nomCBlkH - (tmp / sb.nomCBlkH - 1); } else { sb.numCb.x = sb.numCb.y = 0; } } else { initSubbandsFields(t, c, sb.LL); initSubbandsFields(t, c, sb.HL); initSubbandsFields(t, c, sb.LH); initSubbandsFields(t, c, sb.HH); } }
/// <summary> This function decomposes the mask for a node in the subband tree. /// after the mask is decomposed for a node, this function is called for /// the children of the subband. The decomposition is done line by line /// and column by column /// /// </summary> /// <param name="sb">The subband that is to be used for the decomposition /// /// </param> /// <param name="tilew">The width of the current tile /// /// </param> /// <param name="tileh">The height of the current tile /// /// </param> /// <param name="c">component number /// </param> private void decomp(Subband sb, int tilew, int tileh, int c) { int ulx = sb.ulx; int uly = sb.uly; int w = sb.w; int h = sb.h; int scalVal, maxVal = 0; int j, k, s, mi = 0, pin; // i, hi, li removed int hmax, lmax; // smax removed int lineoffs; // wrap, lastlow removed int[] mask = roiMask[c]; // local copy int[] low = maskLineLow; // local copy int[] high = maskLineHigh; // local copy int[] padLine = paddedMaskLine; // local copy int highFirst = 0; int lastpin; if (!sb.isNode) { return; } // HORIZONTAL DECOMPOSITION // Calculate number of high and low samples after decomposition // and get support for low and high filters WaveletFilter filter = sb.HorWFilter; int lnSup = filter.SynLowNegSupport; int hnSup = filter.SynHighNegSupport; int lpSup = filter.SynLowPosSupport; int hpSup = filter.SynHighPosSupport; int lsup = lnSup + lpSup + 1; int hsup = hnSup + hpSup + 1; // Calculate number of high/low coeffis in subbands highFirst = sb.ulcx % 2; if (sb.w % 2 == 0) { lmax = w / 2 - 1; hmax = lmax; } else { if (highFirst == 0) { lmax = (w + 1) / 2 - 1; hmax = w / 2 - 1; } else { hmax = (w + 1) / 2 - 1; lmax = w / 2 - 1; } } int maxnSup = (lnSup > hnSup)?lnSup:hnSup; // Maximum negative support int maxpSup = (lpSup > hpSup)?lpSup:hpSup; // Maximum positive support // Set padding to 0 for (pin = maxnSup - 1; pin >= 0; pin--) { padLine[pin] = 0; } for (pin = maxnSup + w - 1 + maxpSup; pin >= w; pin--) { padLine[pin] = 0; } // Do decomposition of all lines lineoffs = (uly + h) * tilew + ulx + w - 1; for (j = h - 1; j >= 0; j--) { lineoffs -= tilew; // Get the line to transform from the mask mi = lineoffs; for (k = w, pin = w - 1 + maxnSup; k > 0; k--, mi--, pin--) { padLine[pin] = mask[mi]; } lastpin = maxnSup + highFirst + 2 * lmax + lpSup; for (k = lmax; k >= 0; k--, lastpin -= 2) { // Low frequency samples pin = lastpin; for (s = lsup; s > 0; s--, pin--) { scalVal = padLine[pin]; if (scalVal > maxVal) { maxVal = scalVal; } } low[k] = maxVal; maxVal = 0; } lastpin = maxnSup - highFirst + 2 * hmax + 1 + hpSup; for (k = hmax; k >= 0; k--, lastpin -= 2) { // High frequency samples pin = lastpin; for (s = hsup; s > 0; s--, pin--) { scalVal = padLine[pin]; if (scalVal > maxVal) { maxVal = scalVal; } } high[k] = maxVal; maxVal = 0; } // Put the lows and highs back mi = lineoffs; for (k = hmax; k >= 0; k--, mi--) { mask[mi] = high[k]; } for (k = lmax; k >= 0; k--, mi--) { mask[mi] = low[k]; } } // VERTICAL DECOMPOSITION // Calculate number of high and low samples after decomposition // and get support for low and high filters filter = sb.VerWFilter; lnSup = filter.SynLowNegSupport; hnSup = filter.SynHighNegSupport; lpSup = filter.SynLowPosSupport; hpSup = filter.SynHighPosSupport; lsup = lnSup + lpSup + 1; hsup = hnSup + hpSup + 1; // Calculate number of high/low coeffs in subbands highFirst = sb.ulcy % 2; if (sb.h % 2 == 0) { lmax = h / 2 - 1; hmax = lmax; } else { if (sb.ulcy % 2 == 0) { lmax = (h + 1) / 2 - 1; hmax = h / 2 - 1; } else { hmax = (h + 1) / 2 - 1; lmax = h / 2 - 1; } } maxnSup = (lnSup > hnSup)?lnSup:hnSup; // Maximum negative support maxpSup = (lpSup > hpSup)?lpSup:hpSup; // Maximum positive support // Set padding to 0 for (pin = maxnSup - 1; pin >= 0; pin--) { padLine[pin] = 0; } for (pin = maxnSup + h - 1 + maxpSup; pin >= h; pin--) { padLine[pin] = 0; } // Do decomposition of all columns lineoffs = (uly + h - 1) * tilew + ulx + w; for (j = w - 1; j >= 0; j--) { lineoffs--; // Get the line to transform from the mask mi = lineoffs; for (k = h, pin = k - 1 + maxnSup; k > 0; k--, mi -= tilew, pin--) { padLine[pin] = mask[mi]; } lastpin = maxnSup + highFirst + 2 * lmax + lpSup; for (k = lmax; k >= 0; k--, lastpin -= 2) { // Low frequency samples pin = lastpin; for (s = lsup; s > 0; s--, pin--) { scalVal = padLine[pin]; if (scalVal > maxVal) { maxVal = scalVal; } } low[k] = maxVal; maxVal = 0; } lastpin = maxnSup - highFirst + 2 * hmax + 1 + hpSup; for (k = hmax; k >= 0; k--, lastpin -= 2) { // High frequency samples pin = lastpin; for (s = hsup; s > 0; s--, pin--) { scalVal = padLine[pin]; if (scalVal > maxVal) { maxVal = scalVal; } } high[k] = maxVal; maxVal = 0; } // Put the lows and highs back mi = lineoffs; for (k = hmax; k >= 0; k--, mi -= tilew) { mask[mi] = high[k]; } for (k = lmax; k >= 0; k--, mi -= tilew) { mask[mi] = low[k]; } } if (sb.isNode) { decomp(sb.HH, tilew, tileh, c); decomp(sb.LH, tilew, tileh, c); decomp(sb.HL, tilew, tileh, c); decomp(sb.LL, tilew, tileh, c); } }
/// <summary> The constructor of the SubbandROIMask takes the dimensions of the /// subband as parameters. A tree of masks is generated from the subband /// sb. Each Subband contains the boundaries of each ROI. /// /// </summary> /// <param name="sb">The subband corresponding to this Subband Mask /// /// </param> /// <param name="ulxs">The upper left x coordinates of the ROIs /// /// </param> /// <param name="ulys">The upper left y coordinates of the ROIs /// /// </param> /// <param name="lrxs">The lower right x coordinates of the ROIs /// /// </param> /// <param name="lrys">The lower right y coordinates of the ROIs /// /// </param> /// <param name="lrys">The lower right y coordinates of the ROIs /// /// </param> /// <param name="nr">Number of ROIs that affect this tile /// /// </param> public SubbandRectROIMask(Subband sb, int[] ulxs, int[] ulys, int[] lrxs, int[] lrys, int nr) : base(sb.ulx, sb.uly, sb.w, sb.h) { this.ulxs = ulxs; this.ulys = ulys; this.lrxs = lrxs; this.lrys = lrys; int r; if (sb.isNode) { isNode = true; // determine odd/even - high/low filters int horEvenLow = sb.ulcx % 2; int verEvenLow = sb.ulcy % 2; // Get filter support lengths WaveletFilter hFilter = sb.HorWFilter; WaveletFilter vFilter = sb.VerWFilter; int hlnSup = hFilter.SynLowNegSupport; int hhnSup = hFilter.SynHighNegSupport; int hlpSup = hFilter.SynLowPosSupport; int hhpSup = hFilter.SynHighPosSupport; int vlnSup = vFilter.SynLowNegSupport; int vhnSup = vFilter.SynHighNegSupport; int vlpSup = vFilter.SynLowPosSupport; int vhpSup = vFilter.SynHighPosSupport; // Generate arrays for children int x, y; int[] lulxs = new int[nr]; int[] lulys = new int[nr]; int[] llrxs = new int[nr]; int[] llrys = new int[nr]; int[] hulxs = new int[nr]; int[] hulys = new int[nr]; int[] hlrxs = new int[nr]; int[] hlrys = new int[nr]; for (r = nr - 1; r >= 0; r--) { // For all ROI calculate ... // Upper left x for all children x = ulxs[r]; if (horEvenLow == 0) { lulxs[r] = (x + 1 - hlnSup) / 2; hulxs[r] = (x - hhnSup) / 2; } else { lulxs[r] = (x - hlnSup) / 2; hulxs[r] = (x + 1 - hhnSup) / 2; } // Upper left y for all children y = ulys[r]; if (verEvenLow == 0) { lulys[r] = (y + 1 - vlnSup) / 2; hulys[r] = (y - vhnSup) / 2; } else { lulys[r] = (y - vlnSup) / 2; hulys[r] = (y + 1 - vhnSup) / 2; } // lower right x for all children x = lrxs[r]; if (horEvenLow == 0) { llrxs[r] = (x + hlpSup) / 2; hlrxs[r] = (x - 1 + hhpSup) / 2; } else { llrxs[r] = (x - 1 + hlpSup) / 2; hlrxs[r] = (x + hhpSup) / 2; } // lower right y for all children y = lrys[r]; if (verEvenLow == 0) { llrys[r] = (y + vlpSup) / 2; hlrys[r] = (y - 1 + vhpSup) / 2; } else { llrys[r] = (y - 1 + vlpSup) / 2; hlrys[r] = (y + vhpSup) / 2; } } // Create children hh = new SubbandRectROIMask(sb.HH, hulxs, hulys, hlrxs, hlrys, nr); lh = new SubbandRectROIMask(sb.LH, lulxs, hulys, llrxs, hlrys, nr); hl = new SubbandRectROIMask(sb.HL, hulxs, lulys, hlrxs, llrys, nr); ll = new SubbandRectROIMask(sb.LL, lulxs, lulys, llrxs, llrys, nr); } }