# Class GridCoverageProcessor

Object
GridCoverageProcessor

All Implemented Interfaces:
  `Cloneable`

public class GridCoverageProcessor extends Object implements Cloneable
A predefined set of operations on grid coverages. After instantiation, `GridCoverageProcessor` can be configured for the following aspects:

- Interpolation method to use during resampling operations.
- Fill values to use for cells that cannot be computed.
- Colorization algorithm to apply for colorizing a computed image.
- Positional accuracy hints for enabling the use of faster algorithm when a lower accuracy is acceptable.
- Optimizations to enable.

For each coverage operations, above properties are combined with parameters given to the operation method.

## Thread-safety

`GridCoverageProcessor` is safe for concurrent use in multi-threading environment.

Since:
  1.1
See Also:
  - `ImageProcessor`

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Class
  Description
  `static enum`
  `GridCoverageProcessor​.Optimization`
  Types of changes that a coverage processor can do for executing an operation more efficiently.

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected final ImageProcessor`
  `imageProcessor`
  The processor to use for operations on two-dimensional slices.
  `protected final EnumSet<GridCoverageProcessor​.Optimization>`
  `optimizations`
  The set of optimizations that are enabled.

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `GridCoverageProcessor()`
  Creates a new processor with default configuration.
  `GridCoverageProcessor(ImageProcessor processor)`
  Creates a new processor initialized to the given configuration.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `GridCoverage`
  `aggregateRanges(GridCoverage... sources)`
  Aggregates in a single coverage the ranges of all specified coverages, in order.
  `GridCoverage`
  `aggregateRanges(GridCoverage[] sources, int[][] bandsPerSource)`
  Aggregates in a single coverage the specified bands of a sequence of source coverages, in order.
  `GridCoverage`
  `appendDimension(GridCoverage source, double lower, double span, SingleCRS crs)`
  Appends a single grid dimension after the dimensions of the given source coverage.
  `GridCoverage`
  `appendDimension(GridCoverage source, Instant lower, Duration span)`
  Appends a temporal grid dimension after the dimensions of the given source coverage.
  `GridCoverage`
  `appendDimensions(GridCoverage source, GridGeometry dimToAdd)`
  Appends the specified grid dimensions after the dimensions of the given source coverage.
  `GridCoverage`
  `clip(GridCoverage source, GridExtent clip)`
  Returns the intersection of the given coverage with the given extent.
  `GridCoverageProcessor`
  `clone()`
  Returns a coverage processor with the same configuration as this processor.
  `GridCoverage`
  `convert(GridCoverage source, MathTransform1D[] converters, Function<SampleDimension​.Builder, SampleDimension> sampleDimensionModifier)`
  Returns a coverage with sample values converted by the given functions.
  `boolean`
  `equals(Object object)`
  Returns `true` if the given object is a coverage processor of the same class with the same configuration.
  `Colorizer`
  `getColorizer()`
  Returns the colorization algorithm to apply on computed images.
  `Number[]`
  `getFillValues()`
  Returns the values to use for pixels that cannot be computed.
  `Interpolation`
  `getInterpolation()`
  Returns the interpolation method to use for resampling operations.
  `Set<GridCoverageProcessor​.Optimization>`
  `getOptimizations()`
  Returns the set of optimizations that are enabled.
  `Quantity<?>[]`
  `getPositionalAccuracyHints()`
  Returns hints about the desired positional accuracy, in "real world" units or in pixel units.
  `int`
  `hashCode()`
  Returns a hash code value for this coverage processor based on its current configuration.
  `GridCoverage`
  `mask(GridCoverage source, RegionOfInterest mask, boolean maskInside)`
  Applies a mask defined by a region of interest (ROI).
  `GridCoverage`
  `reduceDimensionality(GridCoverage source)`
  Automatically reduces a grid coverage dimensionality by removing all grid axes with an extent size of 1.
  `GridCoverage`
  `removeGridDimensions(GridCoverage source, int... gridAxesToRemove)`
  Creates a coverage trimmed from the specified grid dimensions.
  `GridCoverage`
  `resample(GridCoverage source, GridGeometry target)`
  Creates a new coverage with a different grid extent, resolution or coordinate reference system.
  `GridCoverage`
  `resample(GridCoverage source, CoordinateReferenceSystem target)`
  Creates a new coverage with a different coordinate reference system.
  `GridCoverage`
  `selectGridDimensions(GridCoverage source, int... gridAxesToPass)`
  Creates a coverage containing only the specified grid dimensions.
  `GridCoverage`
  `selectSampleDimensions(GridCoverage source, int... bands)`
  Selects a subset of sample dimensions (bands) in the given coverage.
  `void`
  `setColorizer(Colorizer colorizer)`
  Sets the colorization algorithm to apply on computed images.
  `void`
  `setFillValues(Number... values)`
  Sets the values to use for pixels that cannot be computed.
  `void`
  `setInterpolation(Interpolation method)`
  Sets the interpolation method to use for resampling operations.
  `void`
  `setOptimizations(Set<GridCoverageProcessor​.Optimization> enabled)`
  Specifies the set of optimizations to enable.
  `void`
  `setPositionalAccuracyHints(Quantity<?>... hints)`
  Sets hints about desired positional accuracy, in "real world" units or in pixel units.
  `GridCoverage`
  `shiftGrid(GridCoverage source, long... translation)`
  Translates grid coordinates by the given number of cells without changing "real world" coordinates.
  `RenderedImage`
  `visualize(GridCoverage source, GridExtent slice)`
  Renders the given grid coverage as an image suitable for displaying purpose.

  ### Methods inherited from class Object

  `finalize, getClass, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### imageProcessor

    protected final ImageProcessor imageProcessor
    The processor to use for operations on two-dimensional slices.

  - ### optimizations

    protected final EnumSet<GridCoverageProcessor.Optimization> optimizations
    The set of optimizations that are enabled. By default, this set contains all enumeration values.
    Since:
      1.3
    See Also:
      - `getOptimizations()`
      - `setOptimizations(Set)`

