Class OpImage

All Implemented Interfaces:
RenderedImage, ImageImageN, PropertyChangeEmitter, PropertySource, WritablePropertySource
Direct Known Subclasses:
AreaOpImage, AttributeOpImage, BorderOpImage, GeometricOpImage, JiffleOpImage, MosaicOpImage, NullOpImage, PointOpImage, SourcelessOpImage, StatisticsOpImage, StatisticsOpImage, TranslateIntOpImage, UntiledOpImage, ZonalStatsOpImage

public abstract class OpImage extends PlanarImage
This is the base class for all image operations. It provides a home for information and functionalities common to all the op-image classes, and implements various utility methods that may be useful to a specific operation. Image operations may be divided into different categories based on their characteristics. A subclass, extending OpImage, represents a category and implements methods unique and common to those operations. Each individual operator should extend the subclass that represents the specific category that operator belongs to.

The layout variables of an OpImage are inherited from the PlanarImage superclass. The layout should be set when the OpImage is constructed. Each subclass must set the appropriate layout variables and supply them via the ImageLayout argument at construction time. This class simply modifies these settings as described in the OpImage constructor comments before forwarding the layout to the PlanarImage constructor. If a subclass needs to modify any of the layout settings subsequent to invoking its superclass constructors it should use the setImageLayout() method defined in PlanarImage in preference to setting the layout variables directly.

A RenderedImage's pixel data type and number of bands are defined by its SampleModel, while the ColorModel translates the pixel data into color/alpha components in the specific ColorSpace that is associated with the ColorModel.

By default, the operators provided by Java Advanced Imaging (ImageN) operate on the image's pixel data only. That is, the computations are performed on the data described by the image's SampleModel. No color translation is performed prior to the actual computation by the operator, regardless of the type of the ColorModel an image has. If a user intends to have an operation performed on the color data, he must perform the color translation explicitly prior to invoking the operation.

There are those operators that specifically deal with the color/alpha data of an image. Such an operator must state its behavior in its OperationDescriptor explicitly and explain its intended usage of the image's color/alpha component data. In such cases, the image's ColorModel as well as the associated ColorSpace should be considered.

However there are certain operations, the results of which are incorrect when the source has colormapped imagery, i.e. the source has an IndexColorModel, and the computations are performed on the image's non color transformed pixel data. In ImageN, such operations are those that are implemented as subclasses of AreaOpImage, GeometricOpImage, and the "format" operation. These operations set the ImageN.KEY_REPLACE_INDEX_COLOR_MODEL RenderingHint to true, thus ensuring that the operations are performed correctly on the colormapped imagery, not treating the indices into the color map as pixel data.

The tile cache and scheduler are handled by this class. ImageN provides a default implementation for TileCache and TileScheduler. However, they may be overriden by each application. An OpImage may share a common cache with other OpImages, or it may have a private cache of its own. To override an existing cache, use the setTileCache method; an input argument of null indicates that this image should not have a tile cache.

The getTile method may be used to request a tile of the image. The default implementation of this method in this class first checks whether the requested tile is in the tile cache, and if not, uses the default TileScheduler to schedule the tile for computation. Once the tile has been computed, it is added to the cache and returned as a Raster.

The ImageN tile scheduler assumes that when a request is made to schedule a tile for computation via the scheduleTile method, that tile is not currently in the cache. To avoid a cycle, it calls OpImage.computeTile for the actual tile computation.

The default implementation of the computeTile method in this class first creates a new Raster to represent the requested tile, then calls one of the two computeRect methods to compute the actual pixel values and store the result in the DataBuffer of the Raster.

Two variants of the computeRect method exist.

The first (with input arguments Raster[], WritableRaster, and Rectangle) is used when the OpImage is constructed with the cobbleSources argument set to true . This indicates that the source data must be cobbled into a single Raster and that all the necessary source data are provided in order to compute the rectangular region of the destination image. The source Raster array contains one entry for each source image.

