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

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


The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
     new 748a5a1fff Adjust the size of the temporary buffer for TIFF 
decompression.
748a5a1fff is described below

commit 748a5a1fff56952bdb47b7bc6a0c81385bc27376
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Wed Jun 29 19:15:08 2022 +0200

    Adjust the size of the temporary buffer for TIFF decompression.
---
 .../main/java/org/apache/sis/image/DataType.java   | 14 ++++++++++-
 .../java/org/apache/sis/image/package-info.java    |  2 +-
 .../storage/inflater/CompressionChannel.java       | 28 +++++++++++++++++-----
 .../sis/internal/storage/inflater/Inflater.java    |  5 ++--
 4 files changed, 39 insertions(+), 10 deletions(-)

diff --git a/core/sis-feature/src/main/java/org/apache/sis/image/DataType.java 
b/core/sis-feature/src/main/java/org/apache/sis/image/DataType.java
index 9c18299b04..56239f37dc 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/DataType.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/DataType.java
@@ -34,7 +34,7 @@ import static 
org.apache.sis.internal.util.Numerics.MAX_INTEGER_CONVERTIBLE_TO_F
  * This is a type-safe version of the {@code TYPE_*} constants defined in 
{@link DataBuffer}.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.3
  * @since   1.1
  * @module
  */
@@ -257,6 +257,18 @@ public enum DataType {
         return DataBuffer.getDataTypeSize(ordinal());
     }
 
+    /**
+     * Returns the size in bytes of this data type.
+     * If the {@linkplain #size() number of bits} is smaller than {@value 
Byte#SIZE}, then this method returns 1.
+     *
+     * @return size in bytes of this data type, not smaller than 1.
+     *
+     * @since 1.3
+     */
+    public final int bytes() {
+        return Math.max(size() >>> 3, 1);
+    }
+
     /**
      * Returns whether this type is an unsigned integer type.
      * Unsigned types are {@link #BYTE} and {@link #USHORT}.
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/image/package-info.java 
b/core/sis-feature/src/main/java/org/apache/sis/image/package-info.java
index 0862082562..234e989c43 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/package-info.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/package-info.java
@@ -42,7 +42,7 @@
  * @author  Rémi Maréchal (Geomatys)
  * @author  Martin Desruisseaux (Geomatys)
  * @author  Johann Sorel (Geomatys)
- * @version 1.2
+ * @version 1.3
  * @since   1.0
  * @module
  */
diff --git 
a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/CompressionChannel.java
 
b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/CompressionChannel.java
index 95e5473fb2..f80239ab1c 100644
--- 
a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/CompressionChannel.java
+++ 
b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/CompressionChannel.java
@@ -16,8 +16,11 @@
  */
 package org.apache.sis.internal.storage.inflater;
 
+import java.util.Arrays;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import org.apache.sis.math.MathFunctions;
+import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.internal.geotiff.Resources;
 import org.apache.sis.internal.storage.io.ChannelDataInput;
 
@@ -29,15 +32,16 @@ import org.apache.sis.internal.storage.io.ChannelDataInput;
  * <p>The {@link #close()} method shall be invoked when this channel is no 
longer used.</p>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.2
+ * @version 1.3
  * @since   1.1
  * @module
  */
 abstract class CompressionChannel extends PixelChannel {
     /**
-     * Size of the buffer where to temporarily copy decompressed data.
+     * Desired size of the buffer where to temporarily copy decompressed data.
+     * The actual buffer size may be larger, but should not be smaller.
      */
-    private static final int BUFFER_SIZE = 4096;
+    private static final int BUFFER_SIZE = 8192;
 
     /**
      * The source of data to decompress.
@@ -86,13 +90,25 @@ abstract class CompressionChannel extends PixelChannel {
      * 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.
      *
-     * @param  channel  the channel to wrap. This is {@code this} unless a 
{@link Predictor} is applied.
+     * <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 amount of copy operations between different 
regions of the buffer.</p>
+     *
+     * @param  channel         the channel to wrap. This is {@code this} 
unless a {@link Predictor} is applied.
+     * @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.
      */
-    final ChannelDataInput createDataInput(final PixelChannel channel) throws 
IOException {
+    final ChannelDataInput createDataInput(final PixelChannel channel, int 
scanlineStride) throws IOException {
+        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.
+            scanlineStride = divisors[i];
+        }
+        final int capacity = Numerics.ceilDiv(BUFFER_SIZE, scanlineStride) * 
scanlineStride;
         // TODO: remove cast with JDK9.
-        final ByteBuffer buffer = (ByteBuffer) 
ByteBuffer.allocate(BUFFER_SIZE).order(input.buffer.order()).limit(0);
+        final ByteBuffer buffer = (ByteBuffer) 
ByteBuffer.allocate(capacity).order(input.buffer.order()).limit(0);
         return new ChannelDataInput(input.filename, channel, buffer, true);
     }
 
diff --git 
a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/Inflater.java
 
b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/Inflater.java
index 7321c5ed6e..cb6137895b 100644
--- 
a/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/Inflater.java
+++ 
b/storage/sis-geotiff/src/main/java/org/apache/sis/internal/storage/inflater/Inflater.java
@@ -239,8 +239,9 @@ public abstract class Inflater implements Closeable {
                 throw unsupportedEncoding(caller, 
Resources.Keys.UnsupportedPredictor_1, predictor);
             }
         }
-        return CopyFromBytes.create(inflater.createDataInput(channel), 
dataType,
-                chunksPerRow, samplesPerChunk, skipAfterChunks, 
pixelsPerElement);
+        final int scanlineStride = Math.multiplyExact(sourceWidth, 
sourcePixelStride * dataType.bytes());
+        return CopyFromBytes.create(inflater.createDataInput(channel, 
scanlineStride),
+                dataType, chunksPerRow, samplesPerChunk, skipAfterChunks, 
pixelsPerElement);
     }
 
     /**

Reply via email to