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 f253a92f25 Support reading range of bytes in data boxes in GIMI store f253a92f25 is described below commit f253a92f25ddaeae396262c2fe0c505879f719dc Author: jsorel <johann.so...@geomatys.com> AuthorDate: Thu Oct 3 15:32:09 2024 +0200 Support reading range of bytes in data boxes in GIMI store --- .../main/org/apache/sis/storage/gimi/Item.java | 35 ++++++++++++++++++---- .../apache/sis/storage/gimi/ResourceImageJpeg.java | 2 +- .../storage/gimi/ResourceImageUncompressed.java | 29 ++++++++---------- .../gimi/isobmff/iso14496_12/MediaData.java | 16 ++++++++++ 4 files changed, 59 insertions(+), 23 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 3fd046d6cf..0d96e375f5 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 @@ -167,25 +167,48 @@ final class Item { return location == NO_LOCATION ? null : location; } - public byte[] getData() throws DataStoreException { + /** + * @param offset start position to read from + * @param count number of bytes to read, -1 for all + * @return + * @throws DataStoreException + */ + public byte[] getData(long dataOffset, int count) 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(); + return mediaData.getData(dataOffset, count); } 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[length]; + final byte[] data = new byte[count == -1 ? length : count]; final ISOBMFFReader reader = store.getReader(); synchronized (reader) { - for (int i = 0, offset = 0; i < location.extentLength.length; i++) { - reader.channel.seek(location.baseOffset + location.extentOffset[i]); - reader.channel.readFully(data, offset, location.extentLength[i]); + long remaining = data.length; + 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)); + bufferOffset += toRead; + remaining -= toRead; + } else if (dataOffset >= (currentOffset + location.extentLength[i])) { + //skip the full block + } else if (dataOffset > currentOffset) { + 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)); + bufferOffset += toRead; + remaining -= toRead; + } + currentOffset += location.extentLength[i]; } } return data; 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 9433723778..e619a11bd7 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(); + final byte[] data = item.getData(0,-1); 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 cc91245c96..03b95d9168 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 @@ -16,7 +16,11 @@ */ package org.apache.sis.storage.gimi; +import java.awt.Point; import java.awt.image.BufferedImage; +import java.awt.image.DataBuffer; +import java.awt.image.DataBufferByte; +import java.awt.image.Raster; import java.awt.image.WritableRaster; import java.util.ArrayList; import java.util.Arrays; @@ -204,7 +208,6 @@ class ResourceImageUncompressed extends AbstractGridCoverageResource implements @Override public GridCoverage read(GridGeometry gg, int... ints) throws DataStoreException { - final byte[] data = item.getData(); final BufferedImage img; if ( (compDef != null && Arrays.equals(compDef.componentType, new int[]{4,5,6})) @@ -217,7 +220,7 @@ class ResourceImageUncompressed extends AbstractGridCoverageResource implements final WritableRaster raster = img.getRaster(); for (int y = 0; y <= frameConf.numTileRowsMinusOne; y++) { for (int x = 0; x <= frameConf.numTileColsMinusOne; x++) { - readTile(data, x, y, raster, x*tileWidth, y*tileHeight); + readTile(x, y, raster, x*tileWidth, y*tileHeight); } } } else { @@ -226,8 +229,7 @@ class ResourceImageUncompressed extends AbstractGridCoverageResource implements final GridGeometry gridGeometry = getGridGeometry(); GridCoverageBuilder gcb = new GridCoverageBuilder(); gcb.setDomain(gridGeometry); - //gcb.setRanges(getSampleDimensions()); - //gcb.setValues(db, new Dimension((int)gridGeometry.getExtent().getSize(0), (int)gridGeometry.getExtent().getSize(1))); + gcb.setRanges(getSampleDimensions()); gcb.setValues(img); return gcb.build(); } @@ -238,19 +240,14 @@ class ResourceImageUncompressed extends AbstractGridCoverageResource implements * @param tileX starting from image left * @param tileY starting from image top */ - private void readTile(byte[] data, int tileX, int tileY, WritableRaster raster, int offsetX, int offsetY) { + private void readTile(int tileX, int tileY, WritableRaster raster, int offsetX, int offsetY) throws DataStoreException { final int tileOffset = (tileX + tileY * (frameConf.numTileColsMinusOne+1)) * tileByteArrayLength; - for (int y = 0; y < tileHeight; y++) { - for (int x = 0; x < tileWidth; x++) { - final int offset = y * tileWidth + x; - final int finalX = offsetX + x; - final int finalY = offsetY + y; - raster.setSample(finalX, finalY, 0, data[tileOffset + offset * 3] & 0xFF); - raster.setSample(finalX, finalY, 1, data[tileOffset + offset * 3 + 1] & 0xFF); - raster.setSample(finalX, finalY, 2, data[tileOffset + offset * 3 + 2] & 0xFF); - } - } - } + 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); + } } 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 028cfcb269..52ebae5045 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,4 +37,20 @@ public final class MediaData extends Box { } } + public byte[] getData(long offset, int count) throws IOException { + synchronized (reader) { + reader.channel.seek(payloadOffset + offset); + long nb = (boxOffset + size) - payloadOffset; + if (count == -1) { + nb = nb - offset; + } else { + if (nb < (offset + count)) { + throw new IOException("Trying to read more data then what is available"); + } + nb = count; + } + return reader.channel.readBytes(Math.toIntExact(nb)); + } + } + }