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

alexismanin pushed a commit to branch fix/image-tile-matrix-get-tile
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 62bbf09a548be167a738d7c9d5395609d79cc5ff
Author: Alexis Manin <[email protected]>
AuthorDate: Mon May 18 12:30:56 2026 +0200

    chore(Storage): improve ImageTileMatrix test to verify multiple ways to 
acquire tiles
---
 .../sis/storage/tiling/ImageTileMatrixTest.java    | 152 +++++++++++++++++----
 1 file changed, 126 insertions(+), 26 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/tiling/ImageTileMatrixTest.java
 
b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/tiling/ImageTileMatrixTest.java
index 372713b087..899f80e4b7 100644
--- 
a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/tiling/ImageTileMatrixTest.java
+++ 
b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/tiling/ImageTileMatrixTest.java
@@ -21,8 +21,8 @@ import java.awt.image.ColorModel;
 import java.awt.image.Raster;
 import java.awt.image.SampleModel;
 import java.awt.image.WritableRaster;
+import java.util.Arrays;
 import java.util.List;
-import java.util.Optional;
 import org.apache.sis.storage.GridCoverageResource;
 import org.opengis.metadata.spatial.DimensionNameType;
 import org.opengis.util.GenericName;
@@ -44,7 +44,11 @@ import org.apache.sis.referencing.crs.HardCodedCRS;
 
 
 /**
- * Minimal test case for image tile matrices
+ * Verify behavior of {@link ImageTileMatrix} in a 3D space.
+ * </br>
+ * This test creates a {@link MockTiledResource coverage mockup} that contains 
two 2D slices.
+ * Each slice contains {@link #NUM_COLS} tile columns and {@link #NUM_ROWS} 
tile rows.
+ * Each tile is a single band image whose diagonal is filled with its tile 
indices.
  *
  * @author  Alexis Manin (Geomatys)
  */
