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 <johann.so...@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; + } } }