# Class PlanarImage

Object
PlanarImage

All Implemented Interfaces:
  `RenderedImage`

Direct Known Subclasses:
  `ComputedImage`

public abstract class PlanarImage extends Object implements RenderedImage
Base class of `RenderedImage` implementations in Apache SIS. The "Planar" part in the class name emphasizes that this image is a representation of two-dimensional data and should not contain an image with three-dimensional effects. Planar images can be used as data storage for `GridCoverage2D`.
Inspirational source: this class takes some inspiration from the `javax​.media​.jai​.PlanarImage` class defined in the Java Advanced Imaging (JAI) library. That excellent library was 20 years in advance on thematic like defining a chain of image operations, multi-threaded execution, distribution over a computer network, etc. But unfortunately the JAI library does not seems to be maintained anymore. We do not try to reproduce the full set of JAI functionalities here, but we progressively reproduce some little bits of functionalities as they are needed by Apache SIS.

This base class does not store any state, but assumes that numbering of pixel coordinates and tile indices start at zero. Subclasses need to implement at least the following methods:

- `RenderedImage​.getWidth()` — the image width in pixels.
- `RenderedImage​.getHeight()` — the image height in pixels.
- `RenderedImage​.getTileWidth()` — the tile width in pixels.
- `RenderedImage​.getTileHeight()` — the tile height in pixels.
- `RenderedImage​.getTile(int,int)` — the tile at given tile indices.

If pixel coordinates or tile indices do not start at zero, then subclasses shall also override the following methods:

- `getMinX()` — the minimum x coordinate (inclusive) of the image.
- `getMinY()` — the minimum y coordinate (inclusive) of the image.
- `getMinTileX()` — the minimum tile index in the x direction.
- `getMinTileY()` — the minimum tile index in the y direction.

Default implementations are provided for `getNumXTiles()`, `getNumYTiles()`, `getTileGridXOffset()`, `getTileGridYOffset()`, `getData()`, `getData(Rectangle)` and `copyData(WritableRaster)` in terms of above methods.

## Writable images

Some subclasses may implement the `WritableRenderedImage` interface. If this image is writable, then the `WritableRenderedImage​.getWritableTile(…)` and `releaseWritableTile(…)` methods should be invoked in `try ... finally` blocks like below:

    WritableRenderedImage image = ...;
    WritableRaster tile = image.getWritableTile(tileX, tileY);
    try {
        // Do some process on the tile.
    } finally {
        image.releaseWritableTile(tileX, tileY);
    }

This is recommended because implementations may count the number of acquisitions and releases for deciding when to notify the `TileObserver`s. Some implementations may also acquire and release synchronization locks in the `getWritableTile(…)` and `releaseWritableTile(…)` methods. Apache SIS does not yet define a synchronization policy for `WritableRenderedImage`, but such policy may be defined in a future version.

Since:
  1.1

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `static final String`
  `GRID_GEOMETRY_KEY`
  Key for a property defining a conversion from pixel coordinates to "real world" coordinates.
  `static final String`
  `MASK_KEY`
  Key of property providing a mask for missing values.
  `static final String`
  `POSITIONAL_ACCURACY_KEY`
  Key for a property giving an estimation of positional accuracy, typically in metres or pixel units.
  `static final String`
  `SAMPLE_DIMENSIONS_KEY`
  Key for a property defining a conversion from pixel values to the units of measurement.
  `static final String`
  `SAMPLE_RESOLUTIONS_KEY`
  Key of a property defining the resolutions of sample values in each band.
  `static final String`
  `STATISTICS_KEY`
  Key of property providing statistics on sample values in each band.
  `static final String`
  `XY_DIMENSIONS_KEY`
  Key for a property identifying the grid dimensions that are represented as a two-dimensional image.