@@ -61,38 +65,130 @@ public final class ImageTileMatrixTest extends TestCase {
     /**
      * Test that a tile from a 3D dataset can return its associated resource.
      * This is an anti-regression test because of a bug encountered while 
fetching tile resource.
-     *
-     * @throws DataStoreException if a data store error occurred.
      */
     @Test
-    public void testGetResourceFromTile3D() throws DataStoreException {
+    public void testGetIndividualTiles3D() throws DataStoreException {
+        final var matrix = get3DMockupTileMatrix();
+        final var tilingExtent = matrix.getTilingScheme().getExtent();
+        assertEquals(3, tilingExtent.getDimension());
+        tilingExtent.latticePointStream(true)
+                .map(tileCoord -> loadTile(tileCoord, matrix))
+                .forEach(ImageTileMatrixTest::checkTileContent);
+    }
+
+    /**
+     * Check another path to obtain and validate tiles: get a batch of (all in 
fact) tiles using {@link TileMatrix#getTiles(GridExtent, boolean)}
+     */
+    @Test
+    public void testGetTileBatch3D() throws DataStoreException {
+        final var matrix = get3DMockupTileMatrix();
+        matrix.getTiles(null, true)
+              .forEach(ImageTileMatrixTest::checkTileContent);
+    }
+
+    /**
+     * Check tile content by querying a full rendering on each slice in the 3D 
coverage mockup.
+     * The aim is to ensure that coverage rendering properly returns a tiled 
image,
+     * and that each tile in the rendered image gives back its associated Tile 
content.
+     * Said otherwise, it checks that there's no tile mismatch or mixup when 
using ImageIO accessor.
+     */
+    @Test
+    public void testGetTilesViaRender() throws DataStoreException {
+        final var resource = new MockTiledResource();
+        final var coverage = resource.read((GridGeometry) null);
+        final var overallExtent = coverage.getGridGeometry().getExtent();
+        overallExtent.resize(1, 1).latticePointStream(true)
+                .forEach(temporalSlice -> {
+                    var sliceHigh = temporalSlice.clone();
+                    sliceHigh[0] = overallExtent.getHigh(0);
+                    sliceHigh[1] = overallExtent.getHigh(1);
+                    final var renderExtent = new GridExtent(null, 
temporalSlice, sliceHigh, true);
+
+                    final var image = coverage.render(renderExtent);
+                    for (int col = 0; col < NUM_COLS; col++) {
+                        for (int row = 0; row < NUM_ROWS; row++) {
+                            final var tileIndices = temporalSlice.clone();
+                            tileIndices[0] = col;
+                            tileIndices[1] = row;
+                            final var tileRaster = image.getTile(col, row);
+                            checkTileOrigin(tileRaster, tileIndices);
+                            checkTileRaster(tileRaster, tileIndices);
+                        }
+                    }
+                });
+    }
+
+    private void checkTileOrigin(Raster tileRaster, long[] tileIndices) {
+        final var expectedTileOrigin = new int[] {
+                Math.toIntExact(Math.multiplyExact(tileIndices[0], 
TILE_WIDTH)),
+                Math.toIntExact(Math.multiplyExact(tileIndices[1], 
TILE_HEIGHT))
+        };
+        final var actualTileOrigin = new int[] { tileRaster.getMinX(), 
tileRaster.getMinY() };
+        assertArrayEquals(expectedTileOrigin, actualTileOrigin,
+                () -> String.format(
+                        "Tile (%s): raster origin does not match rendering 
location. Expected: (%s) but was (%s)",
+                        Arrays.toString(tileIndices), 
Arrays.toString(expectedTileOrigin), Arrays.toString(actualTileOrigin)
+                )
+        );
+    }
+
+    private TileMatrix get3DMockupTileMatrix() throws DataStoreException {
         final var resource = new MockTiledResource();
         final var tileMatrixSets = resource.getTileMatrixSets();
         assertFalse(tileMatrixSets.isEmpty());
-        final TileMatrixSet tms = tileMatrixSets.iterator().next();
-        assertFalse(tms.getTileMatrices().isEmpty());
-        final TileMatrix matrix = 
tms.getTileMatrices().values().iterator().next();
+        final var tms = tileMatrixSets.iterator().next();
+        final var tileMatrixIterator = 
tms.getTileMatrices().values().iterator();
+        assertTrue(tileMatrixIterator.hasNext());
+        final var matrix = tileMatrixIterator.next();
+        assertFalse(tileMatrixIterator.hasNext());
+        return matrix;
+    }
 
-        final GridExtent tilingExtent = matrix.getTilingScheme().getExtent();
-        assertEquals(3, tilingExtent.getDimension());
-        final long[] indices = new long[] {
-            tilingExtent.getLow(0),
-            tilingExtent.getLow(1),
-            tilingExtent.getLow(2)
-        };
+    /**
+     * Load a specific tile from the given tile matrix.
+     * This method expects that tile content will respect this test
+     */
+    private Tile loadTile(long[] requestedTileIndices, TileMatrix matrix) {
+        try {
+            final var optTile = matrix.getTile(requestedTileIndices);
+            assertTrue(optTile.isPresent());
+            final var tile = optTile.get();
+            final var tIndices = tile.getIndices();
+            assertArrayEquals(requestedTileIndices, tIndices, "Tile indices 
differ from request");
+            return tile;
+        } catch (DataStoreException e) {
+            throw new AssertionError("Extraction of tile ("+ 
Arrays.toString(requestedTileIndices)+") failed", e);
+        }
+    }
+
+    private static void checkTileContent(Tile tile) {
+        final var tileIndices = tile.getIndices();
+        try {
+            assertEquals(TileStatus.EXISTS, tile.getStatus());
+            final var tResource = tile.getResource();
+            assertNotNull(tResource);
+            if (!(tResource instanceof GridCoverageResource tileGridResource)) 
{
+                throw new AssertionError("Tile resource is not a grid 
resource");
+            }
+            final var tileImage = tileGridResource.read(null).render(null);
+            assertEquals(TILE_WIDTH, tileImage.getWidth());
+            assertEquals(TILE_HEIGHT, tileImage.getHeight());
+
+            assertEquals(1, tileImage.getNumXTiles() * 
tileImage.getNumYTiles(),
+                    "Tile image should contain only a single raster tile.");
+            final var tileRaster = tileImage.getTile(tileImage.getMinTileX(), 
tileImage.getMinTileY());
+            checkTileRaster(tileRaster, tileIndices);
+        } catch (DataStoreException e) {
+            fail("Validation of tile ("+ Arrays.toString(tileIndices)+") 
failed", e);
+        }
+    }
 
-        final Optional<Tile> optTile = matrix.getTile(indices);
-        assertTrue(optTile.isPresent());
-        final var tile = optTile.get();
-        assertEquals(TileStatus.EXISTS, tile.getStatus());
-        final var tResource = tile.getResource();
-        assertNotNull(tResource);
-        if (!(tResource instanceof GridCoverageResource tileGridResource)) {
-            throw new AssertionError("Tile resource is not a grid resource");
+    private static void checkTileRaster(Raster tileRaster, long[] tileIndices) 
{
+        for (int i=0 ; i < tileIndices.length ; i++) {
+            final var index = i;
+            assertEquals(tileIndices[i], 
tileRaster.getSample(tileRaster.getMinX() + i, tileRaster.getMinY() + i, 0),
+                    () -> String.format("Tile sample at coordinate (%1$d, 
%1$d) should be the tile coordinate at dimension %1$d", index));
         }
-        var tileImage = tileGridResource.read(null).render(null);
-        assertEquals(TILE_WIDTH, tileImage.getWidth());
-        assertEquals(TILE_HEIGHT, tileImage.getHeight());
     }
 
     /**
@@ -180,6 +276,10 @@ public final class ImageTileMatrixTest extends TestCase {
             final Raster[] tiles = new Raster[iterator.tileCountInQuery];
             do {
                 final WritableRaster raster = iterator.createRaster();
+                final var tileCoords = iterator.getTileCoordinatesInResource();
+                for (int i = 0; i < tileCoords.length; i++) {
+                    raster.setSample(raster.getMinX() + i, raster.getMinY() + 
i, 0, tileCoords[i]);
+                }
                 tiles[iterator.getTileIndexInResultArray()] = raster;
             } while (iterator.next());
             return tiles;

Reply via email to