use of org.apache.sis.internal.storage.io.HyperRectangleReader in project sis by apache.
the class DataSubset method readSlice.
/**
* Reads a two-dimensional slice of the data cube from the given input channel. This method is usually
* invoked for reading the tile in full, in which case the {@code lower} argument is (0,0) and the
* {@code upper} argument is the tile size. But those arguments may identify a smaller region if the
* {@link DataSubset} contains only one (potentially large) tile.
*
* <p>The length of {@code lower}, {@code upper} and {@code subsampling} arrays shall be 2.</p>
*
* <h4>Default implementation</h4>
* The default implementation in this base class assumes uncompressed data without band subset.
* Subsampling on the <var>X</var> axis is not supported if the image has interleaved pixels.
* Packed pixels (é.g. bilevel images with 8 pixels per byte) are not supported.
* Those restrictions are verified by {@link DataCube#canReadDirect(TiledGridResource.Subset)}.
* Subclasses must override for handling decompression or for resolving above-cited limitations.
*
* @todo It is possible to relax a little bit some restrictions. If the tile width is a divisor
* of the sample size, we could round {@code lower[0]} and {@code upper[0]} to a multiple
* of {@code sampleSize}. We would need to adjust the coordinates of returned image accordingly.
* This adjustment need to be done by the caller.
*
* @param offsets position in the channel where tile data begins, one value per bank.
* @param byteCounts number of bytes for the compressed tile data, one value per bank.
* @param lower (<var>x</var>, <var>y</var>) coordinates of the first pixel to read relative to the tile.
* @param upper (<var>x</var>, <var>y</var>) coordinates after the last pixel to read relative to the tile.
* @param subsampling (<var>sx</var>, <var>sy</var>) subsampling factors.
* @param location pixel coordinates in the upper-left corner of the tile to return.
* @return a single tile decoded from the GeoTIFF file.
* @throws IOException if an I/O error occurred.
* @throws DataStoreException if a logical error occurred.
* @throws RuntimeException if the Java2D image can not be created for another reason
* (too many exception types to list them all).
*
* @see DataCube#canReadDirect(TiledGridResource.Subset)
*/
Raster readSlice(final long[] offsets, final long[] byteCounts, final long[] lower, final long[] upper, final int[] subsampling, final Point location) throws IOException, DataStoreException {
final DataType type = getDataType();
// Assumed same as `SampleModel.getSampleSize(…)` by pre-conditions.
final int sampleSize = type.size();
final long width = subtractExact(upper[X_DIMENSION], lower[X_DIMENSION]);
final long height = subtractExact(upper[Y_DIMENSION], lower[Y_DIMENSION]);
/*
* The number of bytes to read should not be greater than `byteCount`. It may be smaller however if only
* a subregion is read. Note that the `length` value may be different than `capacity` if the tile to read
* is smaller than the "standard" tile size of the image. It happens often when reading the last strip.
* This length is used only for verification purpose so it does not need to be exact.
*/
final long length = ceilDiv(width * height * sourcePixelStride * sampleSize, Byte.SIZE);
final long[] size = new long[] { multiplyFull(sourcePixelStride, getTileSize(X_DIMENSION)), getTileSize(Y_DIMENSION) };
/*
* If we use an interleaved sample model, each "element" from `HyperRectangleReader` perspective is actually a
* group of `sourcePixelStride` values. Note that in such case, we can not handle subsampling on the first axis.
* Such case should be handled by the `CompressedSubset` subclass instead, even if there is no compression.
*/
assert sourcePixelStride == 1 || subsampling[X_DIMENSION] == 1;
lower[X_DIMENSION] *= sourcePixelStride;
upper[X_DIMENSION] *= sourcePixelStride;
/*
* Read each plane ("banks" in Java2D terminology). Note that a single bank contains all bands
* in the interleaved sample model case. This block assumes that each bank element contains
* exactly one sample value (verified by assertion), as documented in the Javadoc of this method.
* If that assumption was not true, we would have to adjust `capacity`, `lower[0]` and `upper[0]`
* (we may do that as an optimization in a future version).
*/
final HyperRectangleReader hr = new HyperRectangleReader(ImageUtilities.toNumberEnum(type.toDataBufferType()), input());
final Region region = new Region(size, lower, upper, subsampling);
final Buffer[] banks = new Buffer[numBanks];
for (int b = 0; b < numBanks; b++) {
if (b < byteCounts.length && length > byteCounts[b]) {
throw new DataStoreContentException(source.reader.resources().getString(Resources.Keys.UnexpectedTileLength_2, length, byteCounts[b]));
}
hr.setOrigin(offsets[b]);
// See above comment.
assert model.getSampleSize(b) == sampleSize;
final Buffer bank = hr.readAsBuffer(region, getBankCapacity(1));
fillRemainingRows(bank);
banks[b] = bank;
}
final DataBuffer buffer = RasterFactory.wrap(type, banks);
return Raster.createWritableRaster(model, buffer, location);
}
Aggregations