use of org.apache.sis.internal.storage.inflater.Inflater in project sis by apache.
the class CompressedSubset method releaseInflater.
/**
* Invoked after the last tile has been read, or after an exception has been thrown during the reading process.
* This method releases any resources used by the inflater.
*/
private void releaseInflater() throws IOException {
assert Thread.holdsLock(source.getSynchronizationLock());
final Inflater c = inflater;
if (c != null) {
// Clear first in case of failure during `close()` execution.
inflater = null;
c.close();
}
}
use of org.apache.sis.internal.storage.inflater.Inflater in project sis by apache.
the class CompressedSubset method readSlice.
/**
* Reads a two-dimensional slice of the data cube from the given input channel.
*
* @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.
*/
@Override
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 dataType = getDataType();
final int width = pixelCount(lower, upper, subsampling, X_DIMENSION);
final int height = pixelCount(lower, upper, subsampling, Y_DIMENSION);
final int chunksPerRow = width * (targetPixelStride / samplesPerChunk);
final int betweenRows = subsampling[1] - 1;
final long head = beforeFirstBand + sourcePixelStride * (lower[X_DIMENSION]);
final long tail = afterLastBand - sourcePixelStride * (lower[X_DIMENSION] + (width - 1) * subsampling[X_DIMENSION]);
/*
* `head` and `tail` are the number of sample values to skip at the beginning and end of each row.
* `betweenPixels` is the number of sample values to skip between each pixel, but the actual skips
* are more complicated if only a subset of the bands are read. The actual number of sample values
* to skip between "chunks" is detailed by `skipAfterChunks`.
*
* `pixelsPerElement` below is a factor for converting a count of pixels to a count of primitive elements
* in the bank. The `pixelsPerElement` factor is usually 1, except when more than one pixel is packed in
* each single primitive type (e.g. 8 bits per byte in bilevel image). The `head` needs to be a multiple
* of `pixelsPerElement`; this restriction is documented in `Inflater.skip(long)` and should have been
* verified by `TiledGridResource`.
*/
// Always ≥ 1 and usually = 1.
final int pixelsPerElement = getPixelsPerElement();
assert (head % pixelsPerElement) == 0 : head;
if (inflater == null) {
inflater = Inflater.create(this, input(), source.getCompression(), source.getPredictor(), sourcePixelStride, getTileSize(X_DIMENSION), chunksPerRow, samplesPerChunk, skipAfterChunks, pixelsPerElement, dataType);
}
final Inflater inflater = this.inflater;
final int capacity = getBankCapacity(pixelsPerElement);
final Buffer[] banks = new Buffer[numBanks];
for (int b = 0; b < numBanks; b++) {
/*
* Prepare the object which will perform the actual decompression row-by-row,
* optionally skipping chunks if a subsampling is applied.
*/
final Buffer bank = RasterFactory.createBuffer(dataType, capacity);
inflater.setInputOutput(offsets[b], byteCounts[b], bank);
/*
* At this point, `inflater` is a data input doing decompression eventually followed
* by the mathematical operation identified by `predictor`.
*/
for (long y = lower[1]; --y >= 0; ) {
// `skip(…)` may round to next element boundary.
inflater.skip(scanlineStride);
}
for (int y = height; --y > 0; ) {
// (height - 1) iterations.
inflater.skip(head);
inflater.uncompressRow();
inflater.skip(tail);
for (int j = betweenRows; --j >= 0; ) {
inflater.skip(scanlineStride);
}
}
// Last iteration without the trailing `skip(…)` calls.
inflater.skip(head);
inflater.uncompressRow();
fillRemainingRows(bank.flip());
banks[b] = bank;
}
return Raster.createWritableRaster(model, RasterFactory.wrap(dataType, banks), location);
}