/* * CVS identifier: * * $Id: Tiler.java,v 1.34 2001/09/14 09:16:09 grosbois Exp $ * * Class: Tiler * * Description: An object to create TiledImgData from * ImgData * * * * COPYRIGHT: * * This software module was originally developed by Raphaël Grosbois and * Diego Santa Cruz (Swiss Federal Institute of Technology-EPFL); Joel * Askelöf (Ericsson Radio Systems AB); and Bertrand Berthelot, David * Bouchard, Félix Henry, Gerard Mozelle and Patrice Onno (Canon Research * Centre France S.A) in the course of development of the JPEG2000 * standard as specified by ISO/IEC 15444 (JPEG 2000 Standard). This * software module is an implementation of a part of the JPEG 2000 * Standard. Swiss Federal Institute of Technology-EPFL, Ericsson Radio * Systems AB and Canon Research Centre France S.A (collectively JJ2000 * Partners) agree not to assert against ISO/IEC and users of the JPEG * 2000 Standard (Users) any of their rights under the copyright, not * including other intellectual property rights, for this software module * with respect to the usage by ISO/IEC and Users of this software module * or modifications thereof for use in hardware or software products * claiming conformance to the JPEG 2000 Standard. Those intending to use * this software module in hardware or software products are advised that * their use may infringe existing patents. The original developers of * this software module, JJ2000 Partners and ISO/IEC assume no liability * for use of this software module or modifications thereof. No license * or right to this software module is granted for non JPEG 2000 Standard * conforming products. JJ2000 Partners have full right to use this * software module for his/her own purpose, assign or donate this * software module to any third party and to inhibit third parties from * using this software module for non JPEG 2000 Standard conforming * products. This copyright notice must be included in all copies or * derivative works of this software module. * * Copyright (c) 1999/2000 JJ2000 Partners. * */ using System; using CSJ2K.j2k.util; using CSJ2K.j2k; namespace CSJ2K.j2k.image { /// This class places an image in the canvas coordinate system, tiles it, if so /// specified, and performs the coordinate conversions transparently. The /// source must be a 'BlkImgDataSrc' which is not tiled and has a the image /// origin at the canvas origin (i.e. it is not "canvased"), or an exception is /// thrown by the constructor. A tiled and "canvased" output is given through /// the 'BlkImgDataSrc' interface. See the 'ImgData' interface for a /// description of the canvas and tiling. /// ///

All tiles produced are rectangular, non-overlapping and their union /// covers all the image. However, the tiling may not be uniform, depending on /// the nominal tile size, tiling origin, component subsampling and other /// factors. Therefore it might not be assumed that all tiles are of the same /// width and height.

/// ///

The nominal dimension of the tiles is the maximal one, in the reference /// grid. All the components of the image have the same number of tiles.

/// ///
/// /// /// /// /// public class Tiler:ImgDataAdapter, BlkImgDataSrc { /// Returns the overall width of the current tile in pixels. This is the /// tile's width without accounting for any component subsampling. /// /// /// The total current tile width in pixels. /// /// override public int TileWidth { get { return tileW; } } /// Returns the overall height of the current tile in pixels. This is the /// tile's width without accounting for any component subsampling. /// /// /// The total current tile height in pixels. /// /// override public int TileHeight { get { return tileH; } } /// Returns the index of the current tile, relative to a standard scan-line /// order. /// /// /// The current tile's index (starts at 0). /// /// override public int TileIdx { get { return ty * ntX + tx; } } /// Returns the horizontal tile partition offset in the reference grid override public int TilePartULX { get { return xt0siz; } } /// Returns the vertical tile partition offset in the reference grid override public int TilePartULY { get { return yt0siz; } } /// Returns the horizontal coordinate of the image origin, the top-left /// corner, in the canvas system, on the reference grid. /// /// /// The horizontal coordinate of the image origin in the canvas /// system, on the reference grid. /// /// override public int ImgULX { get { return x0siz; } } /// Returns the vertical coordinate of the image origin, the top-left /// corner, in the canvas system, on the reference grid. /// /// /// The vertical coordinate of the image origin in the canvas /// system, on the reference grid. /// /// override public int ImgULY { get { return y0siz; } } /// Returns the nominal width of the tiles in the reference grid. /// /// /// The nominal tile width, in the reference grid. /// /// override public int NomTileWidth { get { return xtsiz; } } /// Returns the nominal width of the tiles in the reference grid. /// /// /// The nominal tile width, in the reference grid. /// /// override public int NomTileHeight { get { return ytsiz; } } /// The source of image data private BlkImgDataSrc src = null; /// Horizontal coordinate of the upper left hand reference grid point. private int x0siz; /// Vertical coordinate of the upper left hand reference grid point. private int y0siz; /// The horizontal coordinate of the tiling origin in the canvas system, /// on the reference grid. /// private int xt0siz; /// The vertical coordinate of the tiling origin in the canvas system, on /// the reference grid. /// private int yt0siz; /// The nominal width of the tiles, on the reference grid. If 0 then there /// is no tiling in that direction. /// private int xtsiz; /// The nominal height of the tiles, on the reference grid. If 0 then /// there is no tiling in that direction. /// private int ytsiz; /// The number of tiles in the horizontal direction. private int ntX; /// The number of tiles in the vertical direction. private int ntY; /// The component width in the current active tile, for each component private int[] compW = null; /// The component height in the current active tile, for each component private int[] compH = null; /// The horizontal coordinates of the upper-left corner of the components /// in the current tile /// private int[] tcx0 = null; /// The vertical coordinates of the upper-left corner of the components in /// the current tile. /// private int[] tcy0 = null; /// The horizontal index of the current tile private int tx; /// The vertical index of the current tile private int ty; /// The width of the current tile, on the reference grid. private int tileW; /// The height of the current tile, on the reference grid. private int tileH; /// Constructs a new tiler with the specified 'BlkImgDataSrc' source, /// image origin, tiling origin and nominal tile size. /// /// /// 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. /// /// /// 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). /// /// /// 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). /// /// /// The horizontal tiling origin, in the canvas system, on the /// reference grid. It must satisfy 'px<=ax'. /// /// /// The vertical tiling origin, in the canvas system, on the /// reference grid. It must satisfy 'py<=ay'. /// /// /// The nominal tile width, on the reference grid. If 0 then /// there is no tiling in that direction. /// /// /// The nominal tile height, on the reference grid. If 0 then /// there is no tiling in that direction. /// /// /// If src is tiled or "canvased", or /// if the arguments do not satisfy the specified constraints. /// /// 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); } /// Returns the width in pixels of the specified tile-component. /// /// /// Tile index /// /// /// The index of the component, from 0 to N-1. /// /// /// The width of specified tile-component. /// /// public override int getTileCompWidth(int t, int c) { if (t != TileIdx) { throw new System.ApplicationException("Asking the width of a tile-component which is " + "not in the current tile (call setTile() or " + "nextTile() methods before)."); } return compW[c]; } /// Returns the height in pixels of the specified tile-component. /// /// /// The tile index. /// /// /// The index of the component, from 0 to N-1. /// /// /// The height of specified tile-component. /// /// public override int getTileCompHeight(int t, int c) { if (t != TileIdx) { throw new System.ApplicationException("Asking the width of a tile-component which is " + "not in the current tile (call setTile() or " + "nextTile() methods before)."); } return compH[c]; } /// Returns the position of the fixed point in the specified /// component. This is the position of the least significant integral /// (i.e. non-fractional) bit, which is equivalent to the number of /// fractional bits. For instance, for fixed-point values with 2 fractional /// bits, 2 is returned. For floating-point data this value does not apply /// and 0 should be returned. Position 0 is the position of the least /// significant bit in the data. /// /// /// The index of the component. /// /// /// The position of the fixed-point, which is the same as the /// number of fractional bits. For floating-point data 0 is returned. /// /// public virtual int getFixedPoint(int c) { return src.getFixedPoint(c); } /// 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 reference to the internal data, if any, instead of as a /// copy, therefore the returned data should not be modified. /// ///

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.

/// ///

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.

/// ///

If the data array in blk is null, 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 blk 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 /// blk after the method has returned.

/// ///

The returned data may have its 'progressive' attribute set. In this /// case the returned data is only an approximation of the "final" /// data.

/// ///
/// 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. /// /// /// The index of the component from which to get the data. /// /// /// The requested DataBlk /// /// /// /// /// public DataBlk getInternCompData(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 sources 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.getInternCompData(blk, c); // Translate back to the tiled coordinates blk.ulx += incx; blk.uly += incy; return blk; } /// 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". /// ///

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.

/// ///

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.

/// ///

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.

/// ///

The returned data may have its 'progressive' attribute set. In this /// case the returned data is only an approximation of the "final" /// data.

/// ///
/// 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. /// /// /// The index of the component from which to get the data. /// /// /// The requested DataBlk /// /// /// /// /// 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; } /// Changes the current tile, given the new tile indexes. An /// IllegalArgumentException is thrown if the coordinates do not correspond /// to a valid tile. /// /// /// The horizontal index of the tile. /// /// /// The vertical index of the new tile. /// /// public override void setTile(int x, int y) { // Check tile indexes if (x < 0 || y < 0 || x >= ntX || y >= ntY) { throw new System.ArgumentException("Tile's indexes out of bounds"); } // Set new current tile tx = x; ty = y; // Calculate tile origins int tx0 = (x != 0)?xt0siz + x * xtsiz:x0siz; int ty0 = (y != 0)?yt0siz + y * ytsiz:y0siz; int tx1 = (x != ntX - 1)?(xt0siz + (x + 1) * xtsiz):(x0siz + src.ImgWidth); int ty1 = (y != ntY - 1)?(yt0siz + (y + 1) * ytsiz):(y0siz + src.ImgHeight); // Set general variables tileW = tx1 - tx0; tileH = ty1 - ty0; // Set component specific variables int nc = src.NumComps; if (compW == null) compW = new int[nc]; if (compH == null) compH = new int[nc]; if (tcx0 == null) tcx0 = new int[nc]; if (tcy0 == null) tcy0 = new int[nc]; for (int i = 0; i < nc; i++) { //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'" tcx0[i] = (int) System.Math.Ceiling(tx0 / (double) src.getCompSubsX(i)); //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'" tcy0[i] = (int) System.Math.Ceiling(ty0 / (double) src.getCompSubsY(i)); //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'" compW[i] = (int) System.Math.Ceiling(tx1 / (double) src.getCompSubsX(i)) - tcx0[i]; //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'" compH[i] = (int) System.Math.Ceiling(ty1 / (double) src.getCompSubsY(i)) - tcy0[i]; } } /// Advances to the next tile, in standard scan-line order (by rows then /// columns). An NoNextElementException is thrown if the current tile is /// the last one (i.e. there is no next tile). /// /// public override void nextTile() { if (tx == ntX - 1 && ty == ntY - 1) { // Already at last tile throw new NoNextElementException(); } else if (tx < ntX - 1) { // If not at end of current tile line setTile(tx + 1, ty); } else { // First tile at next line setTile(0, ty + 1); } } /// Returns the horizontal and vertical indexes of the current tile. /// /// /// If not null this object is used to return the /// information. If null a new one is created and returned. /// /// /// The current tile's horizontal and vertical indexes.. /// /// public override Coord getTile(Coord co) { if (co != null) { co.x = tx; co.y = ty; return co; } else { return new Coord(tx, ty); } } /// Returns the horizontal coordinate of the upper-left corner of the /// specified component in the current tile. /// /// /// The component index. /// /// public override int getCompULX(int c) { return tcx0[c]; } /// Returns the vertical coordinate of the upper-left corner of the /// specified component in the current tile. /// /// /// The component index. /// /// public override int getCompULY(int c) { return tcy0[c]; } /// Returns the number of tiles in the horizontal and vertical directions. /// /// /// If not null this object is used to return the information. If /// null a new one is created and returned. /// /// /// The number of tiles in the horizontal (Coord.x) and vertical /// (Coord.y) directions. /// /// public override Coord getNumTiles(Coord co) { if (co != null) { co.x = ntX; co.y = ntY; return co; } else { return new Coord(ntX, ntY); } } /// Returns the total number of tiles in the image. /// /// /// The total number of tiles in the image. /// /// public override int getNumTiles() { return ntX * ntY; } /// Returns the tiling origin, referred to as '(xt0siz,yt0siz)' in the /// codestream header (SIZ marker segment). /// /// /// If not null this object is used to return the information. If /// null a new one is created and returned. /// /// /// The coordinate of the tiling origin, in the canvas system, on /// the reference grid. /// /// /// /// /// public Coord getTilingOrigin(Coord co) { if (co != null) { co.x = xt0siz; co.y = yt0siz; return co; } else { return new Coord(xt0siz, yt0siz); } } /// Returns a String object representing Tiler's informations /// /// /// Tiler's infos in a string /// /// public override System.String ToString() { //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Object.toString' may return a different value. "ms-help://MS.VSCC.v80/dv_commoner/local/redirect.htm?index='!DefaultContextWindowIndex'&keyword='jlca1043'" return "Tiler: source= " + src + "\n" + getNumTiles() + " tile(s), nominal width=" + xtsiz + ", nominal height=" + ytsiz; } } }