You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by js...@apache.org on 2024/10/04 09:09:35 UTC

(sis) branch geoapi-4.0 updated: In Gimi store, avoid large array copies by reading from Channel directely in image DataBuffer

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

jsorel 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 a9f4e4bc86 In Gimi store, avoid large array copies by reading from Channel directely in image DataBuffer
a9f4e4bc86 is described below

commit a9f4e4bc86ae67c19120f9ac8cfb35f414871991
Author: jsorel <jo...@geomatys.com>
AuthorDate: Fri Oct 4 11:08:59 2024 +0200

    In Gimi store, avoid large array copies by reading from Channel directely in image DataBuffer
---
 .../main/org/apache/sis/storage/gimi/Item.java         | 18 +++++++++++-------
 .../org/apache/sis/storage/gimi/ResourceImageJpeg.java |  2 +-
 .../sis/storage/gimi/ResourceImageUncompressed.java    | 17 +++++++++++------
 .../storage/gimi/isobmff/iso14496_12/MediaData.java    |  9 +++++++--
 4 files changed, 30 insertions(+), 16 deletions(-)

diff --git a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/Item.java b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/Item.java
index 0d96e375f5..2e01cb1789 100644
--- a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/Item.java
+++ b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/Item.java
@@ -170,32 +170,36 @@ final class Item {
     /**
      * @param offset start position to read from
      * @param count number of bytes to read, -1 for all
-     * @return
+     * @param target Optional array to write into
+     * @param targetOffset if target is provided, offset to start writing at
+     * @return new or provided array
      * @throws DataStoreException
      */
-    public byte[] getData(long dataOffset, int count) throws DataStoreException {
+    public byte[] getData(long dataOffset, int count, byte[] target, int targetOffset) throws DataStoreException {
         try {
             final ItemLocation.Item location = getLocation();
             if (location == null) {
                 //read data from the default mediadata box
                 MediaData mediaData = (MediaData) store.getRootBox().getChild(MediaData.FCC, null);
-                return mediaData.getData(dataOffset, count);
+                return mediaData.getData(dataOffset, count, target, targetOffset);
             } else if (location.constructionMethod == 0) {
                 //absolute location
                 if (location.dataReferenceIndex == 0) {
                     //compute total size
                     final int length = IntStream.of(location.extentLength).sum();
                     //read datas
-                    final byte[] data = new byte[count == -1 ? length : count];
+                    if (count == -1) count = length;
+                    if (target == null) targetOffset = 0; //ignore user value if array is null
+                    final byte[] data = target == null ? new byte[count] : target;
                     final ISOBMFFReader reader = store.getReader();
                     synchronized (reader) {
-                        long remaining = data.length;
+                        long remaining = count;
                         int bufferOffset = 0;
                         for (int i = 0, currentOffset = 0; i < location.extentLength.length && remaining > 0; i++) {
                             if (dataOffset <= currentOffset) {
                                 reader.channel.seek(location.baseOffset + location.extentOffset[i]);
                                 final long toRead = Math.min(remaining, location.extentLength[i]);
-                                reader.channel.readFully(data, bufferOffset, Math.toIntExact(toRead));
+                                reader.channel.readFully(data, bufferOffset + targetOffset, Math.toIntExact(toRead));
                                 bufferOffset += toRead;
                                 remaining -= toRead;
                             } else if (dataOffset >= (currentOffset + location.extentLength[i])) {
@@ -204,7 +208,7 @@ final class Item {
                                 long toSkip = dataOffset - currentOffset;
                                 reader.channel.seek(location.baseOffset + location.extentOffset[i] + toSkip);
                                 final long toRead = Math.min(remaining, location.extentLength[i] - toSkip);
-                                reader.channel.readFully(data, bufferOffset, Math.toIntExact(toRead));
+                                reader.channel.readFully(data, bufferOffset + targetOffset, Math.toIntExact(toRead));
                                 bufferOffset += toRead;
                                 remaining -= toRead;
                             }
diff --git a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourceImageJpeg.java b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourceImageJpeg.java
index e619a11bd7..d3cbbdacff 100644
--- a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourceImageJpeg.java
+++ b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourceImageJpeg.java
@@ -42,7 +42,7 @@ final class ResourceImageJpeg extends ResourceImageUncompressed {
 
     @Override
     public GridCoverage read(GridGeometry gg, int... ints) throws DataStoreException {
-        final byte[] data = item.getData(0,-1);
+        final byte[] data = item.getData(0,-1, null, 0);
         ImageInputStream iis;
         BufferedImage img;
         try {
diff --git a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourceImageUncompressed.java b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourceImageUncompressed.java
index 6ec4f1bb41..13aeacf04f 100644
--- a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourceImageUncompressed.java
+++ b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/ResourceImageUncompressed.java
@@ -157,7 +157,7 @@ class ResourceImageUncompressed extends TiledGridResource implements StoreResour
             // RGB case
             final ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
             final int[] nBits = {8, 8, 8};
-            final int[] bOffs = {2, 1, 0};
+            final int[] bOffs = {0, 1, 2};
             colorModel = new ComponentColorModel(
                     cs,
                     nBits,
@@ -268,12 +268,17 @@ class ResourceImageUncompressed extends TiledGridResource implements StoreResour
      */
     private void readTile(long tileX, long tileY, WritableRaster raster, int offsetX, int offsetY) throws DataStoreException {
         final long tileOffset = (tileX + tileY * (frameConf.numTileColsMinusOne+1)) * tileByteArrayLength;
-        final byte[] data = item.getData(tileOffset, tileByteArrayLength);
 
-        final DataBuffer buffer = new DataBufferByte(data, tileByteArrayLength, 0);
-
-        final Raster tile = WritableRaster.createInterleavedRaster(buffer, tileWidth, tileHeight, tileWidth*3, 3, new int[]{0,1,2}, new Point(0,0));
-        raster.setDataElements(offsetX, offsetY, tile);
+        final DataBuffer targetBuffer = raster.getDataBuffer();
+        if (targetBuffer instanceof DataBufferByte) {
+            final DataBufferByte dbb = (DataBufferByte) targetBuffer;
+            item.getData(tileOffset, tileByteArrayLength, dbb.getData(), 0);
+        } else {
+            final byte[] data = item.getData(tileOffset, tileByteArrayLength, null, 0);
+            final DataBuffer buffer = new DataBufferByte(data, tileByteArrayLength, 0);
+            final Raster tile = WritableRaster.createInterleavedRaster(buffer, tileWidth, tileHeight, tileWidth*3, 3, new int[]{0,1,2}, new Point(0,0));
+            raster.setDataElements(offsetX, offsetY, tile);
+        }
     }
 
     @Override
diff --git a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_12/MediaData.java b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_12/MediaData.java
index 52ebae5045..cf3dc4e9bc 100644
--- a/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_12/MediaData.java
+++ b/incubator/src/org.apache.sis.storage.gimi/main/org/apache/sis/storage/gimi/isobmff/iso14496_12/MediaData.java
@@ -37,7 +37,7 @@ public final class MediaData extends Box {
         }
     }
 
-    public byte[] getData(long offset, int count) throws IOException {
+    public byte[] getData(long offset, int count, byte[] target, int targetOffset) throws IOException {
         synchronized (reader) {
             reader.channel.seek(payloadOffset + offset);
             long nb = (boxOffset + size) - payloadOffset;
@@ -49,7 +49,12 @@ public final class MediaData extends Box {
                 }
                 nb = count;
             }
-            return reader.channel.readBytes(Math.toIntExact(nb));
+            if (target == null) {
+                return reader.channel.readBytes(Math.toIntExact(nb));
+            } else {
+                reader.channel.readFully(target, targetOffset, Math.toIntExact(nb));
+                return target;
+            }
         }
     }