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 49945796f423aaf5127a35568bf8b80473448fd0 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Mon Dec 23 16:16:15 2024 +0100 Retrofit the `minTile` property of two `ImageLayout` subclasses into `ImageLayout` directly. --- .../org/apache/sis/image/BandAggregateImage.java | 2 +- .../org/apache/sis/image/BandAggregateLayout.java | 37 ++---- .../main/org/apache/sis/image/ImageLayout.java | 131 +++++++++++++-------- .../main/org/apache/sis/image/ImageProcessor.java | 2 +- .../main/org/apache/sis/image/Visualization.java | 4 +- 5 files changed, 92 insertions(+), 84 deletions(-) diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandAggregateImage.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandAggregateImage.java index 94cba95aa4..a1c7da14f7 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandAggregateImage.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandAggregateImage.java @@ -173,7 +173,7 @@ class BandAggregateImage extends MultiSourceImage { private BandAggregateImage(final BandAggregateLayout layout, final Colorizer colorizer, final boolean allowSharing, final boolean parallel) { - super(layout.filteredSources, layout.domain, layout.getMinTile(), + super(layout.filteredSources, layout.domain, layout.getPreferredMinTile(), layout.sampleModel, layout.createColorModel(colorizer), parallel); this.allowSharing = allowSharing; } diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandAggregateLayout.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandAggregateLayout.java index a1e9a8513b..9ddb2f6ecd 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandAggregateLayout.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandAggregateLayout.java @@ -93,15 +93,6 @@ final class BandAggregateLayout extends ImageLayout { */ final Rectangle domain; - /** - * Index of the first tile. Other tile matrix properties such as the number of tiles and the grid offsets - * are derived from those values together with the {@linkplain #domain}. Contrarily to pixel coordinates, - * the tile coordinate space does not need to be the same for all images. - * - * @see #getMinTile() - */ - private final int minTileX, minTileY; - /** * Computes the layout of an image combining the bands of all the specified source images. * The optional {@code bandsPerSource} argument specifies the bands to select in each source images. @@ -202,10 +193,12 @@ final class BandAggregateLayout extends ImageLayout { final var preferredTileSize = new Dimension((int) cx, (int) cy); final boolean exactTileSize = ((cx | cy) >>> Integer.SIZE) == 0; allowSharing &= exactTileSize; + + final var minTile = new Point(chooseMinTile(tileGridXOffset, domain.x, preferredTileSize.width), + chooseMinTile(tileGridYOffset, domain.y, preferredTileSize.height)); + return new BandAggregateLayout(sources, bandsPerSource, bandSelect, domain, preferredTileSize, exactTileSize, - chooseMinTile(tileGridXOffset, domain.x, preferredTileSize.width), - chooseMinTile(tileGridYOffset, domain.y, preferredTileSize.height), - commonDataType, aggregate.numBands(), allowSharing ? scanlineStride : 0); + minTile, commonDataType, aggregate.numBands(), allowSharing ? scanlineStride : 0); } /** @@ -228,16 +221,13 @@ final class BandAggregateLayout extends ImageLayout { */ private BandAggregateLayout(final RenderedImage[] sources, final int[][] bandsPerSource, final int[] bandSelect, final Rectangle domain, final Dimension preferredTileSize, final boolean exactTileSize, - final int minTileX, final int minTileY, final int commonDataType, final int numBands, - final int scanlineStride) + final Point minTile, final int commonDataType, final int numBands, final int scanlineStride) { - super(preferredTileSize, !exactTileSize, false, false); + super(preferredTileSize, !exactTileSize, false, false, minTile); this.bandsPerSource = bandsPerSource; this.bandSelect = bandSelect; this.sources = sources; this.domain = domain; - this.minTileX = minTileX; - this.minTileY = minTileY; this.sampleModel = createBandedSampleModel(commonDataType, numBands, null, domain, scanlineStride); /* * Note: above call to `createBandedSampleModel(…)` must be last, @@ -310,19 +300,6 @@ final class BandAggregateLayout extends ImageLayout { return 0; } - /** - * Returns indices of the first tile ({@code minTileX}, {@code minTileY}). - * Other tile matrix properties such as the number of tiles and the grid offsets will be derived - * from those values together with the {@linkplain #domain}. Contrarily to pixel coordinates, - * the tile coordinate space does not need to be the same for all images. - * - * @return indices of the first tile ({@code minTileX}, {@code minTileY}). - */ - @Override - public Point getMinTile() { - return new Point(minTileX, minTileY); - } - /** * Returns {@code true} if all filtered sources are writable. * diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ImageLayout.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ImageLayout.java index 179f3e426b..47500f5e33 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ImageLayout.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ImageLayout.java @@ -73,14 +73,16 @@ public class ImageLayout { * Image sizes are preserved but the tile sizes are flexible. The last row and last column of tiles * in an image are allowed to be only partially filled. */ - public static final ImageLayout DEFAULT = new ImageLayout(null, true, false, true); + public static final ImageLayout DEFAULT = new ImageLayout(null, true, false, true, null); /** * Preferred size (in pixels) for tiles. + * The actual tile size will also depend on the size of the image to tile. * The {@linkplain #DEFAULT default} value is {@value #DEFAULT_TILE_SIZE}. * * @see #DEFAULT_TILE_SIZE * @see #getPreferredTileSize() + * @see #suggestTileSize(int, int) */ protected final int preferredTileWidth, preferredTileHeight; @@ -120,6 +122,16 @@ public class ImageLayout { */ public final boolean isPartialTilesAllowed; + /** + * Preferred tile index where images start their tile matrix. + * This property usually has no incidence on the appearance or performance + * of an image and may be ignored by image operations. + * The {@linkplain #DEFAULT default} value is 0. + * + * @see #getPreferredMinTile() + */ + protected final int preferredMinTileX, preferredMinTileY; + /** * Creates a new image layout. * @@ -127,11 +139,13 @@ public class ImageLayout { * @param isTileSizeAdjustmentAllowed whether tile size can be modified if needed. * @param isImageBoundsAdjustmentAllowed whether image size can be modified if needed. * @param isPartialTilesAllowed whether to allow tiles that are only partially filled. + * @param preferredMinTile preferred tile index where image start their tile matrix, or {@code null} for (0,0). */ - public ImageLayout(final Dimension preferredTileSize, - final boolean isTileSizeAdjustmentAllowed, - final boolean isImageBoundsAdjustmentAllowed, - final boolean isPartialTilesAllowed) + protected ImageLayout(final Dimension preferredTileSize, + final boolean isTileSizeAdjustmentAllowed, + final boolean isImageBoundsAdjustmentAllowed, + final boolean isPartialTilesAllowed, + final Point preferredMinTile) { if (preferredTileSize != null) { preferredTileWidth = Math.max(1, preferredTileSize.width); @@ -143,16 +157,13 @@ public class ImageLayout { this.isTileSizeAdjustmentAllowed = isTileSizeAdjustmentAllowed; this.isImageBoundsAdjustmentAllowed = isImageBoundsAdjustmentAllowed; this.isPartialTilesAllowed = isPartialTilesAllowed; - } - - /** - * Creates a new layout with exactly the tile size of the given image. - * - * @param source image from which to take tile size and tile indices. - * @return layout giving exactly the tile size and indices of given image. - */ - static ImageLayout forTileSize(final RenderedImage source) { - return new FixedSize(source, source.getMinTileX(), source.getMinTileY()); + if (preferredMinTile != null) { + preferredMinTileX = preferredMinTile.x; + preferredMinTileY = preferredMinTile.y; + } else { + preferredMinTileX = 0; + preferredMinTileY = 0; + } } /** @@ -167,36 +178,17 @@ public class ImageLayout { return new FixedDestination(source, minTileX, minTileY); } - /** - * Override preferred tile size with a fixed size. - */ - private static class FixedSize extends ImageLayout { - /** Indices of the first tile. */ - private final int minTileX, minTileY; - - /** Creates a new layout with exactly the tile size of given image. */ - FixedSize(final RenderedImage source, final int minTileX, final int minTileY) { - super(new Dimension(source.getTileWidth(), source.getTileHeight()), false, false, true); - this.minTileX = minTileX; - this.minTileY = minTileY; - } - - /** Returns indices of the first tile. */ - @Override public Point getMinTile() { - return new Point(minTileX, minTileY); - } - } - /** * Override sample model with the one of the destination. */ - private static final class FixedDestination extends FixedSize { + private static final class FixedDestination extends ImageLayout { /** The destination image. */ private final WritableRenderedImage destination; /** Creates a new layout with exactly the tile size of given image. */ FixedDestination(final WritableRenderedImage destination, final int minTileX, final int minTileY) { - super(destination, minTileX, minTileY); + super(new Dimension(destination.getTileWidth(), destination.getTileHeight()), + false, false, true, new Point(minTileX, minTileY)); this.destination = destination; } @@ -222,7 +214,8 @@ public class ImageLayout { */ public ImageLayout allowTileSizeAdjustments(boolean allowed) { if (isTileSizeAdjustmentAllowed == allowed) return this; - return new ImageLayout(getPreferredTileSize(), allowed, isImageBoundsAdjustmentAllowed, isPartialTilesAllowed); + return new ImageLayout(getPreferredTileSize(), allowed, isImageBoundsAdjustmentAllowed, isPartialTilesAllowed, + getPreferredMinTile()); } /** @@ -236,7 +229,8 @@ public class ImageLayout { */ public ImageLayout allowImageBoundsAdjustments(boolean allowed) { if (isImageBoundsAdjustmentAllowed == allowed) return this; - return new ImageLayout(getPreferredTileSize(), isTileSizeAdjustmentAllowed, allowed, isPartialTilesAllowed); + return new ImageLayout(getPreferredTileSize(), isTileSizeAdjustmentAllowed, allowed, isPartialTilesAllowed, + getPreferredMinTile()); } /** @@ -250,7 +244,33 @@ public class ImageLayout { */ public ImageLayout allowPartialTiles(boolean allowed) { if (isPartialTilesAllowed == allowed) return this; - return new ImageLayout(getPreferredTileSize(), isTileSizeAdjustmentAllowed, isImageBoundsAdjustmentAllowed, allowed); + return new ImageLayout(getPreferredTileSize(), isTileSizeAdjustmentAllowed, isImageBoundsAdjustmentAllowed, allowed, + getPreferredMinTile()); + } + + /** + * Creates a new layout with the tile size and tile indices of the given image. + * Other properties (all Boolean flags) are copied unchanged. + * If the given argument value results in no change, returns {@code this}. + * + * @param source image from which to take tile size and tile indices. + * @return layout giving exactly the tile size and indices of given image. + * + * @see #getPreferredTileSize() + * @see #getPreferredMinTile() + */ + public ImageLayout withTileMatrix(final RenderedImage source) { + final var preferredTileSize = new Dimension(source.getTileWidth(), source.getTileHeight()); + final var preferredMinTile = new Point(source.getMinTileX(), source.getMinTileY()); + if (preferredTileSize.width == preferredTileWidth && + preferredTileSize.height == preferredTileHeight && + preferredMinTile .x == preferredMinTileX && + preferredMinTile .y == preferredMinTileY) + { + return this; + } + return new ImageLayout(preferredTileSize, isTileSizeAdjustmentAllowed, + isImageBoundsAdjustmentAllowed, isPartialTilesAllowed, preferredMinTile); } /** @@ -266,7 +286,8 @@ public class ImageLayout { if (size.width == preferredTileWidth && size.height == preferredTileHeight) { return this; } - return new ImageLayout(size, isTileSizeAdjustmentAllowed, isImageBoundsAdjustmentAllowed, isPartialTilesAllowed); + return new ImageLayout(size, isTileSizeAdjustmentAllowed, isImageBoundsAdjustmentAllowed, + isPartialTilesAllowed, getPreferredMinTile()); } /** @@ -506,16 +527,19 @@ public class ImageLayout { } /** - * Returns indices of the first tile ({@code minTileX}, {@code minTileY}), or {@code null} for (0,0). - * The default implementation returns {@code null}. + * Returns the preferred indices of the upper-left tile in an image tile matrix. + * This property usually has no incidence on the appearance or performance of an image. + * It usually doesn't change neither the calculations that depend on georeferencing, + * because these calculations depend on pixel coordinates rather than tile coordinates. + * Therefore, this property is only a hint and may be ignored by image operations. * - * <p>This method is not yet in public API because it is currently set only by {@link Visualization}. - * Only the image operations needed by {@code Visualization} take this information in account.</p> + * @return preferred tile indices of the upper-left tile. * - * @return indices of the first tile ({@code minTileX}, {@code minTileY}), or {@code null} for (0,0). + * @see RenderedImage#getMinTileX() + * @see RenderedImage#getMinTileY() */ - Point getMinTile() { - return null; + public final Point getPreferredMinTile() { + return new Point(preferredMinTileX, preferredMinTileY); } /** @@ -537,8 +561,15 @@ public class ImageLayout { */ @Override public String toString() { + var sb = new StringBuilder(); + var preferredTileSize = sb.append(preferredTileWidth).append('×').append(preferredTileHeight).toString(); + sb.setLength(0); + var preferredMinTile = sb.append('(').append(preferredMinTileX).append(", ").append(preferredMinTileY).append(')').toString(); return Strings.toString(getClass(), - "preferredTileSize", new StringBuilder().append(preferredTileWidth).append('×').append(preferredTileHeight), - "isImageBoundsAdjustmentAllowed", isImageBoundsAdjustmentAllowed); + "preferredTileSize", preferredTileSize, + "isTileSizeAdjustmentAllowed", isTileSizeAdjustmentAllowed, + "isImageBoundsAdjustmentAllowed", isImageBoundsAdjustmentAllowed, + "isPartialTilesAllowed", isPartialTilesAllowed, + "preferredMinTile", preferredMinTile); } } diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ImageProcessor.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ImageProcessor.java index bd3e637c58..1dcb702295 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ImageProcessor.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/ImageProcessor.java @@ -1246,7 +1246,7 @@ public class ImageProcessor implements Cloneable { } final WritableRenderedImage destination = layout.getDestination(); final SampleModel rsm = layout.createCompatibleSampleModel(source, bounds); - final var image = new ResampledImage(source, rsm, layout.getMinTile(), bounds, toSource, + final var image = new ResampledImage(source, rsm, layout.getPreferredMinTile(), bounds, toSource, interpolation, fillValues, positionalAccuracyHints); image.setDestination(destination); resampled = unique(image); diff --git a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/Visualization.java b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/Visualization.java index 375f3477ed..260c5edf15 100644 --- a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/Visualization.java +++ b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/Visualization.java @@ -260,7 +260,7 @@ final class Visualization extends ResampledImage { */ final boolean shortcut = toSource.isIdentity() && (bounds == null || ImageUtilities.getBounds(source).contains(bounds)); if (shortcut) { - layout = ImageLayout.forTileSize(source); + layout = ImageLayout.DEFAULT.withTileMatrix(source).allowTileSizeAdjustments(false); } /* * Sample values will be unconditionally converted to integers in the [0 … 255] range. @@ -479,7 +479,7 @@ final class Visualization extends ResampledImage { private Visualization(final Builder builder) { super(builder.source, builder.sampleModel, - builder.layout.getMinTile(), + builder.layout.getPreferredMinTile(), builder.bounds, builder.toSource, builder.interpolation,