- ## Constructor Details

  - ### GridCoverageProcessor

    public GridCoverageProcessor()
    Creates a new processor with default configuration.

  - ### GridCoverageProcessor

    public GridCoverageProcessor(ImageProcessor processor)
    Creates a new processor initialized to the given configuration.
    Parameters:
      `processor` - the processor to use for operations on two-dimensional slices.

- ## Method Details

  - ### getInterpolation

    public Interpolation getInterpolation()
    Returns the interpolation method to use for resampling operations. The default implementation delegates to the image processor.
    Returns:
      interpolation method to use in resampling operations.
    See Also:
      - `ImageProcessor​.getInterpolation()`

  - ### setInterpolation

    public void setInterpolation(Interpolation method)
    Sets the interpolation method to use for resampling operations. The default implementation delegates to the image processor.
    Parameters:
      `method` - interpolation method to use in resampling operations.
    See Also:
      - `ImageProcessor​.setInterpolation(Interpolation)`

  - ### getFillValues

    public Number[] getFillValues()
    Returns the values to use for pixels that cannot be computed. The default implementation delegates to the image processor.
    Returns:
      fill values to use for pixels that cannot be computed, or `null` for the defaults.
    Since:
      1.2
    See Also:
      - `ImageProcessor​.getFillValues()`

  - ### setFillValues

    public void setFillValues(Number... values)
    Sets the values to use for pixels that cannot be computed. The default implementation delegates to the image processor.
    Parameters:
      `values` - fill values to use for pixels that cannot be computed, or `null` for the defaults.
    Since:
      1.2
    See Also:
      - `ImageProcessor​.setFillValues(Number...)`

  - ### getColorizer

    public Colorizer getColorizer()
    Returns the colorization algorithm to apply on computed images. The default implementation delegates to the image processor.
    Returns:
      colorization algorithm to apply on computed image, or `null` for default.
    Since:
      1.4
    See Also:
      - `ImageProcessor​.getColorizer()`

  - ### setColorizer

    public void setColorizer(Colorizer colorizer)
    Sets the colorization algorithm to apply on computed images. The colorizer is used by `convert(…)` and `aggregateRanges(…)` operations among others. The default implementation delegates to the image processor.
    Parameters:
      `colorizer` - colorization algorithm to apply on computed image, or `null` for default.
    Since:
      1.4
    See Also:
      - `ImageProcessor​.setColorizer(Colorizer)`
      - `visualize(GridCoverage, GridExtent)`

  - ### getPositionalAccuracyHints

    public Quantity<?>[] getPositionalAccuracyHints()
    Returns hints about the desired positional accuracy, in "real world" units or in pixel units. The default implementation delegates to the image processor.
    Returns:
      desired accuracy in no particular order, or an empty array if none.
    See Also:
      - `ImageProcessor​.getPositionalAccuracyHints()`

  - ### setPositionalAccuracyHints

    public void setPositionalAccuracyHints(Quantity<?>... hints)
    Sets hints about desired positional accuracy, in "real world" units or in pixel units. The default implementation delegates to the image processor.
    Parameters:
      `hints` - desired accuracy in no particular order, or a `null` array if none. Null elements in the array are ignored.
    See Also:
      - `ImageProcessor​.setPositionalAccuracyHints(Quantity...)`

  - ### getOptimizations

    public Set<GridCoverageProcessor.Optimization> getOptimizations()
    Returns the set of optimizations that are enabled. By default, the returned set contains all optimizations.

    The returned set is a copy. Changes in this set will not affect the state of this processor.

    Returns:
      copy of the set of optimizations that are enabled.
    Since:
      1.3

  - ### setOptimizations

    public void setOptimizations(Set<GridCoverageProcessor.Optimization> enabled)
    Specifies the set of optimizations to enable. All optimizations not in the given set will be disabled.
    Parameters:
      `enabled` - set of optimizations to enable.
    Since:
      1.3

  - ### mask

    public GridCoverage mask(GridCoverage source, RegionOfInterest mask, boolean maskInside) throws TransformException
    Applies a mask defined by a region of interest (ROI). If `maskInside` is `true`, then all pixels inside the given ROI are set to the fill values. If `maskInside` is `false`, then the mask is reversed: the pixels set to fill values are the ones outside the ROI.

    #### Properties used

    This operation uses the following properties in addition to method parameters:
    - Fill values values to assign to pixels inside/outside the region of interest.
    Parameters:
      `source` - the coverage on which to apply a mask.
      `mask` - region (in arbitrary CRS) of the mask.
      `maskInside` - `true` for masking pixels inside the shape, or `false` for masking outside.
    Returns:
      a coverage with mask applied.
    Throws:
      `TransformException` - if ROI coordinates cannot be transformed to grid coordinates.
    Since:
      1.2
    See Also:
      - `ImageProcessor​.mask(RenderedImage, Shape, boolean)`

  - ### convert

    public GridCoverage convert(GridCoverage source, MathTransform1D[] converters, Function<SampleDimension.Builder, SampleDimension> sampleDimensionModifier)
    Returns a coverage with sample values converted by the given functions. The number of sample dimensions in the returned coverage is the length of the `converters` array, which must be greater than 0 and not greater than the number of sample dimensions in the source coverage. If the `converters` array length is less than the number of source sample dimensions, then all sample dimensions at index ≥ `converters​.length` will be ignored.

    #### Sample dimensions customization

    By default, this method creates new sample dimensions with the same names and categories than in the previous coverage, but with sample ranges converted using the given converters and with units of measurement omitted. This behavior can be modified by specifying a non-null `sampleDimensionModifier` function. If non-null, that function will be invoked with, as input, a pre-configured sample dimension builder. The `sampleDimensionModifier` function can change the sample dimension name or rebuild the categories.

    #### Result relationship with source

    If the source coverage is backed by a `WritableRenderedImage`, then changes in the source coverage are reflected in the returned coverage and conversely.

    #### Properties used

    This operation uses the following properties in addition to method parameters:
    - Colorizer for customizing the rendered image color model.
    Parameters:
      `source` - the coverage for which to convert sample values.
      `converters` - the transfer functions to apply on each sample dimension of the source coverage.
      `sampleDimensionModifier` - a callback for modifying the `SampleDimension​.Builder` default configuration for each sample dimension of the target coverage, or `null` if none.
    Returns:
      the coverage which computes converted values from the given source.
    Since:
      1.3
    See Also:
      - `ImageProcessor​.convert(RenderedImage, NumberRange<?>[], MathTransform1D[], DataType)`

  - ### shiftGrid

    public GridCoverage shiftGrid(GridCoverage source, long... translation)
    Translates grid coordinates by the given number of cells without changing "real world" coordinates. The translated grid has the same size than the source, i.e. both low and high grid coordinates are displaced by the same number of cells. The "grid to CRS" transforms are adjusted accordingly in order to map to the same "real world" coordinates.

    #### Number of arguments

    The `translation` array length should be equal to the number of dimensions in the source coverage. If the array is shorter, missing values default to 0 (i.e. no translation in unspecified dimensions). If the array is longer, extraneous values are ignored.

    #### Optimizations

    The following optimizations are applied by default and can be disabled if desired:
    - `GridCoverageProcessor​.Optimization​.REPLACE_SOURCE` for merging many calls of this `translate(…)` method into a single translation.

    #### Properties used

    This operation uses the following properties in addition to method parameters:
    - (none)
    Parameters:
      `source` - the grid coverage to translate.
      `translation` - translation to apply on each grid axis in order.
    Returns:
      a grid coverage whose grid coordinates (both low and high ones) and the "grid to CRS" transforms have been translated by given amounts. If the given translation is a no-op (no value or only 0 ones), then the source is returned as is.
    Throws:
      `ArithmeticException` - if the translation results in coordinates that overflow 64-bits integer.
    Since:
      1.3
    See Also:
      - `GridExtent​.translate(long...)`
      - `GridGeometry​.shiftGrid(long...)`

  - ### clip

    public GridCoverage clip(GridCoverage source, GridExtent clip)
    Returns the intersection of the given coverage with the given extent. The extent shall have the same number of dimensions than the coverage. The "grid to CRS" transform is unchanged.

    This method is useful for taking a slice of a multi-dimensional grid. Having a slice allows to invoke `GridCoverage​.render(GridExtent)` with a null argument value.

    Parameters:
      `source` - the grid coverage to clip.
      `clip` - the clip to apply in units of source grid coordinates.
    Returns:
      a coverage with grid coordinates contained inside the given clip.
    Throws:
      `IncompleteGridGeometryException` - if the given coverage has no grid extent.
      `DisjointExtentException` - if the given extent does not intersect the given coverage.
      `IllegalArgumentException` - if axes of the given extent are inconsistent with the axes of the grid of the given coverage.
    Since:
      1.5

  - ### resample

    public GridCoverage resample(GridCoverage source, GridGeometry target) throws TransformException
    Creates a new coverage with a different grid extent, resolution or coordinate reference system. The desired properties are specified by the `GridGeometry` argument, which may be incomplete. The missing grid geometry components are completed as below:

    Default values for undefined grid geometry components
    Component | Default value
    --- | ---
    Grid extent | A default size preserving resolution at source point of interest.
    Grid to CRS transform | Whatever it takes for fitting data inside the supplied extent.
    Coordinate reference system | Same as source coverage.

    The interpolation method can be specified by `setInterpolation(Interpolation)`. If the grid coverage values are themselves interpolated, this method tries to use the original data. The intent is to avoid adding interpolations on top of other interpolations.

    #### Optimizations

    The following optimizations are applied by default and can be disabled if desired:
    - `GridCoverageProcessor​.Optimization​.REPLACE_SOURCE` for merging many calls of `resample(…)` or `translate(…)` method into a single resampling.
    - `GridCoverageProcessor​.Optimization​.REPLACE_OPERATION` for replacing `resample(…)` operation by `translate(…)` when possible.

    #### Properties used

    This operation uses the following properties in addition to method parameters:
    - Interpolation method (nearest neighbor, bilinear, etc).
    - Fill values for pixels outside source image.
    - Positional accuracy hints for enabling faster resampling at the cost of lower precision.
    Parameters:
      `source` - the grid coverage to resample.
      `target` - the desired geometry of returned grid coverage. May be incomplete.
    Returns:
      a grid coverage with the characteristics specified in the given grid geometry.
    Throws:
      `IncompleteGridGeometryException` - if the source grid geometry is missing an information. It may be the source CRS, the source extent, etc. depending on context.
      `TransformException` - if some coordinates cannot be transformed to the specified target.
    See Also:
      - `ImageProcessor​.resample(RenderedImage, Rectangle, MathTransform)`

  - ### resample

    public GridCoverage resample(GridCoverage source, CoordinateReferenceSystem target) throws TransformException
    Creates a new coverage with a different coordinate reference system. The grid extent and "grid to CRS" transform are determined automatically with default values preserving the resolution of source coverage at its point of interest.

    See `resample(GridCoverage, GridGeometry)` for more information about interpolation and allowed optimizations.

    Parameters:
      `source` - the grid coverage to resample.
      `target` - the desired coordinate reference system.
    Returns:
      a grid coverage with the given coordinate reference system.
    Throws:
      `IncompleteGridGeometryException` - if the source grid geometry is missing an information.
      `TransformException` - if some coordinates cannot be transformed to the specified target.
    Since:
      1.3

  - ### appendDimensions

    public GridCoverage appendDimensions(GridCoverage source, GridGeometry dimToAdd)
    Appends the specified grid dimensions after the dimensions of the given source coverage. This method is typically invoked for adding a vertical or temporal axis to a two-dimensional coverage. The grid extent must have a size of one cell in all the specified additional dimensions.
    Parameters:
      `source` - the source on which to append dimensions.
      `dimToAdd` - the dimensions to append. The grid extent size must be 1 cell in all dimensions.
    Returns:
      a coverage with the specified dimensions added.
    Throws:
      `IllegalGridGeometryException` - if a dimension has more than one grid cell, or concatenation would result in duplicated grid axis types, or the compound CRS cannot be created.
    Since:
      1.5

  - ### appendDimension

    public GridCoverage appendDimension(GridCoverage source, double lower, double span, SingleCRS crs)
    Appends a single grid dimension after the dimensions of the given source coverage. This method is typically invoked for adding a vertical axis to a two-dimensional coverage. The default implementation delegates to `appendDimensions(GridCoverage, GridGeometry)`.
    Parameters:
      `source` - the source on which to append a dimension.
      `lower` - lower coordinate value of the slice, in units of the CRS.
      `span` - size of the slice, in units of the CRS.
      `crs` - one-dimensional coordinate reference system of the slice, or `null` if unknown.
    Returns:
      a coverage with the specified dimension added.
    Throws:
      `IllegalGridGeometryException` - if the compound CRS or compound extent cannot be created.
    Since:
      1.5

  - ### appendDimension

    public GridCoverage appendDimension(GridCoverage source, Instant lower, Duration span)
    Appends a temporal grid dimension after the dimensions of the given source coverage. The default implementation delegates to `appendDimensions(GridCoverage, GridGeometry)`.
    Parameters:
      `source` - the source on which to append a temporal dimension.
      `lower` - start time of the slice.
      `span` - duration of the slice.
    Returns:
      a coverage with the specified temporal dimension added.
    Throws:
      `IllegalGridGeometryException` - if the compound CRS or compound extent cannot be created.
    Since:
      1.5

  - ### reduceDimensionality

    public GridCoverage reduceDimensionality(GridCoverage source)
    Automatically reduces a grid coverage dimensionality by removing all grid axes with an extent size of 1. Axes in the reduced grid coverage will be in the same order as in the source coverage.
    Parameters:
      `source` - the coverage to reduce to a lower number of dimensions.
    Returns:
      the reduced grid coverage, or `source` if no grid dimensions can be removed.
    Since:
      1.4
    See Also:
      - `DimensionalityReduction​.reduce(GridGeometry)`

  - ### removeGridDimensions

    public GridCoverage removeGridDimensions(GridCoverage source, int... gridAxesToRemove)
    Creates a coverage trimmed from the specified grid dimensions. This is a dimensionality reduction operation applied to the coverage domain. The dimensions to remove are specified as indices of grid extent axes. It may be the same indices as the indices of the CRS axes which will be removed, but not necessarily.

    #### Constraints

    If the source coverage contains dimensions that are not separable and if only a subset of those dimensions are specified for removal, then this method will throw an `IllegalGridGeometryException`.

    For each dimension that is removed, the size of the grid extent must be 1 cell. If this condition does not hold, then this method will throw a `SubspaceNotSpecifiedException`. If desired, this restriction can be relaxed by direct use of `DimensionalityReduction` as below, where (x, y, z, t) are grid coordinates of a point in the desired slice:

        var reduction = DimensionalityReduction.remove(source.getGridGeometry(), gridAxesToPass);
        reduction = reduction.withSlicePoint(x, y, z, t);
        GridCoverage output = reduction.apply(source);

    Alternatively the `withSlicePoint(…)` call can be omitted if the caller knows that the source coverage can handle ambiguous grid extents.
    Parameters:
      `source` - the coverage to reduce to a lower number of dimensions.
      `gridAxesToRemove` - indices of each grid dimension to strip from result. Duplicated values are ignored.
    Returns:
      the reduced grid coverage, or `source` if no grid dimensions was specified.
    Throws:
      `IndexOutOfBoundsException` - if a grid axis index is out of bounds.
      `SubspaceNotSpecifiedException` - if at least one removed dimension has a grid extent size larger than 1 cell.
      `IllegalGridGeometryException` - if the dimensions to keep cannot be separated from the dimensions to omit.
    Since:
      1.4
    See Also:
      - `DimensionalityReduction​.remove(GridGeometry, int...)`

  - ### selectGridDimensions

    public GridCoverage selectGridDimensions(GridCoverage source, int... gridAxesToPass)
    Creates a coverage containing only the specified grid dimensions. This is a dimensionality reduction operation applied to the coverage domain. The dimensions to keep are specified as indices of grid extent axes. It may be the same indices as the indices of the CRS axes which will pass through, but not necessarily.

    The axis order in the returned coverage is always the same as in the given `source` coverage, whatever the order in which axes are specified as input in the `gridAxesToPass` array. Duplicated values in the array are also ignored.

    #### Constraints

    If the source coverage contains dimensions that are not separable and if only a subset of those dimensions are selected in the `gridAxesToPass` array, then this method will throw an `IllegalGridGeometryException`.

    For each dimension that is not passed to the output grid coverage, the size of the grid extent must be 1 cell. If this condition does not hold, then this method will throw a `SubspaceNotSpecifiedException`. If desired, this restriction can be relaxed by direct use of `DimensionalityReduction` as below, where (x, y, z, t) are grid coordinates of a point in the desired slice:

        var reduction = DimensionalityReduction.select(source.getGridGeometry(), gridAxesToPass);
        reduction = reduction.withSlicePoint(x, y, z, t);
        GridCoverage output = reduction.apply(source);

    Alternatively the `withSlicePoint(…)` call can be omitted if the caller knows that the source coverage can handle ambiguous grid extents.
    Parameters:
      `source` - the coverage to reduce to a lower number of dimensions.
      `gridAxesToPass` - indices of each grid dimension to maintain in result. Order and duplicated values are ignored.
    Returns:
      the reduced grid coverage, or `source` if all grid dimensions where specified.
    Throws:
      `IndexOutOfBoundsException` - if a grid axis index is out of bounds.
      `SubspaceNotSpecifiedException` - if at least one removed dimension has a grid extent size larger than 1 cell.
      `IllegalGridGeometryException` - if the dimensions to keep cannot be separated from the dimensions to omit.
    Since:
      1.4
    See Also:
      - `DimensionalityReduction​.select(GridGeometry, int...)`

  - ### selectSampleDimensions

    public GridCoverage selectSampleDimensions(GridCoverage source, int... bands)
    Selects a subset of sample dimensions (bands) in the given coverage. This method can also be used for changing sample dimension order or for repeating the same sample dimension from the source coverage. If the specified `bands` indices select all sample dimensions in the same order, then `source` is returned directly.
    Parameters:
      `source` - the coverage in which to select sample dimensions.
      `bands` - indices of sample dimensions to retain.
    Returns:
      coverage width selected sample dimensions.
    Throws:
      `IllegalArgumentException` - if a sample dimension index is invalid.
    Since:
      1.4
    See Also:
      - `ImageProcessor​.selectBands(RenderedImage, int...)`

  - ### aggregateRanges

    public GridCoverage aggregateRanges(GridCoverage... sources)
    Aggregates in a single coverage the ranges of all specified coverages, in order. The list of sample dimensions of the aggregated coverage will be the concatenation of the lists from all sources.

    This convenience method delegates to `aggregateRanges(GridCoverage[], int[][])`. See that method for more information on restrictions.

    Parameters:
      `sources` - coverages whose ranges shall be aggregated, in order. At least one coverage must be provided.
    Returns:
      the aggregated coverage, or `sources[0]` returned directly if only one coverage was supplied.
    Throws:
      `IllegalGridGeometryException` - if a grid geometry is not compatible with the others.
    Since:
      1.4
    See Also:
      - `aggregateRanges(GridCoverage[], int[][])`
      - `ImageProcessor​.aggregateBands(RenderedImage...)`

  - ### aggregateRanges

    public GridCoverage aggregateRanges(GridCoverage[] sources, int[][] bandsPerSource)
    Aggregates in a single coverage the specified bands of a sequence of source coverages, in order. This method performs the same work as `aggregateRanges(GridCoverage...)`, but with the possibility to specify the sample dimensions to retain in each source coverage. The `bandsPerSource` argument specifies the sample dimensions to keep, in order. That array can be `null` for selecting all sample dimensions in all source coverages, or may contain `null` elements for selecting all sample dimensions of the corresponding coverage. An empty array element (i.e. zero sample dimension to select) discards the corresponding source coverage.

    #### Restrictions

    - All coverage shall use the same CRS.
    - All coverage shall use the same grid to CRS transform except for translation terms.
    - Translation terms in grid to CRS can differ only by an integer number of grid cells.
    - The intersection of the domain of all coverages shall be non-empty.
    - All coverages shall use the same data type in their rendered image.
    Some of those restrictions may be relaxed in future Apache SIS versions.
    Parameters:
      `sources` - coverages whose bands shall be aggregated, in order. At least one coverage must be provided.
      `bandsPerSource` - bands to use for each source coverage, in order. May contain `null` elements.
    Returns:
      the aggregated coverage, or one of the sources if it can be used directly.
    Throws:
      `IllegalGridGeometryException` - if a grid geometry is not compatible with the others.
      `IllegalArgumentException` - if some band indices are duplicated or outside their range of validity.
    Since:
      1.4
    See Also:
      - `ImageProcessor​.aggregateBands(RenderedImage[], int[][])`

  - ### visualize

    public RenderedImage visualize(GridCoverage source, GridExtent slice)
    Renders the given grid coverage as an image suitable for displaying purpose. The resulting image is for visualization only and should not be used for computational purposes. There is no guarantee about the number of bands in returned image or about which formula is used for converting floating point values to integer values.

    #### How to specify colors

    The image colors can be controlled by the `Colorizer` set on this coverage processor. The recommended way is to associate colors to category names, units of measurement or other category properties. Example:

        Map<String,Color[]> colors = Map.of(
            "Temperature", new Color[] {Color.BLUE, Color.MAGENTA, Color.RED},
            "Wind speed",  new Color[] {Color.GREEN, Color.CYAN, Color.BLUE});

        processor.setColorizer(Colorizer.forCategories((category) ->
            colors.get(category.getName().toString(Locale.ENGLISH))));

        RenderedImage visualization = processor.visualize(source, slice);

    #### Properties used

    This operation uses the following properties in addition to method parameters:
    - Colorizer for customizing the rendered image color model.
    Parameters:
      `source` - the grid coverage to visualize.
      `slice` - the slice and extent to render, or `null` for the whole coverage.
    Returns:
      rendered image for visualization purposes only.
    Throws:
      `IllegalArgumentException` - if the given extent does not have the same number of dimensions than the specified coverage or does not intersect.
    Since:
      1.4
    See Also:
      - `ImageProcessor​.visualize(RenderedImage)`

  - ### equals

    public boolean equals(Object object)
    Returns `true` if the given object is a coverage processor of the same class with the same configuration.
    Overrides:
      `equals` in class `Object`
    Parameters:
      `object` - the other object to compare with this processor.
    Returns:
      whether the other object is a coverage processor of the same class with the same configuration.

  - ### hashCode

    public int hashCode()
    Returns a hash code value for this coverage processor based on its current configuration.
    Overrides:
      `hashCode` in class `Object`
    Returns:
      a hash code value for this processor.

  - ### clone

    public GridCoverageProcessor clone()
    Returns a coverage processor with the same configuration as this processor.
    Overrides:
      `clone` in class `Object`
    Returns:
      a clone of this coverage processor.