jj2000.j2k.image.Tiler Maven / Gradle / Ivy
Show all versions of jai-imageio-jpeg2000 Show documentation
/*
* $RCSfile: Tiler.java,v $
* $Revision: 1.1 $
* $Date: 2005/02/11 05:02:13 $
* $State: 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.
* */
package jj2000.j2k.image;
import java.awt.Point;
import jj2000.j2k.NoNextElementException;
import jj2000.j2k.util.FacilityManager;
import jj2000.j2k.util.MsgLogger;
/**
* 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.
*
* @see ImgData
* @see BlkImgDataSrc
* */
public class Tiler extends ImgDataAdapter implements BlkImgDataSrc {
/** 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.
*
* @param 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 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 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 px The horizontal tiling origin, in the canvas system, on the
* reference grid. It must satisfy 'px<=ax'.
*
* @param py The vertical tiling origin, in the canvas system, on the
* reference grid. It must satisfy 'py<=ay'.
*
* @param nw The nominal tile width, on the reference grid. If 0 then
* there is no tiling in that direction.
*
* @param nh The nominal tile height, on the reference grid. If 0 then
* there is no tiling in that direction.
*
* @exception IllegalArgumentException 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) {
super(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 IllegalArgumentException("Source is tiled");
}
*/
// Verify that source is not "canvased"
/*
if (src.getImgULX()!=0 || src.getImgULY()!=0) {
throw new IllegalArgumentException("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 IllegalArgumentException("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.getImgWidth()-xt0siz;
if (ytsiz==0) ytsiz = y0siz+src.getImgHeight()-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(MsgLogger.INFO,"Automatically adjusted tiling "+
"origin to equivalent one ("+xt0siz+","+
yt0siz+") so that "+
"first tile overlaps the image");
}
// Calculate the number of tiles
ntX = (int)Math.ceil((x0siz+src.getImgWidth() - xt0siz)/(double)xtsiz);
ntY = (int)Math.ceil((y0siz+src.getImgHeight() - yt0siz)/(double)ytsiz);
}
/**
* Returns the overall width of the current tile in pixels. This is the
* tile's width without accounting for any component subsampling.
*
* @return The total current tile width in pixels.
* */
public final int getTileWidth() {
return tileW;
}
/**
* Returns the overall height of the current tile in pixels. This is the
* tile's width without accounting for any component subsampling.
*
* @return The total current tile height in pixels.
* */
public final int getTileHeight() {
return tileH;
}
/**
* Returns the width in pixels of the specified tile-component.
*
* @param t Tile index
*
* @param c The index of the component, from 0 to N-1.
*
* @return The width of specified tile-component.
* */
public final int getTileCompWidth(int t,int c) {
if(t!=getTileIdx()) {
throw new Error("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.
*
* @param t The tile index.
*
* @param c The index of the component, from 0 to N-1.
*
* @return The height of specified tile-component.
* */
public final int getTileCompHeight(int t,int c) {
if(t!=getTileIdx()) {
throw new Error("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.
*
* @param c The index of the component.
*
* @return The position of the fixed-point, which is the same as the
* number of fractional bits. For floating-point data 0 is returned.
* */
public 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.
*
* @param 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 c The index of the component from which to get the data.
*
* @return The requested DataBlk
*
* @see #getCompData
* */
public final 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 IllegalArgumentException("Block is outside the tile");
}
// Translate to the sources coordinates
int incx = (int)Math.ceil(x0siz/(double)src.getCompSubsX(c));
int incy = (int)Math.ceil(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.
*
* @param 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 c The index of the component from which to get the data.
*
* @return The requested DataBlk
*
* @see #getInternCompData
* */
public final 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 IllegalArgumentException("Block is outside the tile");
}
// Translate to the source's coordinates
int incx = (int)Math.ceil(x0siz/(double)src.getCompSubsX(c));
int incy = (int)Math.ceil(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.
*
* @param x The horizontal index of the tile.
*
* @param y The vertical index of the new tile.
* */
public final void setTile(int x,int y) {
src.setTile(x, y);
// Check tile indexes
if (x<0 || y<0 || x>=ntX || y>=ntY) {
throw new IllegalArgumentException("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.getImgWidth());
int ty1 = (y!=ntY-1) ? (yt0siz+(y+1)*ytsiz) :
(y0siz+src.getImgHeight());
// Set general variables
tileW = tx1 - tx0;
tileH = ty1 - ty0;
// Set component specific variables
int nc = src.getNumComps();
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