public override DataBlk getInternCompData(DataBlk blk, int c) { if (c < 0 || c >= this.nc) { throw new ArgumentOutOfRangeException("c"); } blk.offset = 0; blk.scanw = blk.w; blk.progressive = false; blk.Data = this.GetDataArray(blk.ulx, blk.uly, blk.w, blk.h); return blk; }
/// <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>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> /// /// <p>This method, in general, is less efficient than the /// 'getInternCompData()' method since, in general, it copies the /// data. However if the array of returned data is to be modified by the /// caller then this method is preferable.</p> /// /// <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> /// /// <p>The returned data may have its 'progressive' attribute set. In this /// case the returned data is only an approximation of the "final" /// data.</p> /// /// </summary> /// <param name="blk">Its coordinates and dimensions specify the area to return, /// relative to the current tile. If it contains a non-null data array, /// then it must be large enough. If it contains a null data array a new /// one is created. 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. /// /// </param> /// <returns> The requested DataBlk /// /// </returns> /// <seealso cref="getInternCompData"> /// /// </seealso> public DataBlk getCompData(DataBlk blk, int c) { // Check that block is inside tile if (blk.ulx < 0 || blk.uly < 0 || blk.w > compW[c] || blk.h > compH[c]) { throw new System.ArgumentException("Block is outside the tile"); } // Translate to the source's coordinates //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'" int incx = (int)System.Math.Ceiling(x0siz / (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'" int incy = (int)System.Math.Ceiling(y0siz / (double)src.getCompSubsY(c)); blk.ulx -= incx; blk.uly -= incy; blk = src.getCompData(blk, c); // Translate back to the tiled coordinates blk.ulx += incx; blk.uly += incy; return(blk); }
/// <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, 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; }
/// <summary> Conceals decoding errors detected in the last bit-plane. The /// concealement resets the state of the decoded data to what it was before /// the decoding of bit-plane 'bp' started. No more data should be decoded /// after this method is called for this code-block's data to which it is /// applied. /// /// </summary> /// <param name="cblk">The code-block's data /// /// </param> /// <param name="bp">The last decoded bit-plane (which contains errors). /// /// </param> private void conceal(DataBlk cblk, int bp) { int l; // line index int k; // array index int kmax; // 'k' limit int dk; // Value of data[k] int[] data; // the data array int setmask; // Bitmask to set approximation to 1/2 of // known interval on significant data int resetmask; // Bitmask to erase all the data from // bit-plane 'bp' // Initialize masks setmask = 1 << bp; resetmask = (- 1) << (bp); // Get the data array data = (int[]) cblk.Data; // Visit each sample, apply the reset mask to it and add an // approximation if significant. for (l = cblk.h - 1, k = cblk.offset; l >= 0; l--) { for (kmax = k + cblk.w; k < kmax; k++) { dk = data[k]; if ((dk & resetmask & 0x7FFFFFFF) != 0) { // Something was decoded in previous bit-planes => set the // approximation for previous bit-plane data[k] = (dk & resetmask) | setmask; } else { // Was insignificant in previous bit-planes = set to zero data[k] = 0; } } k += cblk.scanw - cblk.w; } }
/// <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; // 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); } } }
/// <summary> Returns, in the blk argument, a block of image data containing the /// specifed rectangular area, in the specified component, using the /// 'transfer type' specified in the block given as argument. 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>This method, in general, is less efficient than the /// 'getInternCompData()' method since, in general, it copies the /// data. However if the array of returned data is to be modified by the /// caller then this method is preferable. /// /// <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 may have its 'progressive' attribute set. In this /// case the returned data is only an approximation of the "final" data. /// /// </summary> /// <param name="blk">Its coordinates and dimensions specify the area to return, /// relative to the current tile. If it contains a non-null data array, /// then it must be large enough. If it contains a null data array a new /// one is created. 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. /// /// </param> /// <seealso cref="getInternCompData"> /// /// </seealso> public virtual DataBlk getCompData(DataBlk blk, int c) { return getData(blk, c, false); }
/// <summary> Implements the 'getInternCompData()' and the 'getCompData()' /// methods. The 'intern' flag signals which of the two methods should run /// as. /// /// </summary> /// <param name="blk">The data block to get. /// /// </param> /// <param name="c">The index of the component from which to get the data. /// /// </param> /// <param name="intern">If true behave as 'getInternCompData(). Otherwise behave /// as 'getCompData()' /// /// </param> /// <returns> The requested data block /// /// </returns> /// <seealso cref="getInternCompData"> /// /// </seealso> /// <seealso cref="getCompData"> /// /// </seealso> private DataBlk getData(DataBlk blk, int c, bool intern) { DataBlk reqBlk; // Reference to block used in request to source // Keep request data type int otype = blk.DataType; if (otype == srcBlk.DataType) { // Probably requested type is same as source type reqBlk = blk; } else { // Probably requested type is not the same as source type reqBlk = srcBlk; // We need to copy requested coordinates and size reqBlk.ulx = blk.ulx; reqBlk.uly = blk.uly; reqBlk.w = blk.w; reqBlk.h = blk.h; } // Get source data block if (intern) { // We can use the intern variant srcBlk = src.getInternCompData(reqBlk, c); } else { // Do not use the intern variant. Note that this is not optimal // since if we are going to convert below then we could have used // the intern variant. But there is currently no way to know if we // will need to do conversion or not before getting the data. srcBlk = src.getCompData(reqBlk, c); } // Check if casting is needed if (srcBlk.DataType == otype) { return srcBlk; } int i; int k, kSrc, kmin; float mult; int w = srcBlk.w; int h = srcBlk.h; switch (otype) { case DataBlk.TYPE_FLOAT: // Cast INT -> FLOAT float[] farr; int[] srcIArr; // Get data array from resulting blk farr = (float[]) blk.Data; if (farr == null || farr.Length < w * h) { farr = new float[w * h]; blk.Data = farr; } blk.scanw = srcBlk.w; blk.offset = 0; blk.progressive = srcBlk.progressive; srcIArr = (int[]) srcBlk.Data; // Cast data from source to blk fp = src.getFixedPoint(c); if (fp != 0) { mult = 1.0f / (1 << fp); for (i = h - 1, k = w * h - 1, kSrc = srcBlk.offset + (h - 1) * srcBlk.scanw + w - 1; i >= 0; i--) { for (kmin = k - w; k > kmin; k--, kSrc--) { farr[k] = ((srcIArr[kSrc] * mult)); } // Jump to geggining of next line in source kSrc -= (srcBlk.scanw - w); } } else { for (i = h - 1, k = w * h - 1, kSrc = srcBlk.offset + (h - 1) * srcBlk.scanw + w - 1; i >= 0; i--) { for (kmin = k - w; k > kmin; k--, kSrc--) { //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'" farr[k] = ((float) (srcIArr[kSrc])); } // Jump to geggining of next line in source kSrc -= (srcBlk.scanw - w); } } break; // End of cast INT-> FLOAT case DataBlk.TYPE_INT: // cast FLOAT -> INT int[] iarr; float[] srcFArr; // Get data array from resulting blk iarr = (int[]) blk.Data; if (iarr == null || iarr.Length < w * h) { iarr = new int[w * h]; blk.Data = iarr; } blk.scanw = srcBlk.w; blk.offset = 0; blk.progressive = srcBlk.progressive; srcFArr = (float[]) srcBlk.Data; // Cast data from source to blk if (fp != 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'" mult = (float) (1 << fp); for (i = h - 1, k = w * h - 1, kSrc = srcBlk.offset + (h - 1) * srcBlk.scanw + w - 1; i >= 0; i--) { for (kmin = k - w; k > kmin; k--, kSrc--) { if (srcFArr[kSrc] > 0.0f) { //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'" iarr[k] = (int) (srcFArr[kSrc] * mult + 0.5f); } 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'" iarr[k] = (int) (srcFArr[kSrc] * mult - 0.5f); } } // Jump to geggining of next line in source kSrc -= (srcBlk.scanw - w); } } else { for (i = h - 1, k = w * h - 1, kSrc = srcBlk.offset + (h - 1) * srcBlk.scanw + w - 1; i >= 0; i--) { for (kmin = k - w; k > kmin; k--, kSrc--) { if (srcFArr[kSrc] > 0.0f) { //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'" iarr[k] = (int) (srcFArr[kSrc] + 0.5f); } 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'" iarr[k] = (int) (srcFArr[kSrc] - 0.5f); } } // Jump to geggining of next line in source kSrc -= (srcBlk.scanw - w); } } break; // End cast FLOAT -> INT default: throw new System.ArgumentException("Only integer and float data " + "are " + "supported by JJ2000"); } return blk; }
/// <summary> Apply the component transformation associated with the current tile. If /// no component transformation has been requested by the user, data are /// not modified. Else, appropriate method is called (forwRCT or forwICT). /// /// </summary> /// <seealso cref="forwRCT"> /// /// </seealso> /// <seealso cref="forwICT"> /// /// </seealso> /// <param name="blk">Determines the rectangular area to return. /// /// </param> /// <param name="c">Index of the output component. /// /// </param> /// <returns> The requested DataBlk /// /// </returns> public virtual DataBlk getInternCompData(DataBlk blk, int c) { switch (transfType) { case NONE: return src.getInternCompData(blk, c); case FORW_RCT: return forwRCT(blk, c); case FORW_ICT: return forwICT(blk, c); default: throw new System.ArgumentException("Non JPEG 2000 part 1 " + "component" + " transformation for tile: " + tIdx); } }
/// <summary> Performs the forward wavelet transform on the whole band. It /// iteratively decomposes the subbands from the top node to the leaves. /// /// </summary> /// <param name="band">The band containing the float data to decompose /// /// </param> /// <param name="subband">The structure containing the coordinates of the current /// subband in the whole band to decompose. /// /// </param> /// <param name="c">The index of the current component to decompose /// /// </param> private void waveletTreeDecomposition(DataBlk band, SubbandAn subband, int c) { //If the current subband is a leaf then nothing to be done (a leaf is //not decomposed). if (!subband.isNode) { return ; } else { //Perform the 2D wavelet decomposition of the current subband wavelet2DDecomposition(band, (SubbandAn) subband, c); //Perform the decomposition of the four resulting subbands waveletTreeDecomposition(band, (SubbandAn) subband.HH, c); waveletTreeDecomposition(band, (SubbandAn) subband.LH, c); waveletTreeDecomposition(band, (SubbandAn) subband.HL, c); waveletTreeDecomposition(band, (SubbandAn) subband.LL, c); } }
/// <summary> Returns, in the blk argument, a block of image data containing the /// specifed rectangular area, in the specified component, using the /// 'transfer type' defined in the block given as argument. 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>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 source data and expected data (blk) are using the same type, /// block returned without any modification. If not appropriate cast is /// used. /// /// <P>This method, in general, is more efficient than the 'getCompData()' /// method since it may not copy the data. However if the array of returned /// data is to be modified by the caller then the other method is probably /// preferable. /// /// <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 may have its 'progressive' attribute set. In this /// case the returned data is only an approximation of the "final" data. /// /// </summary> /// <param name="blk">Its coordinates and dimensions specify the area to return, /// relative to the current tile. 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. /// /// </param> /// <returns> The requested DataBlk /// /// </returns> /// <seealso cref="getCompData"> /// /// </seealso> public DataBlk getInternCompData(DataBlk blk, int c) { return(getData(blk, c, true)); }
/// <summary> Implements the 'getInternCompData()' and the 'getCompData()' /// methods. The 'intern' flag signals which of the two methods should run /// as. /// /// </summary> /// <param name="blk">The data block to get. /// /// </param> /// <param name="c">The index of the component from which to get the data. /// /// </param> /// <param name="intern">If true behave as 'getInternCompData(). Otherwise behave /// as 'getCompData()' /// /// </param> /// <returns> The requested data block /// /// </returns> /// <seealso cref="getInternCompData"> /// /// </seealso> /// <seealso cref="getCompData"> /// /// </seealso> private DataBlk getData(DataBlk blk, int c, bool intern) { DataBlk reqBlk; // Reference to block used in request to source // Keep request data type int otype = blk.DataType; if (otype == srcBlk.DataType) { // Probably requested type is same as source type reqBlk = blk; } else { // Probably requested type is not the same as source type reqBlk = srcBlk; // We need to copy requested coordinates and size reqBlk.ulx = blk.ulx; reqBlk.uly = blk.uly; reqBlk.w = blk.w; reqBlk.h = blk.h; } // Get source data block if (intern) { // We can use the intern variant srcBlk = src.getInternCompData(reqBlk, c); } else { // Do not use the intern variant. Note that this is not optimal // since if we are going to convert below then we could have used // the intern variant. But there is currently no way to know if we // will need to do conversion or not before getting the data. srcBlk = src.getCompData(reqBlk, c); } // Check if casting is needed if (srcBlk.DataType == otype) { return(srcBlk); } int i; int k, kSrc, kmin; float mult; int w = srcBlk.w; int h = srcBlk.h; switch (otype) { case DataBlk.TYPE_FLOAT: // Cast INT -> FLOAT float[] farr; int[] srcIArr; // Get data array from resulting blk farr = (float[])blk.Data; if (farr == null || farr.Length < w * h) { farr = new float[w * h]; blk.Data = farr; } blk.scanw = srcBlk.w; blk.offset = 0; blk.progressive = srcBlk.progressive; srcIArr = (int[])srcBlk.Data; // Cast data from source to blk fp = src.getFixedPoint(c); if (fp != 0) { mult = 1.0f / (1 << fp); for (i = h - 1, k = w * h - 1, kSrc = srcBlk.offset + (h - 1) * srcBlk.scanw + w - 1; i >= 0; i--) { for (kmin = k - w; k > kmin; k--, kSrc--) { farr[k] = ((srcIArr[kSrc] * mult)); } // Jump to geggining of next line in source kSrc -= (srcBlk.scanw - w); } } else { for (i = h - 1, k = w * h - 1, kSrc = srcBlk.offset + (h - 1) * srcBlk.scanw + w - 1; i >= 0; i--) { for (kmin = k - w; k > kmin; k--, kSrc--) { //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'" farr[k] = ((float)(srcIArr[kSrc])); } // Jump to geggining of next line in source kSrc -= (srcBlk.scanw - w); } } break; // End of cast INT-> FLOAT case DataBlk.TYPE_INT: // cast FLOAT -> INT int[] iarr; float[] srcFArr; // Get data array from resulting blk iarr = (int[])blk.Data; if (iarr == null || iarr.Length < w * h) { iarr = new int[w * h]; blk.Data = iarr; } blk.scanw = srcBlk.w; blk.offset = 0; blk.progressive = srcBlk.progressive; srcFArr = (float[])srcBlk.Data; // Cast data from source to blk if (fp != 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'" mult = (float)(1 << fp); for (i = h - 1, k = w * h - 1, kSrc = srcBlk.offset + (h - 1) * srcBlk.scanw + w - 1; i >= 0; i--) { for (kmin = k - w; k > kmin; k--, kSrc--) { if (srcFArr[kSrc] > 0.0f) { //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'" iarr[k] = (int)(srcFArr[kSrc] * mult + 0.5f); } 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'" iarr[k] = (int)(srcFArr[kSrc] * mult - 0.5f); } } // Jump to geggining of next line in source kSrc -= (srcBlk.scanw - w); } } else { for (i = h - 1, k = w * h - 1, kSrc = srcBlk.offset + (h - 1) * srcBlk.scanw + w - 1; i >= 0; i--) { for (kmin = k - w; k > kmin; k--, kSrc--) { if (srcFArr[kSrc] > 0.0f) { //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'" iarr[k] = (int)(srcFArr[kSrc] + 0.5f); } 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'" iarr[k] = (int)(srcFArr[kSrc] - 0.5f); } } // Jump to geggining of next line in source kSrc -= (srcBlk.scanw - w); } } break; // End cast FLOAT -> INT default: throw new System.ArgumentException("Only integer and float data " + "are " + "supported by JJ2000"); } return(blk); }
/// <summary> Returns, in the blk argument, a block of image data containing the /// specifed rectangular area, in the specified component, using the /// 'transfer type' specified in the block given as argument. 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>This method, in general, is less efficient than the /// 'getInternCompData()' method since, in general, it copies the /// data. However if the array of returned data is to be modified by the /// caller then this method is preferable. /// /// <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 may have its 'progressive' attribute set. In this /// case the returned data is only an approximation of the "final" data. /// /// </summary> /// <param name="blk">Its coordinates and dimensions specify the area to return, /// relative to the current tile. If it contains a non-null data array, /// then it must be large enough. If it contains a null data array a new /// one is created. 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. /// /// </param> /// <seealso cref="getInternCompData"> /// /// </seealso> public virtual DataBlk getCompData(DataBlk blk, int c) { return(getData(blk, c, false)); }
/// <summary> Performs the significance propagation pass on the specified data and /// bit-plane. It decodes all insignificant samples which have, at least, /// one of its immediate eight neighbors already significant, using the ZC /// and SC primitives as needed. It toggles the "visited" state bit to 1 /// for all those samples. /// /// <p>This method also checks for segmentation markers if those are /// present and returns true if an error is detected, or false /// otherwise. If an error is detected it means that the bit stream /// contains some erroneous bit that have led to the decoding of incorrect /// data. This data affects the whole last decoded bit-plane /// (i.e. 'bp'). If 'true' is returned the 'conceal' method should be /// called and no more passes should be decoded for this code-block's bit /// stream.</p> /// /// </summary> /// <param name="cblk">The code-block data to decode /// /// </param> /// <param name="mq">The MQ-coder to use /// /// </param> /// <param name="bp">The bit-plane to decode /// /// </param> /// <param name="state">The state information for the code-block /// /// </param> /// <param name="zc_lut">The ZC lookup table to use in ZC. /// /// </param> /// <param name="isterm">If this pass has been terminated. If the pass has been /// terminated it can be used to check error resilience. /// /// </param> /// <returns> True if an error was detected in the bit stream, false /// otherwise. /// /// </returns> private bool sigProgPass(DataBlk cblk, MQDecoder mq, int bp, int[] state, int[] zc_lut, bool isterm) { int j, sj; // The state index for line and stripe int k, sk; // The data index for line and stripe int dscanw; // The data scan-width int sscanw; // The state scan-width int jstep; // Stripe to stripe step for 'sj' int kstep; // Stripe to stripe step for 'sk' int stopsk; // The loop limit on the variable sk int csj; // Local copy (i.e. cached) of 'state[j]' int setmask; // The mask to set current and lower bit-planes to 1/2 // approximation int sym; // The symbol to code int ctxt; // The context to use int[] data; // The data buffer int s; // The stripe index bool causal; // Flag to indicate if stripe-causal context // formation is to be used int nstripes; // The number of stripes in the code-block int sheight; // Height of the current stripe int off_ul, off_ur, off_dr, off_dl; // offsets bool error; // The error condition // Initialize local variables dscanw = cblk.scanw; sscanw = cblk.w + 2; jstep = sscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT / 2 - cblk.w; kstep = dscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - cblk.w; setmask = (3 << bp) >> 1; data = (int[]) cblk.Data; nstripes = (cblk.h + CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - 1) / CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT; causal = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_VERT_STR_CAUSAL) != 0; // Pre-calculate offsets in 'state' for diagonal neighbors off_ul = - sscanw - 1; // up-left off_ur = - sscanw + 1; // up-right off_dr = sscanw + 1; // down-right off_dl = sscanw - 1; // down-left // Decode stripe by stripe sk = cblk.offset; sj = sscanw + 1; for (s = nstripes - 1; s >= 0; s--, sk += kstep, sj += jstep) { sheight = (s != 0)?CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT:cblk.h - (nstripes - 1) * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT; stopsk = sk + cblk.w; // Scan by set of 1 stripe column at a time for (; sk < stopsk; sk++, sj++) { // Do half top of column j = sj; csj = state[j]; // If any of the two samples is not significant and has a // non-zero context (i.e. some neighbor is significant) we can // not skip them if ((((~ csj) & (csj << 2)) & SIG_MASK_R1R2) != 0) { k = sk; // Scan first row if ((csj & (STATE_SIG_R1 | STATE_NZ_CTXT_R1)) == STATE_NZ_CTXT_R1) { // Use zero coding if (mq.decodeSymbol(zc_lut[csj & ZC_MASK]) != 0) { // Became significant // Use sign coding ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK]; sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); // Update data data[k] = (sym << 31) | setmask; // Update state information (significant bit, // visited bit, neighbor significant bit of // neighbors, non zero context of neighbors, sign // of neighbors) if (!causal) { // If in causal mode do not change contexts of // previous stripe. state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2; state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2; } // Update sign state information of neighbors if (sym != 0) { csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2; if (!causal) { // If in causal mode do not change // contexts of previous stripe. state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2; } state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2; } else { csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2; if (!causal) { // If in causal mode do not change // contexts of previous stripe. state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2; } state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2; } } else { csj |= STATE_VISITED_R1; } } if (sheight < 2) { state[j] = csj; continue; } // Scan second row if ((csj & (STATE_SIG_R2 | STATE_NZ_CTXT_R2)) == STATE_NZ_CTXT_R2) { k += dscanw; // Use zero coding if (mq.decodeSymbol(zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK]) != 0) { // Became significant // Use sign coding ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK]; sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); // Update data data[k] = (sym << 31) | setmask; // Update state information (significant bit, // visited bit, neighbor significant bit of // neighbors, non zero context of neighbors, sign // of neighbors) state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1; state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1; // Update sign state information of neighbors if (sym != 0) { csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1; state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1; state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2; } else { csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1; state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1; state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2; } } else { csj |= STATE_VISITED_R2; } } state[j] = csj; } // Do half bottom of column if (sheight < 3) continue; j += sscanw; csj = state[j]; // If any of the two samples is not significant and has a // non-zero context (i.e. some neighbor is significant) we can // not skip them if ((((~ csj) & (csj << 2)) & SIG_MASK_R1R2) != 0) { k = sk + (dscanw << 1); // Scan first row if ((csj & (STATE_SIG_R1 | STATE_NZ_CTXT_R1)) == STATE_NZ_CTXT_R1) { // Use zero coding if (mq.decodeSymbol(zc_lut[csj & ZC_MASK]) != 0) { // Became significant // Use sign coding ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK]; sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); // Update data data[k] = (sym << 31) | setmask; // Update state information (significant bit, // visited bit, neighbor significant bit of // neighbors, non zero context of neighbors, sign // of neighbors) state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2; state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2; // Update sign state information of neighbors if (sym != 0) { csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2; state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2; state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2; } else { csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2; state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2; state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2; } } else { csj |= STATE_VISITED_R1; } } if (sheight < 4) { state[j] = csj; continue; } // Scan second row if ((csj & (STATE_SIG_R2 | STATE_NZ_CTXT_R2)) == STATE_NZ_CTXT_R2) { k += dscanw; // Use zero coding if (mq.decodeSymbol(zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK]) != 0) { // Became significant // Use sign coding ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK]; sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); // Update data data[k] = (sym << 31) | setmask; // Update state information (significant bit, // visited bit, neighbor significant bit of // neighbors, non zero context of neighbors, sign // of neighbors) state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1; state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1; // Update sign state information of neighbors if (sym != 0) { csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1; state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1; state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2; } else { csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1; state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1; state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2; } } else { csj |= STATE_VISITED_R2; } } state[j] = csj; } } } error = false; // Check the error resilience termination if (isterm && (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0) { error = mq.checkPredTerm(); } // Reset the MQ context states if we need to if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_RESET_MQ) != 0) { mq.resetCtxts(); } // Return error condition return error; }
/// <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>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>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. /// /// </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 getCodeBlock(int c, int m, int n, SubbandSyn sb, DataBlk cblk) { //long stime = 0L; // Start time for timed sections int[] zc_lut; // The ZC lookup table to use int[] out_data; // The outupt data buffer int npasses; // The number of coding passes to perform int curbp; // The current magnitude bit-plane (starts at 30) bool error; // Error indicator int tslen; // Length of first terminated segment int tsidx; // Index of current terminated segment ByteInputBuffer in_Renamed = null; bool isterm; // Get the code-block to decode srcblk = src.getCodeBlock(c, m, n, sb, 1, - 1, srcblk); #if DO_TIMING stime = (System.DateTime.Now.Ticks - 621355968000000000) / 10000; #endif // Retrieve options from decSpec options = ((System.Int32) decSpec.ecopts.getTileCompVal(tIdx, c)); // Reset state ArrayUtil.intArraySet(state, 0); // Initialize output code-block if (cblk == null) cblk = new DataBlkInt(); cblk.progressive = srcblk.prog; cblk.ulx = srcblk.ulx; cblk.uly = srcblk.uly; cblk.w = srcblk.w; cblk.h = srcblk.h; cblk.offset = 0; cblk.scanw = cblk.w; out_data = (int[]) cblk.Data; if (out_data == null || out_data.Length < srcblk.w * srcblk.h) { out_data = new int[srcblk.w * srcblk.h]; cblk.Data = out_data; } else { // Set data values to 0 ArrayUtil.intArraySet(out_data, 0); } if (srcblk.nl <= 0 || srcblk.nTrunc <= 0) { // 0 layers => no data to decode => return all 0s return cblk; } // Get the length of the first terminated segment tslen = (srcblk.tsLengths == null)?srcblk.dl:srcblk.tsLengths[0]; tsidx = 0; // Initialize for decoding npasses = srcblk.nTrunc; if (mq == null) { in_Renamed = new ByteInputBuffer(srcblk.data, 0, tslen); mq = new MQDecoder(in_Renamed, NUM_CTXTS, MQ_INIT); } else { // We always start by an MQ segment mq.nextSegment(srcblk.data, 0, tslen); mq.resetCtxts(); } error = false; if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0) { if (bin == null) { if (in_Renamed == null) in_Renamed = mq.ByteInputBuffer; bin = new ByteToBitInput(in_Renamed); } } // Choose correct ZC lookup table for global orientation switch (sb.orientation) { case Subband.WT_ORIENT_HL: zc_lut = ZC_LUT_HL; break; case Subband.WT_ORIENT_LH: case Subband.WT_ORIENT_LL: zc_lut = ZC_LUT_LH; break; case Subband.WT_ORIENT_HH: zc_lut = ZC_LUT_HH; break; default: throw new System.ApplicationException("JJ2000 internal error"); } // NOTE: we don't currently detect which is the last magnitude // bit-plane so that 'isterm' is true for the last pass of it. Doing // so would aid marginally in error detection with the predictable // error resilient MQ termination. However, determining which is the // last magnitude bit-plane is quite hard (due to ROI, quantization, // etc.) and in any case the predictable error resilient termination // used without the arithmetic coding bypass and/or regular // termination modes is almost useless. // Loop on bit-planes and passes curbp = 30 - srcblk.skipMSBP; // Check for maximum number of bitplanes quit condition if (mQuit != - 1 && (mQuit * 3 - 2) < npasses) { npasses = mQuit * 3 - 2; } // First bit-plane has only the cleanup pass if (curbp >= 0 && npasses > 0) { isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP) >= curbp); error = cleanuppass(cblk, mq, curbp, state, zc_lut, isterm); npasses--; if (!error || !doer) curbp--; } // Other bit-planes have the three coding passes if (!error || !doer) { while (curbp >= 0 && npasses > 0) { if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (curbp < 31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP)) { // Use bypass decoding mode (only all bit-planes // after the first 4 bit-planes). // Here starts a new raw segment bin.setByteArray(null, - 1, srcblk.tsLengths[++tsidx]); isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0; error = rawSigProgPass(cblk, bin, curbp, state, isterm); npasses--; if (npasses <= 0 || (error && doer)) break; if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0) { // Start a new raw segment bin.setByteArray(null, - 1, srcblk.tsLengths[++tsidx]); } isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP > curbp)); error = rawMagRefPass(cblk, bin, curbp, state, isterm); } else { // Do not use bypass decoding mode if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0) { // Here starts a new MQ segment mq.nextSegment(null, - 1, srcblk.tsLengths[++tsidx]); } isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0; error = sigProgPass(cblk, mq, curbp, state, zc_lut, isterm); npasses--; if (npasses <= 0 || (error && doer)) break; if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0) { // Here starts a new MQ segment mq.nextSegment(null, - 1, srcblk.tsLengths[++tsidx]); } isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP > curbp)); error = magRefPass(cblk, mq, curbp, state, isterm); } npasses--; if (npasses <= 0 || (error && doer)) break; if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (curbp < 31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP))) { // Here starts a new MQ segment mq.nextSegment(null, - 1, srcblk.tsLengths[++tsidx]); } isterm = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_TERM_PASS) != 0 || ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_BYPASS) != 0 && (31 - CSJ2K.j2k.entropy.StdEntropyCoderOptions.NUM_NON_BYPASS_MS_BP - srcblk.skipMSBP) >= curbp); error = cleanuppass(cblk, mq, curbp, state, zc_lut, isterm); npasses--; if (error && doer) break; // Goto next bit-plane curbp--; } } // If an error ocurred conceal it if (error && doer) { if (verber) { FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.WARNING, "Error detected at bit-plane " + curbp + " in code-block (" + m + "," + n + "), sb_idx " + sb.sbandIdx + ", res. level " + sb.resLvl + ". Concealing..."); } conceal(cblk, curbp); } #if DO_TIMING time[c] += (System.DateTime.Now.Ticks - 621355968000000000) / 10000 - stime; #endif // Return decoded block return cblk; }
/// <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>This method just calls 'getInternCompData(blk, n)'. /// /// <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 /// is valid. /// /// </param> /// <returns> The requested DataBlk /// /// </returns> /// <seealso cref="getInternCompData"> /// /// </seealso> /// <seealso cref="JJ2KExceptionHandler"> /// /// </seealso> public override DataBlk getCompData(DataBlk blk, int c) { return getInternCompData(blk, c); }
/// <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; }
/// <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>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>This method, in general, is less efficient than the /// 'getInternCompData()' method since, in general, it copies the /// data. However if the array of returned data is to be modified by the /// caller then this method is preferable. /// /// <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 may have its 'progressive' attribute set. In this /// case the returned data is only an approximation of the "final" data. /// /// </summary> /// <param name="blk">Its coordinates and dimensions specify the area to return, /// relative to the current tile. If it contains a non-null data array, /// then it must be large enough. If it contains a null data array a new /// one is created. 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. /// /// </param> /// <returns> The requested DataBlk /// /// </returns> /// <seealso cref="getInternCompData"> /// /// </seealso> public virtual DataBlk getCompData(DataBlk blk, int c) { return(imageData[c].getCompData(blk, compIdx[c])); }
/// <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; }
/// <summary> Performs the 2D forward wavelet transform on a subband of the initial /// band. This method will successively perform 1D filtering steps on all /// lines and then all columns of the subband. In this class only filters /// with floating point implementations can be used. /// /// </summary> /// <param name="band">The band containing the float data to decompose /// /// </param> /// <param name="subband">The structure containing the coordinates of the subband /// in the whole band to decompose. /// /// </param> /// <param name="c">The index of the current component to decompose /// /// </param> private void wavelet2DDecomposition(DataBlk band, SubbandAn subband, int c) { int ulx, uly, w, h; int band_w, band_h; // If subband is empty (i.e. zero size) nothing to do if (subband.w == 0 || subband.h == 0) { return ; } ulx = subband.ulx; uly = subband.uly; w = subband.w; h = subband.h; band_w = getTileCompWidth(tIdx, c); band_h = getTileCompHeight(tIdx, c); if (intData) { //Perform the decompositions if the filter is implemented with an //integer arithmetic. int i, j; int offset; int[] tmpVector = new int[System.Math.Max(w, h)]; int[] data = ((DataBlkInt) band).DataInt; //Perform the vertical decomposition if (subband.ulcy % 2 == 0) { // Even start index => use LPF for (j = 0; j < w; j++) { offset = uly * band_w + ulx + j; for (i = 0; i < h; i++) tmpVector[i] = data[offset + (i * band_w)]; subband.vFilter.analyze_lpf(tmpVector, 0, h, 1, data, offset, band_w, data, offset + ((h + 1) / 2) * band_w, band_w); } } else { // Odd start index => use HPF for (j = 0; j < w; j++) { offset = uly * band_w + ulx + j; for (i = 0; i < h; i++) tmpVector[i] = data[offset + (i * band_w)]; subband.vFilter.analyze_hpf(tmpVector, 0, h, 1, data, offset, band_w, data, offset + (h / 2) * band_w, band_w); } } //Perform the horizontal decomposition. if (subband.ulcx % 2 == 0) { // Even start index => use LPF for (i = 0; i < h; i++) { offset = (uly + i) * band_w + ulx; for (j = 0; j < w; j++) tmpVector[j] = data[offset + j]; subband.hFilter.analyze_lpf(tmpVector, 0, w, 1, data, offset, 1, data, offset + (w + 1) / 2, 1); } } else { // Odd start index => use HPF for (i = 0; i < h; i++) { offset = (uly + i) * band_w + ulx; for (j = 0; j < w; j++) tmpVector[j] = data[offset + j]; subband.hFilter.analyze_hpf(tmpVector, 0, w, 1, data, offset, 1, data, offset + w / 2, 1); } } } else { //Perform the decompositions if the filter is implemented with a //float arithmetic. int i, j; int offset; float[] tmpVector = new float[System.Math.Max(w, h)]; float[] data = ((DataBlkFloat) band).DataFloat; //Perform the vertical decomposition. if (subband.ulcy % 2 == 0) { // Even start index => use LPF for (j = 0; j < w; j++) { offset = uly * band_w + ulx + j; for (i = 0; i < h; i++) tmpVector[i] = data[offset + (i * band_w)]; subband.vFilter.analyze_lpf(tmpVector, 0, h, 1, data, offset, band_w, data, offset + ((h + 1) / 2) * band_w, band_w); } } else { // Odd start index => use HPF for (j = 0; j < w; j++) { offset = uly * band_w + ulx + j; for (i = 0; i < h; i++) tmpVector[i] = data[offset + (i * band_w)]; subband.vFilter.analyze_hpf(tmpVector, 0, h, 1, data, offset, band_w, data, offset + (h / 2) * band_w, band_w); } } //Perform the horizontal decomposition. if (subband.ulcx % 2 == 0) { // Even start index => use LPF for (i = 0; i < h; i++) { offset = (uly + i) * band_w + ulx; for (j = 0; j < w; j++) tmpVector[j] = data[offset + j]; subband.hFilter.analyze_lpf(tmpVector, 0, w, 1, data, offset, 1, data, offset + (w + 1) / 2, 1); } } else { // Odd start index => use HPF for (i = 0; i < h; i++) { offset = (uly + i) * band_w + ulx; for (j = 0; j < w; j++) tmpVector[j] = data[offset + j]; subband.hFilter.analyze_hpf(tmpVector, 0, w, 1, data, offset, 1, data, offset + w / 2, 1); } } } }
public DataBlk getInternCompData(DataBlk blk, int c) { if (c < 0 || c >= this.nc) { throw new ArgumentOutOfRangeException("c"); } var data = new int[blk.w * blk.h]; for (int y = blk.uly, k = 0; y < blk.uly + blk.h; ++y) { for (int x = blk.ulx, xy = blk.uly * this.w + blk.ulx; x < blk.ulx + blk.w; ++x, ++k, ++xy) { data[k] = this.comps[c][xy]; } } blk.offset = 0; blk.scanw = blk.w; blk.progressive = false; blk.Data = data; return blk; }
/// <summary> Returns, in the blk argument, a block of image data containing the /// specifed rectangular area, in the specified component, using the /// 'transfer type' defined in the block given as argument. 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>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 source data and expected data (blk) are using the same type, /// block returned without any modification. If not appropriate cast is /// used. /// /// <P>This method, in general, is more efficient than the 'getCompData()' /// method since it may not copy the data. However if the array of returned /// data is to be modified by the caller then the other method is probably /// preferable. /// /// <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 may have its 'progressive' attribute set. In this /// case the returned data is only an approximation of the "final" data. /// /// </summary> /// <param name="blk">Its coordinates and dimensions specify the area to return, /// relative to the current tile. 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. /// /// </param> /// <returns> The requested DataBlk /// /// </returns> /// <seealso cref="getCompData"> /// /// </seealso> public DataBlk getInternCompData(DataBlk blk, int c) { return getData(blk, c, true); }
/// <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 (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; }
public DataBlk getCompData(DataBlk blk, int c) { var newBlk = new DataBlkInt(blk.ulx, blk.uly, blk.w, blk.h); return this.getInternCompData(newBlk, c); }
/// <summary> Performs the cleanup pass on the specified data and bit-plane. It /// decodes all insignificant samples which have its "visited" state bit /// off, using the ZC, SC, and RLC primitives. It toggles the "visited" /// state bit to 0 (off) for all samples in the code-block. /// /// <P>This method also checks for segmentation markers if those are /// present and returns true if an error is detected, or false /// otherwise. If an error is detected it measn that the bit stream /// contains some erroneous bit that have led to the decoding of incorrect /// data. This data affects the whole last decoded bit-plane /// (i.e. 'bp'). If 'true' is returned the 'conceal' method should be /// called and no more passes should be decoded for this code-block's bit /// stream. /// /// </summary> /// <param name="cblk">The code-block data to code /// /// </param> /// <param name="mq">The MQ-coder to use /// /// </param> /// <param name="bp">The bit-plane to decode /// /// </param> /// <param name="state">The state information for the code-block /// /// </param> /// <param name="zc_lut">The ZC lookup table to use in ZC. /// /// </param> /// <param name="isterm">If this pass has been terminated. If the pass has been /// terminated it can be used to check error resilience. /// /// </param> /// <returns> True if an error was detected in the bit stream, false /// otherwise. /// /// </returns> private bool cleanuppass(DataBlk cblk, MQDecoder mq, int bp, int[] state, int[] zc_lut, bool isterm) { int j, sj; // The state index for line and stripe int k, sk; // The data index for line and stripe int dscanw; // The data scan-width int sscanw; // The state scan-width int jstep; // Stripe to stripe step for 'sj' int kstep; // Stripe to stripe step for 'sk' int stopsk; // The loop limit on the variable sk int csj; // Local copy (i.e. cached) of 'state[j]' int setmask; // The mask to set current and lower bit-planes to 1/2 // approximation int sym; // The decoded symbol int rlclen; // Length of RLC int ctxt; // The context to use int[] data; // The data buffer int s; // The stripe index bool causal; // Flag to indicate if stripe-causal context // formation is to be used int nstripes; // The number of stripes in the code-block int sheight; // Height of the current stripe int off_ul, off_ur, off_dr, off_dl; // offsets bool error; // The error condition // Initialize local variables dscanw = cblk.scanw; sscanw = cblk.w + 2; jstep = sscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT / 2 - cblk.w; kstep = dscanw * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - cblk.w; setmask = (3 << bp) >> 1; data = (int[]) cblk.Data; nstripes = (cblk.h + CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT - 1) / CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT; causal = (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_VERT_STR_CAUSAL) != 0; // Pre-calculate offsets in 'state' for diagonal neighbors off_ul = - sscanw - 1; // up-left off_ur = - sscanw + 1; // up-right off_dr = sscanw + 1; // down-right off_dl = sscanw - 1; // down-left // Decode stripe by stripe sk = cblk.offset; sj = sscanw + 1; for (s = nstripes - 1; s >= 0; s--, sk += kstep, sj += jstep) { sheight = (s != 0)?CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT:cblk.h - (nstripes - 1) * CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT; stopsk = sk + cblk.w; // Scan by set of 1 stripe column at a time for (; sk < stopsk; sk++, sj++) { // Start column j = sj; csj = state[j]; { // Check for RLC: if all samples are not significant, not // visited and do not have a non-zero context, and column // is full height, we do RLC. if (csj == 0 && state[j + sscanw] == 0 && sheight == CSJ2K.j2k.entropy.StdEntropyCoderOptions.STRIPE_HEIGHT) { if (mq.decodeSymbol(RLC_CTXT) != 0) { // run-length is significant, decode length rlclen = mq.decodeSymbol(UNIF_CTXT) << 1; rlclen |= mq.decodeSymbol(UNIF_CTXT); // Set 'k' and 'j' accordingly k = sk + rlclen * dscanw; if (rlclen > 1) { j += sscanw; csj = state[j]; } } else { // RLC is insignificant // Goto next column continue; } // We just decoded the length of a significant RLC // and a sample became significant // Use sign coding if ((rlclen & 0x01) == 0) { // Sample that became significant is first row of // its column half ctxt = SC_LUT[(csj >> SC_SHIFT_R1) & SC_MASK]; sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); // Update the data data[k] = (sym << 31) | setmask; // Update state information (significant bit, // visited bit, neighbor significant bit of // neighbors, non zero context of neighbors, sign // of neighbors) if (rlclen != 0 || !causal) { // If in causal mode do not change // contexts of previous stripe. state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2; state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2; } // Update sign state information of neighbors if (sym != 0) { csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2; if (rlclen != 0 || !causal) { // If in causal mode do not change // contexts of previous stripe. state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2; } state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2; } else { csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2; if (rlclen != 0 || !causal) { // If in causal mode do not change // contexts of previous stripe. state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2; } state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2; } // Changes to csj are saved later if ((rlclen >> 1) != 0) { // Sample that became significant is in // bottom half of column => jump to bottom // half //UPGRADE_NOTE: Labeled break statement was changed to a goto statement. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1012'" goto top_half_brk; } // Otherwise sample that became significant is in // top half of column => continue on top half } else { // Sample that became significant is second row of // its column half ctxt = SC_LUT[(csj >> SC_SHIFT_R2) & SC_MASK]; sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); // Update the data data[k] = (sym << 31) | setmask; // Update state information (significant bit, // neighbor significant bit of neighbors, non zero // context of neighbors, sign of neighbors) state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1; state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1; // Update sign state information of neighbors if (sym != 0) { csj |= STATE_SIG_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1; state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1; state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2; } else { csj |= STATE_SIG_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1; state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1; state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2; } // Save changes to csj state[j] = csj; if ((rlclen >> 1) != 0) { // Sample that became significant is in bottom // half of column => we're done with this // column continue; } // Otherwise sample that became significant is in // top half of column => we're done with top // column j += sscanw; csj = state[j]; //UPGRADE_NOTE: Labeled break statement was changed to a goto statement. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1012'" goto top_half_brk; } } // Do half top of column // If any of the two samples is not significant and has // not been visited in the current bit-plane we can not // skip them if ((((csj >> 1) | csj) & VSTD_MASK_R1R2) != VSTD_MASK_R1R2) { k = sk; // Scan first row if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == 0) { // Use zero coding if (mq.decodeSymbol(zc_lut[csj & ZC_MASK]) != 0) { // Became significant // Use sign coding ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R1)) & SC_MASK]; sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); // Update the data data[k] = (sym << 31) | setmask; // Update state information (significant bit, // visited bit, neighbor significant bit of // neighbors, non zero context of neighbors, // sign of neighbors) if (!causal) { // If in causal mode do not change // contexts of previous stripe. state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2; state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2; } // Update sign state information of neighbors if (sym != 0) { csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2; if (!causal) { // If in causal mode do not change // contexts of previous stripe. state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2; } state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2; } else { csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2; if (!causal) { // If in causal mode do not change // contexts of previous stripe. state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2; } state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2; } } } if (sheight < 2) { csj &= ~ (STATE_VISITED_R1 | STATE_VISITED_R2); state[j] = csj; continue; } // Scan second row if ((csj & (STATE_SIG_R2 | STATE_VISITED_R2)) == 0) { k += dscanw; // Use zero coding if (mq.decodeSymbol(zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK]) != 0) { // Became significant // Use sign coding ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK]; sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); // Update the data data[k] = (sym << 31) | setmask; // Update state information (significant bit, // visited bit, neighbor significant bit of // neighbors, non zero context of neighbors, // sign of neighbors) state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1; state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1; // Update sign state information of neighbors if (sym != 0) { csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1; state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1; state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2; } else { csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1; state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1; state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2; } } } } csj &= ~ (STATE_VISITED_R1 | STATE_VISITED_R2); state[j] = csj; // Do half bottom of column if (sheight < 3) continue; j += sscanw; csj = state[j]; } //UPGRADE_NOTE: Label 'top_half_brk' was added. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1011'" top_half_brk: ; // end of 'top_half' block // If any of the two samples is not significant and has // not been visited in the current bit-plane we can not // skip them if ((((csj >> 1) | csj) & VSTD_MASK_R1R2) != VSTD_MASK_R1R2) { k = sk + (dscanw << 1); // Scan first row if ((csj & (STATE_SIG_R1 | STATE_VISITED_R1)) == 0) { // Use zero coding if (mq.decodeSymbol(zc_lut[csj & ZC_MASK]) != 0) { // Became significant // Use sign coding ctxt = SC_LUT[(csj >> SC_SHIFT_R1) & SC_MASK]; sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); // Update the data data[k] = (sym << 31) | setmask; // Update state information (significant bit, // visited bit, neighbor significant bit of // neighbors, non zero context of neighbors, // sign of neighbors) state[j + off_ul] |= STATE_NZ_CTXT_R2 | STATE_D_DR_R2; state[j + off_ur] |= STATE_NZ_CTXT_R2 | STATE_D_DL_R2; // Update sign state information of neighbors if (sym != 0) { csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2 | STATE_V_U_SIGN_R2; state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2 | STATE_V_D_SIGN_R2; state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_H_L_SIGN_R1 | STATE_D_UL_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_H_R_SIGN_R1 | STATE_D_UR_R2; } else { csj |= STATE_SIG_R1 | STATE_VISITED_R1 | STATE_NZ_CTXT_R2 | STATE_V_U_R2; state[j - sscanw] |= STATE_NZ_CTXT_R2 | STATE_V_D_R2; state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_L_R1 | STATE_D_UL_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_H_R_R1 | STATE_D_UR_R2; } } } if (sheight < 4) { csj &= ~ (STATE_VISITED_R1 | STATE_VISITED_R2); state[j] = csj; continue; } // Scan second row if ((csj & (STATE_SIG_R2 | STATE_VISITED_R2)) == 0) { k += dscanw; // Use zero coding if (mq.decodeSymbol(zc_lut[(SupportClass.URShift(csj, STATE_SEP)) & ZC_MASK]) != 0) { // Became significant // Use sign coding ctxt = SC_LUT[(SupportClass.URShift(csj, SC_SHIFT_R2)) & SC_MASK]; sym = mq.decodeSymbol(ctxt & SC_LUT_MASK) ^ (SupportClass.URShift(ctxt, SC_SPRED_SHIFT)); // Update the data data[k] = (sym << 31) | setmask; // Update state information (significant bit, // visited bit, neighbor significant bit of // neighbors, non zero context of neighbors, // sign of neighbors) state[j + off_dl] |= STATE_NZ_CTXT_R1 | STATE_D_UR_R1; state[j + off_dr] |= STATE_NZ_CTXT_R1 | STATE_D_UL_R1; // Update sign state information of neighbors if (sym != 0) { csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1 | STATE_V_D_SIGN_R1; state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1 | STATE_V_U_SIGN_R1; state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2 | STATE_H_L_SIGN_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2 | STATE_H_R_SIGN_R2; } else { csj |= STATE_SIG_R2 | STATE_VISITED_R2 | STATE_NZ_CTXT_R1 | STATE_V_D_R1; state[j + sscanw] |= STATE_NZ_CTXT_R1 | STATE_V_U_R1; state[j + 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DL_R1 | STATE_H_L_R2; state[j - 1] |= STATE_NZ_CTXT_R1 | STATE_NZ_CTXT_R2 | STATE_D_DR_R1 | STATE_H_R_R2; } } } } csj &= ~ (STATE_VISITED_R1 | STATE_VISITED_R2); state[j] = csj; } } // Decode segment symbol if we need to if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_SEG_SYMBOLS) != 0) { sym = mq.decodeSymbol(UNIF_CTXT) << 3; sym |= mq.decodeSymbol(UNIF_CTXT) << 2; sym |= mq.decodeSymbol(UNIF_CTXT) << 1; sym |= mq.decodeSymbol(UNIF_CTXT); // Set error condition accordingly error = sym != SEG_SYMBOL; } else { // We can not detect any errors error = false; } // Check the error resilience termination if (isterm && (options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_PRED_TERM) != 0) { error = mq.checkPredTerm(); } // Reset the MQ context states if we need to if ((options & CSJ2K.j2k.entropy.StdEntropyCoderOptions.OPT_RESET_MQ) != 0) { mq.resetCtxts(); } // Return error condition return error; }
/// <summary> Returns a block of image data containing the specifed rectangular area, /// in the specified component, as a copy (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 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 block's width. See the 'DataBlk' /// class.</p> /// /// <p>If the data array in 'blk' is <tt>null</tt>, then a new one is /// created. If the data array is not <tt>null</tt> then it must be big /// enough to contain the requested area.</p> /// /// <p>The returned data always has its 'progressive' attribute unset (i.e /// false)</p> /// /// </summary> /// <param name="blk">Its coordinates and dimensions specify the area to /// return. If it contains a non-null data array, then it must be large /// enough. 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. /// /// </param> /// <returns> The requested DataBlk /// /// </returns> /// <seealso cref="getCompData"> /// /// </seealso> public override DataBlk getCompData(DataBlk blk, int c) { //int j; System.Object dst_data; // src_data removed int[] dst_data_int; // src_data_int removed float[] dst_data_float; // src_data_float removed // To keep compiler happy dst_data = null; // Ensure output buffer switch (blk.DataType) { case DataBlk.TYPE_INT: dst_data_int = (int[]) blk.Data; if (dst_data_int == null || dst_data_int.Length < blk.w * blk.h) { dst_data_int = new int[blk.w * blk.h]; } dst_data = dst_data_int; break; case DataBlk.TYPE_FLOAT: dst_data_float = (float[]) blk.Data; if (dst_data_float == null || dst_data_float.Length < blk.w * blk.h) { dst_data_float = new float[blk.w * blk.h]; } dst_data = dst_data_float; break; } // Use getInternCompData() to get the data, since getInternCompData() // returns reference to internal buffer, we must copy it. blk = getInternCompData(blk, c); // Copy the data blk.Data = dst_data; 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; }
/// <summary> Performs the 2D inverse wavelet transform on a subband of the image, on /// the specified component. This method will successively perform 1D /// filtering steps on all columns and then all lines of the subband. /// /// </summary> /// <param name="db">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 wavelet2DReconstruction(DataBlk db, SubbandSyn sb, int c) { System.Object data; System.Object buf; int ulx, uly, w, h; int i, j, k; int offset; // If subband is empty (i.e. zero size) nothing to do if (sb.w == 0 || sb.h == 0) { return ; } data = db.Data; ulx = sb.ulx; uly = sb.uly; w = sb.w; h = sb.h; buf = null; // To keep compiler happy switch (sb.HorWFilter.DataType) { case DataBlk.TYPE_INT: buf = new int[(w >= h)?w:h]; break; case DataBlk.TYPE_FLOAT: buf = new float[(w >= h)?w:h]; break; } //Perform the horizontal reconstruction offset = (uly - db.uly) * db.w + ulx - db.ulx; if (sb.ulcx % 2 == 0) { // start index is even => use LPF for (i = 0; i < h; i++, offset += db.w) { // CONVERSION PROBLEM? Array.Copy((System.Array)data, offset, (System.Array)buf, 0, w); sb.hFilter.synthetize_lpf(buf, 0, (w + 1) / 2, 1, buf, (w + 1) / 2, w / 2, 1, data, offset, 1); } } else { // start index is odd => use HPF for (i = 0; i < h; i++, offset += db.w) { // CONVERSION PROBLEM? Array.Copy((System.Array)data, offset, (System.Array)buf, 0, w); sb.hFilter.synthetize_hpf(buf, 0, w / 2, 1, buf, w / 2, (w + 1) / 2, 1, data, offset, 1); } } //Perform the vertical reconstruction offset = (uly - db.uly) * db.w + ulx - db.ulx; switch (sb.VerWFilter.DataType) { case DataBlk.TYPE_INT: int[] data_int, buf_int; data_int = (int[]) data; buf_int = (int[]) buf; if (sb.ulcy % 2 == 0) { // start index is even => use LPF for (j = 0; j < w; j++, offset++) { for (i = h - 1, k = offset + i * db.w; i >= 0; i--, k -= db.w) buf_int[i] = data_int[k]; sb.vFilter.synthetize_lpf(buf, 0, (h + 1) / 2, 1, buf, (h + 1) / 2, h / 2, 1, data, offset, db.w); } } else { // start index is odd => use HPF for (j = 0; j < w; j++, offset++) { for (i = h - 1, k = offset + i * db.w; i >= 0; i--, k -= db.w) buf_int[i] = data_int[k]; sb.vFilter.synthetize_hpf(buf, 0, h / 2, 1, buf, h / 2, (h + 1) / 2, 1, data, offset, db.w); } } break; case DataBlk.TYPE_FLOAT: float[] data_float, buf_float; data_float = (float[]) data; buf_float = (float[]) buf; if (sb.ulcy % 2 == 0) { // start index is even => use LPF for (j = 0; j < w; j++, offset++) { for (i = h - 1, k = offset + i * db.w; i >= 0; i--, k -= db.w) buf_float[i] = data_float[k]; sb.vFilter.synthetize_lpf(buf, 0, (h + 1) / 2, 1, buf, (h + 1) / 2, h / 2, 1, data, offset, db.w); } } else { // start index is odd => use HPF for (j = 0; j < w; j++, offset++) { for (i = h - 1, k = offset + i * db.w; i >= 0; i--, k -= db.w) buf_float[i] = data_float[k]; sb.vFilter.synthetize_hpf(buf, 0, h / 2, 1, buf, h / 2, (h + 1) / 2, 1, data, offset, db.w); } } break; } }
public abstract CSJ2K.j2k.image.DataBlk getCompData(CSJ2K.j2k.image.DataBlk param1, int param2);
/// <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> Apply inverse component transformation associated with the current /// tile. If no component transformation has been requested by the user, /// data are not modified. /// /// <P>This method calls the getInternCompData() method, but respects the /// definitions of the getCompData() method defined in the BlkImgDataSrc /// interface. /// /// </summary> /// <param name="blk">Determines the rectangular area to return, and the /// data is returned in this object. /// /// </param> /// <param name="c">Index of the output component. /// /// </param> /// <returns> The requested DataBlk /// /// </returns> /// <seealso cref="BlkImgDataSrc.getCompData"> /// /// </seealso> public virtual DataBlk getCompData(DataBlk blk, int c) { // If requesting a component whose index is greater than 3 or there is // no transform return a copy of data (getInternCompData returns the // actual data in those cases) if (c >= 3 || transfType == NONE || noCompTransf) { return src.getCompData(blk, c); } else { // We can use getInternCompData (since data is a copy anyways) return getInternCompData(blk, c); } }
/// <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; }
/// <summary> Apply the inverse component transformation associated with the current /// tile. If no component transformation has been requested by the user, /// data are not modified. Else, appropriate method is called (invRCT or /// invICT). /// /// </summary> /// <seealso cref="invRCT"> /// /// </seealso> /// <seealso cref="invICT"> /// /// </seealso> /// <param name="blk">Determines the rectangular area to return. /// /// </param> /// <param name="c">Index of the output component. /// /// </param> /// <returns> The requested DataBlk /// /// </returns> public virtual DataBlk getInternCompData(DataBlk blk, int c) { // if specified in the command line that no component transform should // be made, return original data if (noCompTransf) return src.getInternCompData(blk, c); switch (transfType) { case NONE: return src.getInternCompData(blk, c); case INV_RCT: return invRCT(blk, c); case INV_ICT: return invICT(blk, c); default: throw new System.ArgumentException("Non JPEG 2000 part I" + " component transformation"); } }
/// <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> Apply inverse 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 invRCT(DataBlk blk, int c) { // If the component number is three or greater, return original data if (c >= 3 && c < NumComps) { // Requesting a component whose index is greater than 3 return src.getInternCompData(blk, c); } // If asking a component for the first time for this block, // do transform for the 3 components else if ((outdata[c] == null) || (dbi.ulx > blk.ulx) || (dbi.uly > blk.uly) || (dbi.ulx + dbi.w < blk.ulx + blk.w) || (dbi.uly + dbi.h < blk.uly + blk.h)) { int k, k0, k1, k2, mink, i; int w = blk.w; //width of output block int h = blk.h; //height of ouput block //Reference to output block data array outdata[c] = (int[]) blk.Data; //Create data array of blk if necessary if (outdata[c] == null || outdata[c].Length != h * w) { outdata[c] = new int[h * w]; blk.Data = outdata[c]; } outdata[(c + 1) % 3] = new int[outdata[c].Length]; outdata[(c + 2) % 3] = new int[outdata[c].Length]; if (block0 == null || block0.DataType != DataBlk.TYPE_INT) block0 = new DataBlkInt(); if (block1 == null || block1.DataType != DataBlk.TYPE_INT) block1 = new DataBlkInt(); if (block2 == null || block2.DataType != DataBlk.TYPE_INT) 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; int[] data0, data1, data2; // input data arrays // 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); 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; // set attributes of the DataBlk used for buffering dbi.progressive = blk.progressive; dbi.ulx = blk.ulx; dbi.uly = blk.uly; dbi.w = blk.w; dbi.h = blk.h; // Perform conversion // Initialize general indexes k = w * h - 1; k0 = block0.offset + (h - 1) * block0.scanw + w - 1; k1 = block1.offset + (h - 1) * block1.scanw + w - 1; k2 = block2.offset + (h - 1) * block2.scanw + w - 1; for (i = h - 1; i >= 0; i--) { for (mink = k - w; k > mink; k--, k0--, k1--, k2--) { outdata[1][k] = (data0[k0] - ((data1[k1] + data2[k2]) >> 2)); outdata[0][k] = data2[k2] + outdata[1][k]; outdata[2][k] = data1[k1] + outdata[1][k]; } // Jump to beggining of previous line in input k0 -= (block0.scanw - w); k1 -= (block1.scanw - w); k2 -= (block2.scanw - w); } outdata[c] = null; } else if ((c >= 0) && (c < 3)) { //Asking for the 2nd or 3rd block component blk.Data = outdata[c]; blk.progressive = dbi.progressive; blk.offset = (blk.uly - dbi.uly) * dbi.w + blk.ulx - dbi.ulx; blk.scanw = dbi.w; outdata[c] = null; } else { // Requesting a non valid component index throw new System.ArgumentException(); } return blk; }
public abstract CSJ2K.j2k.image.DataBlk getInternCodeBlock(int param1, int param2, int param3, CSJ2K.j2k.wavelet.synthesis.SubbandSyn param4, CSJ2K.j2k.image.DataBlk param5);
/// <summary> Apply inverse irreversible component transformation to obtain requested /// component from specified block of data. Whatever the type of requested /// DataBlk, it always returns a DataBlkFloat. /// /// </summary> /// <param name="blk">Determine the rectangular area to return /// /// </param> /// <param name="c">The index of the requested component /// /// </param> /// <returns> Data of requested component /// /// </returns> private DataBlk invICT(DataBlk blk, int c) { if (c >= 3 && c < NumComps) { // Requesting a component whose index is greater than 3 int k, k0, mink, i; // k1, k2 removed int w = blk.w; //width of output block int h = blk.h; //height of ouput block int[] out_data; // array of output data //Reference to output block data array out_data = (int[]) blk.Data; //Create data array of blk if necessary if (out_data == null) { out_data = new int[h * w]; blk.Data = out_data; } // Variables DataBlkFloat indb = new DataBlkFloat(blk.ulx, blk.uly, w, h); float[] indata; // input data array // Get the input data // (returned block may be larger than requested one) src.getInternCompData(indb, c); indata = (float[]) indb.Data; // Copy the data converting from int to int k = w * h - 1; k0 = indb.offset + (h - 1) * indb.scanw + w - 1; for (i = h - 1; i >= 0; i--) { for (mink = k - w; k > mink; k--, k0--) { //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" out_data[k] = (int) (indata[k0]); } // Jump to beggining of previous line in input k0 -= (indb.scanw - w); } // Set the progressivity and offset blk.progressive = indb.progressive; blk.offset = 0; blk.scanw = w; } // If asking a component for the first time for this block, // do transform for the 3 components else if ((outdata[c] == null) || (dbi.ulx > blk.ulx) || (dbi.uly > blk.uly) || (dbi.ulx + dbi.w < blk.ulx + blk.w) || (dbi.uly + dbi.h < blk.uly + blk.h)) { int k, k0, k1, k2, mink, i; int w = blk.w; //width of output block int h = blk.h; //height of ouput block //Reference to output block data array outdata[c] = (int[]) blk.Data; //Create data array of blk if necessary if (outdata[c] == null || outdata[c].Length != w * h) { outdata[c] = new int[h * w]; blk.Data = outdata[c]; } outdata[(c + 1) % 3] = new int[outdata[c].Length]; outdata[(c + 2) % 3] = new int[outdata[c].Length]; if (block0 == null || block0.DataType != DataBlk.TYPE_FLOAT) block0 = new DataBlkFloat(); if (block2 == null || block2.DataType != DataBlk.TYPE_FLOAT) block2 = new DataBlkFloat(); if (block1 == null || block1.DataType != DataBlk.TYPE_FLOAT) block1 = new DataBlkFloat(); block0.w = block2.w = block1.w = blk.w; block0.h = block2.h = block1.h = blk.h; block0.ulx = block2.ulx = block1.ulx = blk.ulx; block0.uly = block2.uly = block1.uly = blk.uly; float[] data0, data1, data2; // input data arrays // Fill in buffer blocks (to be read only) // Returned blocks may have different size and position block0 = (DataBlkFloat) src.getInternCompData(block0, 0); data0 = (float[]) block0.Data; block2 = (DataBlkFloat) src.getInternCompData(block2, 1); data2 = (float[]) block2.Data; block1 = (DataBlkFloat) src.getInternCompData(block1, 2); data1 = (float[]) block1.Data; // Set the progressiveness of the output data blk.progressive = block0.progressive || block1.progressive || block2.progressive; blk.offset = 0; blk.scanw = w; // set attributes of the DataBlk used for buffering dbi.progressive = blk.progressive; dbi.ulx = blk.ulx; dbi.uly = blk.uly; dbi.w = blk.w; dbi.h = blk.h; //Perform conversion // Initialize general indexes k = w * h - 1; k0 = block0.offset + (h - 1) * block0.scanw + w - 1; k2 = block2.offset + (h - 1) * block2.scanw + w - 1; k1 = block1.offset + (h - 1) * block1.scanw + w - 1; for (i = h - 1; i >= 0; i--) { for (mink = k - w; k > mink; k--, k0--, k2--, k1--) { //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" outdata[0][k] = (int) (data0[k0] + 1.402f * data1[k1] + 0.5f); //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" outdata[1][k] = (int) (data0[k0] - 0.34413f * data2[k2] - 0.71414f * data1[k1] + 0.5f); //UPGRADE_WARNING: Data types in Visual C# might be different. Verify the accuracy of narrowing conversions. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1042'" outdata[2][k] = (int) (data0[k0] + 1.772f * data2[k2] + 0.5f); } // Jump to beggining of previous line in input k0 -= (block0.scanw - w); k2 -= (block2.scanw - w); k1 -= (block1.scanw - w); } outdata[c] = null; } else if ((c >= 0) && (c <= 3)) { //Asking for the 2nd or 3rd block component blk.Data = outdata[c]; blk.progressive = dbi.progressive; blk.offset = (blk.uly - dbi.uly) * dbi.w + blk.ulx - dbi.ulx; blk.scanw = dbi.w; outdata[c] = null; } else { // Requesting a non valid component index throw new System.ArgumentException(); } return blk; }