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 76386d6d1cae39d80f7b0794c33c61ba109b3d8f Author: Martin Desruisseaux <[email protected]> AuthorDate: Sat Aug 1 15:41:51 2026 +0200 Modify `RenderingDataTest` for using the image mock. --- .../test/org/apache/sis/image/TiledImageMock.java | 71 +++++++++++++- .../image/internal/shared/ReshapedImageTest.java | 5 +- .../apache/sis/map/coverage/RenderingDataTest.java | 103 +++++++++++---------- 3 files changed, 124 insertions(+), 55 deletions(-) diff --git a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/TiledImageMock.java b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/TiledImageMock.java index 70989ebf3b..36fb739b6f 100644 --- a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/TiledImageMock.java +++ b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/TiledImageMock.java @@ -16,10 +16,13 @@ */ package org.apache.sis.image; +import java.util.Map; +import java.util.HashMap; import java.util.Arrays; import java.util.Random; import java.util.stream.Collectors; import java.util.concurrent.atomic.AtomicInteger; +import java.awt.Image; import java.awt.Point; import java.awt.Transparency; import java.awt.color.ColorSpace; @@ -47,8 +50,7 @@ import static org.junit.jupiter.api.Assertions.*; /** * A rendered image which can contain an arbitrary number of tiles. Tiles are stored in memory. - * We use this class for testing purpose only because tiled images in production use need a more - * sophisticated implementation capable to store some tiles on disk (for memory consumption reasons). + * We use this class for testing purpose only. * * @author Rémi Maréchal (Geomatys) * @author Martin Desruisseaux (Geomatys) @@ -142,6 +144,29 @@ public final class TiledImageMock extends PlanarImage implements WritableRendere */ private ColorModel colorModel; + /** + * Image properties as a writable map. + */ + private final Map<String, Object> properties; + + /** + * Creates a new tiled image starting a (0,0) and storing data as unsigned short (16 bits) integers. + * This is a convenience constructor for cases simpler than the full-featured constructor. + * + * @param width number of pixels along X axis in the whole rendered image. + * @param height number of pixels along Y axis in the whole rendered image. + * @param tileWidth number of pixels along X axis in a single tile of the image. + * @param tileHeight number of pixels along Y axis in a single tile of the image. + * @param numBands number of bands in the sample model to create. + * @param banded whether to use {@link BandedSampleModel} instead of {@link PixelInterleavedSampleModel}. + */ + public TiledImageMock(final int width, final int height, + final int tileWidth, final int tileHeight, + final int numBands, final boolean banded) + { + this(DataBuffer.TYPE_SHORT, numBands, 0, 0, width, height, tileWidth, tileHeight, 0, 0, banded); + } + /** * Creates a new tiled image. Testers should invoke {@link #validate()} after construction. * @@ -178,6 +203,7 @@ public final class TiledImageMock extends PlanarImage implements WritableRendere this.sampleModel = banded ? new BandedSampleModel(dataType, tileWidth, tileHeight, numBands) : new PixelInterleavedSampleModel(dataType, tileWidth, tileHeight, numBands, StrictMath.multiplyExact(numBands, tileWidth), ArraysExt.range(0, numBands)); + this.properties = new HashMap<>(); } /** @@ -210,8 +236,45 @@ public final class TiledImageMock extends PlanarImage implements WritableRendere return colorModel; } - /** Returns a sample model for data type given to the constructor. */ - @Override public SampleModel getSampleModel() {return sampleModel;} + /** + * Returns a sample model for data type given to the constructor. + */ + @Override + public SampleModel getSampleModel() { + return sampleModel; + } + + /** + * Returns the name of all properties, or {@code null} if none. + * + * @return the name of all properties, or {@code null} if none. + */ + @Override + public synchronized String[] getPropertyNames() { + return properties.isEmpty() ? null : properties.keySet().toArray(String[]::new); + } + + /** + * Returns the value associated to the given property name. + * + * @param name name of the property to fetch. + * @return the associated value, or {@link Image#UndefinedProperty} if none. + */ + @Override + public synchronized Object getProperty(final String name) { + return properties.getOrDefault(name, Image.UndefinedProperty); + } + + /** + * Adds a value associated to the given property name. + * Each property name can be associated to a value only once. + * + * @param name name of the property to set. + * @param value value of the property. + */ + public synchronized void addProperty(final String name, final Object value) { + assertNull(properties.putIfAbsent(name, value), name); + } /* * Information specified to the constructor. diff --git a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/internal/shared/ReshapedImageTest.java b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/internal/shared/ReshapedImageTest.java index 7230007200..1c6201cc16 100644 --- a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/internal/shared/ReshapedImageTest.java +++ b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/internal/shared/ReshapedImageTest.java @@ -203,11 +203,12 @@ public final class ReshapedImageTest extends TestCase { } /** - * Verify a reshaped image created to expose a single tile from a source tiled image only serves the requested tile. + * Verifies a reshaped image created to expose a single tile + * from a source tiled image which only serves the requested tile. */ @Test public void testExposeSingleTileFromTiledImage() { - var source = new TiledImageMock(DataBuffer.TYPE_USHORT, 1, 0, 0, 4, 4, 2, 2, 0, 0, false); + var source = new TiledImageMock(4, 4, 2, 2, 1, false); source.validate(); source.initializeAllTiles(0); RenderedImage lastTile = ReshapedImage.singleTile(source, 1, 1); diff --git a/endorsed/src/org.apache.sis.portrayal/test/org/apache/sis/map/coverage/RenderingDataTest.java b/endorsed/src/org.apache.sis.portrayal/test/org/apache/sis/map/coverage/RenderingDataTest.java index 7cf6ac1de4..7249c74974 100644 --- a/endorsed/src/org.apache.sis.portrayal/test/org/apache/sis/map/coverage/RenderingDataTest.java +++ b/endorsed/src/org.apache.sis.portrayal/test/org/apache/sis/map/coverage/RenderingDataTest.java @@ -16,15 +16,6 @@ */ package org.apache.sis.map.coverage; -import java.util.Map; -import java.util.Arrays; -import java.awt.Point; -import java.awt.color.ColorSpace; -import java.awt.image.ComponentColorModel; -import java.awt.image.DataBuffer; -import java.awt.image.DataBufferByte; -import java.awt.image.MultiPixelPackedSampleModel; -import java.awt.image.Raster; import java.awt.image.RenderedImage; import org.opengis.geometry.Envelope; import org.opengis.geometry.DirectPosition; @@ -42,7 +33,7 @@ import org.apache.sis.geometry.GeneralDirectPosition; import org.apache.sis.geometry.GeneralEnvelope; import org.apache.sis.image.ErrorHandler; import org.apache.sis.image.PlanarImage; -import org.apache.sis.image.internal.shared.TiledImage; +import org.apache.sis.image.TiledImageMock; import org.apache.sis.referencing.CommonCRS; import org.apache.sis.referencing.operation.transform.LinearTransform; import org.apache.sis.referencing.operation.transform.MathTransforms; @@ -62,25 +53,41 @@ import org.apache.sis.test.TestCase; */ public final class RenderingDataTest extends TestCase { /** - * Width and height (in pixels) of the rendered image produced in output. + * Number of tiles horizontally and vertically. + * The number of horizontal tiles is such as a Region Of Interest (<abbr>ROI</abbr>) in the middle + * and covering half the image width will intersect all 3 tiles, thus preventing tile subsetting. + * The number of vertical tiles makes such tile subsetting possible on the <var>y</var> axis. + */ + private static final int NUM_X_TILES = 3, NUM_Y_TILES = 4; + + /** + * Tile size (width and height) in pixels. */ - private static final int RENDERED_SIZE = 8; + private static final int TILE_WIDTH = 8, TILE_HEIGHT = 5; /** - * Width and height (in pixels) of the resource used as input. + * Image size (width and height) in pixels. */ - private static final int DATA_SIZE = 128; + private static final int IMAGE_WIDTH = NUM_X_TILES * TILE_WIDTH, + IMAGE_HEIGHT = NUM_Y_TILES * TILE_HEIGHT; /** - * Tile height in pixels. There is no tile width as this test does not tile the image horizontally. - * It is sufficient to focus the test on the tiling in only one axis, which is <abbr>y</abbr>. + * Width and height (in pixels) of the rendered image produced in output. */ - private static final int TILE_HEIGHT = 16; + private static final int RENDERED_WIDTH = 9, RENDERED_HEIGHT = 8; /** * Number of meters per pixel at full resolution. + * The <var>y</var> resolution is negative for flipping axis direction. + */ + private static final double X_RESOLUTION = 10, Y_RESOLUTION = -8; + + /** + * Envelope extent (width and height) in metres. + * The height is intentionally negative. */ - private static final double RESOLUTION = 10; + private static final double ENVELOPE_WIDTH = X_RESOLUTION * IMAGE_WIDTH, + ENVELOPE_HEIGHT = Y_RESOLUTION * IMAGE_HEIGHT; /** * The western-most coordinate of the limit of the resource extent. @@ -122,22 +129,15 @@ public final class RenderingDataTest extends TestCase { /** * Creates a two-dimensional coverage wrapping a tiled image with an <var>UTM</var> projection. - * The pixel values do not matter and are all zeros. What matter for this test is the tiling. - * Therefore, for saving memory and <abbr>CPU</abbr>, all tiles share the same data buffer. */ private static GridCoverage createTiledCoverage() { - final var gridToCRS = new AffineTransform2D(RESOLUTION, 0, 0, -RESOLUTION, WEST_BOUND, NORTH_BOUND); + final var gridToCRS = new AffineTransform2D(X_RESOLUTION, 0, 0, Y_RESOLUTION, WEST_BOUND, NORTH_BOUND); final var crs = CommonCRS.WGS84.universal(45, 3); // UTM zone 31N. - final var gg = new GridGeometry(new GridExtent(DATA_SIZE, DATA_SIZE), PixelInCell.CELL_CORNER, gridToCRS, crs); - final var properties = Map.of(TiledImage.GRID_GEOMETRY_KEY, gg); - - final var colorSpace = ColorSpace.getInstance(ColorSpace.CS_GRAY); - final var colors = new ComponentColorModel(colorSpace, false, true, ComponentColorModel.OPAQUE, DataBuffer.TYPE_BYTE); - final var layout = new MultiPixelPackedSampleModel(DataBuffer.TYPE_BYTE, DATA_SIZE, TILE_HEIGHT, 1); - final var buffer = new DataBufferByte(DATA_SIZE * TILE_HEIGHT / Byte.SIZE, 1); - final var tiles = new Raster[DATA_SIZE / TILE_HEIGHT]; - Arrays.setAll(tiles, (i) -> Raster.createRaster(layout, buffer, new Point(0, i * TILE_HEIGHT))); - final var image = new TiledImage(properties, colors, DATA_SIZE, DATA_SIZE, 0, 0, tiles); + final var gg = new GridGeometry(new GridExtent(IMAGE_WIDTH, IMAGE_HEIGHT), PixelInCell.CELL_CORNER, gridToCRS, crs); + final var image = new TiledImageMock(IMAGE_WIDTH, IMAGE_HEIGHT, TILE_WIDTH, TILE_HEIGHT, 1, true); + image.addProperty(TiledImageMock.GRID_GEOMETRY_KEY, gg); + image.validate(); + image.initializeAllTiles(0); return new GridCoverage2D(gg, null, image); } @@ -194,11 +194,12 @@ public final class RenderingDataTest extends TestCase { assertArrayEquals(new int[] {0, 1}, r.getXYDimensions()); } domain = domain.selectDimensions(0, 1); - final double scale = ((double) RENDERED_SIZE) / (DATA_SIZE * RESOLUTION); - final var objectiveToDisplay = new AffineTransform2D(scale, 0, 0, -scale, WEST_BOUND * -scale, NORTH_BOUND * scale); + final double scaleX = RENDERED_WIDTH / ENVELOPE_WIDTH; + final double scaleY = RENDERED_HEIGHT / ENVELOPE_HEIGHT; // Negative. + final var objectiveToDisplay = new AffineTransform2D(scaleX, 0, 0, scaleY, WEST_BOUND * -scaleX, NORTH_BOUND * -scaleY); final CoordinateReferenceSystem objectiveCRS = domain.getCoordinateReferenceSystem(); - final var poi = new DirectPosition2D(objectiveCRS, WEST_BOUND + DATA_SIZE * RESOLUTION / 2, - NORTH_BOUND - DATA_SIZE * RESOLUTION / 2); + final var poi = new DirectPosition2D(objectiveCRS, WEST_BOUND + ENVELOPE_WIDTH / 2, + NORTH_BOUND + ENVELOPE_HEIGHT / 2); /* * Render the request which has been prepared above. * Get the result, but also the source of the result. @@ -215,16 +216,20 @@ public final class RenderingDataTest extends TestCase { * The source should have the same size as the original data, * but translated for having the request at coordinates (0,0). */ - assertEquals(-DATA_SIZE / 4, source.getMinX()); // Difference relative to requested area. - assertEquals( DATA_SIZE, source.getWidth()); - assertEquals( 0, source.getMinY()); - assertEquals( DATA_SIZE / 2, source.getHeight()); - assertEquals(0, shown.getMinX()); - assertEquals(RENDERED_SIZE, shown.getWidth()); - assertEquals(RENDERED_SIZE, shown.getTileWidth()); - assertEquals(RENDERED_SIZE / 4, shown.getMinY()); - assertEquals(RENDERED_SIZE / 2, shown.getHeight()); - assertEquals(RENDERED_SIZE / 2, shown.getTileHeight()); + assertEquals(TILE_WIDTH, source.getTileWidth()); + assertEquals(TILE_HEIGHT, source.getTileHeight()); + assertEquals(NUM_X_TILES, source.getNumXTiles()); // Couldn't retain only a subset of the tiles. + assertEquals(NUM_Y_TILES / 2, source.getNumYTiles()); // Could retain a subset of the tiles. + assertEquals(IMAGE_WIDTH, source.getWidth()); // Full width because tile subsetting couldn't be applied. + assertEquals(IMAGE_HEIGHT / 2, source.getHeight()); + assertEquals(IMAGE_WIDTH / -4, source.getMinX()); // Difference relative to requested area. + assertEquals(0, source.getMinY()); // No difference because tile subsetting was applied. + assertEquals(0, shown.getMinX()); + assertEquals(RENDERED_HEIGHT / 4, shown.getMinY()); + assertEquals(RENDERED_WIDTH, shown.getWidth()); + assertEquals(RENDERED_WIDTH, shown.getTileWidth()); + assertEquals(RENDERED_HEIGHT / 2, shown.getHeight()); + assertEquals(RENDERED_HEIGHT / 2, shown.getTileHeight()); /* * Verify georeferencing. */ @@ -236,8 +241,8 @@ public final class RenderingDataTest extends TestCase { */ private static void verifyLocationOfCenter(final GridGeometry domain) throws TransformException { final Envelope envelope = domain.getEnvelope(); - assertEquals( WEST_BOUND + RESOLUTION * (DATA_SIZE / 2), envelope.getMedian(0)); - assertEquals(NORTH_BOUND - RESOLUTION * (DATA_SIZE / 2), envelope.getMedian(1)); + assertEquals( WEST_BOUND + ENVELOPE_WIDTH / 2, envelope.getMedian(0)); + assertEquals(NORTH_BOUND + ENVELOPE_HEIGHT / 2, envelope.getMedian(1)); final GridExtent extent = domain.getExtent(); final var center = new GeneralDirectPosition(extent.getDimension()); @@ -245,7 +250,7 @@ public final class RenderingDataTest extends TestCase { center.setCoordinate(i, extent.getMedian(i)); } assertSame(center, (domain.getGridToCRS(PixelInCell.CELL_CORNER).transform(center, center))); - assertEquals( WEST_BOUND + RESOLUTION * (DATA_SIZE / 2), center.getCoordinate(0)); - assertEquals(NORTH_BOUND - RESOLUTION * (DATA_SIZE / 2), center.getCoordinate(1)); + assertEquals( WEST_BOUND + ENVELOPE_WIDTH / 2, center.getCoordinate(0)); + assertEquals(NORTH_BOUND + ENVELOPE_HEIGHT / 2, center.getCoordinate(1)); } }