- ## Constructor Summary

  Constructors
  Modifier
  Constructor
  Description
  `protected`
  `PlanarImage()`
  Creates a new rendered image.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `WritableRaster`
  `copyData(WritableRaster raster)`
  Copies an arbitrary rectangular region of this image to the supplied writable raster.
  `Rectangle`
  `getBounds()`
  Returns the image location (x, y) and image size (width, height).
  `Raster`
  `getData()`
  Returns a copy of this image as one large tile.
  `Raster`
  `getData(Rectangle aoi)`
  Returns a copy of an arbitrary region of this image.
  `int`
  `getMinTileX()`
  Returns the minimum tile index in the x direction.
  `int`
  `getMinTileY()`
  Returns the minimum tile index in the y direction.
  `int`
  `getMinX()`
  Returns the minimum x coordinate (inclusive) of this image.
  `int`
  `getMinY()`
  Returns the minimum y coordinate (inclusive) of this image.
  `int`
  `getNumXTiles()`
  Returns the number of tiles in the x direction.
  `int`
  `getNumYTiles()`
  Returns the number of tiles in the y direction.
  `Object`
  `getProperty(String key)`
  Gets a property from this image.
  `String[]`
  `getPropertyNames()`
  Returns the names of all recognized properties, or `null` if this image has no properties.
  `Vector<RenderedImage>`
  `getSources()`
  Returns the immediate sources of image data for this image.
  `int`
  `getTileGridXOffset()`
  Returns the x coordinate of the upper-left pixel of tile (0, 0).
  `int`
  `getTileGridYOffset()`
  Returns the y coordinate of the upper-left pixel of tile (0, 0).
  `Shape`
  `getValidArea()`
  Returns a shape containing all pixels that are valid in this image.
  `String`
  `toString()`
  Returns a string representation of this image for debugging purpose.
  `String`
  `verify()`
  Verifies whether image layout information are consistent.

  ### Methods inherited from class Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

  ### Methods inherited from interface RenderedImage

  `getColorModel, getHeight, getSampleModel, getTile, getTileHeight, getTileWidth, getWidth`

- ## Field Details

  - ### XY_DIMENSIONS_KEY

    public static final String XY_DIMENSIONS_KEY
    Key for a property identifying the grid dimensions that are represented as a two-dimensional image. For an image which is the result of rendering a two-dimensional slice of a multi-dimensional grid coverage, this property maps the x and y axes of this image to the dimensions of the grid of the source coverage.

    The property value is an `int[]` array of length 2. The value at array index 0 identifies the source grid dimension of the x image axis, which is usually 0. The value at array index 1 identifies the source grid dimension of the y image axis, which is usually 1.

    Since:
      1.5
    See Also:
      - `ImageRenderer​.getXYDimensions()`
      - `GridExtent​.getSubspaceDimensions(int)`
      - Constant Field Values

  - ### GRID_GEOMETRY_KEY

    public static final String GRID_GEOMETRY_KEY
    Key for a property defining a conversion from pixel coordinates to "real world" coordinates. Other information include an envelope in "real world" coordinates and an estimation of pixel resolution. The value is a `GridGeometry` instance with following properties:
    - The number of grid dimensions is always 2.
    - The number of CRS dimensions is always 2.
    - The grid extent is the image bounds.
    - The grid to CRS map pixel coordinates "real world" coordinates (always two-dimensional).
    See Also:
      - `ImageRenderer​.getImageGeometry(int)`
      - Constant Field Values

  - ### POSITIONAL_ACCURACY_KEY

    public static final String POSITIONAL_ACCURACY_KEY
    Key for a property giving an estimation of positional accuracy, typically in metres or pixel units. Pixel positions may have limited accuracy when they are computed by coordinate transformations. The position may also be inaccurate because of approximation applied for faster rendering.

    Values should be instances of ``Quantity``. The array length is typically 1 or 2. If accuracy is limited by a coordinate transformation, then the array should contain an accuracy expressed in a linear unit such as meter. If accuracy is limited by an approximation applied during resampling operation, then the array should contain an accuracy expressed in pixel units.

    See Also:
      - `ResampledImage​.POSITIONAL_CONSISTENCY_KEY`
      - `CoordinateOperation​.getCoordinateOperationAccuracy()`
      - Constant Field Values

  - ### SAMPLE_DIMENSIONS_KEY

    public static final String SAMPLE_DIMENSIONS_KEY
    Key for a property defining a conversion from pixel values to the units of measurement. The value should be an array of `SampleDimension` instances. The array length should be the number of bands. The array may contain null elements if this information is missing in some bands.
    Example: null elements may happen if this image is an aggregation of bands of two or more images, and some but not all images define this property.
    Since:
      1.4
    See Also:
      - `GridCoverage​.getSampleDimensions()`
      - Constant Field Values

  - ### SAMPLE_RESOLUTIONS_KEY

    public static final String SAMPLE_RESOLUTIONS_KEY
    Key of a property defining the resolutions of sample values in each band. This property is recommended for images having sample values as floating point numbers. For example if sample values were computed by value = integer × scale factor, then the resolution is the scale factor. This information can be used for choosing the number of fraction digits to show when writing sample values in text format.

    Resolution is not accuracy. There is no guarantee that the data accuracy is as good as the resolution given by this property.

    Values should be instances of `double[]`. The array length should be the number of bands. This property may be computed automatically during conversions from integer values to floating point values. Values should be strictly positive and finite but may be `Double​.NaN` if this information is unknown for a band.

    See Also:
      - Constant Field Values

  - ### STATISTICS_KEY

    public static final String STATISTICS_KEY
    Key of property providing statistics on sample values in each band. Providing a value for this key is recommended when those statistics are known in advance (for example if they are provided in some metadata of a raster format). Statistics are useful for stretching a color palette over the values actually used in an image.

    Values should be instances of `Statistics[]`. The array length should be the number of bands. Some array elements may be `null` if the statistics are not available for all bands.

    Statistics are only indicative. They may be computed on a subset of the sample values. If this property is not provided, some image rendering or exportation processes may have to compute statistics themselves by iterating over pixel values, which can be costly.

    See Also:
      - `ImageProcessor​.statistics(RenderedImage, Shape, DoubleUnaryOperator...)`
      - Constant Field Values

  - ### MASK_KEY

    public static final String MASK_KEY
    Key of property providing a mask for missing values. Values should be instances of `RenderedImage` with a single band, binary sample values and a color model of `Transparency​.BITMASK` type. The binary values 0 and 1 are alpha values: 0 for fully transparent pixels and 1 for fully opaque pixels. For every pixel (x,y) in this image, the pixel at the same coordinates in the mask is either fully transparent (sample value 0) if the sample value in this image is valid, or fully opaque (sample value 1) if the sample value in this image is invalid (`Float​.NaN`).

    If this `PlanarImage` has more than one band, then the value for this property is the overlay of masks of each band: pixels are 0 when sample values are valid in all bands, and 1 when sample value is invalid in at least one band.

    Note that it is usually not necessary to use masks explicitly in Apache SIS because missing values are represented by `Float​.NaN`. This property is provided for algorithms that cannot work with NaN values.

    See Also:
      - Constant Field Values

