/// <summary> Constructs a new tiler with the specified 'BlkImgDataSrc' source, /// image origin, tiling origin and nominal tile size. /// /// </summary> /// <param name="src">The 'BlkImgDataSrc' source from where to get the image /// data. It must not be tiled and the image origin must be at '(0,0)' on /// its canvas. /// /// </param> /// <param name="ax">The horizontal coordinate of the image origin in the canvas /// system, on the reference grid (i.e. the image's top-left corner in the /// reference grid). /// /// </param> /// <param name="ay">The vertical coordinate of the image origin in the canvas /// system, on the reference grid (i.e. the image's top-left corner in the /// reference grid). /// /// </param> /// <param name="px">The horizontal tiling origin, in the canvas system, on the /// reference grid. It must satisfy 'px<=ax'. /// /// </param> /// <param name="py">The vertical tiling origin, in the canvas system, on the /// reference grid. It must satisfy 'py<=ay'. /// /// </param> /// <param name="nw">The nominal tile width, on the reference grid. If 0 then /// there is no tiling in that direction. /// /// </param> /// <param name="nh">The nominal tile height, on the reference grid. If 0 then /// there is no tiling in that direction. /// /// </param> /// <exception cref="IllegalArgumentException">If src is tiled or "canvased", or /// if the arguments do not satisfy the specified constraints. /// /// </exception> public Tiler(BlkImgDataSrc src, int ax, int ay, int px, int py, int nw, int nh) : base(src) { // Initialize this.src = src; this.x0siz = ax; this.y0siz = ay; this.xt0siz = px; this.yt0siz = py; this.xtsiz = nw; this.ytsiz = nh; // Verify that input is not tiled if (src.getNumTiles() != 1) { throw new System.ArgumentException("Source is tiled"); } // Verify that source is not "canvased" if (src.ImgULX != 0 || src.ImgULY != 0) { throw new System.ArgumentException("Source is \"canvased\""); } // Verify that arguments satisfy trivial requirements if (x0siz < 0 || y0siz < 0 || xt0siz < 0 || yt0siz < 0 || xtsiz < 0 || ytsiz < 0 || xt0siz > x0siz || yt0siz > y0siz) { throw new System.ArgumentException("Invalid image origin, " + "tiling origin or nominal " + "tile size"); } // If no tiling has been specified, creates a unique tile with maximum // dimension. if (xtsiz == 0) { xtsiz = x0siz + src.ImgWidth - xt0siz; } if (ytsiz == 0) { ytsiz = y0siz + src.ImgHeight - yt0siz; } // Automatically adjusts xt0siz,yt0siz so that tile (0,0) always // overlaps with the image. if (x0siz - xt0siz >= xtsiz) { xt0siz += ((x0siz - xt0siz) / xtsiz) * xtsiz; } if (y0siz - yt0siz >= ytsiz) { yt0siz += ((y0siz - yt0siz) / ytsiz) * ytsiz; } if (x0siz - xt0siz >= xtsiz || y0siz - yt0siz >= ytsiz) { FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.INFO, "Automatically adjusted tiling " + "origin to equivalent one (" + xt0siz + "," + yt0siz + ") so that " + "first tile overlaps the image"); } // Calculate the number of tiles //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'" ntX = (int)System.Math.Ceiling((x0siz + src.ImgWidth) / (double)xtsiz); //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'" ntY = (int)System.Math.Ceiling((y0siz + src.ImgHeight) / (double)ytsiz); }
/// <summary> Writes the entire image or only specified tiles to the output. The /// implementation in this class calls the write() method for each tile /// starting with the upper-left one and proceding in standard scanline /// order. It changes the current tile of the source data. /// /// </summary> /// <exception cref="IOException">If an I/O error occurs. /// /// </exception> /// <seealso cref="DataBlk"> /// /// </seealso> public virtual void writeAll() { // Find the list of tile to decode. Coord nT = src.getNumTiles(null); // Loop on vertical tiles for (int y = 0; y < nT.y; y++) { // Loop on horizontal tiles for (int x = 0; x < nT.x; x++) { src.setTile(x, y); write(); } // End loop on horizontal tiles } // End loop on vertical tiles }
/// <summary> Initializes this object with the given source of image data and with /// all the decompositon parameters /// /// </summary> /// <param name="src">From where the image data should be obtained. /// /// </param> /// <param name="encSpec">The encoder specifications /// /// </param> /// <param name="cb0x">The horizontal coordinate of the code-block partition /// origin on the reference grid. /// /// </param> /// <param name="cb0y">The vertical coordinate of the code-block partition origin /// on the reference grid. /// /// </param> /// <seealso cref="ForwardWT"> /// /// </seealso> public ForwWTFull(BlkImgDataSrc src, EncoderSpecs encSpec, int cb0x, int cb0y) : base(src) { this.src = src; this.cb0x = cb0x; this.cb0y = cb0y; this.dls = encSpec.dls; this.filters = encSpec.wfs; this.cblks = encSpec.cblks; this.pss = encSpec.pss; int ncomp = src.NumComps; int ntiles = src.getNumTiles(); currentSubband = new SubbandAn[ncomp]; decomposedComps = new DataBlk[ncomp]; subbTrees = new SubbandAn[ntiles][]; for (int i = 0; i < ntiles; i++) { subbTrees[i] = new SubbandAn[ncomp]; } lastn = new int[ncomp]; lastm = new int[ncomp]; }
public static Image FromStream(Stream stream) { RandomAccessIO in_stream = new ISRandomAccessIO(stream); // Initialize default parameters ParameterList defpl = GetDefaultParameterList(decoder_pinfo); // Create parameter list using defaults ParameterList pl = new ParameterList(defpl); // **** File Format **** // If the codestream is wrapped in the jp2 fileformat, Read the // file format wrapper FileFormatReader ff = new FileFormatReader(in_stream); ff.readFileFormat(); if (ff.JP2FFUsed) { in_stream.seek(ff.FirstCodeStreamPos); } // +----------------------------+ // | Instantiate decoding chain | // +----------------------------+ // **** Header decoder **** // Instantiate header decoder and read main header HeaderInfo hi = new HeaderInfo(); HeaderDecoder hd; try { hd = new HeaderDecoder(in_stream, pl, hi); } catch (EndOfStreamException e) { throw new ApplicationException("Codestream too short or bad header, unable to decode.", e); } int nCompCod = hd.NumComps; int nTiles = hi.sizValue.NumTiles; DecoderSpecs decSpec = hd.DecoderSpecs; // Get demixed bitdepths int[] depth = new int[nCompCod]; for (int i = 0; i < nCompCod; i++) { depth[i] = hd.getOriginalBitDepth(i); } // **** Bit stream reader **** BitstreamReaderAgent breader; try { breader = BitstreamReaderAgent. createInstance(in_stream, hd, pl, decSpec, false, hi); } catch (IOException e) { throw new ApplicationException("Error while reading bit stream header or parsing packets.", e); } catch (ArgumentException e) { throw new ApplicationException("Cannot instantiate bit stream reader.", e); } // **** Entropy decoder **** EntropyDecoder entdec; try { entdec = hd.createEntropyDecoder(breader, pl); } catch (ArgumentException e) { throw new ApplicationException("Cannot instantiate entropy decoder.", e); } // **** ROI de-scaler **** ROIDeScaler roids; try { roids = hd.createROIDeScaler(entdec, pl, decSpec); } catch (ArgumentException e) { throw new ApplicationException("Cannot instantiate roi de-scaler.", e); } // **** Dequantizer **** Dequantizer deq; try { deq = hd.createDequantizer(roids, depth, decSpec); } catch (ArgumentException e) { throw new ApplicationException("Cannot instantiate dequantizer.", e); } // **** Inverse wavelet transform *** InverseWT invWT; try { // full page inverse wavelet transform invWT = InverseWT.createInstance(deq, decSpec); } catch (ArgumentException e) { throw new ApplicationException("Cannot instantiate inverse wavelet transform.", e); } int res = breader.ImgRes; invWT.ImgResLevel = res; // **** Data converter **** (after inverse transform module) ImgDataConverter converter = new ImgDataConverter(invWT, 0); // **** Inverse component transformation **** InvCompTransf ictransf = new InvCompTransf(converter, decSpec, depth, pl); // **** Color space mapping **** BlkImgDataSrc color; if (ff.JP2FFUsed && pl.getParameter("nocolorspace").Equals("off")) { try { ColorSpace csMap = new ColorSpace(in_stream, hd, pl); BlkImgDataSrc channels = hd.createChannelDefinitionMapper(ictransf, csMap); BlkImgDataSrc resampled = hd.createResampler(channels, csMap); BlkImgDataSrc palettized = hd.createPalettizedColorSpaceMapper(resampled, csMap); color = hd.createColorSpaceMapper(palettized, csMap); } catch (ArgumentException e) { throw new ApplicationException("Could not instantiate ICC profiler.", e); } catch (ColorSpaceException e) { throw new ApplicationException("Error processing ColorSpace information.", e); } } else { // Skip colorspace mapping color = ictransf; } // This is the last image in the decoding chain and should be // assigned by the last transformation: BlkImgDataSrc decodedImage = color; if (color == null) { decodedImage = ictransf; } int numComps = decodedImage.NumComps; int bytesPerPixel = numComps; // Assuming 8-bit components // **** Copy to Bitmap **** PixelFormat pixelFormat; switch (numComps) { case 1: pixelFormat = PixelFormat.Format24bppRgb; break; case 3: pixelFormat = PixelFormat.Format24bppRgb; break; case 4: case 5: pixelFormat = PixelFormat.Format32bppArgb; break; default: throw new ApplicationException("Unsupported PixelFormat. " + numComps + " components."); } Bitmap dst = new Bitmap(decodedImage.ImgWidth, decodedImage.ImgHeight, pixelFormat); Coord numTiles = decodedImage.getNumTiles(null); int tIdx = 0; for (int y = 0; y < numTiles.y; y++) { // Loop on horizontal tiles for (int x = 0; x < numTiles.x; x++, tIdx++) { decodedImage.setTile(x, y); int height = decodedImage.getTileCompHeight(tIdx, 0); int width = decodedImage.getTileCompWidth(tIdx, 0); int tOffx = decodedImage.getCompULX(0) - (int)Math.Ceiling(decodedImage.ImgULX / (double)decodedImage.getCompSubsX(0)); int tOffy = decodedImage.getCompULY(0) - (int)Math.Ceiling(decodedImage.ImgULY / (double)decodedImage.getCompSubsY(0)); DataBlkInt[] db = new DataBlkInt[numComps]; int[] ls = new int[numComps]; int[] mv = new int[numComps]; int[] fb = new int[numComps]; for (int i = 0; i < numComps; i++) { db[i] = new DataBlkInt(); ls[i] = 1 << (decodedImage.getNomRangeBits(0) - 1); mv[i] = (1 << decodedImage.getNomRangeBits(0)) - 1; fb[i] = decodedImage.getFixedPoint(0); } for (int l = 0; l < height; l++) { for (int i = numComps - 1; i >= 0; i--) { db[i].ulx = 0; db[i].uly = l; db[i].w = width; db[i].h = 1; decodedImage.getInternCompData(db[i], i); } int[] k = new int[numComps]; for (int i = numComps - 1; i >= 0; i--) { k[i] = db[i].offset + width - 1; } int outputBytesPerPixel = Math.Max(3, Math.Min(4, bytesPerPixel)); byte[] rowvalues = new byte[width * outputBytesPerPixel]; for (int i = width - 1; i >= 0; i--) { int[] tmp = new int[numComps]; for (int j = numComps - 1; j >= 0; j--) { tmp[j] = (db[j].data_array[k[j]--] >> fb[j]) + ls[j]; tmp[j] = (tmp[j] < 0) ? 0 : ((tmp[j] > mv[j]) ? mv[j] : tmp[j]); if (decodedImage.getNomRangeBits(j) != 8) { tmp[j] = (int)Math.Round(((double)tmp[j] / Math.Pow(2D, (double)decodedImage.getNomRangeBits(j))) * 255D); } } int offset = i * outputBytesPerPixel; switch (numComps) { case 1: rowvalues[offset + 0] = (byte)tmp[0]; rowvalues[offset + 1] = (byte)tmp[0]; rowvalues[offset + 2] = (byte)tmp[0]; break; case 3: rowvalues[offset + 0] = (byte)tmp[2]; rowvalues[offset + 1] = (byte)tmp[1]; rowvalues[offset + 2] = (byte)tmp[0]; break; case 4: case 5: rowvalues[offset + 0] = (byte)tmp[2]; rowvalues[offset + 1] = (byte)tmp[1]; rowvalues[offset + 2] = (byte)tmp[0]; rowvalues[offset + 3] = (byte)tmp[3]; break; } } BitmapData dstdata = dst.LockBits( new System.Drawing.Rectangle(tOffx, tOffy + l, width, 1), ImageLockMode.WriteOnly, pixelFormat); IntPtr ptr = dstdata.Scan0; System.Runtime.InteropServices.Marshal.Copy(rowvalues, 0, ptr, rowvalues.Length); dst.UnlockBits(dstdata); } } } return(dst); }
/// <summary> Initializes this object with the given source of image data and with /// all the decompositon parameters /// /// </summary> /// <param name="src">From where the image data should be obtained. /// /// </param> /// <param name="encSpec">The encoder specifications /// /// </param> /// <param name="cb0x">The horizontal coordinate of the code-block partition /// origin on the reference grid. /// /// </param> /// <param name="cb0y">The vertical coordinate of the code-block partition origin /// on the reference grid. /// /// </param> /// <seealso cref="ForwardWT"> /// /// </seealso> public ForwWTFull(BlkImgDataSrc src, EncoderSpecs encSpec, int cb0x, int cb0y):base(src) { this.src = src; this.cb0x = cb0x; this.cb0y = cb0y; this.dls = encSpec.dls; this.filters = encSpec.wfs; this.cblks = encSpec.cblks; this.pss = encSpec.pss; int ncomp = src.NumComps; int ntiles = src.getNumTiles(); currentSubband = new SubbandAn[ncomp]; decomposedComps = new DataBlk[ncomp]; subbTrees = new SubbandAn[ntiles][]; for (int i = 0; i < ntiles; i++) { subbTrees[i] = new SubbandAn[ncomp]; } lastn = new int[ncomp]; lastm = new int[ncomp]; }
/// <summary> Constructs a new tiler with the specified 'BlkImgDataSrc' source, /// image origin, tiling origin and nominal tile size. /// /// </summary> /// <param name="src">The 'BlkImgDataSrc' source from where to get the image /// data. It must not be tiled and the image origin must be at '(0,0)' on /// its canvas. /// /// </param> /// <param name="ax">The horizontal coordinate of the image origin in the canvas /// system, on the reference grid (i.e. the image's top-left corner in the /// reference grid). /// /// </param> /// <param name="ay">The vertical coordinate of the image origin in the canvas /// system, on the reference grid (i.e. the image's top-left corner in the /// reference grid). /// /// </param> /// <param name="px">The horizontal tiling origin, in the canvas system, on the /// reference grid. It must satisfy 'px<=ax'. /// /// </param> /// <param name="py">The vertical tiling origin, in the canvas system, on the /// reference grid. It must satisfy 'py<=ay'. /// /// </param> /// <param name="nw">The nominal tile width, on the reference grid. If 0 then /// there is no tiling in that direction. /// /// </param> /// <param name="nh">The nominal tile height, on the reference grid. If 0 then /// there is no tiling in that direction. /// /// </param> /// <exception cref="IllegalArgumentException">If src is tiled or "canvased", or /// if the arguments do not satisfy the specified constraints. /// /// </exception> public Tiler(BlkImgDataSrc src, int ax, int ay, int px, int py, int nw, int nh):base(src) { // Initialize this.src = src; this.x0siz = ax; this.y0siz = ay; this.xt0siz = px; this.yt0siz = py; this.xtsiz = nw; this.ytsiz = nh; // Verify that input is not tiled if (src.getNumTiles() != 1) { throw new System.ArgumentException("Source is tiled"); } // Verify that source is not "canvased" if (src.ImgULX != 0 || src.ImgULY != 0) { throw new System.ArgumentException("Source is \"canvased\""); } // Verify that arguments satisfy trivial requirements if (x0siz < 0 || y0siz < 0 || xt0siz < 0 || yt0siz < 0 || xtsiz < 0 || ytsiz < 0 || xt0siz > x0siz || yt0siz > y0siz) { throw new System.ArgumentException("Invalid image origin, " + "tiling origin or nominal " + "tile size"); } // If no tiling has been specified, creates a unique tile with maximum // dimension. if (xtsiz == 0) xtsiz = x0siz + src.ImgWidth - xt0siz; if (ytsiz == 0) ytsiz = y0siz + src.ImgHeight - yt0siz; // Automatically adjusts xt0siz,yt0siz so that tile (0,0) always // overlaps with the image. if (x0siz - xt0siz >= xtsiz) { xt0siz += ((x0siz - xt0siz) / xtsiz) * xtsiz; } if (y0siz - yt0siz >= ytsiz) { yt0siz += ((y0siz - yt0siz) / ytsiz) * ytsiz; } if (x0siz - xt0siz >= xtsiz || y0siz - yt0siz >= ytsiz) { FacilityManager.getMsgLogger().printmsg(CSJ2K.j2k.util.MsgLogger_Fields.INFO, "Automatically adjusted tiling " + "origin to equivalent one (" + xt0siz + "," + yt0siz + ") so that " + "first tile overlaps the image"); } // Calculate the number of tiles //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'" ntX = (int) System.Math.Ceiling((x0siz + src.ImgWidth) / (double) xtsiz); //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'" ntY = (int) System.Math.Ceiling((y0siz + src.ImgHeight) / (double) ytsiz); }