This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit a32a606dbf8f96f54f619a0abeae43c0b946d789 Author: Martin Desruisseaux <[email protected]> AuthorDate: Sun Dec 29 22:55:45 2019 +0100 Add more tests for ReshapedImage and fix a few bugs in this process. --- .../apache/sis/coverage/grid/ReshapedImage.java | 31 +++- .../sis/coverage/grid/ReshapedImageTest.java | 171 +++++++++++++++++++-- .../sis/internal/coverage/j2d/PlanarImageTest.java | 2 +- .../apache/sis/test/suite/FeatureTestSuite.java | 6 +- 4 files changed, 183 insertions(+), 27 deletions(-) diff --git a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ReshapedImage.java b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ReshapedImage.java index 7fd6ab3..bb4fe6c 100644 --- a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ReshapedImage.java +++ b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ReshapedImage.java @@ -24,6 +24,7 @@ import java.awt.image.SampleModel; import java.awt.image.ColorModel; import java.awt.image.WritableRaster; import org.apache.sis.internal.coverage.j2d.PlanarImage; +import org.apache.sis.util.ArgumentChecks; import static java.lang.Math.min; import static java.lang.Math.max; @@ -131,8 +132,8 @@ final class ReshapedImage extends PlanarImage { minY = toIntExact(y); width = toIntExact(min(upperX, (maxTX + 1) * tw + xo) - sx); height = toIntExact(min(upperY, (maxTY + 1) * th + yo) - sy); - offsetX = toIntExact(x - lowerX); - offsetY = toIntExact(y - lowerY); + offsetX = toIntExact(x - sx); + offsetY = toIntExact(y - sy); minTileX = toIntExact(minTX); minTileY = toIntExact(minTY); } @@ -224,7 +225,15 @@ final class ReshapedImage extends PlanarImage { */ @Override public Raster getData() { - return offset(image.getData()); + /* + * If this image contains all data, delegate to RenderedImage.getData() + * in case some implementations provide an optimized method. Otherwise + * ask only the sub-region covered by this image. + */ + if (width >= image.getWidth() && height >= image.getHeight()) { + return offset(image.getData()); + } + return copyData(new Rectangle(minX, minY, width, height)); } /** @@ -235,8 +244,16 @@ final class ReshapedImage extends PlanarImage { * @return a copy of this image in the given area of interest. */ @Override - public Raster getData(Rectangle aoi) { - aoi = new Rectangle(aoi); + public Raster getData(final Rectangle aoi) { + ArgumentChecks.ensureNonNull("aoi", aoi); + return copyData(new Rectangle(aoi)); + } + + /** + * Implementation of {@link #getData(Rectangle)}. This implementation will modify the given {@code aoi} + * argument. If that argument was supplied by user, then it should first be copied by the caller. + */ + private Raster copyData(final Rectangle aoi) { aoi.x = subtractExact(aoi.x, offsetX); // Convert coordinate from this image to wrapped image. aoi.y = subtractExact(aoi.y, offsetY); final Raster data = image.getData(aoi); @@ -276,8 +293,8 @@ final class ReshapedImage extends PlanarImage { public String verify() { final String error = super.verify(); if (error == null) { - if (getMinX() != image.getMinX() + offsetX) return "minX"; - if (getMinY() != image.getMinY() + offsetY) return "minY"; + if (getMinX() != image.getMinX() + (minTileX - image.getMinTileX()) * getTileWidth() + offsetX) return "minX"; + if (getMinY() != image.getMinY() + (minTileY - image.getMinTileY()) * getTileHeight() + offsetY) return "minY"; if (getTileGridXOffset() != super.getTileGridXOffset()) return "tileGridXOffset"; if (getTileGridYOffset() != super.getTileGridYOffset()) return "tileGridYOffset"; } diff --git a/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/ReshapedImageTest.java b/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/ReshapedImageTest.java index de15b71..6155bf9 100644 --- a/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/ReshapedImageTest.java +++ b/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/ReshapedImageTest.java @@ -16,8 +16,12 @@ */ package org.apache.sis.coverage.grid; +import java.util.Random; +import java.awt.image.DataBuffer; import java.awt.image.BufferedImage; -import java.awt.image.WritableRaster; +import org.apache.sis.image.TiledImageMock; +import org.apache.sis.test.DependsOn; +import org.apache.sis.test.TestUtilities; import org.apache.sis.test.TestCase; import org.junit.Test; @@ -34,25 +38,160 @@ import static org.apache.sis.test.FeatureAssert.assertValuesEqual; * @since 1.1 * @module */ +@DependsOn(org.apache.sis.internal.coverage.j2d.PlanarImageTest.class) public final strictfp class ReshapedImageTest extends TestCase { /** - * Tests with a request starting on the left and on top of data. + * Size of tiles used in this test. + */ + private static final int TILE_WIDTH = 3, TILE_HEIGHT = 2; + + /** + * Expected coordinates of image upper-left corner. Default value is (0,0). + */ + private int minX, minY; + + /** + * Expected index of first tile. Default value is (0,0). + */ + private int minTileX, minTileY; + + /** + * Expected number of tiles. Shall be initialized by test method + * before to invoke {@link #verifyLayout(ReshapedImage)}. + */ + private int numXTiles, numYTiles; + + /** + * Expected values of image size. Shall be initialized by test + * method before to invoke {@link #verifyLayout(ReshapedImage)}. + */ + private int width, height; + + /** + * Expected values of tile grid offset. Shall be initialized by test + * method before to invoke {@link #verifyLayout(ReshapedImage)}. + */ + private int tileXOffset, tileYOffset; + + /** + * Tests wrapping a {@link BufferedImage}. This single case has only one tile + * with pixel coordinates starting at (0,0). */ @Test - public void testRequestBefore() { - final BufferedImage image = new BufferedImage(2, 2, BufferedImage.TYPE_BYTE_GRAY); - final WritableRaster raster = image.getRaster(); - raster.setSample(0, 0, 0, 1); - raster.setSample(1, 0, 0, 2); - raster.setSample(0, 1, 0, 3); - raster.setSample(1, 1, 0, 4); - - final ReshapedImage trs = new ReshapedImage(image, -1, -2, 4, 4); - assertEquals(1, trs.getMinX()); - assertEquals(2, trs.getMinY()); - assertValuesEqual(trs.getData(), 0, new int[][] { - {1, 2}, - {3, 4} + public void testSingleTile() { + numXTiles = 1; + numYTiles = 1; + width = TILE_WIDTH; + height = TILE_HEIGHT; + final BufferedImage data = new BufferedImage(TILE_WIDTH, TILE_HEIGHT, BufferedImage.TYPE_BYTE_GRAY); + data.getRaster().setSamples(0, 0, TILE_WIDTH, TILE_HEIGHT, 0, new int[] { + 1, 2, 3, + 4, 7, 6 + }); + /* + * Tests with a request starting on the left and on top of data. + * The requested size is larger than image size; constructor shall clamp. + */ + tileXOffset = minX = 1; + tileYOffset = minY = 2; + verifySingleTile(new ReshapedImage(data, -1, -2, 4, 4)); + /* + * Tests with a request inside the image. Constructor should expand to + * an integer number of tiles, which is the whole image for this test. + */ + tileXOffset = minX = -2; + tileYOffset = minY = -1; + verifySingleTile(new ReshapedImage(data, 2, 1, 1, 1)); + } + + /** + * Verify an image created by {@link #testSingleTile()}. + * + * @param image the reshaped image. + */ + private void verifySingleTile(final ReshapedImage image) { + verifyLayout(image); + assertValuesEqual(image.getData(), 0, new int[][] { + {1, 2, 3}, + {4, 7, 6} + }); + } + + /** + * Verifies the image properties (size, number of tiles). + * + * @param image the image to verify. + */ + private void verifyLayout(final ReshapedImage image) { + assertNull( image.verify()); + assertEquals(minX, image.getMinX()); + assertEquals(minY, image.getMinY()); + assertEquals(width, image.getWidth()); + assertEquals(height, image.getHeight()); + assertEquals(TILE_WIDTH, image.getTileWidth()); + assertEquals(TILE_HEIGHT, image.getTileHeight()); + assertEquals(minTileX, image.getMinTileX()); + assertEquals(minTileY, image.getMinTileY()); + assertEquals(numXTiles, image.getNumXTiles()); + assertEquals(numYTiles, image.getNumYTiles()); + assertEquals(tileXOffset, image.getTileGridXOffset()); + assertEquals(tileYOffset, image.getTileGridYOffset()); + } + + /** + * Tests wrapping a {@link TiledImageMock}. + */ + @Test + public void testMultiTiles() { + final Random random = TestUtilities.createRandomNumberGenerator(219970242558564L); + final int dataMinX, dataMinY; + dataMinX = random.nextInt(20) - 10; + dataMinY = random.nextInt(20) - 10; + minTileX = random.nextInt(20) - 10; + minTileY = random.nextInt(20) - 10; + numXTiles = 5; + numYTiles = 4; + width = numXTiles * TILE_WIDTH; + height = numYTiles * TILE_HEIGHT; + final TiledImageMock data = new TiledImageMock(DataBuffer.TYPE_USHORT, 1, dataMinX, dataMinY, + width, height, TILE_WIDTH, TILE_HEIGHT, minTileX, minTileY); + data.validate(); + data.initializeAllTiles(0); + /* + * Apply only a translation, keep all tiles. + */ + tileXOffset = (minX = 7) - minTileX * TILE_WIDTH; + tileYOffset = (minY = 13) - minTileY * TILE_HEIGHT; + ReshapedImage image = new ReshapedImage(data, dataMinX - 7, dataMinY - 13, 100, 100); + verifyLayout(image); + assertValuesEqual(image.getData(), 0, new int[][] { + { 100, 101, 102 , 200, 201, 202 , 300, 301, 302 , 400, 401, 402 , 500, 501, 502}, + { 110, 111, 112 , 210, 211, 212 , 310, 311, 312 , 410, 411, 412 , 510, 511, 512}, + { 600, 601, 602 , 700, 701, 702 , 800, 801, 802 , 900, 901, 902 , 1000, 1001, 1002}, + { 610, 611, 612 , 710, 711, 712 , 810, 811, 812 , 910, 911, 912 , 1010, 1011, 1012}, + {1100, 1101, 1102 , 1200, 1201, 1202 , 1300, 1301, 1302 , 1400, 1401, 1402 , 1500, 1501, 1502}, + {1110, 1111, 1112 , 1210, 1211, 1212 , 1310, 1311, 1312 , 1410, 1411, 1412 , 1510, 1511, 1512}, + {1600, 1601, 1602 , 1700, 1701, 1702 , 1800, 1801, 1802 , 1900, 1901, 1902 , 2000, 2001, 2002}, + {1610, 1611, 1612 , 1710, 1711, 1712 , 1810, 1811, 1812 , 1910, 1911, 1912 , 2010, 2011, 2012} + }); + /* + * Ask for a subregion of the image. The subregion starts at (5,3) and ends at (9,5) inclusive. + * ReshapedImageTest shall expand to an integer number of tiles, which result in (3,2) - (11,5). + * This is 3×2 tiles. + */ + minTileX++; // Skip one tile on the left. + minTileY++; // Skip one tile on the bottom. + width = (numXTiles = 3) * TILE_WIDTH; + height = (numYTiles = 2) * TILE_HEIGHT; + tileXOffset = (minX = -2) - minTileX * TILE_WIDTH; + tileYOffset = (minY = -1) - minTileY * TILE_HEIGHT; + image = new ReshapedImage(data, dataMinX + 5, dataMinY + 3, dataMinX + 9, dataMinY + 5); + verifyLayout(image); + assertValuesEqual(image.getData(), 0, new int[][] { + { 700, 701, 702 , 800, 801, 802 , 900, 901, 902}, + { 710, 711, 712 , 810, 811, 812 , 910, 911, 912}, + {1200, 1201, 1202 , 1300, 1301, 1302 , 1400, 1401, 1402}, + {1210, 1211, 1212 , 1310, 1311, 1312 , 1410, 1411, 1412} }); } } diff --git a/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/j2d/PlanarImageTest.java b/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/j2d/PlanarImageTest.java index e25f534..c983c3e 100644 --- a/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/j2d/PlanarImageTest.java +++ b/core/sis-feature/src/test/java/org/apache/sis/internal/coverage/j2d/PlanarImageTest.java @@ -66,7 +66,7 @@ public final strictfp class PlanarImageTest extends TestCase { TILE_HEIGHT * 3, // height TILE_WIDTH, TILE_HEIGHT, - random.nextInt(20) - 10, // minTileX, + random.nextInt(20) - 10, // minTileX random.nextInt(20) - 10); // minTileY image.validate(); image.initializeAllTiles(0); diff --git a/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java b/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java index e9a6f4c..73940c8 100644 --- a/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java +++ b/core/sis-feature/src/test/java/org/apache/sis/test/suite/FeatureTestSuite.java @@ -74,6 +74,9 @@ import org.junit.runners.Suite; org.apache.sis.feature.builder.FeatureTypeBuilderTest.class, // Rasters + org.apache.sis.internal.coverage.j2d.ImageUtilitiesTest.class, + org.apache.sis.internal.coverage.j2d.ScaledColorSpaceTest.class, + org.apache.sis.internal.coverage.j2d.PlanarImageTest.class, org.apache.sis.image.DefaultIteratorTest.class, org.apache.sis.image.LinearIteratorTest.class, org.apache.sis.coverage.CategoryTest.class, @@ -87,9 +90,6 @@ import org.junit.runners.Suite; org.apache.sis.coverage.grid.FractionalGridCoordinatesTest.class, org.apache.sis.coverage.grid.ReshapedImageTest.class, org.apache.sis.coverage.grid.GridCoverage2DTest.class, - org.apache.sis.internal.coverage.j2d.ImageUtilitiesTest.class, - org.apache.sis.internal.coverage.j2d.ScaledColorSpaceTest.class, - org.apache.sis.internal.coverage.j2d.PlanarImageTest.class, org.apache.sis.internal.coverage.j2d.BufferedGridCoverageTest.class }) public final strictfp class FeatureTestSuite extends TestSuite {
