Search in sources :

Example 1 with Inflater

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();
    }
}
Also used : Inflater(org.apache.sis.internal.storage.inflater.Inflater)

Example 2 with Inflater

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);
}
Also used : Buffer(java.nio.Buffer) DataType(org.apache.sis.image.DataType) Inflater(org.apache.sis.internal.storage.inflater.Inflater) Point(java.awt.Point)

Aggregations

Inflater (org.apache.sis.internal.storage.inflater.Inflater)2 Point (java.awt.Point)1 Buffer (java.nio.Buffer)1 DataType (org.apache.sis.image.DataType)1