use of org.apache.sis.coverage.grid.GridCoverageBuilder in project sis by apache.
the class MemoryGridResource method read.
/**
* Returns a subset of the wrapped grid coverage. If a non-null grid geometry is specified, then
* this method tries to return a grid coverage matching the given grid geometry on a best-effort basis.
* In current implementation this is either a {@link org.apache.sis.coverage.grid.GridCoverage2D} or
* the original grid coverage.
*
* @param domain desired grid extent and resolution, or {@code null} for the whole domain.
* @param range 0-based indices of sample dimensions to read, or {@code null} or an empty sequence for reading them all.
* @return the grid coverage for the specified domain and range.
*/
@Override
public GridCoverage read(GridGeometry domain, final int... range) {
List<SampleDimension> bands = coverage.getSampleDimensions();
final RangeArgument rangeIndices = validateRangeArgument(bands.size(), range);
/*
* The given `domain` may use arbitrary `gridToCRS` and `CRS` properties.
* For this simple implementation we need the same `gridToCRS` and `CRS`
* than the wrapped coverage; only domain `extent` is allowed to differ.
* Subsampling is ignored for now because it is an expensive operation.
* Clipping and range selection are light and do not copy any data.
*
* TODO: a future implementation may apply subsampling efficiently,
* by adjusting the pixel stride in SampleModel.
*/
GridExtent intersection = null;
final GridGeometry source = coverage.getGridGeometry();
if (domain == null) {
domain = source;
} else {
intersection = source.derive().rounding(GridRoundingMode.ENCLOSING).subgrid(domain).getIntersection();
if (intersection.equals(source.getExtent())) {
// Will request the whole image.
intersection = null;
domain = source;
}
}
/*
* Quick check before to invoke the potentially costly `coverage.render(…)` method.
*/
final boolean sameBands = rangeIndices.isIdentity();
if (sameBands && intersection == null) {
return coverage;
}
/*
* After `render(…)` execution, the (minX, minY) image coordinates are the differences between
* the extent that we requested and the one that we got. If that differences is not zero, then
* we need to translate the `GridExtent` in order to make it matches what we got. But before to
* apply that translation, we adjust the grid size (because it may add another translation).
*/
RenderedImage data = coverage.render(intersection);
if (intersection != null) {
final int[] sd = intersection.getSubspaceDimensions(2);
final int dimX = sd[0];
final int dimY = sd[1];
final long ox = intersection.getLow(dimX);
final long oy = intersection.getLow(dimY);
final long[] changes = new long[Math.max(dimX, dimY) + 1];
for (int i = changes.length; --i >= 0; ) {
// We need only the dimensions that may change.
changes[i] = intersection.getSize(i);
}
changes[dimX] = data.getWidth();
changes[dimY] = data.getHeight();
intersection = intersection.resize(changes);
/*
* Apply the translation after we resized the grid extent, because the resize operation
* may have caused an additional translation. We cancel that translation with terms that
* restore the (ox,oy) lower coordinates before to add the data minimum X,Y.
*/
Arrays.fill(changes, 0);
changes[dimX] = Math.addExact(ox - intersection.getLow(dimX), data.getMinX());
changes[dimY] = Math.addExact(oy - intersection.getLow(dimY), data.getMinX());
intersection = intersection.translate(changes);
/*
* If the result is the same intersection than the source coverage,
* we may be able to return that coverage directly.
*/
if (intersection.equals(source.getExtent())) {
if (sameBands) {
return coverage;
}
domain = source;
} else {
domain = new GridGeometry(intersection, PixelInCell.CELL_CORNER, source.getGridToCRS(PixelInCell.CELL_CORNER), source.getCoordinateReferenceSystem());
}
}
if (!sameBands) {
data = new ImageProcessor().selectBands(data, range);
bands = UnmodifiableArrayList.wrap(rangeIndices.select(bands));
}
return new GridCoverageBuilder().setValues(data).setRanges(bands).setDomain(domain).build();
}
Aggregations