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 bb8db50cd2512ece873f8ec39f5d820e2c4d5ad9 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Tue Dec 24 17:26:10 2024 +0100 `BandAggregateLayout` does not need anymore to extend `ImageLayout`. This simplication makes easier to complete the constructor, for example with the concatenated list of sample dimensions. --- .../org/apache/sis/image/BandAggregateImage.java | 68 +++++++-- .../org/apache/sis/image/BandAggregateLayout.java | 158 +++++++++++++-------- .../main/org/apache/sis/image/ImageProcessor.java | 1 + .../apache/sis/image/BandAggregateImageTest.java | 32 ++--- 4 files changed, 165 insertions(+), 94 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 a1c7da14f7..ca2e6c4c27 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 @@ -16,6 +16,7 @@ */ package org.apache.sis.image; +import java.util.Arrays; import java.awt.Rectangle; import java.awt.image.ColorModel; import java.awt.image.BandedSampleModel; @@ -24,6 +25,7 @@ import java.awt.image.RenderedImage; import java.awt.image.WritableRaster; import java.awt.image.WritableRenderedImage; import org.apache.sis.util.ArraysExt; +import org.apache.sis.coverage.SampleDimension; import org.apache.sis.coverage.privy.ImageUtilities; import org.apache.sis.coverage.privy.BandAggregateArgument; @@ -49,6 +51,12 @@ class BandAggregateImage extends MultiSourceImage { */ private final boolean allowSharing; + /** + * Concatenated array of the sample dimensions declared in all sources, or {@code null} if none. + * This field is non-null only if this information is present in all sources. + */ + private final SampleDimension[] sampleDimensions; + /* * The method declaration order below is a little bit unusual, * but it follows an execution order. @@ -140,12 +148,12 @@ class BandAggregateImage extends MultiSourceImage { static RenderedImage create(final RenderedImage[] sources, final int[][] bandsPerSource, final Colorizer colorizer, final boolean forceColors, final boolean allowSharing, final boolean parallel) { - final var layout = BandAggregateLayout.create(sources, bandsPerSource, allowSharing); + final var layout = new BandAggregateLayout(sources, bandsPerSource, allowSharing); final BandAggregateImage image; if (layout.isWritable()) { - image = new Writable(layout, colorizer, allowSharing, parallel); + image = new Writable(layout, colorizer, parallel); } else { - image = new BandAggregateImage(layout, colorizer, allowSharing, parallel); + image = new BandAggregateImage(layout, colorizer, parallel); } RenderedImage result = image; if (image.getNumSources() == 1) { @@ -170,12 +178,12 @@ class BandAggregateImage extends MultiSourceImage { * @param colorizer provider of color model to use for this image, or {@code null} for automatic. * @param parallel whether parallel computation is allowed. */ - private BandAggregateImage(final BandAggregateLayout layout, final Colorizer colorizer, - final boolean allowSharing, final boolean parallel) - { - super(layout.filteredSources, layout.domain, layout.getPreferredMinTile(), - layout.sampleModel, layout.createColorModel(colorizer), parallel); - this.allowSharing = allowSharing; + private BandAggregateImage(final BandAggregateLayout layout, final Colorizer colorizer, final boolean parallel) { + super(layout.filteredSources, layout.domain, layout.minTile, layout.sampleModel, + layout.createColorModel(colorizer), parallel); + + this.allowSharing = layout.allowSharing; + this.sampleDimensions = layout.sampleDimensions; } /** @@ -229,6 +237,31 @@ class BandAggregateImage extends MultiSourceImage { return tile; } + /** + * Returns the names of all recognized properties, + * or {@code null} if this image has no properties. + */ + @Override + public String[] getPropertyNames() { + if (sampleDimensions != null) { + return new String[] {SAMPLE_DIMENSIONS_KEY}; + } else { + return null; + } + } + + /** + * Gets a property of this image as a value derived from all source images. + */ + @Override + public Object getProperty(final String key) { + if (sampleDimensions != null && SAMPLE_DIMENSIONS_KEY.equals(key)) { + return sampleDimensions.clone(); + } else { + return super.getProperty(key); + } + } + /** * A {@code BandAggregateImage} where all sources are writable rendered images. */ @@ -239,10 +272,8 @@ class BandAggregateImage extends MultiSourceImage { * @param layout pixel and tile coordinate spaces of this image, together with sample model. * @param colorizer provider of color model to use for this image, or {@code null} for automatic. */ - Writable(final BandAggregateLayout layout, final Colorizer colorizer, - final boolean allowSharing, final boolean parallel) - { - super(layout, colorizer, allowSharing, parallel); + Writable(final BandAggregateLayout layout, final Colorizer colorizer, final boolean parallel) { + super(layout, colorizer, parallel); } /** @@ -332,7 +363,12 @@ class BandAggregateImage extends MultiSourceImage { */ @Override public boolean equals(final Object object) { - return super.equals(object) && ((BandAggregateImage) object).allowSharing == allowSharing; + if (super.equals(object)) { + final var that = (BandAggregateImage) object; + return that.allowSharing == allowSharing && + Arrays.equals(that.sampleDimensions, sampleDimensions); + } + return false; } /** @@ -340,6 +376,8 @@ class BandAggregateImage extends MultiSourceImage { */ @Override public int hashCode() { - return super.hashCode() ^ Boolean.hashCode(allowSharing); + return super.hashCode() + + Boolean.hashCode(allowSharing) + + Arrays.hashCode(sampleDimensions); } } 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 a52a519d45..71094b89ba 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 @@ -16,6 +16,8 @@ */ package org.apache.sis.image; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Optional; import java.awt.Point; import java.awt.Dimension; @@ -27,9 +29,10 @@ import java.awt.image.SampleModel; import java.awt.image.BandedSampleModel; import java.awt.image.ComponentSampleModel; import java.awt.image.WritableRenderedImage; -import org.apache.sis.util.Workaround; import org.apache.sis.util.collection.FrequencySortedSet; +import org.apache.sis.util.privy.UnmodifiableArrayList; import org.apache.sis.feature.internal.Resources; +import org.apache.sis.coverage.SampleDimension; import org.apache.sis.coverage.grid.DisjointExtentException; import org.apache.sis.coverage.privy.ImageUtilities; import org.apache.sis.coverage.privy.ColorModelFactory; @@ -44,19 +47,13 @@ import org.apache.sis.coverage.privy.CommonDomainFinder; * * <p>Instances of this class are temporary and used only during image construction.</p> * - * <h2>Restrictions</h2> - * The inherited {@link #sampleModel} must be a {@link BandedSampleModel}. - * All {@linkplain BandedSampleModel#getBandOffsets() band offsets} are zeros and - * all {@linkplain BandedSampleModel#getBankIndices() bank indices} are identity mapping. - * This simplicity is needed by current implementation of {@link BandAggregateImage}. - * * @author Alexis Manin (Geomatys) * @author Martin Desruisseaux (Geomatys) * * @see ImageCombiner * @see BandAggregateImage */ -final class BandAggregateLayout extends ImageLayout { +final class BandAggregateLayout { /** * The source images. This is a copy of the user-specified array, * except that images associated to an empty set of bands are discarded. @@ -66,6 +63,7 @@ final class BandAggregateLayout extends ImageLayout { /** * The source images with only the user-specified bands. * Those images are views, the pixels are not copied. + * The array length is the same as {@link #sources}. */ final RenderedImage[] filteredSources; @@ -99,6 +97,31 @@ final class BandAggregateLayout extends ImageLayout { */ final Rectangle domain; + /** + * Indices of the upper-left tile in an image tile matrix. + */ + final Point minTile; + + /** + * Concatenated array of the sample dimensions declared in all sources, or {@code null} if none. + * This field is non-null only if this information is present in all sources. + */ + final SampleDimension[] sampleDimensions; + + /** + * Whether to allow the sharing of data buffers (instead of copying) if possible. + * This flag depends on the {@link ImageProcessor} configuration. Its purpose is + * to express <em>user intend</em>, not whether sharing is effectively enabled. + * + * <h4>Design note</h4> + * This flag is not the result of the modification done in {@code BandAggregateLayout} constructor + * because whether buffer sharing is effectively enabled will be determined on a case-by-case basis + * by {@link BandAggregateImage} by inspection of sample models. + * + * @see BandAggregateImage#allowSharing + */ + final boolean allowSharing; + /** * 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. @@ -106,24 +129,25 @@ final class BandAggregateLayout extends ImageLayout { * or may contain {@code null} elements for selecting all bands of the corresponding image. * An empty array element (i.e. zero band to select) discards the corresponding source image. * - * <p>This static method is a workaround while waiting for JEP 447: Statements before super(…). - * This method may become the constructor after JEP 447 is available.</p> - * * @param sources images to combine, in order. * @param bandsPerSource bands to use for each source image, in order. May contain {@code null} elements. * @param allowSharing whether to allow the sharing of data buffers (instead of copying) if possible. * @throws IllegalArgumentException if there is an incompatibility between some source images * or if some band indices are duplicated or outside their range of validity. */ - @Workaround(library="JDK", version="1.8") - static BandAggregateLayout create(RenderedImage[] sources, int[][] bandsPerSource, boolean allowSharing) { - final var aggregate = new BandAggregateArgument<RenderedImage>(sources, bandsPerSource); - aggregate.unwrap(BandAggregateImage::unwrap); - aggregate.validate(ImageUtilities::getNumBands); - - int[] bandSelect = aggregate.mergeDuplicatedSources(); - sources = aggregate.sources(); - bandsPerSource = aggregate.bandsPerSource(true); + BandAggregateLayout(RenderedImage[] sources, int[][] bandsPerSource, boolean allowSharing) { + this.allowSharing = allowSharing; // Save user preferrence before modification. + final int numBands; + { // For keeping `aggregate` local. + final var aggregate = new BandAggregateArgument<RenderedImage>(sources, bandsPerSource); + aggregate.unwrap(BandAggregateImage::unwrap); + aggregate.validate(ImageUtilities::getNumBands); + bandSelect = aggregate.mergeDuplicatedSources(); + sources = aggregate.sources(); + bandsPerSource = aggregate.bandsPerSource(true); + numBands = aggregate.numBands(); + } + @SuppressWarnings("LocalVariableHidesMemberVariable") Rectangle domain = null; // Nullity check used for telling when the first image is processed. int scanlineStride = 0; int tileWidth = 0; @@ -176,6 +200,7 @@ final class BandAggregateLayout extends ImageLayout { } } } + this.domain = domain; if (domain == null) { // `domain` is guaranteed non-null if above block has been executed at least once. throw new IllegalArgumentException(Resources.format(Resources.Keys.UnspecifiedBands)); @@ -187,7 +212,7 @@ final class BandAggregateLayout extends ImageLayout { * the combined image causes the computation of a single tile of each source image. */ long cx, cy; // A combination of tile size with alignment on the tile matrix grid. - cx = cy = (((long) Integer.MAX_VALUE) << Integer.SIZE) | DEFAULT_TILE_SIZE; + cx = cy = (((long) Integer.MAX_VALUE) << Integer.SIZE) | ImageLayout.DEFAULT_TILE_SIZE; final var tileGridXOffset = new FrequencySortedSet<Integer>(true); final var tileGridYOffset = new FrequencySortedSet<Integer>(true); for (final RenderedImage source : sources) { @@ -197,49 +222,24 @@ final class BandAggregateLayout extends ImageLayout { tileGridYOffset.add(source.getTileGridYOffset()); } 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, - minTile, DataType.forDataBufferType(commonDataType), aggregate.numBands(), - allowSharing ? scanlineStride : 0); - } - - /** - * Creates a new image layout from the values computed by {@code create(…)}. - * - * <h4>Tile size</h4> - * The {@code exactTileSize} argument tells whether to use the preferred tile size exactly as specified, - * without trying to compute a better size. This flag may be {@code true} if the tiles of the destination - * image are at exact same location as the tiles of a source image having the preferred tile size. - * In such case, keeping the same size will reduce the number of tiles requested in that source image. - * - * @param sources images to combine, in order. - * @param bandsPerSource bands to use for each source image, in order. May contain {@code null} elements. - * @param bandSelect final band select operation to apply on the aggregated result. - * @param domain bounds of the image to create. - * @param preferredTileSize the preferred tile size. - * @param commonDataType data type of the combined image. - * @param scanlineStride common scanline stride if data buffers will be shared, or 0 if no sharing. - * @param numBands number of bands of the image to create. - */ - private BandAggregateLayout(final RenderedImage[] sources, final int[][] bandsPerSource, final int[] bandSelect, - final Rectangle domain, final Dimension preferredTileSize, final boolean exactTileSize, - final Point minTile, final DataType commonDataType, final int numBands, final int scanlineStride) - { - super(null, preferredTileSize, !exactTileSize, false, false, minTile); - this.bandsPerSource = bandsPerSource; - this.bandSelect = bandSelect; - this.sources = sources; - this.domain = domain; - this.sampleModel = createBandedSampleModel(null, domain, commonDataType, numBands, scanlineStride); + minTile = new Point(chooseMinTile(tileGridXOffset, domain.x, preferredTileSize.width), + chooseMinTile(tileGridYOffset, domain.y, preferredTileSize.height)); /* - * Note: above call to `createBandedSampleModel(…)` must be last, - * except for `filteredSources` which is not needed by that method. + * The `exactTileSize` flag tells whether to use the preferred tile size exactly as specified, + * without trying to compute a better size. This flag may be `true` if the tiles of the destination + * image are at exact same locations as the tiles of a source image having the preferred tile size. + * In such case, keeping the same size will reduce the number of tiles requested in that source image. */ + { // For keeping variables local. + final boolean exactTileSize = ((cx | cy) >>> Integer.SIZE) == 0; + allowSharing &= exactTileSize; + if (!allowSharing) scanlineStride = 0; // Means to force the use of tile width. + final var dataType = DataType.forDataBufferType(commonDataType); + final var layout = new ImageLayout(null, preferredTileSize, !exactTileSize, false, false, minTile); + sampleModel = layout.createBandedSampleModel(null, domain, dataType, numBands, scanlineStride); + } + this.bandsPerSource = bandsPerSource; + this.sources = sources; filteredSources = new RenderedImage[sources.length]; for (int i=0; i<filteredSources.length; i++) { RenderedImage source = sources[i]; @@ -249,6 +249,7 @@ final class BandAggregateLayout extends ImageLayout { } filteredSources[i] = source; } + sampleDimensions = getSampleDimensions(); } /** @@ -354,7 +355,8 @@ search: for (int i=0; i < sources.length; i++) { base += (bands != null) ? bands.length : ImageUtilities.getNumBands(source); } if (colorizer != null) { - Optional<ColorModel> candidate = colorizer.apply(new Colorizer.Target(sampleModel, null, visibleBand)); + var target = new Colorizer.Target(sampleModel, UnmodifiableArrayList.wrap(sampleDimensions), visibleBand); + Optional<ColorModel> candidate = colorizer.apply(target); if (candidate.isPresent()) { return candidate.get(); } @@ -365,4 +367,34 @@ search: for (int i=0; i < sources.length; i++) { } return ColorModelFactory.createGrayScale(sampleModel, visibleBand, null); } + + /** + * Gets a concatenated array of the sample dimensions declared in all sources, or {@code null} if none. + * This method returns a non-null array only if this information is present in all sources. + */ + private SampleDimension[] getSampleDimensions() { + final var selected = new ArrayList<SampleDimension>(); + for (int i=0; i < sources.length; i++) { + final Object value = sources[i].getProperty(PlanarImage.SAMPLE_DIMENSIONS_KEY); + if (!(value instanceof SampleDimension[])) { + return null; + } + final var sd = (SampleDimension[]) value; + final int[] bands = bandsPerSource[i]; + if (bands == null) { + selected.addAll(Arrays.asList(sd)); + } else for (int j=0; j < bands.length; j++) { + final int t = bands[j]; + if (t < 0 || t >= sd.length) { + return null; + } + selected.add(sd[t]); + } + } + final var result = new SampleDimension[bandSelect.length]; + for (int i=0; i < result.length; i++) { + result[i] = selected.get(bandSelect[i]); + } + return result; + } } 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 a79c0c775a..f3e660e94e 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 @@ -972,6 +972,7 @@ public class ImageProcessor implements Cloneable { colorizer = this.colorizer; parallel = executionMode != Mode.SEQUENTIAL; } + // `allowSharing` is currently hard-coded to `true`, but it may change in a future version. return BandAggregateImage.create(sources, bandsPerSource, colorizer, true, true, parallel); } diff --git a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/BandAggregateImageTest.java b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/BandAggregateImageTest.java index c7f6fa1de0..18bd44bb2a 100644 --- a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/BandAggregateImageTest.java +++ b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/BandAggregateImageTest.java @@ -93,8 +93,8 @@ public final class BandAggregateImageTest extends TestCase { public void testUntiledImages() { final int width = 3; final int height = 4; - final BufferedImage im1 = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); - final BufferedImage im2 = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); + final var im1 = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); + final var im2 = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); im1.getRaster().setSamples(0, 0, width, height, 0, IntStream.range(0, width*height).map(s -> s + 1).toArray()); im2.getRaster().setSamples(0, 0, width, height, 0, IntStream.range(0, width*height).map(s -> s * 2).toArray()); sourceImages = new RenderedImage[] {im1, im2}; @@ -125,7 +125,7 @@ public final class BandAggregateImageTest extends TestCase { if (WRITABLE) { final int tileX = 0; final int tileY = 0; - final WritableRenderedImage writable = (WritableRenderedImage) result; + final var writable = assertInstanceOf(WritableRenderedImage.class, result); final WritableRaster target = writable.getWritableTile(tileX, tileY); assertSame(tile, target); target.setPixel(2, 1, new int[] {100, 80}); @@ -185,8 +185,8 @@ public final class BandAggregateImageTest extends TestCase { final int minY = -5; final int width = 6; final int height = 9; - final TiledImageMock im1 = new TiledImageMock(DataBuffer.TYPE_USHORT, 2, minX, minY, width, height, 3, 3, 1, 2, firstBanded); - final TiledImageMock im2 = new TiledImageMock(DataBuffer.TYPE_USHORT, 2, minX, minY, width, height, 3, 3, 3, 4, secondBanded); + final var im1 = new TiledImageMock(DataBuffer.TYPE_USHORT, 2, minX, minY, width, height, 3, 3, 1, 2, firstBanded); + final var im2 = new TiledImageMock(DataBuffer.TYPE_USHORT, 2, minX, minY, width, height, 3, 3, 3, 4, secondBanded); initializeAllTiles(im1, im2); RenderedImage result = createBandAggregate(); @@ -228,7 +228,7 @@ public final class BandAggregateImageTest extends TestCase { if (testWrite) { final int tileX = 2; // minTileX = 1 final int tileY = 3; // minTileY = 2 - final WritableRenderedImage writable = (WritableRenderedImage) result; + final var writable = assertInstanceOf(WritableRenderedImage.class, result); final WritableRaster target = writable.getWritableTile(tileX, tileY); target.setPixel(10, -2, new int[] {100, 80, 20, 30}); // Upper left corner of tile 4 target.setPixel(12, -1, new int[] {200, 240, 260, 250}); @@ -310,9 +310,9 @@ public final class BandAggregateImageTest extends TestCase { * The aggregation algorithm should rely on pixel coordinates * for absolute positioning and alignment of image domains. */ - final TiledImageMock tiled2x2 = new TiledImageMock(DataBuffer.TYPE_FLOAT, 1, minX, minY, width, height, 2, 2, 1, 2, true); - final TiledImageMock tiled4x1 = new TiledImageMock(DataBuffer.TYPE_FLOAT, 1, minX, minY, width, height, 4, 1, 3, 4, true); - final TiledImageMock oneTile = new TiledImageMock(DataBuffer.TYPE_FLOAT, 1, minX, minY, width, height, 8, 4, 5, 6, true); + final var tiled2x2 = new TiledImageMock(DataBuffer.TYPE_FLOAT, 1, minX, minY, width, height, 2, 2, 1, 2, true); + final var tiled4x1 = new TiledImageMock(DataBuffer.TYPE_FLOAT, 1, minX, minY, width, height, 4, 1, 3, 4, true); + final var oneTile = new TiledImageMock(DataBuffer.TYPE_FLOAT, 1, minX, minY, width, height, 8, 4, 5, 6, true); initializeAllTiles(tiled2x2, tiled4x1, oneTile); final RenderedImage result = createBandAggregate(); @@ -374,10 +374,10 @@ public final class BandAggregateImageTest extends TestCase { * tiled 4x4 → bands 4 and 5 * tiled 6x6 → band 6 */ - final TiledImageMock untiled = new TiledImageMock(DataBuffer.TYPE_SHORT, 1, 0, 0, 16, 13, 16, 13, 0, 0, true); - final TiledImageMock tiled2x2 = new TiledImageMock(DataBuffer.TYPE_SHORT, 2, 4, 2, 8, 10, 2, 2, 0, 0, true); - final TiledImageMock tiled4x4 = new TiledImageMock(DataBuffer.TYPE_SHORT, 2, 4, 2, 8, 8, 4, 4, 0, 0, true); - final TiledImageMock tiled6x6 = new TiledImageMock(DataBuffer.TYPE_SHORT, 1, 2, 0, 12, 6, 6, 6, 0, 0, true); + final var untiled = new TiledImageMock(DataBuffer.TYPE_SHORT, 1, 0, 0, 16, 13, 16, 13, 0, 0, true); + final var tiled2x2 = new TiledImageMock(DataBuffer.TYPE_SHORT, 2, 4, 2, 8, 10, 2, 2, 0, 0, true); + final var tiled4x4 = new TiledImageMock(DataBuffer.TYPE_SHORT, 2, 4, 2, 8, 8, 4, 4, 0, 0, true); + final var tiled6x6 = new TiledImageMock(DataBuffer.TYPE_SHORT, 1, 2, 0, 12, 6, 6, 6, 0, 0, true); initializeAllTiles(untiled, tiled2x2, tiled4x4, tiled6x6); RenderedImage result = BandAggregateImage.create(sourceImages, null, null, false, allowSharing, prefetch); @@ -424,9 +424,9 @@ public final class BandAggregateImageTest extends TestCase { final int minY = -5; final int width = 6; final int height = 4; - final TiledImageMock im1 = new TiledImageMock(DataBuffer.TYPE_USHORT, 3, minX, minY, width, height, 3, 2, 1, 2, true); - final TiledImageMock im2 = new TiledImageMock(DataBuffer.TYPE_USHORT, 1, minX, minY, width, height, 3, 2, 3, 4, true); - final TiledImageMock im3 = new TiledImageMock(DataBuffer.TYPE_USHORT, 2, minX, minY, width, height, 3, 2, 2, 1, true); + final var im1 = new TiledImageMock(DataBuffer.TYPE_USHORT, 3, minX, minY, width, height, 3, 2, 1, 2, true); + final var im2 = new TiledImageMock(DataBuffer.TYPE_USHORT, 1, minX, minY, width, height, 3, 2, 3, 4, true); + final var im3 = new TiledImageMock(DataBuffer.TYPE_USHORT, 2, minX, minY, width, height, 3, 2, 2, 1, true); initializeAllTiles(im1, im2, im3); RenderedImage result;