You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2026/08/11 11:00:55 UTC
(sis) 01/02: Add a "todo" note about the use of `prefetch` in context of artificially tiled image. Minor edition as a side-effect of the review of the situation regarding prefetch.
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 f6e6c072f0606b89675cde7bc2cf4bad1e51a4f1
Author: Martin Desruisseaux <ma...@geomatys.com>
AuthorDate: Mon Aug 10 12:41:22 2026 +0200
Add a "todo" note about the use of `prefetch` in context of artificially tiled image.
Minor edition as a side-effect of the review of the situation regarding prefetch.
---
.../org/apache/sis/image/BandedSampleConverter.java | 6 +++---
.../main/org/apache/sis/image/ComputedImage.java | 4 ++--
.../main/org/apache/sis/image/ImageOverlay.java | 2 +-
.../org/apache/sis/image/MultiSourcePrefetch.java | 5 +++--
.../main/org/apache/sis/image/PlanarImage.java | 2 ++
.../main/org/apache/sis/image/PrefetchedImage.java | 4 ++--
.../org/apache/sis/image/SourceAlignedImage.java | 2 +-
.../image/internal/shared/BatchComputedImage.java | 21 +++++++++++++++++++--
.../sis/storage/tiling/ArtificiallyTiledImage.java | 13 ++++++++++---
.../storage/tiling/TiledGridCoverageResource.java | 2 +-
10 files changed, 44 insertions(+), 17 deletions(-)
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandedSampleConverter.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandedSampleConverter.java
index 9cf90055f5..8a4270ad36 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandedSampleConverter.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandedSampleConverter.java
@@ -454,10 +454,10 @@ class BandedSampleConverter extends WritableComputedImage {
@Override
public void setData(final Raster data) {
final Rectangle bounds = data.getBounds();
- final WritableRenderedImage target = (WritableRenderedImage) getSource();
+ final var target = (WritableRenderedImage) getSource();
ImageUtilities.clipBounds(target, bounds);
if (!bounds.isEmpty()) {
- final TileOpExecutor executor = new TileOpExecutor(target, bounds) {
+ final var executor = new TileOpExecutor(target, bounds) {
@Override protected void writeTo(final WritableRaster target) throws TransformException {
final Rectangle aoi = target.getBounds().intersection(bounds);
Transferer.create(data, target, aoi).compute(inverses);
@@ -506,7 +506,7 @@ class BandedSampleConverter extends WritableComputedImage {
@Override
public boolean equals(final Object object) {
if (equalsBase(object)) {
- final BandedSampleConverter other = (BandedSampleConverter) object;
+ final var other = (BandedSampleConverter) object;
return Arrays .equals(converters, other.converters) &&
Objects.equals(colorModel, other.colorModel) &&
Arrays .equals(sampleResolutions, other.sampleResolutions);
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ComputedImage.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ComputedImage.java
index 7d6ec91caa..986e9b6e98 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ComputedImage.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ComputedImage.java
@@ -593,9 +593,9 @@ public abstract class ComputedImage extends PlanarImage implements Disposable {
}
/**
- * Notifies this image that tiles will be computed soon in the given region.
+ * Notifies this image that tiles will be computed soon for the given tile indices.
* This method is invoked by {@link ImageProcessor#prefetch(RenderedImage, Rectangle)}
- * before to request (potentially in multi-threads) all tiles in the area of interest.
+ * before to request (potentially in multi-threads) tiles at the specified indices.
* If the returned {@code Disposable} is non-null, {@code ImageProcessor} guarantees
* that the {@link Disposable#dispose()} method will be invoked after the prefetch
* operation completed, successfully or not.
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ImageOverlay.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ImageOverlay.java
index 3c7253e944..29b718e84e 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ImageOverlay.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ImageOverlay.java
@@ -399,7 +399,7 @@ final class ImageOverlay extends MultiSourceImage {
*/
@Override
protected Raster computeTile(final int tileX, final int tileY, WritableRaster target) {
- final Rectangle aoi = new Rectangle(
+ final var aoi = new Rectangle(
ImageUtilities.tileToPixelX(this, tileX),
ImageUtilities.tileToPixelY(this, tileY),
getTileWidth(),
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/MultiSourcePrefetch.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/MultiSourcePrefetch.java
index 7f1452b754..d0aa7605bf 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/MultiSourcePrefetch.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/MultiSourcePrefetch.java
@@ -29,7 +29,7 @@ import org.apache.sis.image.internal.shared.ImageUtilities;
/**
* A helper class for forwarding a {@code prefetch(…)} operation to multiple sources.
* This implementation assumes that all sources share the same pixel coordinates space.
- * However the tile matrix does not need to be the same.
+ * However, the tile matrix does not need to be the same.
*
* @author Martin Desruisseaux (Geomatys)
*/
@@ -102,12 +102,13 @@ final class MultiSourcePrefetch implements Disposable {
* @param parallel whether parallelism is allowed.
* @return a handler for disposing resources after prefetch, or {@code null} if none.
*/
+ @SuppressWarnings("UseSpecificCatch")
final Disposable run(boolean parallel) {
switch (count) {
case 0: return null;
case 1: parallel = false;
}
- @SuppressWarnings({"unchecked","rawtypes"})
+ @SuppressWarnings({"unchecked", "rawtypes"})
final var workers = (Future<Disposable>[]) (parallel ? new Future[count] : null);
cleaners = new Disposable[count];
for (int i=0; i<count; i++) {
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/PlanarImage.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/PlanarImage.java
index 4cadfc431d..8c32509269 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/PlanarImage.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/PlanarImage.java
@@ -25,6 +25,7 @@ import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.awt.image.WritableRenderedImage;
import java.awt.image.RenderedImage;
+import java.awt.image.ImagingOpException;
import java.util.Objects;
import java.util.Vector;
import java.util.function.DoubleUnaryOperator;
@@ -633,6 +634,7 @@ public abstract class PlanarImage implements RenderedImage {
* @param tiles indices of the tiles which will be prefetched.
* @return handler on which to invoke {@code dispose()} after the prefetch operation
* completed (successfully or not), or {@code null} if none.
+ * @throws ImagingOpException if an error occurred while preparing tile computation.
*/
Disposable prefetch(Rectangle tiles) {
return null;
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/PrefetchedImage.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/PrefetchedImage.java
index ee5ac4274e..b8b05b7b10 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/PrefetchedImage.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/PrefetchedImage.java
@@ -35,7 +35,7 @@ import org.apache.sis.util.resources.Errors;
/**
- * An image which delegate all tile requests to another image except for some tiles that are fetched in advance.
+ * An image which delegates all tile requests to another image except for some tiles that are fetched in advance.
* This image has the same coordinate systems as the source image.
*
* @author Martin Desruisseaux (Geomatys)
@@ -108,7 +108,7 @@ final class PrefetchedImage extends PlanarImage implements TileErrorHandler.Exec
return;
}
}
- final Worker worker = new Worker(source, areaOfInterest);
+ final var worker = new Worker(source, areaOfInterest);
final Rectangle ti = worker.getTileIndices();
minTileX = ti.x;
minTileY = ti.y;
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/SourceAlignedImage.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/SourceAlignedImage.java
index 96c778b03d..21265e35e1 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/SourceAlignedImage.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/SourceAlignedImage.java
@@ -199,7 +199,7 @@ abstract class SourceAlignedImage extends ComputedImage {
/**
* Notifies the source image that tiles will be computed soon in the given region.
* If the source image is an instance of {@link PlanarImage}, then this method
- * forwards the notification to it. Otherwise default implementation does nothing.
+ * forwards the notification to it. Otherwise, the default implementation does nothing.
*/
@Override
protected Disposable prefetch(final Rectangle tiles) {
diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/internal/shared/BatchComputedImage.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/internal/shared/BatchComputedImage.java
index 07aa6ae592..8b24a29c5c 100644
--- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/internal/shared/BatchComputedImage.java
+++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/internal/shared/BatchComputedImage.java
@@ -38,6 +38,9 @@ import org.apache.sis.util.resources.Errors;
* Implementations should manage their own cache for avoiding to compute the same tiles many times.
* The caching mechanism inherited from {@link ComputedImage} is less useful here.
*
+ * @todo Consider moving as a public class in {@link org.apache.sis.image.internal}
+ * for leveraging {@code MultiSourcePrefetch}.
+ *
* @author Martin Desruisseaux (Geomatys)
*/
public abstract class BatchComputedImage extends ComputedImage {
@@ -76,6 +79,13 @@ public abstract class BatchComputedImage extends ComputedImage {
this.tiles = tiles;
}
+ /**
+ * Tests whether this set of tiles contains the given set.
+ */
+ final boolean contains(final Rectangle other) {
+ return new Rectangle(x, y, width, height).contains(other);
+ }
+
/** Discards this set of tiles. */
@Override public void dispose() {
remove(this);
@@ -179,7 +189,14 @@ public abstract class BatchComputedImage extends ComputedImage {
* @throws ImagingOpException if an error occurred while preparing tile computation.
*/
@Override
- protected Disposable prefetch(final Rectangle region) {
+ public Disposable prefetch(final Rectangle region) {
+ synchronized (this) {
+ for (Rasters r = prefetched; r != null; r = r.next) {
+ if (r.contains(region)) {
+ return null; // Already prefetched.
+ }
+ }
+ }
final Raster[] tiles;
try {
tiles = computeTiles(region);
@@ -188,7 +205,7 @@ public abstract class BatchComputedImage extends ComputedImage {
} catch (Exception e) {
throw (ImagingOpException) new ImagingOpException(e.getMessage()).initCause(e);
}
- final Rasters r = new Rasters(region, tiles);
+ final var r = new Rasters(region, tiles);
synchronized (this) {
r.next = prefetched;
prefetched = r;
diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/ArtificiallyTiledImage.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/ArtificiallyTiledImage.java
index ba659a2afb..1f6ad12f91 100644
--- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/ArtificiallyTiledImage.java
+++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/ArtificiallyTiledImage.java
@@ -152,11 +152,13 @@ final class ArtificiallyTiledImage extends BatchComputedImage {
int minTileY = Integer.MAX_VALUE;
int maxTileX = Integer.MIN_VALUE;
int maxTileY = Integer.MIN_VALUE;
+ final int tilex0 = tiles.x; // Tile index of the raster at index 0 in the returned array.
+ final int tileY0 = tiles.y;
final int numXTiles = tiles.width;
final var rasters = new Raster[Math.multiplyExact(numXTiles, tiles.height)];
for (int i = 0; i < rasters.length; i++) {
- final int x = tiles.x + i % numXTiles;
- final int y = tiles.y + i / numXTiles;
+ final int x = tilex0 + i % numXTiles;
+ final int y = tileY0 + i / numXTiles;
if ((rasters[i] = cache.get(new Point(x, y))) == null) {
if (x < minTileX) minTileX = x;
if (x > maxTileX) maxTileX = x;
@@ -195,6 +197,11 @@ final class ArtificiallyTiledImage extends BatchComputedImage {
* Then, the requested extent is converted to the coverage grid coordinate system.
* Because this is also expected to be an identity operation or at most a translation,
* the rounding more is set to `NEAREST` instead of `ENCLOSING`.
+ *
+ * TODO: we use `RasterLoadingStrategy.AT_GET_TILE_TIME` because we don't know if we are going
+ * to use all requested tiles (because the cache in this class may make some reading unnecessary).
+ * We should do something more advanced, with a mask (potentially made of many rectangles) of the
+ * tiles that we really need to read.
*/
final GridGeometry request = domain.relocate(extent.reshape(low, high, true));
final GridCoverage coverage = source.readAtGetTileTime(request, requestedBands);
@@ -207,7 +214,7 @@ final class ArtificiallyTiledImage extends BatchComputedImage {
for (int y = minTileY; y <= maxTileY; y++) {
for (int x = minTileX; x <= maxTileX; x++) {
// No integer arithmetic can overflow in this loop.
- final int i = (y - tiles.y) * numXTiles + (x - tiles.x);
+ final int i = (y - tileY0) * numXTiles + (x - tilex0);
if (rasters[i] == null) {
rasters[i] = cache.computeIfAbsent(new Point(x, y), (key) -> {
final int tileWidth = sampleModel.getWidth();
diff --git a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverageResource.java b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverageResource.java
index 7d9655bd5a..c5be80aebe 100644
--- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverageResource.java
+++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/tiling/TiledGridCoverageResource.java
@@ -872,7 +872,7 @@ check: if (dataType.isInteger()) {
if (virtualSize / stride > ImageLayout.MAX_TILE_SIZE) {
// Tile is too large, even after subsampling.
if (i == xDimension || i == yDimension) {
- applyArtificialTiling |= !loadAtReadTime;
+ applyArtificialTiling = !loadAtReadTime;
}
}
virtualTileSize[i] = virtualSize;