This is an automated email from the ASF dual-hosted git repository.

asf-gitbox-commits pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 3e9a1deb2e05a01c5712c793a89771a5ec61347a
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Fri Jun 12 19:17:58 2026 +0200

    Move also the predictor base class to the shared package.
    Reuse the byte buffer in the GeoHEIF reader when possible.
---
 .../storage/geotiff/base/CompressionMethod.java    | 10 ----
 .../geotiff/inflater/HorizontalPredictor.java      |  1 +
 .../sis/storage/geotiff/inflater/Inflater.java     |  4 +-
 .../io/stream/inflater/ComputedByteChannel.java    | 66 +++++++++++++++++++++-
 .../org/apache/sis/io/stream/inflater/Deflate.java | 10 ++++
 .../sis/io/stream/inflater/InflaterChannel.java    | 50 +++-------------
 .../sis/io/stream}/inflater/PredictorChannel.java  | 25 ++++++--
 .../apache/sis/storage/geoheif/ImageResource.java  | 64 +++++++++++++--------
 .../sis/storage/geoheif/UncompressedImage.java     | 12 +++-
 9 files changed, 154 insertions(+), 88 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/base/CompressionMethod.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/base/CompressionMethod.java
index 61d29ba9c1..d0b69b31d0 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/base/CompressionMethod.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/base/CompressionMethod.java
@@ -162,16 +162,6 @@ public enum CompressionMethod {
         return UNKNOWN;
     }
 
-    /**
-     * Whether the decompression uses native library.
-     * In such case, the use of direct buffer may be more efficient.
-     *
-     * @return whether the compression may use a native library.
-     */
-    public final boolean useNativeLibrary() {
-        return this == DEFLATE;
-    }
-
     /**
      * Returns whether the compression can be configured with different levels.
      *
diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/HorizontalPredictor.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/HorizontalPredictor.java
index 14bb7c2c69..14854e44af 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/HorizontalPredictor.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/HorizontalPredictor.java
@@ -20,6 +20,7 @@ import java.io.IOException;
 import java.nio.ByteBuffer;
 import org.apache.sis.image.DataType;
 import org.apache.sis.io.stream.inflater.InflaterChannel;
+import org.apache.sis.io.stream.inflater.PredictorChannel;
 import org.apache.sis.pending.jdk.JDK13;
 
 
diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/Inflater.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/Inflater.java
index 659b447b13..f8d8f9117d 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/Inflater.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/Inflater.java
@@ -238,8 +238,8 @@ public abstract class Inflater implements Closeable {
             }
         }
         final int scanlineStride = Math.multiplyExact(sourceWidth, 
sourcePixelStride * dataType.bytes());
-        return CopyFromBytes.create(inflater.createDataInput(channel, 
scanlineStride, compression.useNativeLibrary()),
-                dataType, chunksPerRow, samplesPerChunk, skipAfterChunks, 
pixelsPerElement);
+        final ChannelDataInput inflated = channel.createDataInput(null, 
scanlineStride);
+        return CopyFromBytes.create(inflated, dataType, chunksPerRow, 
samplesPerChunk, skipAfterChunks, pixelsPerElement);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/inflater/ComputedByteChannel.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/inflater/ComputedByteChannel.java
index cddd8c803b..95c92da1da 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/inflater/ComputedByteChannel.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/inflater/ComputedByteChannel.java
@@ -16,8 +16,14 @@
  */
 package org.apache.sis.io.stream.inflater;
 
+import java.util.Arrays;
 import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.nio.channels.ReadableByteChannel;