- ## Constructor Details

  - ### PlanarImage

    protected PlanarImage()
    Creates a new rendered image.

- ## Method Details

  - ### getSources

    public Vector<RenderedImage> getSources()
    Returns the immediate sources of image data for this image. This method returns `null` if the image has no information about its immediate sources. It returns an empty vector if the image object has no immediate sources.

    The default implementation returns `null`. Note that this is not equivalent to an empty vector.

    Specified by:
      `getSources` in interface `RenderedImage`
    Returns:
      the immediate sources, or `null` if unknown.

  - ### getProperty

    public Object getProperty(String key)
    Gets a property from this image. The property to get is identified by the specified key. The set of available keys is given by `getPropertyNames()` and depends on the image instance. The following table gives examples of keys recognized by some Apache SIS `RenderedImage` instances:

    Examples of property keys
    Keys | Values
    --- | ---
    "org.apache.sis.XYDimensions" | Indexes of the dimensions of the source grid which are represented as a rendered image.
    "org.apache.sis.GridGeometry" | Conversion from pixel coordinates to "real world" coordinates.
    "org.apache.sis.PositionalAccuracy" | Estimation of positional accuracy, typically in metres or pixel units.
    "org.apache.sis.SampleDimensions" | Conversions from pixel values to the units of measurement for each band.
    "org.apache.sis.SampleResolutions" | Resolutions of sample values in each band.
    "org.apache.sis.Statistics" | Minimum, maximum and mean values for each band.
    "org.apache.sis.Mask" | Image with transparent pixels at locations of valid values and opaque pixels elsewhere.
    "org.apache.sis.PositionalConsistency" | Estimation of positional error for each pixel as a consistency check.
    "org.apache.sis.SourcePadding" | Amount of additional source pixels needed on each side of a destination pixel for computing its value.

    This method shall return `Image​.UndefinedProperty` if the specified property is not defined. The default implementation returns `Image​.UndefinedProperty` in all cases.
    Specified by:
      `getProperty` in interface `RenderedImage`
    Parameters:
      `key` - the name of the property to get.
    Returns:
      the property value, or `Image​.UndefinedProperty` if none.

  - ### getPropertyNames

    public String[] getPropertyNames()
    Returns the names of all recognized properties, or `null` if this image has no properties. This method may conservatively return the names of properties that may exist, when checking if they actually exist would cause a potentially costly computation.

    The default implementation returns `null`.

    Specified by:
      `getPropertyNames` in interface `RenderedImage`
    Returns:
      names of all recognized properties, or `null` if none.

  - ### getValidArea

    public Shape getValidArea()
    Returns a shape containing all pixels that are valid in this image. The returned shape may conservatively contain more than the minimal set of valid pixels. It should be relatively quick to compute. In particular, invoking this method should not cause the calculation of tiles (e.g. for searching NaN sample values). The shape should be fully contained inside the image bounds.

    #### Default implementation

    The default implementation returns `getBounds()`.
    Returns:
      a shape containing all pixels that are valid. Not necessarily the smallest shape containing those pixels, but shall be fully contained inside the image bounds.
    Since:
      1.5

  - ### getBounds

    public Rectangle getBounds()
    Returns the image location (x, y) and image size (width, height). This is a convenience method encapsulating the results of 4 method calls in a single object.
    Returns:
      the image location and image size as a new rectangle.
    See Also:
      - `getMinX()`
      - `getMinY()`
      - `RenderedImage​.getWidth()`
      - `RenderedImage​.getHeight()`

  - ### getMinX

    public int getMinX()
    Returns the minimum x coordinate (inclusive) of this image.

    Default implementation returns zero. Subclasses shall override this method if the image starts at another coordinate.

    Specified by:
      `getMinX` in interface `RenderedImage`
    Returns:
      the minimum x coordinate (column) of this image.

  - ### getMinY

    public int getMinY()
    Returns the minimum y coordinate (inclusive) of this image.

    The default implementation returns zero. Subclasses shall override this method if the image starts at another coordinate.

    Specified by:
      `getMinY` in interface `RenderedImage`
    Returns:
      the minimum y coordinate (row) of this image.

  - ### getMinTileX

    public int getMinTileX()
    Returns the minimum tile index in the x direction.

    The default implementation returns zero. Subclasses shall override this method if the tile grid starts at another index.

    Specified by:
      `getMinTileX` in interface `RenderedImage`
    Returns:
      the minimum tile index in the x direction.

  - ### getMinTileY

    public int getMinTileY()
    Returns the minimum tile index in the y direction.

    The default implementation returns zero. Subclasses shall override this method if the tile grid starts at another index.

    Specified by:
      `getMinTileY` in interface `RenderedImage`
    Returns:
      the minimum tile index in the y direction.

  - ### getNumXTiles

    public int getNumXTiles()
    Returns the number of tiles in the x direction.

    The default implementation computes this value from `RenderedImage​.getWidth()` and `RenderedImage​.getTileWidth()` on the assumption that `getMinX()` is the coordinate of the leftmost pixels of tiles located at `getMinTileX()` index. This assumption can be verified by `verify()`.

    Specified by:
      `getNumXTiles` in interface `RenderedImage`
    Returns:
      returns the number of tiles in the x direction.

  - ### getNumYTiles

    public int getNumYTiles()
    Returns the number of tiles in the y direction.

    The default implementation computes this value from `RenderedImage​.getHeight()` and `RenderedImage​.getTileHeight()` on the assumption that `getMinY()` is the coordinate of the uppermost pixels of tiles located at `getMinTileY()` index. This assumption can be verified by `verify()`.

    Specified by:
      `getNumYTiles` in interface `RenderedImage`
    Returns:
      returns the number of tiles in the y direction.

  - ### getTileGridXOffset

    public int getTileGridXOffset()
    Returns the x coordinate of the upper-left pixel of tile (0, 0). That tile (0, 0) may not actually exist.

    The default implementation computes this value from `getMinX()`, `getMinTileX()` and `RenderedImage​.getTileWidth()`.

    Specified by:
      `getTileGridXOffset` in interface `RenderedImage`
    Returns:
      the x offset of the tile grid relative to the origin.

  - ### getTileGridYOffset

    public int getTileGridYOffset()
    Returns the y coordinate of the upper-left pixel of tile (0, 0). That tile (0, 0) may not actually exist.

    The default implementation computes this value from `getMinY()`, `getMinTileY()` and `RenderedImage​.getTileHeight()`.

    Specified by:
      `getTileGridYOffset` in interface `RenderedImage`
    Returns:
      the y offset of the tile grid relative to the origin.

  - ### getData

    public Raster getData()
    Returns a copy of this image as one large tile. The returned raster will not be updated if this image is changed.
    Specified by:
      `getData` in interface `RenderedImage`
    Returns:
      a copy of this image as one large tile.

  - ### getData

    public Raster getData(Rectangle aoi)
    Returns a copy of an arbitrary region of this image. The returned raster will not be updated if this image is changed.
    Specified by:
      `getData` in interface `RenderedImage`
    Parameters:
      `aoi` - the region of this image to copy.
    Returns:
      a copy of this image in the given area of interest.
    Throws:
      `IllegalArgumentException` - if the given rectangle is not contained in this image bounds.

  - ### copyData

    public WritableRaster copyData(WritableRaster raster)
    Copies an arbitrary rectangular region of this image to the supplied writable raster. The region to be copied is determined from the bounds of the supplied raster. The supplied raster must have a `SampleModel` that is compatible with this image. If the given raster is `null`, a new raster is created by this method.
    Specified by:
      `copyData` in interface `RenderedImage`
    Parameters:
      `raster` - the raster to hold a copy of this image, or `null`.
    Returns:
      the given raster if it was not-null, or a new raster otherwise.

  - ### verify

    public String verify()
    Verifies whether image layout information are consistent. This method verifies that the coordinates of image upper-left corner are equal to the coordinates of the upper-left corner of the tile in the upper-left corner, and that image size is equal to the sum of the sizes of all tiles. Compatibility of sample model and color model is also verified.

    The default implementation may return the following identifiers, in that order (i.e. this method returns the identifier of the first test that fail):

    Identifiers of inconsistent values
    Identifier | Meaning
    --- | ---
    `"colorModel"` | Color model is incompatible with sample model.
    `"tileWidth"` | Tile width is greater than sample model width.
    `"tileHeight"` | Tile height is greater than sample model height.
    `"numXTiles"` | Number of tiles on the X axis is inconsistent with image width.
    `"numYTiles"` | Number of tiles on the Y axis is inconsistent with image height.
    `"tileX"` | `minTileX` and/or `tileGridXOffset` is inconsistent.
    `"tileY"` | `minTileY` and/or `tileGridYOffset` is inconsistent.
    `"width"` | image width is not an integer multiple of tile width.
    `"height"` | Image height is not an integer multiple of tile height.

    Subclasses may perform additional checks. For example, some subclasses have specialized checks for `"minX"`, `"minY"`, `"tileGridXOffset"` and `"tileGridYOffset"` values before to fallback on the more generic `"tileX"` and `"tileY"` above checks. The returned identifiers may also have subcategories. For example `"colorModel"` may be subdivided with `"colorModel​.numBands"` and `"colorModel​.transferType"`.

    #### Ignorable inconsistency

    Inconsistency in `"width"` and `"height"` values may be acceptable if all other verifications pass (in particular the `"numXTiles"` and `"numYTiles"` checks). It happens when tiles in the last row or last column have some unused space compared to the image size. This is legal in TIFF format for example. For this reason, the `"width"` and `"height"` values should be checked last, after all other values have been verified consistent.
    Returns:
      `null` if image layout information are consistent, or the name of inconsistent attribute if a problem is found.

  - ### toString

    public String toString()
    Returns a string representation of this image for debugging purpose. This string representation may change in any future SIS version.
    Overrides:
      `toString` in class `Object`
    Returns:
      a string representation of this image for debugging purpose only.