You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by am...@apache.org on 2026/05/20 10:34:25 UTC
(sis) 04/06: chore(Storage): improve ImageTileMatrix test to verify multiple ways to acquire tiles
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 0b70760026ebf135cf2970d08de5281072153641
Author: Alexis Manin <al...@geomatys.com>
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;