+import org.apache.sis.io.stream.ChannelDataInput;
+import org.apache.sis.storage.StorageConnector;
+import org.apache.sis.math.MathFunctions;
+import org.apache.sis.pending.jdk.JDK18;
 
 
 /**
@@ -36,12 +42,26 @@ import java.nio.channels.ReadableByteChannel;
  * @author  Martin Desruisseaux (Geomatys)
  */
 public abstract class ComputedByteChannel implements ReadableByteChannel {
+    /**
+     * Desired size of the buffer where to temporarily copy decompressed data.
+     * The actual buffer size may become larger (but not smaller)
+     * because we try to use a multiple of scanline stride.
+     */
+    private static final int BUFFER_SIZE = 
StorageConnector.DEFAULT_BUFFER_SIZE / 2;
+
     /**
      * Creates a new channel.
      */
-    protected ComputedByteChannel() {
+    ComputedByteChannel() {
     }
 
+    /**
+     * Returns the channel from which to read compressed data.
+     *
+     * @return the input channel, typically opened on a file.
+     */
+    public abstract ChannelDataInput compressedInput();
+
     /**
      * Prepares this channel for reading a new block of data.
      * A block may be, for example, a tile or a band of a tile.
@@ -51,4 +71,48 @@ public abstract class ComputedByteChannel implements 
ReadableByteChannel {
      * @throws IOException if the stream cannot be seek to the given start 
position.
      */
     public abstract void setInputRegion(long start, long byteCount) throws 
IOException;
+
+    /**
+     * Returns whether the inflater or predictor algorithm prefers native byte 
buffer.
+     * The default implementation returns {@code false}.
+     * Subclasses that depends on native library may return {@code true}.
+     *
+     * @return whether the inflater or predictor prefers native byte buffer.
+     */
+    protected boolean preferNativeBuffer() {
+        return false;
+    }
+
+    /**
+     * Creates the data input stream to use for getting uncompressed data.
+     * The source {@link ChannelDataInput} must be on the start position 
before to invoke this method.
+     *
+     * <p>This method tries to create a buffer of the size of scanline stride, 
or a multiple of that size,
+     * for performance reasons. A well adjusted buffer size reduces calls to 
{@link ByteBuffer#compact()},
+     * which in turn reduces the number of copy operations between different 
regions of the buffer.</p>
+     *
+     * @param  buffer          buffer to reuse if {@code null}. The content of 
this buffer will be discarded.
+     * @param  scanlineStride  the scanline stride of the image to read. Used 
for choosing a buffer size.
+     * @throws IOException if an error occurred while filling the buffer with 
initial data.
+     * @return the data input for uncompressed data.
+     */
+    public final ChannelDataInput createDataInput(ByteBuffer buffer, final int 
scanlineStride) throws IOException {
+        final int capacity;
+        if (scanlineStride > BUFFER_SIZE) {
+            final int[] divisors = MathFunctions.divisors(scanlineStride);
+            int i = Arrays.binarySearch(divisors, BUFFER_SIZE);
+            if (i < 0) i = ~i;              // Really tild, not minus.
+            capacity = divisors[i];         // Smallest divisor ≥ BUFFER_SIZE
+        } else if (scanlineStride > Long.SIZE) {
+            capacity = JDK18.ceilDiv(BUFFER_SIZE, scanlineStride) * 
scanlineStride;      // ≥ BUFFER_SIZE
+        } else {
+            capacity = BUFFER_SIZE;
+        }
+        final ChannelDataInput input = compressedInput();
+        if (buffer == null) {
+            buffer = preferNativeBuffer() ? 
ByteBuffer.allocateDirect(capacity) : ByteBuffer.allocate(capacity);
+        }
+        buffer = buffer.order(input.buffer.order()).limit(0);
+        return new ChannelDataInput(input.filename, this, buffer, true);
+    }
 }
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/inflater/Deflate.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/inflater/Deflate.java
index 49d7bd0eef..d364d64180 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/inflater/Deflate.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/inflater/Deflate.java
@@ -51,6 +51,16 @@ public final class Deflate extends InflaterChannel {
         inflater = new Inflater();
     }
 
+    /**
+     * Notifies that this inflater prefers native buffer.
+     *
+     * @return {@code true}.
+     */
+    @Override
+    protected boolean preferNativeBuffer() {
+        return true;
+    }
+
     /**
      * Prepares this channel for reading a new block of data.
      *
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/inflater/InflaterChannel.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/inflater/InflaterChannel.java
index 16d81de18f..7fa5cb95ba 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/inflater/InflaterChannel.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/inflater/InflaterChannel.java
@@ -16,15 +16,11 @@
  */
 package org.apache.sis.io.stream.inflater;
 
-import java.util.Arrays;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.BufferOverflowException;
-import org.apache.sis.math.MathFunctions;
-import org.apache.sis.storage.StorageConnector;
 import org.apache.sis.io.stream.ChannelDataInput;
 import org.apache.sis.storage.event.StoreListeners;
-import org.apache.sis.pending.jdk.JDK18;
 
 
 /**
@@ -36,13 +32,6 @@ import org.apache.sis.pending.jdk.JDK18;
  * @author  Martin Desruisseaux (Geomatys)
  */
 public abstract class InflaterChannel extends ComputedByteChannel {
-    /**
-     * Desired size of the buffer where to temporarily copy decompressed data.
-     * The actual buffer size may become larger (but not smaller)
-     * because we try to use a multiple of scanline stride.
-     */
-    private static final int BUFFER_SIZE = 
StorageConnector.DEFAULT_BUFFER_SIZE / 2;
-
     /**
      * The source of data to decompress.
      */
@@ -71,6 +60,14 @@ public abstract class InflaterChannel extends 
ComputedByteChannel {
         this.listeners = listeners;
     }
 
+    /**
+     * Returns the channel from which to read compressed data.
+     */
+    @Override
+    public final ChannelDataInput compressedInput() {
+        return input;
+    }
+
     /**
      * Prepares this channel for reading a new block of data.
      *
@@ -94,37 +91,6 @@ public abstract class InflaterChannel extends 
ComputedByteChannel {
         return input.getStreamPosition() >= endPosition;
     }
 
-    /**
-     * Creates the data input stream to use for getting uncompressed data.
-     * The {@linkplain #input} stream must be on the start position before to 
invoke this method.
-     *
-     * <p>This method tries to create a buffer of the size of scanline stride, 
or a multiple of that size,
-     * for performance reasons. A well adjusted buffer size reduces calls to 
{@link ByteBuffer#compact()},
-     * which in turn reduces the number of copy operations between different 
regions of the buffer.</p>
-     *
-     * @param  channel         the channel to wrap. This is {@code this} 
unless a predictor is applied.
-     * @param  scanlineStride  the scanline stride of the image to read. Used 
for choosing a buffer size.
-     * @param  directBuffer    whether the use of direct buffer is preferred 
to heap buffer.
-     * @throws IOException if an error occurred while filling the buffer with 
initial data.
-     * @return the data input for uncompressed data.
-     */
-    public final ChannelDataInput createDataInput(final ComputedByteChannel 
channel, final int scanlineStride, final boolean directBuffer)
-            throws IOException
-    {
-        final int capacity;
-        if (scanlineStride > BUFFER_SIZE) {
-            final int[] divisors = MathFunctions.divisors(scanlineStride);
-            int i = Arrays.binarySearch(divisors, BUFFER_SIZE);
-            if (i < 0) i = ~i;              // Really tild, not minus.
-            capacity = divisors[i];         // Smallest divisor ≥ BUFFER_SIZE
-        } else {
-            capacity = JDK18.ceilDiv(BUFFER_SIZE, scanlineStride) * 
scanlineStride;      // ≥ BUFFER_SIZE
-        }
-        ByteBuffer buffer = directBuffer ? ByteBuffer.allocateDirect(capacity) 
: ByteBuffer.allocate(capacity);
-        buffer = buffer.order(input.buffer.order()).limit(0);
-        return new ChannelDataInput(input.filename, channel, buffer, true);
-    }
-
     /**
      * Copies the given byte <var>n</var> times in the given buffer.
      * This is a convenience method for an operation frequently found in 
different compression algorithms.
diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/PredictorChannel.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/inflater/PredictorChannel.java
similarity index 88%
rename from 
endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/PredictorChannel.java
rename to 
endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/inflater/PredictorChannel.java
index e80589f39e..65e40fe0a8 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/inflater/PredictorChannel.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/io/stream/inflater/PredictorChannel.java
@@ -14,14 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.sis.storage.geotiff.inflater;
+package org.apache.sis.io.stream.inflater;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.pending.jdk.JDK13;
-import org.apache.sis.io.stream.inflater.ComputedByteChannel;
-import org.apache.sis.io.stream.inflater.InflaterChannel;
+import org.apache.sis.io.stream.ChannelDataInput;
 
 
 /**
@@ -31,7 +30,7 @@ import org.apache.sis.io.stream.inflater.InflaterChannel;
  *
  * @author  Martin Desruisseaux (Geomatys)
  */
-abstract class PredictorChannel extends ComputedByteChannel {
+public abstract class PredictorChannel extends ComputedByteChannel {
     /**
      * The channel from which to read data.
      */
@@ -59,6 +58,14 @@ abstract class PredictorChannel extends ComputedByteChannel {
         deferred = ArraysExt.EMPTY_BYTE;
     }
 
+    /**
+     * Returns the channel from which to read compressed data.
+     */
+    @Override
+    public final ChannelDataInput compressedInput() {
+        return input.compressedInput();
+    }
+
     /**
      * Prepares this predictor for reading a new tile or a new band of a 
planar image.
      *
@@ -91,7 +98,7 @@ abstract class PredictorChannel extends ComputedByteChannel {
      * @throws IOException if some other I/O error occurs.
      */
     @Override
-    public int read(final ByteBuffer target) throws IOException {
+    public final int read(final ByteBuffer target) throws IOException {
         final int start = target.position();
         if (deferredCount != 0) {
             /*
@@ -123,6 +130,14 @@ abstract class PredictorChannel extends 
ComputedByteChannel {
         return end - start;
     }
 
+    /**
+     * Returns whether the inflater or predictor algorithm prefers native byte 
buffer.
+     */
+    @Override
+    protected final boolean preferNativeBuffer() {
+        return input.preferNativeBuffer();
+    }
+
     /**
      * Tells whether this channel is still open.
      */
diff --git 
a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageResource.java
 
b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageResource.java
index c767e2a646..3686e778f6 100644
--- 
a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageResource.java
+++ 
b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/ImageResource.java
@@ -21,6 +21,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.HashMap;
 import java.util.Optional;
+import java.util.concurrent.atomic.AtomicReference;
+import java.nio.ByteBuffer;
 import java.io.IOException;
 import java.io.UncheckedIOException;
 import static java.lang.Math.addExact;
@@ -299,13 +301,15 @@ final class ImageResource extends 
TiledGridCoverageResource implements StoreReso
             final var requests = new ReadContext[result.length];
             int count = 0;
             synchronized (getSynchronizationLock()) {
-                try (final var context = new ReadContext(iterator)) {
+                final var readers = new HashMap<ImageReaderSpi, ImageReader>();
+                final var buffer  = new AtomicReference<ByteBuffer>();
+                try {
                     do {
                         Raster raster = iterator.getCachedTile();
                         if (raster != null) {
                             result[iterator.getTileIndexInResultArray()] = 
raster;
                         } else {
-                            requests[count++] = new ReadContext(context, 
ImageResource.this);
+                            requests[count++] = new ReadContext(iterator, 
readers, buffer, ImageResource.this);
                         }
                     } while (iterator.next());
                     /*
@@ -324,6 +328,8 @@ final class ImageResource extends TiledGridCoverageResource 
implements StoreReso
                     for (int i=0; i<count; i++) {
                         requests[i].readTile(input, result);        // 
Implementation may create an `input` view.
                     }
+                } finally {
+                    readers.values().forEach(ImageReader::dispose);
                 }
             }
             return result;
@@ -333,7 +339,7 @@ final class ImageResource extends TiledGridCoverageResource 
implements StoreReso
          * Context about a {@code readTile(…)} operation. Contains the tile to 
create, or
          * the image reader to use in the case of read operations delegated to 
Image I/O.
          */
-        static final class ReadContext extends ByteRanges implements 
AutoCloseable {
+        static final class ReadContext extends ByteRanges {
             /**
              * Iterator over the tiles to read.
              */
@@ -356,29 +362,28 @@ final class ImageResource extends 
TiledGridCoverageResource implements StoreReso
             final long subTileX, subTileY;
 
             /**
-             * Creates a new read context.
-             *
-             * @param  iterator  iterator over the tiles to read.
+             * Buffer to reuse for each tile.
              */
-            private ReadContext(final AOI iterator) {
-                this.iterator = iterator;
-                this.readers  = new HashMap<>();
-                this.reader   = null;
-                this.subTileX = 0;
-                this.subTileY = 0;
-            }
+            private final AtomicReference<ByteBuffer> buffer;
 
             /**
-             * Creates a context which is a snapshot of the given context at 
the current iterator position.
+             * Creates a new read context.
              *
-             * @param  parent  the parent from which to create a snapshot.
-             * @param  tileX   0-based column index of the tile to read, 
starting from image left.
-             * @param  tileY   0-based row index of the tile to read, starting 
from image top.
+             * @param  iterator  iterator over the tiles to read.
+             * @param  readers   an initially empty map where to store image 
readers for reuse.
+             * @param  buffer    an initially empty reference to a buffer.
+             * @param  owner     the resource for which to read a tile.
              */
             @SuppressWarnings("LeakingThisInConstructor")
-            private ReadContext(final ReadContext parent, final ImageResource 
owner) throws DataStoreException {
-                this.iterator = new Snapshot(parent.iterator);
-                this.readers  = parent.readers;
+            private ReadContext(final AOI iterator,
+                                final Map<ImageReaderSpi, ImageReader> readers,
+                                final AtomicReference<ByteBuffer> buffer,
+                                final ImageResource owner)
+                    throws DataStoreException
+            {
+                this.iterator = new Snapshot(iterator);
+                this.readers  = readers;
+                this.buffer   = buffer;
                 final long[] tileCoord = 
iterator.getTileCoordinatesInResource();
                 final Image tile = owner.getTile(tileCoord[0], tileCoord[1]);
                 subTileX = tileCoord[0] % tile.numXTiles;
@@ -436,12 +441,21 @@ final class ImageResource extends 
TiledGridCoverageResource implements StoreReso
             }
 
             /**
-             * Invoked after a sequence of tiles have been read.
-             * This method disposes the image readers.
+             * If a buffer has already been used in a previous read operation, 
returns that buffer.
+             *
+             * @return buffer that can be reused, or {@code null} if none.
+             */
+            public ByteBuffer reuseBuffer() {
+                return buffer.getAndSet(null);
+            }
+
+            /**
+             * Saves the given buffer for reuse.
+             *
+             * @param  done  a buffer which is no longer needed.
              */
-            @Override
-            public void close() {
-                readers.values().forEach(ImageReader::dispose);
+            public void saveForReuse(final ByteBuffer done) {
+                buffer.set(done);
             }
         }
     }
diff --git 
a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/UncompressedImage.java
 
b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/UncompressedImage.java
index a9c77ede8c..b98ac9980f 100644
--- 
a/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/UncompressedImage.java
+++ 
b/incubator/src/org.apache.sis.storage.geoheif/main/org/apache/sis/storage/geoheif/UncompressedImage.java
@@ -28,11 +28,11 @@ import org.apache.sis.image.internal.shared.RasterFactory;
 import org.apache.sis.io.stream.ChannelDataInput;
 import org.apache.sis.io.stream.HyperRectangleReader;
 import org.apache.sis.io.stream.Region;
+import org.apache.sis.io.stream.inflater.ComputedByteChannel;
 import org.apache.sis.io.stream.inflater.Deflate;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.isobmff.ByteRanges;
 import org.apache.sis.storage.isobmff.mpeg.CompressedUnitsItemInfo;
-import org.apache.sis.util.internal.shared.Numerics;
 
 
 /**
@@ -135,12 +135,15 @@ final class UncompressedImage extends Image {
         locator.resolve(offset, tileSize, context);
         return (ChannelDataInput input) -> {
             long origin = context.offset();
+            final ComputedByteChannel inflater;
             final CompressedUnitsItemInfo.Unit unit = compressedImageUnit;
             if (unit != null) {
-                final var inflater = new Deflate(input, listeners);
+                inflater = new Deflate(input, listeners);
                 inflater.setInputRegion(addExact(origin, unit.offset), 
unit.size);
-                input = inflater.createDataInput(inflater, 
Numerics.clamp(sourceSize[0]), true);
+                input = inflater.createDataInput(context.reuseBuffer(), (int) 
sourceSize[0]);    // (int) cast okay even if inexact.
                 origin = 0;
+            } else {
+                inflater = null;
             }
             /*
              * Now read all banks and store the values in the image buffer.
@@ -162,6 +165,9 @@ final class UncompressedImage extends Image {
                 hr.setDestination(RasterFactory.wrapAsBuffer(data, b));
                 hr.readAsBuffer(rasterRegion, 0);
             }
+            if (inflater != null) {
+                context.saveForReuse(inflater.compressedInput().buffer);
+            }
             return raster;
         };
     }

Reply via email to