The second (with input arguments PlanarImage[], WritableRaster, and Rectangle ) is used when the OpImage is constructed with the cobbleSources argument set to false. This indicates that the source data are not cobbled into a single Raster; instead an array of PlanarImages, one for each source, supply the source data and each image is responsible for performing its own data accesses. This variant is generally useful if iterators are to be used for the underlying implementation of accessing the image data.

The two computeRect methods are not abstract because normally only one needs to be implemented by the subclass depending on the cobbleSources value. The default implementation of these two methods in this class throws a RuntimeException.

Every operator who follows the above default implementation must supply an overridden version of at least one of the computeRect method variants, and specify which one is to be called via the cobbleSources argument of the constructor, or an exception will be thrown at run time.

If a subclass overrides getTile not to call computeTile, does not use the ImageN implementation of TileScheduler, overrides computeTile not to call computeRect , or does not follow the above default implementation in any way, then it may need to handle issues such as tile caching, multi-threading, and etc. by itself and may not need to override some of the methods described above. In some cases, some of the methods or variables are even irrelevant. However, subclasses should be careful when not following the default path for computing a tile. Most importantly, when a subclass overrides getTile, it should also override computeTile.

To request multiple tiles at a time, it is preferable to call the getTiles method with a complete list of the requested tiles' indices, than to call getTile once per tile. The implementation of getTiles in this class is optimized using multi-threading so that multiple tiles are computed simultaneously.

