/// <summary> Splits the current subband in its four subbands. It changes the status /// of this element (from a leaf to a node, and sets the filters), creates /// the childs and initializes them. An IllegalArgumentException is thrown /// if this subband is not a leaf. /// /// <p>It uses the initChilds() method to initialize the childs.</p> /// /// </summary> /// <param name="hfilter">The horizontal wavelet filter used to decompose this /// subband. It has to be a SynWTFilter object. /// /// </param> /// <param name="vfilter">The vertical wavelet filter used to decompose this /// subband. It has to be a SynWTFilter object. /// /// </param> /// <returns> A reference to the LL leaf (subb_LL). /// /// </returns> /// <seealso cref="Subband.initChilds"> /// /// </seealso> protected internal override Subband split(WaveletFilter hfilter, WaveletFilter vfilter) { // Test that this is a node if (isNode) { throw new System.ArgumentException(); } // Modify this element into a node and set the filters isNode = true; this.hFilter = (SynWTFilter)hfilter; this.vFilter = (SynWTFilter)vfilter; // Create childs subb_LL = new SubbandSyn(); subb_LH = new SubbandSyn(); subb_HL = new SubbandSyn(); subb_HH = new SubbandSyn(); // Assign parent subb_LL.parent = this; subb_HL.parent = this; subb_LH.parent = this; subb_HH.parent = this; // Initialize childs initChilds(); // Return reference to LL subband return(subb_LL); }
/// <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> /// /// <p>The 'ulx' and 'uly' members of the returned 'DataBlk' 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="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 requested code-block in the current tile for component 'c'. /// /// </returns> /// <seealso cref="DataBlk"> /// /// </seealso> public virtual DataBlk getInternCodeBlock(int c, int m, int n, SubbandSyn sb, DataBlk cblk) { int i, j, k, wrap; // mi removed int ulx, uly, w, h; int[] data; // local copy of quantized data int tmp; //int limit; // Get data block from entropy decoder cblk = src.getInternCodeBlock(c, m, n, sb, cblk); // If there are no ROIs in the tile, Or if we already got all blocks bool noRoiInTile = false; if (mss == null || mss.getTileCompVal(TileIdx, c) == null) { noRoiInTile = true; } if (noRoiInTile || cblk == null) { return(cblk); } data = (int[])cblk.Data; ulx = cblk.ulx; uly = cblk.uly; w = cblk.w; h = cblk.h; // Scale coefficients according to magnitude. If the magnitude of a // coefficient is lower than 2 pow 31-magbits then it is a background // coeff and should be up-scaled int boost = ((System.Int32)mss.getTileCompVal(TileIdx, c)); int mask = ((1 << sb.magbits) - 1) << (31 - sb.magbits); int mask2 = (~mask) & 0x7FFFFFFF; wrap = cblk.scanw - w; i = cblk.offset + cblk.scanw * (h - 1) + w - 1; for (j = h; j > 0; j--) { for (k = w; k > 0; k--, i--) { tmp = data[i]; if ((tmp & mask) == 0) { // BG data[i] = (tmp & unchecked ((int)0x80000000)) | (tmp << boost); } else { // ROI if ((tmp & mask2) != 0) { // decoded more than magbits bit-planes, set // quantization mid-interval approx. bit just after // the magbits. data[i] = (tmp & (~mask2)) | (1 << (30 - sb.magbits)); } } } i -= wrap; } return(cblk); }
/// <summary> Returns the specified code-block in the current tile for the specified /// component, as a copy (see below). /// /// <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 is always a copy of the internal /// data of this object, if any, and it can be modified "in place" without /// any problems after being returned. The 'offset' of the returned data is /// 0, and the 'scanw' is the same as the code-block width. See the /// 'DataBlk' class.</p> /// /// <p>The 'ulx' and 'uly' members of the returned 'DataBlk' 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="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 'c', or /// null if all code-blocks for the current tile have been returned. /// /// </returns> /// <seealso cref="DataBlk"> /// /// </seealso> public virtual DataBlk getCodeBlock(int c, int m, int n, SubbandSyn sb, DataBlk cblk) { return(getInternCodeBlock(c, m, n, sb, cblk)); }
/// <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); }