Class TiledGridCoverageResource

All Implemented Interfaces:
Data­Set, Grid­Coverage­Resource, Resource, Tiled­Resource

public abstract class TiledGridCoverageResource extends AbstractGridCoverageResource implements TiledResource
Base class of grid coverage resources that store data in tiles. The word "tile" is used for simplicity but can be understood as "chunk" in a n-dimensional generalization. Subclasses need to implement the following methods:
Since:
1.7
  • Field Details

    • BIDIMENSIONAL

      protected static final int BIDIMENSIONAL
      Number of dimensions in a two-dimensional slice of data represented as a rendered image. This constant can be used for making easier to identify codes where a two-dimensional slice is assumed.
      See Also:
  • Constructor Details

    • TiledGridCoverageResource

      protected TiledGridCoverageResource(Resource parent)
      Creates a new resource.
      Parameters:
      parent - the parent resource, or null if none.
  • Method Details

    • getTileSize

      protected abstract int[] getTileSize() throws DataStoreException
      Returns the size of tiles in the grid coverages read by this resource. The length of the returned array is the number of dimensions, which must be 2 or greater.
      Returns:
      the size of tiles (in pixels) in the Rendered­Images created by this resource.
      Throws:
      Data­Store­Exception - if an error occurred while fetching the tile size.
    • getAtomSize

      protected int getAtomSize(int dim) throws DataStoreException
      Returns the number of sample values in an indivisible element of a tile. An element is a primitive type such as byte, int or float. This value is usually 1 when each sample value is stored in a separated element. However, in multi-pixels packed sample model (e.g. bilevel image with 8 pixels per byte), it is difficult to start reading an image at x location other than a byte boundary. By declaring an "atom" size of 8 sample values in dimension 0 (x), the Tiled­Grid­Coverage­Resource​.Subset constructor will ensure that the sub-region to read starts at a byte boundary when reading a bilevel image.

      The default implementation returns the number of pixels per data element for dimension 0 and returns 1 for all other dimensions.

      Parameters:
      dim - the dimension: 0 for x, 1 for y, etc.
      Returns:
      indivisible number of sample values to read in the specified dimension. Must be ≥ 1. This is in units of sample values (may be bits, bytes, floats, etc).
      Throws:
      Data­Store­Exception - if an error occurred while fetching the sample model.
    • supportsVirtualTileSize

      protected boolean supportsVirtualTileSize(long[] virtualTileSize) throws DataStoreException
      Returns whether this resource can read a tiled image as if the tiles had the specified size. This method is invoked when Tiled­Grid­Coverage­Resource wishes to create an image with tiles that are larger or smaller than the real tile size returned by get­Tile­Size(). A return value of true means that the subclass can use the given tile size easily. It is the case, for example, if the subclass delegates its work to another library such as GDAL which answers to arbitrary requests with its own tile management. If this method returns false, then Tiled­Grid­Coverage­Resource may try a different tile size or use a fallback simulating the desired tiling.

      Tile size amendment

      If the subclass does not support exactly the given size but would support a slightly different size, then this method can modify the given virtual­Tile­Size array in-place and return true. The updated values will be used by the caller as the new virtual tile size.

      Use cases

      Tiled­Grid­Coverage­Resource may want to read many tiles as if they were a single tile. Such coalescing can be useful for avoiding that a read operation produces tiles that become too small after subsampling. In such case, virtual tile sizes are larger than real tile sizes.

      Conversely, Tiled­Grid­Coverage­Resource may want to apply an artificial tiling on an untiled image, or re-tile an image having unreasonably large tiles (with "unreasonable" defined by an arbitrary threshold). This is done by using a virtual tile size which is smaller than the real tile size. Note that this artificial tiling is applied only if the loading strategy is Raster­Loading­Strategy​.AT_GET_TILE_TIME or, to a lesser extent, AT_RENDER_TIME.

      Note for implementers

      Except in untiled cases, Tiled­Grid­Coverage aligns the Grid­Extents requested by users on the boundaries of real tiles, not on the boundaries of virtual tiles. Therefore, a subclass should return true for arbitrary virtual tile sizes only if that subclass can read fractions of the areas covered by real tiles and assemble these areas in a single Raster. If the subclass can assemble only whole real tiles, then this method should accept only virtual tile sizes that are multiple of the real tile size.

      This method is not invoked for the values returned by get­Tile­Size(). It may not be invoked neither for untiled image. Therefore, this method does not need to handle those special cases. The default implementation unconditionally returns false.

      Parameters:
      virtual­Tile­Size - the size of virtual tiles. Can be amended in-place.
      Returns:
      whether this resource can pretend that tiles have the given size.
      Throws:
      Data­Store­Exception - if an error occurred while verifying the tile size.
      See Also:
    • canReadTruncatedTiles

      protected boolean canReadTruncatedTiles(int dim, boolean suggested)
      Returns true if the reader can load truncated tiles. Truncated tiles may happen in the last row and last column of a tile matrix when the image size is not a multiple of the tile size. Some file formats, such as GeoTIFF, unconditionally store full tiles, in which case this method should return false. At the opposite, some implementations, such as GDAL, accept only requests over the valid area, in which case this method should return true.

      Suggested value

      The suggested argument is a value computed by the caller based on common usages. The default implementation of Tiled­Grid­Coverage suggests true if the read operation is inside a single big tile, or false otherwise. The default implementation of this method returns suggested unchanged.

      Note that even for subclasses that generally do not support the reading of truncated tiles, it is often safe to return true for the last dimension (for example, y in a two-dimensional image), because there is no data after that dimension. Therefore, it is often safe to stop the reading process in that dimension.

      Parameters:
      dim - the dimension: 0 for x, 1 for y, etc.
      suggested - suggested response to return (see above heuristic rules).
      Returns:
      whether the reader can load truncated tiles along the specified dimension.
    • canSeparateBands

      protected boolean canSeparateBands() throws DataStoreException
      Returns true if the reader can load only the requested bands and skip the other bands, or false if the reader must load all bands. This value controls the amount of data to be loaded by read(Grid­Geometry, int...):
      • If false, then Tiled­Grid­Coverage​.model will expect the same Data­Buffer than the one expected by the sample model of this resource. All bands will be loaded but the coverage sample model will ignore the bands that were not enumerated in the range argument. This strategy is convenient when skipping bands at reading time is difficult.
      • If true, then Tiled­Grid­Coverage​.model will have its band indices and bit masks "compressed" for making them consecutive. For example if the range argument specifies that the bands to read are {1, 3, 4, 6}, then after "compression" band indices become {0, 1, 2, 3}. This strategy is efficient when the reader is capable to skip bands at reading time.

      The default implementation returns true if the sample model is a Component­Sample­Model and false in all other cases, because skipping bands in a packed sample model is more difficult to implement.

      Returns:
      true if the reader can load only the requested bands and skip other bands, or false if the reader needs to load all bands regardless the range subset.
      Throws:
      Data­Store­Exception - if an error occurred while fetching the sample model.
      See Also:
      • Range­Argument​.select(Sample­Model, boolean)
    • getSampleModel

      protected SampleModel getSampleModel(int[] bands) throws DataStoreException
      Returns the Java2D sample model describing pixel type and layout for the specified bands. The raster size shall be the two first dimensions of the tile size. This is the size of tiles as stored in the resource, i.e. ignoring sub-sampling.

      If the bands argument is null, then this method shall return the sample model for all bands and cannot return null. If the bands argument is non-null, then this method may compute the sample model for the specified bands, or return null for instructing the caller to derive the sample model from get­Sample­Model(null).

      Implementation note

      The default implementation creates a sample model compatible with the color model if available, or otherwise defaults to a Banded­Sample­Model which stores samples as floating point values. This is okay for prototyping, but it is recommended to override this method with a simple model that better matches the data. A simple implementation can be as below:
      private SampleModel sampleModel;
      
      @Override
      protected SampleModel getSampleModel(int[] bands) throws DataStoreException {
          if (bands != null) {
              return null;
          }
          synchronized (getSynchronizationLock()) {
              if (sampleModel == null) {
                  sampleModel = ...;   // Compute and cache, because requested many times.
              }
              return sampleModel;
          }
      }
      
      Parameters:
      bands - indices (not necessarily in increasing order) of desired bands, or null for all bands.
      Returns:
      the sample model for tiles at full resolution with the specified bands. Shall be non-null if bands is null (i.e. the caller is requesting the main sample model).
      Throws:
      Data­Store­Exception - if an error occurred during sample model construction.
    • getColorModel

      protected ColorModel getColorModel(int[] bands) throws DataStoreException
      Returns the Java2D color model for rendering images, or null if none. The color model shall be compatible with the sample model returned by get­Sample­Model(int[]).

      The default implementation returns a gray scale color model if there is only one band to show and the range of the sample dimension is known. OTherwise, this method returns null. This is okay for prototyping, but it is recommended to override.

      Parameters:
      bands - indices (not necessarily in increasing order) of desired bands, or null for all bands.
      Returns:
      a color model compatible with get­Sample­Model(int[]), or null if none.
      Throws:
      Data­Store­Exception - if an error occurred during color model construction.
    • getFillValues

      protected Number[] getFillValues(int[] bands) throws DataStoreException
      Returns the values to use for filling empty spaces in rasters, with one value per band. The returned array can be null if there is no fill value, or if the fill values are not different than zero, or are not valid for the image data type.

      Fill values are used when a tile contains less pixels than expected. A null array is a shortcut for skipping the filling of new tiles, because new tiles are already initialized with zero values by default.

      The default implementation returns an array of Data­Type​.fill­Value() except for the transparent pixel if any. If the array would contain only zero values, the default implementation returns null.

      Parameters:
      bands - indices (not necessarily in increasing order) of desired bands, or null for all bands.
      Returns:
      the value to use for filling empty spaces in each band, or null for defaulting to zero.
      Throws:
      Data­Store­Exception - if an error occurred while fetching filling information.
    • getAvailableResolutions

      public List<double[]> getAvailableResolutions() throws DataStoreException
      Returns the preferred resolutions (in units of CRS axes) for read operations in this data store. The list elements are ordered from coarsest (largest numerical values) to finest (smallest numerical values).

      The default implementation uses information in the first element returned by get­Pyramids(). It is generally easier for subclasses to override get­Pyramids() instead of this method.

      This returned list may defer the calculations of resolutions until first requested. If a Data­Store­Exception occurs during the invocation of a List method, the exception will be wrapped in a Backing­Store­Exception.

      Specified by:
      get­Available­Resolutions in interface Grid­Coverage­Resource
      Returns:
      resolutions at all levels in the default pyramid.
      Throws:
      Data­Store­Exception - if an error occurred while fetching the resolution.
      See Also:
    • getTileMatrixSets

      public Collection<? extends TileMatrixSet> getTileMatrixSets() throws DataStoreException
      Returns the collection of all available tile matrix sets in this resource. The returned collection typically contains exactly one instance, which describes a pyramid in the same CRS as this Grid Coverage Resource.

      The default implementation uses the information provided by get­Pyramids() for creating default Tile­Matrix­Set instances. It is generally easier for subclasses to override get­Pyramids() instead of this method.

      Specified by:
      get­Tile­Matrix­Sets in interface Tiled­Resource
      Returns:
      all available Tile­Matrix­Set instances, or an empty collection if none.
      Throws:
      Data­Store­Exception - if an error occurred while fetching the tile matrix sets.
    • describeSubset

      protected TiledGridCoverageResource.Subset describeSubset(GridGeometry domain, int[] range) throws DataStoreException
      Prepares a description of the resource subset to be accepted by the Tiled­Grid­Coverage constructor. This method is invoked by the default implementation of read(Grid­Geometry, int...) for computing the argument given to read(Subset). The default implementation is as below:
      return new Subset(domain, range, ImageLayout.DEFAULT);
      
      The Image­Layout​.DEFAULT argument is a provider of virtual tile size suggestions. See the Subset constructor for more information. The suggested virtual tile sizes are submitted to the supports­Virtual­Tile­Size(long[]) method and, if accepted, used by the Tiled­Grid­Coverage constructor.

      Usage

      This method is invoked by the default implementation of read(Grid­Geometry, int...). This method should generally not be invoked by user's code. It is rather for overriding in subclasses. The caller is responsible for holding the synchronization lock.
      Parameters:
      domain - the domain argument specified by user in a call to Grid­Coverage­Resource​.read(…).
      range - the range argument specified by user in a call to Grid­Coverage­Resource​.read(…).
      Returns:
      descriptions of the grid coverage subset identified by the given domain and range.
      Throws:
      Data­Store­Exception - if an error occurred while computing the subset description.
      Runtime­Exception - in case of arithmetic error, Java2D error or other errors.
      See Also:
    • read

      Creates a coverage which will read the specified subset from this resource when first requested. This method is invoked (indirectly) by the default implementation of read(Grid­Geometry, int...). This method creates a subclass of Tiled­Grid­Coverage which will read tiles later, when first requested. The implementation of this method does not need to care about synchronization, immediate (rather than deferred) loading of tiles, logging of loading time and handling of Runtime­Exception. Those tasks should be handled by the caller.
      Parameters:
      subset - desired grid extent, resolution and sample dimensions to read.
      Returns:
      the grid coverage for the specified domain, resolution and ranges.
      Throws:
      Data­Store­Exception - if the coverage cannot be created.
      Runtime­Exception - if the coverage cannot be created for a reason not handled as a data store exception.
      See Also:
    • read

      public GridCoverage read(GridGeometry domain, int... ranges) throws DataStoreException
      Loads a subset of the grid coverage represented by this resource. While this method name suggests an immediate reading, the actual reading may be deferred. This method performs the following steps:
      1. Selects a Tiled­Grid­Coverage­Resource instance for the pyramid level which is considered the best fit for the resolution of the specified domain. The selected instance may be this.
      2. Invokes the describe­Subset(Grid­Geometry, int[]) method on the instance selected in above step. The created Tiled­Grid­Coverage­Resource​.Subset contains tiling and subsampling information adapted to the pyramid level.
      3. Invokes the Tiled­Grid­Coverage­Resource​.Subset​.create­Coverage() method on the Subset created in above step.
      4. Above create­Coverage() method may callback read(Subset) immediately, or may defer that callback to a later time. That callback is done on the same Tiled­Grid­Coverage­Resource instance as the one that created the Subset (i.e., the instance selected in the first step as the best fit for the pyramid level).
      5. If the current loading strategy is Raster­Loading­Strategy​.AT_READ_TIME, forces the immediate reading of tiles and logs the time required for this operation.
      These steps are executed inside a block synchronized on the synchronization lock.
      Specified by:
      read in interface Grid­Coverage­Resource
      Parameters:
      domain - desired grid extent and resolution, or null for reading the whole domain.
      ranges - 0-based indices of sample dimensions to read, or null or an empty sequence for reading them all.
      Returns:
      the grid coverage for the specified domain and ranges.
      Throws:
      Data­Store­Exception - if an error occurred while reading the grid coverage data.
      See Also:
    • choosePyramid

      protected TiledGridCoverageResource.Pyramid choosePyramid(GridGeometry domain, int[] ranges) throws DataStoreException
      Chooses the pyramid to use for reading the specified subset from this resource. This method should return an element of the list returned by get­Pyramids(). The chosen pyramid should be a best match, but does not need to be an exact match.

      The current implementation returns the first pyramid returned by get­Pyramids(). Future versions of Apache SIS may improve this algorithm for taking in account at least the CRS.

      Parameters:
      domain - desired grid extent and resolution, or null for reading the whole domain.
      ranges - 0-based indices of sample dimensions to read, or null or an empty sequence for reading them all.
      Returns:
      the pyramid to use, or null if no pyramid can satisfy the given request.
      Throws:
      Data­Store­Exception - if an error occurred while reading the grid coverage data.
    • getLoadingStrategy

      public RasterLoadingStrategy getLoadingStrategy() throws DataStoreException
      Returns an indication about when the "physical" loading of raster data will happen.
      Specified by:
      get­Loading­Strategy in interface Grid­Coverage­Resource
      Returns:
      current raster data loading strategy for this resource.
      Throws:
      Data­Store­Exception - if an error occurred while fetching data store configuration.
    • setLoadingStrategy

      public boolean setLoadingStrategy(RasterLoadingStrategy strategy) throws DataStoreException
      Sets the preferred strategy about when to do the "physical" loading of raster data.
      Specified by:
      set­Loading­Strategy in interface Grid­Coverage­Resource
      Parameters:
      strategy - the desired strategy for loading raster data.
      Returns:
      true if the given strategy has been accepted, or false if this implementation replaced the given strategy by an alternative.
      Throws:
      Data­Store­Exception - if an error occurred while setting data store configuration.
    • setRasterSubspaceDimensions

      protected void setRasterSubspaceDimensions(int xDimension, int yDimension) throws DataStoreException
      Sets the mapping from grid dimensions to image axes. This method specifies the dimensions of the slices obtained when reading tiles. The values specified to this method are used, directly or indirectly, at Tiled­Grid­Coverage­Resource​.Subset creation time. Therefore, calls to this method have an effect on the next Tiled­Grid­Coverage instances to be read, but not on the instances that are already read.

      If this method is never invoked, then by default the dimension 0 of the grid is mapped to the image x axis and the dimension 1 of the grid is mapped to the image y axis.

      Parameters:
      x­Dimension - dimension of the grid which is mapped to the x axis (column indexes) in rendered images.
      y­Dimension - dimension of the grid which is mapped to the y axis (row indexes) in rendered images.
      Throws:
      Illegal­Argument­Exception - if x­Dimension or y­Dimension is negative, or the two values are equal.
      Data­Store­Exception - if another error occurred while setting the mapping from grid dimensions to image axes.
      See Also:
    • getPyramids

      Returns information about the Tile­Matrix­Set instances to create. If the returned list is non-empty, then the first element shall be the default pyramid using the same Coordinate Reference System (CRS) as this Grid Coverage Resource. Other elements, if any, can use any CRS.

      This method is invoked by the default implementation of get­Tile­Matrix­Sets() when first needed. By default, this method returns an empty list if this resource is untiled, or otherwise a list of exactly one element describing a pyramid of only one level. This single level describes a Tile­Matrix at the resolution of this Tiled­Grid­Coverage­Resource.

      Returns:
      information about the tile matrix sets to create.
      Throws:
      Data­Store­Exception - if an error occurred while fetching information about the pyramid.
      See Also:
    • getGridGeometryWithDefaults

      protected GridGeometry getGridGeometryWithDefaults() throws DataStoreException
      Returns the grid geometry with missing properties defaulting to the properties of a grid CRS. This method usually returns Grid­Coverage­Resource​.get­Grid­Geometry() unchanged, except in the following rare circumstance: if the grid geometry has no resolution, no "grid to CRS" transform and no CRS, then this method returns a grid geometry with the resolution set to 1, i.e. the resolution is defined as one unit of grid cell.

      This method can be invoked for computing the grid geometry of Tiled­Grid­Coverage. This is particularly important in the context of pyramids because the levels are selected on the basis of their resolution. Implementations of Tiled­Grid­Coverage­Resource​.Pyramid​.for­Pyramid­Level(int) are encouraged to use this method for the base level, and only that level.

      Returns:
      grid geometry potentially completed with the addition of resolution and engineering CRS.
      Throws:
      Data­Store­Exception - if an error occurred while reading definitions from the underlying data store.
    • clearCache

      protected void clearCache()
      Clears all data cached in this resource, forcing the data to be reloaded when needed again.
      Overrides:
      clear­Cache in class Abstract­Resource