See Also:
  • Field Details

    • OP_COMPUTE_BOUND

      public static final int OP_COMPUTE_BOUND
      A constant indicating that an operation is likely to spend its time mainly performing computation.
      See Also:
    • OP_IO_BOUND

      public static final int OP_IO_BOUND
      A constant indicating that an operation is likely to spend its time mainly performing local I/O.
      See Also:
    • OP_NETWORK_BOUND

      public static final int OP_NETWORK_BOUND
      A constant indicating that an operation is likely to spend its time mainly performing network I/O.
      See Also:
  • Constructor Details

    • OpImage

      public OpImage(Vector sources, ImageLayout layout, Map configuration, boolean cobbleSources)
      Constructor.

      The image's layout is encapsulated in the layout argument. The variables of the image layout which are not set in the layout parameter are copied from the first source if sources are available. In the case of the ColorModel, the copy is performed if and only if the ColorModel is compatible with the destination SampleModel and is not set by another higher priority mechanism as described presently.

      Assuming that there is at least one source, the image's ColorModel will be set by the first applicable means in the following priority-ordered list:

      1. null ColorModel from ImageLayout;
      2. Non-null ColorModel from ImageLayout if compatible with SampleModel in ImageLayout or if SampleModel in ImageLayout is null;
      3. Value returned by ColorModelFactory set via the ImageN.KEY_COLOR_MODEL_FACTORY configuration variable if compatible with SampleModel;
      4. An instance of a non-IndexColorModel (or null if no compatible non- IndexColorModel could be generated), if the source has an IndexColorModel and ImageN.KEY_REPLACE_INDEX_COLOR_MODEL is Boolean.TRUE;
      5. ColorModel of first source if compatible with SampleModel;
      6. Value returned by default method specified by the ImageN.KEY_DEFAULT_COLOR_MODEL_METHOD configuration variable if ImageN.KEY_DEFAULT_COLOR_MODEL_ENABLED is Boolean.TRUE.
      If it is not possible to set the ColorModel by any of these means it will remain null. The image's tile dimensions will be set by the first applicable means in the following priority-ordered list. Note that each tile dimension, the tileWidth and the tileHeight, is considered independently :
      1. Tile dimension set in the ImageLayout (either by the user or the operator itself);
      2. Tile dimension of source, if source is non-null. The tile dimension will be clamped to the minimum of that of the source tile dimension and the image's corresponding dimension;
      3. Non-null default tile size returned by ImageN.getDefaultTileSize(), if the corresponding image dimension is at least double the default tile size;
      4. The dimensions of the image itself;

      The sources contains a list of immediate sources of this image. Elements in the list may not be null. If this image has no sources this argument should be null. This parameter is forwarded unmodified to the PlanarImage constructor.

      The configuration contains a mapping of configuration variables and image properties. Entries which have keys of type RenderingHints.Key are taken to be configuration variables. Entries with a key which is either a String or a CaselessStringKey are interpreted as image properties. This parameter is forwarded unmodified to the PlanarImage constructor.

      This image class recognizes the configuration variables referenced by the following keys:

      • ImageN.KEY_TILE_CACHE: specifies the TileCache in which to store the image tiles; if this key is not supplied no tile caching will be performed.
      • ImageN.KEY_TILE_CACHE_METRIC: establishes an ordering of tiles stored in the tile cache. This ordering is used to determine which tiles will be removed first, if a condition causes tiles to be removed from the cache.
      • ImageN.KEY_TILE_SCHEDULER: specifies the TileScheduler to use to schedule tile computation; if this key is not supplied the default scheduler will be used.
      • ImageN.KEY_COLOR_MODEL_FACTORY: specifies a ColorModelFactory to be used to generate the ColorModel of the image. If such a callback is provided it will be invoked if and only if either no ImageLayout hint is given, or an ImageLayout hint is given but contains a non-null ColorModel which is incompatible with the image SampleModel . In other words, such a callback provides the second priority mechanism for setting the ColorModel of the image.
      • ImageN.KEY_DEFAULT_COLOR_MODEL_ENABLED: specifies whether a default ColorModel will be derived if none is specified and one cannot be inherited from the first source; if this key is not supplied a default ColorModel will be computed if necessary.
      • ImageN.KEY_DEFAULT_COLOR_MODEL_METHOD: specifies the method to be used to compute the default ColorModel; if this key is not supplied and a default ColorModel is required, PlanarImage.createColorModel() will be used to compute it.
      • ImageN.KEY_TILE_FACTORY: specifies a TileFactory to be used to generate the tiles of the image via TileFactory.createTile(SampleModel,Point). If no such configuration variable is given, a new Raster will be created for each image tile. This behavior may be overridden by subclasses which have alternate means of saving memory, for example as in the case of point operations which may overwrite a source image not referenced by user code. Note that the corresponding instance variable is actually set by the superclass constructor.
      • ImageN.KEY_TILE_RECYCLER: specifies a TileRecycler to be used to recycle the tiles of the image when the dispose() method is invoked. If such a configuration variable is set, the image has a non-null TileCache, and tile recycling is enabled, then invoking dispose() will cause each of the tiles of this image currently in the cache to be passed to the configured TileRecycler via TileRecycler.recycleTile(Raster).
      • ImageN.KEY_CACHED_TILE_RECYCLING_ENABLED: specifies a Boolean value which indicates whether {#dispose()} should pass to tileRecycler.recycleTile() any image tiles remaining in the cache.

      The cobbleSources indicates which one of the two variants of the computeRect method should be called. If a subclass does not follow the default tile computation scheme, then this argument may be irrelevant.

      Parameters:
      layout - The layout of this image.
      sources - The immediate sources of this image.
      configuration - Configurable attributes of the image including configuration variables indexed by RenderingHints.Keys and image properties indexed by Strings or CaselessStringKey s. This parameter may be null.
      cobbleSources - Indicates which variant of the computeRect method should be called.
      Throws:
      IllegalArgumentException - If sources is non-null and any object in sources is null.
      RuntimeException - If default ColorModel setting is enabled via a hint in the configuration Map and the supplied Method does not conform to the requirements stated in the ImageN class for the hint key KEY_DEFAULT_COLOR_MODEL_METHOD.
  • Method Details

    • getTileCache

      public TileCache getTileCache()
      Returns the tile cache object of this image by reference. If this image does not have a tile cache, this method returns null.
    • setTileCache

      public void setTileCache(TileCache cache)
      Sets the tile cache object of this image. A null input indicates that this image should have no tile cache and subsequently computed tiles will not be cached.

      The existing cache object is informed to release all the currently cached tiles of this image.

      Parameters:
      cache - A cache object to be used for caching this image's tiles, or null if no tile caching is desired.
    • getTileCacheMetric

      public Object getTileCacheMetric()
      Returns the tileCacheMetric instance variable by reference.
    • getTile

      public Raster getTile(int tileX, int tileY)
      Returns a tile of this image as a Raster. If the requested tile is completely outside of this image's bounds, this method returns null.

      This method attempts to retrieve the requested tile from the cache. If the tile is not currently in the cache, it schedules the tile for computation and adds it to the cache once the tile has been computed.

      If a subclass overrides this method, then it needs to handle tile caching and scheduling. It should also override computeTile() which may be invoked directly by the TileScheduler.

      Specified by:
      getTile in interface RenderedImage
      Specified by:
      getTile in class PlanarImage
      Parameters:
      tileX - The X index of the tile.
      tileY - The Y index of the tile.
    • computeTile

      public Raster computeTile(int tileX, int tileY)
      Computes the image data of a tile.

      When a tile is requested via the getTile method and that tile is not in this image's tile cache, this method is invoked by the TileScheduler to compute the data of the new tile. Even though this method is marked public, it should not be called by the applications directly. Rather, it is meant to be called by the TileScheduler for the actual computation.

      The implementation of this method in this class assumes that the requested tile either intersects the image, or is within the image's bounds. It creates a new Raster to represent the requested tile, then calls one of the two variants of computeRect to calculate the pixels of the tile that are within the image's bounds. The value of cobbleSources determines which variant of computeRect is invoked, as described in the class comments.

      Subclasses may provide a more optimized implementation of this method. If they override this method not to call either variant of computeRect, then neither variant of computeRect needs to be implemented.

      Parameters:
      tileX - The X index of the tile.
      tileY - The Y index of the tile.
    • getTileDependencies

      public Point[] getTileDependencies(int tileX, int tileY, int sourceIndex)
      Returns a list of indices of the tiles of a given source image that may be required in order to compute a given tile. Ideally, only tiles that will be requested by means of calls to the source's getTile() method should be reported. The default implementation uses mapDestRect() to obtain a conservative estimate.

      If no dependencies exist, this method returns null.

      This method may be used by optimized implementations of ImageN in order to predict future work and create an optimized schedule for performing it.

      A given OpImage may mix calls to getTile() with calls to other methods such as getData() and copyData() in order to avoid requesting entire tiles where only a small portion is needed. In such a case, this method may be overridden to provide a more accurate estimate of the set of getTile() calls that will actually be performed.

      Parameters:
      tileX - the X index of the tile.
      tileY - the Y index of the tile.
      sourceIndex - the index of the source image.
      Returns:
      An array of Points indicating the source tile dependencies.
      Throws:
      IllegalArgumentException - If sourceIndex is negative or greater than the index of the last source.
    • getTiles

      public Raster[] getTiles(Point[] tileIndices)
      Computes the tiles indicated by the given tile indices. This call is preferable to a series of getTile() calls because certain implementations can make optimizations based on the knowledge that multiple tiles are being asked for at once.

      The implementation of this method in this class uses multiple threads to compute multiple tiles at a time.

      Overrides:
      getTiles in class PlanarImage
      Parameters:
      tileIndices - An array of Points representing tile indices.
      Returns:
      An array of Rasters containing the tiles corresponding to the given tile indices.
      Throws:
      IllegalArgumentException - If tileIndices is null.
    • queueTiles

      public TileRequest queueTiles(Point[] tileIndices)
      Queues a list of tiles for computation. Registered listeners will be notified after each tile has been computed. The event source parameter passed to such listeners will be the TileScheduler and the image parameter will be this image.
      Overrides:
      queueTiles in class PlanarImage
      Parameters:
      tileIndices - A list of tile indices indicating which tiles to schedule for computation.
      Throws:
      IllegalArgumentException - If tileIndices is null.
    • cancelTiles

      public void cancelTiles(TileRequest request, Point[] tileIndices)
      Issue an advisory cancellation request to nullify processing of the indicated tiles via the TileScheduler for this image. This method should merely forward the request to the associated TileScheduler.
      Overrides:
      cancelTiles in class PlanarImage
      Parameters:
      request - The request for which tiles are to be cancelled.
      tileIndices - The tiles to be cancelled; may be null. Any tiles not actually in the TileRequest will be ignored.
      Throws:
      IllegalArgumentException - If request is null.
    • prefetchTiles

      public void prefetchTiles(Point[] tileIndices)
      Hints that the given tiles might be needed in the near future. Some implementations may spawn one or more threads to compute the tiles, while others may ignore the hint.
      Overrides:
      prefetchTiles in class PlanarImage
      Parameters:
      tileIndices - A list of tile indices indicating which tiles to prefetch.
      Throws:
      IllegalArgumentException - If tileIndices is null.
    • mapDestPoint

      public Point2D mapDestPoint(Point2D destPt, int sourceIndex)
      Computes the position in the specified source that best matches the supplied destination image position. If it is not possible to compute the requested position, null will be returned. If the point is mapped outside the source bounds, the coordinate value or null may be returned at the discretion of the implementation.

      Floating-point input and output coordinates are supported, and recommended when possible. Subclass implementations may however use integer computation if necessary for simplicity.

      The implementation in this class returns the value of pt in the following code snippet:

       Rectangle destRect = new Rectangle((int)destPt.getX(),
                                          (int)destPt.getY(),
                                          1, 1);
       Rectangle sourceRect = mapDestRect(destRect, sourceIndex);
       Point2D pt = (Point2D)destPt.clone();
       pt.setLocation(sourceRect.x + (sourceRect.width - 1.0)/2.0,
                      sourceRect.y + (sourceRect.height - 1.0)/2.0);
       
      Subclasses requiring different behavior should override this method.
      Parameters:
      destPt - the position in destination image coordinates to map to source image coordinates.
      sourceIndex - the index of the source image.
      Returns:
      a Point2D of the same class as destPt or null.
      Throws:
      IllegalArgumentException - if destPt is null.
      IndexOutOfBoundsException - if sourceIndex is negative or greater than or equal to the number of sources.
    • mapSourcePoint

      public Point2D mapSourcePoint(Point2D sourcePt, int sourceIndex)
      Computes the position in the destination that best matches the supplied source image position. If it is not possible to compute the requested position, null will be returned. If the point is mapped outside the destination bounds, the coordinate value or null may be returned at the discretion of the implementation.

      Floating-point input and output coordinates are supported, and recommended when possible. Subclass implementations may however use integer computation if necessary for simplicity.

      The implementation in this class returns the value of pt in the following code snippet:

       Rectangle sourceRect = new Rectangle((int)sourcePt.getX(),
                                            (int)sourcePt.getY(),
                                            1, 1);
       Rectangle destRect = mapSourceRect(sourceRect, sourceIndex);
       Point2D pt = (Point2D)sourcePt.clone();
       pt.setLocation(destRect.x + (destRect.width - 1.0)/2.0,
                      destRect.y + (destRect.height - 1.0)/2.0);
       
      Parameters:
      sourcePt - the position in source image coordinates to map to destination image coordinates.
      sourceIndex - the index of the source image.
      Returns:
      a Point2D of the same class as sourcePt or null.
      Throws:
      IllegalArgumentException - if sourcePt is null.
      IndexOutOfBoundsException - if sourceIndex is negative or greater than or equal to the number of sources.
    • mapSourceRect

      public abstract Rectangle mapSourceRect(Rectangle sourceRect, int sourceIndex)
      Returns a conservative estimate of the destination region that can potentially be affected by the pixels of a rectangle of a given source. An empty Rectangle may be returned if the destination is unaffected by the contents of the source rectangle. This is distinct from a null return value which serves rather to indicate that it is not possible to determine the bounds of the affected region. The safest interpretation of a null return value is that the entire destination might be affected by any pixel within the given source rectangle.
      Parameters:
      sourceRect - The Rectangle in source coordinates.
      sourceIndex - The index of the source image.
      Returns:
      A Rectangle indicating the potentially affected destination region, or null if the region is unknown.
      Throws:
      IllegalArgumentException - If the source index is negative or greater than that of the last source.
      IllegalArgumentException - If sourceRect is null.
    • mapDestRect

      public abstract Rectangle mapDestRect(Rectangle destRect, int sourceIndex)
      Returns a conservative estimate of the region of a specified source that is required in order to compute the pixels of a given destination rectangle. The computation may as appropriate clip the mapped Rectangle to the actual bounds of the source or may treat the source as having infinite extent. It is therefore the responsibility of the invoking object to constrain the region in accordance with its needs. Returning an empty Rectangle should indicate that the data of the source image in question are not required for the computation of the specified destination region. If the entire source image might be required to compute this destination region, then getSourceImage(sourceIndex).getBounds() should be returned.

      To illustrate the issue of whether the source should be thought to have infinite extent, consider the case wherein computing a destination pixel requires multiple source pixels of context. At the source image boundary, these pixels might only be available if the source data were extrapolated, e.g., using a BorderExtender. If such an extender were available, destination pixels could be computed even if they mapped to a region on the source boundary so in this case the source could be considered to have infinite extent. If no such extender were available, only destination pixels with source context contained within the source image bounds could be considered so that it might be preferable to clip the rectangle to the source bounds.

      Parameters:
      destRect - The Rectangle in destination coordinates.
      sourceIndex - The index of the source image.
      Returns:
      A non-null Rectangle indicating the required source region.
      Throws:
      IllegalArgumentException - If the source index is negative or greater than that of the last source.
      IllegalArgumentException - If destRect is null.
    • getOperationComputeType

      public int getOperationComputeType()
      Returns one of OP_COMPUTE_BOUND, OP_IO_BOUND, or OP_NETWORK_BOUND to indicate how the operation is likely to spend its time. The answer does not affect the output of the operation, but may allow a scheduler to parallelize the computation of multiple operations more effectively.

      The implementation of this method in this class returns OP_COMPUTE_BOUND.

    • computesUniqueTiles

      public boolean computesUniqueTiles()
      Returns true if the OpImage returns an unique Raster object every time computeTile is called. OpImages that internally cache Rasters and return them via computeTile should return false for this method.

      The implementation of this method in this class always returns true.

    • dispose

      public void dispose()
      Uncaches all tiles and calls super.dispose(). If a TileRecycler was defined via the configuration variable ImageN.KEY_TILE_RECYCLER when this image was constructed and tile recycling was enabled via the configuration variable ImageN.KEY_CACHED_TILE_RECYCLING_ENABLED, then each of this image's tiles which is currently in the cache will be recycled. This method may be invoked more than once although invocations after the first one may do nothing.

      The results of referencing an image after a call to dispose() are undefined.

      Overrides:
      dispose in class PlanarImage
    • hasExtender

      public boolean hasExtender(int sourceIndex)
      Deprecated.
      as of ImageN 0.4.0.
      Indicates whether the source with the given index has a BorderExtender. If the source index is out of bounds for the source vector of this OpImage then an ArrayIndexOutOfBoundsException may be thrown.
      Parameters:
      sourceIndex - The index of the source in question.
      Returns:
      true if the indicated source has an extender.
    • getExpandedNumBands

      public static int getExpandedNumBands(SampleModel sampleModel, ColorModel colorModel)
      Deprecated.
      as of ImageN 0.4.0.
      Returns the effective number of bands of an image with a given SampleModel and ColorModel . Normally, this is given by sampleModel.getNumBands(), but for images with an IndexColorModel the effective number of bands is given by colorModel.getNumComponents(), since a single physical sample represents multiple color components.
    • getTileRecycler

      public TileRecycler getTileRecycler()
      Returns the value of the instance variable tileRecycler.