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 2a7346399cee74a04d065e8e750307d2a3b4965f
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Tue Dec 24 17:05:30 2024 +0100

    Consolidation in the way that a sample model is created from an 
`ImageLayout` for an image operation.
    Some `int` arguments are replaced by more type-safe objects such as 
`DataType` or `Dimension`.
---
 .../sis/coverage/grid/GridCoverageBuilder.java     |   3 +-
 .../apache/sis/coverage/grid/ImageRenderer.java    |   3 +-
 .../sis/coverage/privy/ColorScaleBuilder.java      |  35 +++++--
 .../sis/coverage/privy/SampleModelFactory.java     |  12 +--
 .../org/apache/sis/image/BandAggregateLayout.java  |   7 +-
 .../apache/sis/image/BandedSampleConverter.java    |   6 +-
 .../main/org/apache/sis/image/Colorizer.java       |   2 +-
 .../main/org/apache/sis/image/ImageLayout.java     | 104 ++++++++++++++-------
 .../main/org/apache/sis/image/ImageProcessor.java  |   3 +-
 .../main/org/apache/sis/image/Visualization.java   |  16 ++--
 .../sis/coverage/privy/ColorModelBuilderTest.java  |  11 ++-
 .../sis/coverage/privy/SampleModelFactoryTest.java |  18 +++-
 .../sis/image/BandedSampleConverterTest.java       |  16 ++--
 .../sis/storage/geotiff/ImageFileDirectory.java    |   4 +-
 14 files changed, 154 insertions(+), 86 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCoverageBuilder.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCoverageBuilder.java
index 37e9c3e3f7..042ac90136 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCoverageBuilder.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/GridCoverageBuilder.java
@@ -37,7 +37,6 @@ import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.image.PlanarImage;
 import org.apache.sis.coverage.SampleDimension;
 import org.apache.sis.coverage.privy.ColorScaleBuilder;
-import org.apache.sis.coverage.privy.ImageUtilities;
 import org.apache.sis.coverage.privy.ObservableImage;
 import org.apache.sis.coverage.privy.TiledImage;
 import org.apache.sis.coverage.privy.WritableTiledImage;
@@ -476,7 +475,7 @@ public class GridCoverageBuilder {
                 final var colorizer = new 
ColorScaleBuilder(ColorScaleBuilder.GRAYSCALE, null, false);
                 final ColorModel colors;
                 if (colorizer.initialize(sm, bands.get(visibleBand)) || 
colorizer.initialize(sm, visibleBand)) {
-                    colors = 
colorizer.createColorModel(ImageUtilities.getBandType(sm), bands.size(), 
visibleBand);
+                    colors = colorizer.createColorModel(sm, bands.size(), 
visibleBand);
                 } else {
                     colors = ColorScaleBuilder.NULL_COLOR_MODEL;
                 }
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/ImageRenderer.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/ImageRenderer.java
index 8867349e4f..5483da9234 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/ImageRenderer.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/grid/ImageRenderer.java
@@ -754,7 +754,8 @@ public class ImageRenderer {
         final ColorModel cm;
         final SampleModel sm = raster.getSampleModel();
         if (colorizer.initialize(sm, bands[visibleBand]) || 
colorizer.initialize(sm, visibleBand)) {
-            cm = colorizer.createColorModel(buffer.getDataType(), 
bands.length, visibleBand);
+            DataType type = DataType.forDataBufferType(buffer.getDataType());
+            cm = colorizer.createColorModel(type, bands.length, visibleBand);
         } else {
             cm = ColorScaleBuilder.NULL_COLOR_MODEL;
         }
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/privy/ColorScaleBuilder.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/privy/ColorScaleBuilder.java
index d36c7adad2..54905cfc09 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/privy/ColorScaleBuilder.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/privy/ColorScaleBuilder.java
@@ -35,10 +35,11 @@ import 
org.apache.sis.referencing.operation.transform.MathTransforms;
 import org.apache.sis.coverage.Category;
 import org.apache.sis.coverage.SampleDimension;
 import org.apache.sis.feature.internal.Resources;
+import org.apache.sis.image.DataType;
+import org.apache.sis.measure.NumberRange;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.privy.Numerics;
-import org.apache.sis.measure.NumberRange;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.resources.Vocabulary;
 
@@ -666,24 +667,40 @@ reuse:  if (source != null) {
      * given by {@link #getSampleToIndexValues()}. Images using this color 
model shall
      * use a {@link DataBuffer} of type {@link #TYPE_COMPACT}.
      *
-     * @param  dataType     the color model type. One of {@link 
DataBuffer#TYPE_BYTE}, {@link DataBuffer#TYPE_USHORT},
-     *                      {@link DataBuffer#TYPE_SHORT}, {@link 
DataBuffer#TYPE_INT}, {@link DataBuffer#TYPE_FLOAT}
-     *                      or {@link DataBuffer#TYPE_DOUBLE}.
+     * @param  dataType     the type of data elements used for storing sample 
values.
      * @param  numBands     the number of bands for the color model (usually 
1). The returned color model will render only
      *                      the {@code visibleBand} and ignore the others, but 
the existence of all {@code numBands} will
      *                      be at least tolerated. Supplemental bands, even 
invisible, are useful for processing.
      * @param  visibleBand  the band to be made visible (usually 0). All other 
bands, if any, will be ignored.
      * @return a color model suitable for {@link java.awt.image.RenderedImage} 
objects with values in the given ranges.
      */
-    public ColorModel createColorModel(int dataType, final int numBands, final 
int visibleBand) {
+    public ColorModel createColorModel(final DataType dataType, final int 
numBands, final int visibleBand) {
         checkInitializationStatus(true);
+        int typeCode = dataType.toDataBufferType();
+        ArgumentChecks.ensureStrictlyPositive("numBands", numBands);
+        ArgumentChecks.ensureBetween("visibleBand", 0, numBands - 1, 
visibleBand);
         if (compact) {
             compact();
-            dataType = TYPE_COMPACT;
+            typeCode = TYPE_COMPACT;
         }
-        ArgumentChecks.ensureStrictlyPositive("numBands", numBands);
-        ArgumentChecks.ensureBetween("visibleBand", 0, numBands - 1, 
visibleBand);
-        return ColorModelFactory.createPiecewise(dataType, numBands, 
visibleBand, entries);
+        return ColorModelFactory.createPiecewise(typeCode, numBands, 
visibleBand, entries);
+    }
+
+    /**
+     * Returns a color model to use in a rendered image together with the 
given sample model.
+     * This method delegates to {@link #createColorModel(DataType, int, int)} 
after having
+     * inferred the data type from the given sample model.
+     *
+     * @todo Current implementation does not verify that the color model is 
compatible
+     *       with the sample model. We should add that verification.
+     *
+     * @param  target       the sample model for which to create a color model.
+     * @param  numBands     the number of bands for the color model (usually 
1).
+     * @param  visibleBand  the band to be made visible (usually 0). All other 
bands, if any, will be ignored.
+     * @return a color model using a data type inferred from the given sample 
model.
+     */
+    public ColorModel createColorModel(final SampleModel target, final int 
numBands, final int visibleBand) {
+        return 
createColorModel(DataType.forDataBufferType(ImageUtilities.getBandType(target)),
 numBands, visibleBand);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/privy/SampleModelFactory.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/privy/SampleModelFactory.java
index b842cc5e11..ce47dee9e2 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/privy/SampleModelFactory.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/coverage/privy/SampleModelFactory.java
@@ -17,6 +17,7 @@
 package org.apache.sis.coverage.privy;
 
 import java.util.Arrays;
+import java.awt.Dimension;
 import java.awt.image.DataBuffer;
 import java.awt.image.SampleModel;
 import java.awt.image.BandedSampleModel;
@@ -103,22 +104,21 @@ public final class SampleModelFactory {
     private int scanlineStride;
 
     /**
-     * Creates a factory initialized to the given values.
+     * Creates a builder for a sample model of a type inferred from the given 
properties.
      *
      * @param  type           type of sample values.
-     * @param  width          tile width in pixels.
-     * @param  height         tile height in pixels.
+     * @param  size           tile width and height in pixels.
      * @param  numBands       number of bands.
      * @param  bitsPerSample  number of bits per sample values.
      * @param  isBanded       {@code true} if each band is stored in a 
separated bank.
      * @throws RasterFormatException if the arguments imply a sample model of 
unsupported type.
      */
-    public SampleModelFactory(final DataType type, final int width, final int 
height,
+    public SampleModelFactory(final DataType type, final Dimension size,
             final int numBands, final int bitsPerSample, final boolean 
isBanded)
     {
         this.dataType  = type.toDataBufferType();
-        this.width     = width;
-        this.height    = height;
+        this.width     = size.width;
+        this.height    = size.height;
         this.numBands  = numBands;
         scanlineStride = width;
         pixelStride    = 1;
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 7b5ae49354..a52a519d45 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
@@ -204,7 +204,8 @@ final class BandAggregateLayout extends ImageLayout {
                                       chooseMinTile(tileGridYOffset, domain.y, 
preferredTileSize.height));
 
         return new BandAggregateLayout(sources, bandsPerSource, bandSelect, 
domain, preferredTileSize, exactTileSize,
-                    minTile, commonDataType, aggregate.numBands(), 
allowSharing ? scanlineStride : 0);
+                    minTile, DataType.forDataBufferType(commonDataType), 
aggregate.numBands(),
+                    allowSharing ? scanlineStride : 0);
     }
 
     /**
@@ -227,14 +228,14 @@ 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 Point minTile, final int commonDataType, final int numBands, 
final int scanlineStride)
+            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(commonDataType, 
numBands, null, domain, scanlineStride);
+        this.sampleModel    = createBandedSampleModel(null, domain, 
commonDataType, numBands, scanlineStride);
         /*
          * Note: above call to `createBandedSampleModel(…)` must be last,
          * except for `filteredSources` which is not needed by that method.
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandedSampleConverter.java
 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandedSampleConverter.java
index 99aed560f5..9d18e48b88 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandedSampleConverter.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/BandedSampleConverter.java
@@ -25,7 +25,6 @@ import java.awt.image.RenderedImage;
 import java.awt.image.WritableRenderedImage;
 import java.awt.image.BandedSampleModel;
 import java.awt.image.ColorModel;
-import java.awt.image.DataBuffer;
 import java.awt.image.SampleModel;
 import java.lang.reflect.Array;
 import org.opengis.referencing.operation.MathTransform1D;
@@ -196,7 +195,6 @@ class BandedSampleConverter extends WritableComputedImage {
      * @param  sourceRanges  the expected range of values for each band in 
source image, or {@code null} if unknown.
      * @param  converters    the transfer functions to apply on each band of 
the source image.
      * @param  targetType    the type of this image resulting from conversion 
of given image.
-     *                       Shall be one of {@link DataBuffer} constants.
      * @param  colorizer     provider of color model for the expected range of 
values, or {@code null}.
      * @return the image which compute converted values from the given source.
      *
@@ -204,7 +202,7 @@ class BandedSampleConverter extends WritableComputedImage {
      */
     static BandedSampleConverter create(RenderedImage source, final 
ImageLayout layout,
             final NumberRange<?>[] sourceRanges, final MathTransform1D[] 
converters,
-            final int targetType, final Colorizer colorizer)
+            final DataType targetType, final Colorizer colorizer)
     {
         /*
          * Since this operation applies its own ColorModel anyway, skip 
operation that was doing nothing else
@@ -215,7 +213,7 @@ class BandedSampleConverter extends WritableComputedImage {
             source = ((RecoloredImage) source).source;
         }
         final int numBands = converters.length;
-        final BandedSampleModel sampleModel = 
layout.createBandedSampleModel(targetType, numBands, source, null, 0);
+        final BandedSampleModel sampleModel = 
layout.createBandedSampleModel(source, null, targetType, numBands, 0);
         final SampleDimension[] sampleDimensions = 
SampleDimensions.IMAGE_PROCESSOR_ARGUMENT.get();
         final int visibleBand = ImageUtilities.getVisibleBand(source);
         ColorModel colorModel = ColorScaleBuilder.NULL_COLOR_MODEL;
diff --git 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/Colorizer.java 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/Colorizer.java
index be69136e2f..2c6c9e363a 100644
--- 
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/Colorizer.java
+++ 
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/image/Colorizer.java
@@ -321,7 +321,7 @@ public interface Colorizer extends 
Function<Colorizer.Target, Optional<ColorMode
                         final SampleModel model = target.getSampleModel();
                         final var c = new ColorScaleBuilder(colors, null, 
false);
                         if (c.initialize(model, ranges.get(visibleBand))) {
-                            return 
Optional.ofNullable(c.createColorModel(model.getDataType(), 
model.getNumBands(), visibleBand));
+                            return 
Optional.ofNullable(c.createColorModel(model, model.getNumBands(), 
visibleBand));
                         }
                     }
                 }
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 2aa8e81412..469b5bb49e 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
@@ -28,6 +28,7 @@ import java.awt.image.SampleModel;
 import java.awt.image.BandedSampleModel;
 import java.awt.image.WritableRenderedImage;
 import org.apache.sis.math.MathFunctions;
+import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ArraysExt;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.privy.Strings;
@@ -526,39 +527,22 @@ public class ImageLayout {
     }
 
     /**
-     * Creates a banded sample model of the given type with an automatic tile 
size.
-     * At least one of {@code image} and {@code bounds} arguments must be non 
null.
-     * This method uses the {@linkplain #suggestTileSize(RenderedImage, 
Rectangle)
-     * suggested tile size} for the given image and bounds.
-     *
-     * <p>This method constructs the simplest possible banded sample model:
-     * All {@linkplain BandedSampleModel#getBandOffsets() band offsets} are 
zero and
-     * all {@linkplain BandedSampleModel#getBankIndices() bank indices} are 
identity mapping.
-     * This simplicity is needed by current implementation of {@link 
BandAggregateImage}.</p>
+     * Ensures that the number of bands specified (directly or indirectly) in 
a method call
+     * is compatible with the sample model.
      *
-     * @param  dataType        desired data type as a {@link 
java.awt.image.DataBuffer} constant.
-     * @param  numBands        desired number of bands.
-     * @param  image           the image which will be the source of the image 
for which a sample model is created.
-     * @param  bounds          the bounds of the image to create, or {@code 
null} if same as {@code image}.
-     * @param  scanlineStride  the line stride of the of the image data, or ≤ 
0 for automatic.
-     * @return a banded sample model of the given type with the given number 
of bands.
+     * @param  actual  the number of bands inferred from the argument in a 
method call.
      */
-    final BandedSampleModel createBandedSampleModel(final int dataType, final 
int numBands,
-            final RenderedImage image, final Rectangle bounds, int 
scanlineStride)
-    {
-        final Dimension tileSize = suggestTileSize(image, bounds);
-        if (scanlineStride <= 0) {
-            scanlineStride = tileSize.width;
+    private void checkBandCount(final int actual) {
+        int expected = sampleModel.getNumBands();
+        if (expected != actual) {
+            throw new 
IllegalStateException(Resources.format(Resources.Keys.UnexpectedNumberOfBands_2,
 expected, actual));
         }
-        // Pixel stride, bank indices and band offsets intentionally 
non-configurable. See Javadoc.
-        return RasterFactory.unique(new BandedSampleModel(dataType, 
tileSize.width, tileSize.height,
-                                    scanlineStride, ArraysExt.range(0, 
numBands), new int[numBands]));
     }
 
     /**
-     * Creates a sample model with a size computed from the given image size.
-     * If a {@link #sampleModel} has been specified, the new sample model is 
derived from that field value.
-     * Otherwise, the new sample model is derived from the image sample model.
+     * Returns a sample model with a size computed from the given image size.
+     * If this {@code ImageLayout} contains a {@link #sampleModel}, then the 
latter is used as a template.
+     * Otherwise, the new sample model is {@linkplain 
RenderedImage#getSampleModel() derived from the image}.
      *
      * @param  image   the image from which to derive a sample model.
      * @param  bounds  the bounds of the image to create, or {@code null} if 
same as {@code image}.
@@ -571,14 +555,17 @@ public class ImageLayout {
     public SampleModel createCompatibleSampleModel(final RenderedImage image, 
final Rectangle bounds) {
         SampleModel sm = image.getSampleModel();
         if (sampleModel != null) {
-            int expected = sampleModel.getNumBands();
-            int actual   = sm.getNumBands();
-            if (expected != actual) {
-                throw new 
IllegalStateException(Resources.format(Resources.Keys.UnexpectedNumberOfBands_2,
 expected, actual));
-            }
+            checkBandCount(sm.getNumBands());
             sm = sampleModel;
         }
-        final Dimension tile = suggestTileSize(image, bounds);
+        return createCompatibleSampleModel(sm, suggestTileSize(image, bounds));
+    }
+
+    /**
+     * Returns a sample model equivalent to the given one, but using a 
different width and height.
+     * If the given sample model already has the desired size, then it is 
returned unchanged.
+     */
+    private static SampleModel createCompatibleSampleModel(SampleModel sm, 
final Dimension tile) {
         if (sm.getWidth() != tile.width || sm.getHeight() != tile.height) {
             sm = sm.createCompatibleSampleModel(tile.width, tile.height);
             sm = RasterFactory.unique(sm);
@@ -586,6 +573,57 @@ public class ImageLayout {
         return sm;
     }
 
+    /**
+     * Returns a sample model for the given data type with a size computed 
from the given image bounds.
+     * If this {@code ImageLayout} contains a {@link #sampleModel}, then the 
latter is used as a template.
+     *
+     * @param  dataType  the default data type for the sample model to create.
+     * @param  bounds    the bounds of the image to create.
+     * @param  numBands  the number of bands in the sample model to create.
+     * @return image sample model with a tile size derived from the given 
image bounds.
+     * @throws IllegalStateException if {@link #sampleModel} is non-null but 
does not
+     *         have the same number of bands as the given {@code numBands} 
argument.
+     */
+    public SampleModel createSampleModel(final DataType dataType, final 
Rectangle bounds, final int numBands) {
+        ArgumentChecks.ensureNonNull("bounds", bounds);
+        if (sampleModel != null) {
+            checkBandCount(numBands);
+            return createCompatibleSampleModel(sampleModel, 
suggestTileSize(null, bounds));
+        }
+        return createBandedSampleModel(null, bounds, dataType, numBands, 0);
+    }
+
+    /**
+     * Creates a banded sample model for the given data type.
+     * At least one of {@code image} and {@code bounds} arguments must be non 
null.
+     * This method uses the {@linkplain #suggestTileSize(RenderedImage, 
Rectangle)
+     * suggested tile size} for the given image and bounds.
+     *
+     * <p>This method constructs the simplest possible banded sample model:
+     * All {@linkplain BandedSampleModel#getBandOffsets() band offsets} are 
zero and
+     * all {@linkplain BandedSampleModel#getBankIndices() bank indices} are 
identity mapping.
+     * This simplicity is needed by current implementation of {@link 
BandAggregateImage}.
+     * User-specified {@link #sampleModel} is ignored.</p>
+     *
+     * @param  image           the image which will be the source of the image 
for which a sample model is created.
+     * @param  bounds          the bounds of the image to create, or {@code 
null} if same as {@code image}.
+     * @param  dataType        desired data type.
+     * @param  numBands        desired number of bands.
+     * @param  scanlineStride  the line stride of the image data, or ≤ 0 for 
automatic.
+     * @return a banded sample model of the given type with the given number 
of bands.
+     */
+    final BandedSampleModel createBandedSampleModel(final RenderedImage image, 
final Rectangle bounds,
+            final DataType dataType, final int numBands, int scanlineStride)
+    {
+        final Dimension tileSize = suggestTileSize(image, bounds);
+        if (scanlineStride <= 0) {
+            scanlineStride = tileSize.width;
+        }
+        // Pixel stride, bank indices and band offsets intentionally 
non-configurable. See Javadoc.
+        return RasterFactory.unique(new 
BandedSampleModel(dataType.toDataBufferType(),
+                tileSize.width, tileSize.height, scanlineStride, 
ArraysExt.range(0, numBands), new int[numBands]));
+    }
+
     /**
      * 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.
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 3ea729e744..a79c0c775a 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
@@ -1155,8 +1155,7 @@ public class ImageProcessor implements Cloneable {
             colorizer = this.colorizer;
         }
         // No need to clone `sourceRanges` because it is not stored by 
`BandedSampleConverter`.
-        return unique(BandedSampleConverter.create(source, layout, 
sourceRanges, converters,
-                                                   
targetType.toDataBufferType(), colorizer));
+        return unique(BandedSampleConverter.create(source, layout, 
sourceRanges, converters, targetType, colorizer));
     }
 
     /**
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 260c5edf15..a712ae34d9 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
@@ -258,7 +258,13 @@ final class Visualization extends ResampledImage {
              * requires the tile layout of destination image to be the same as 
source image.
              * Otherwise combine interpolation and value conversions in a 
single operation.
              */
-            final boolean shortcut = toSource.isIdentity() && (bounds == null 
|| ImageUtilities.getBounds(source).contains(bounds));
+            final boolean shortcut;
+            if (bounds == null) {
+                bounds = ImageUtilities.getBounds(source);
+                shortcut = toSource.isIdentity();
+            } else {
+                shortcut = toSource.isIdentity() && 
ImageUtilities.getBounds(source).contains(bounds);
+            }
             if (shortcut) {
                 layout = 
ImageLayout.DEFAULT.withTileMatrix(source).allowTileSizeAdjustments(false);
             }
@@ -267,7 +273,8 @@ final class Visualization extends ResampledImage {
              * The sample model is a mandatory argument before we invoke user 
supplied colorizer,
              * which must be done before to build the color model.
              */
-            sampleModel = 
layout.createBandedSampleModel(ColorScaleBuilder.TYPE_COMPACT, NUM_BANDS, 
source, bounds, 0);
+            final DataType dataType = 
DataType.forDataBufferType(ColorScaleBuilder.TYPE_COMPACT);
+            sampleModel = layout.createSampleModel(dataType, bounds, 
NUM_BANDS);
             final Target target = new Target(sampleModel, VISIBLE_BAND, 
visibleSD != null);
             if (colorizer != null) {
                 colorModel = colorizer.apply(target).orElse(null);
@@ -335,7 +342,7 @@ final class Visualization extends ResampledImage {
                 builder.initialize(statistics.minimum(), statistics.maximum(), 
sourceSM.getDataType());
             }
             if (colorModel == null) {
-                colorModel = 
builder.createColorModel(ColorScaleBuilder.TYPE_COMPACT, NUM_BANDS, 
VISIBLE_BAND);
+                colorModel = builder.createColorModel(dataType, NUM_BANDS, 
VISIBLE_BAND);
             }
             converters = new MathTransform1D[] {
                 builder.getSampleToIndexValues()            // Must be after 
`createColorModel(…)`.
@@ -349,9 +356,6 @@ final class Visualization extends ResampledImage {
                 interpolation = combine(interpolation.toCompatible(source), 
converters);
                 converters    = null;
             }
-            if (bounds == null) {
-                bounds = ImageUtilities.getBounds(source);
-            }
             return ImageProcessor.unique(new Visualization(this));
         }
     }
diff --git 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/privy/ColorModelBuilderTest.java
 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/privy/ColorModelBuilderTest.java
index f14aac7103..c031e3c3d6 100644
--- 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/privy/ColorModelBuilderTest.java
+++ 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/privy/ColorModelBuilderTest.java
@@ -19,11 +19,11 @@ package org.apache.sis.coverage.privy;
 import java.util.List;
 import java.util.AbstractMap.SimpleEntry;
 import java.awt.Color;
-import java.awt.image.DataBuffer;
 import java.awt.image.IndexColorModel;
 import org.opengis.referencing.operation.MathTransform1D;
 import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.coverage.SampleDimension;
+import org.apache.sis.image.DataType;
 import org.apache.sis.math.MathFunctions;
 import org.apache.sis.measure.NumberRange;
 import org.apache.sis.measure.Units;
@@ -53,7 +53,7 @@ public final class ColorModelBuilderTest extends TestCase {
      */
     @Test
     public void testRangeAndColors() throws TransformException {
-        final ColorScaleBuilder colorizer = new ColorScaleBuilder(List.of(
+        final var colorizer = new ColorScaleBuilder(List.of(
                 new SimpleEntry<>(NumberRange.create(0, true,  0, true), new 
Color[] {Color.GRAY}),
                 new SimpleEntry<>(NumberRange.create(1, true,  1, true), new 
Color[] {ColorModelFactory.TRANSPARENT}),
                 new SimpleEntry<>(NumberRange.create(2, true, 15, true), new 
Color[] {Color.BLUE, Color.WHITE, Color.RED})), null);
@@ -62,7 +62,7 @@ public final class ColorModelBuilderTest extends TestCase {
          * above-given ranges already fit in a 4-bits IndexColormodel.
          */
         assertTrue(colorizer.getSampleToIndexValues().isIdentity());
-        final IndexColorModel cm = (IndexColorModel) 
colorizer.createColorModel(DataBuffer.TYPE_BYTE, 1, 0);
+        final var cm = (IndexColorModel) 
colorizer.createColorModel(DataType.BYTE, 1, 0);
         final int[] expected = {
             0xFF808080,     // Color.GRAY
             0x00000000,     // ColorModelFactory.TRANSPARENT
@@ -102,9 +102,10 @@ public final class ColorModelBuilderTest extends TestCase {
                 .addQualitative ("Error", MathFunctions.toNanFloat(3))
                 .setName("Temperature").build();
 
-        final ColorScaleBuilder colorizer = new 
ColorScaleBuilder(ColorScaleBuilder.GRAYSCALE, null, true);
+        final var colorizer = new 
ColorScaleBuilder(ColorScaleBuilder.GRAYSCALE, null, true);
         assertTrue(colorizer.initialize(null, sd));
-        final var cm = (IndexColorModel) 
colorizer.createColorModel(ColorScaleBuilder.TYPE_COMPACT, 1, 0);      // Must 
be first.
+        final var dt = 
DataType.forDataBufferType(ColorScaleBuilder.TYPE_COMPACT);
+        final var cm = (IndexColorModel) colorizer.createColorModel(dt, 1, 0); 
     // Must be first.
         /*
          * Test conversion of a few sample values to packed values.
          */
diff --git 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/privy/SampleModelFactoryTest.java
 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/privy/SampleModelFactoryTest.java
index 2507bdb347..421485a15b 100644
--- 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/privy/SampleModelFactoryTest.java
+++ 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/coverage/privy/SampleModelFactoryTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.sis.coverage.privy;
 
+import java.awt.Dimension;
 import java.awt.image.DataBuffer;
 import java.awt.image.SampleModel;
 import java.awt.image.BandedSampleModel;
@@ -48,13 +49,20 @@ public final class SampleModelFactoryTest extends TestCase {
     public SampleModelFactoryTest() {
     }
 
+    /**
+     * Returns the width and height of the sample models to create.
+     */
+    private static Dimension size() {
+        return new Dimension(WIDTH, HEIGHT);
+    }
+
     /**
      * Tests the creation and modification of a {@link BandedSampleModel}.
      */
     @Test
     public void testBanded() {
         final BandedSampleModel model = test(BandedSampleModel.class,
-                new SampleModelFactory(DataType.FLOAT, WIDTH, HEIGHT, 
NUM_BANDS, Float.SIZE, true));
+                new SampleModelFactory(DataType.FLOAT, size(), NUM_BANDS, 
Float.SIZE, true));
 
         assertArrayEquals(new int[] {1, 0, 2}, model.getBankIndices());
         assertArrayEquals(new int[] {0, 0, 0}, model.getBandOffsets());
@@ -69,7 +77,7 @@ public final class SampleModelFactoryTest extends TestCase {
     @Test
     public void testPixelInterleaved() {
         final PixelInterleavedSampleModel model = 
test(PixelInterleavedSampleModel.class,
-                new SampleModelFactory(DataType.BYTE, WIDTH, HEIGHT, 
NUM_BANDS, Byte.SIZE, false));
+                new SampleModelFactory(DataType.BYTE, size(), NUM_BANDS, 
Byte.SIZE, false));
 
         assertArrayEquals(new int[] {0, 0, 0}, model.getBankIndices());
         assertArrayEquals(new int[] {1, 0, 2}, model.getBandOffsets());
@@ -86,7 +94,7 @@ public final class SampleModelFactoryTest extends TestCase {
     @Test
     public void testSinglePixelPacked() {
         final SinglePixelPackedSampleModel model = 
test(SinglePixelPackedSampleModel.class,
-                new SampleModelFactory(DataType.INT, WIDTH, HEIGHT, NUM_BANDS, 
5, false));
+                new SampleModelFactory(DataType.INT, size(), NUM_BANDS, 5, 
false));
 
         final int[] expected = {
             0b1111100000,           // Band 2 specified, 1 after compression.
@@ -106,8 +114,8 @@ public final class SampleModelFactoryTest extends TestCase {
     @Test
     public void testPixelMultiPixelPacked() {
         final int bitsPerSample = 4;
-        SampleModelFactory factory = new SampleModelFactory(DataType.INT, 
WIDTH, HEIGHT, 1, bitsPerSample, false);
-        final MultiPixelPackedSampleModel model = 
(MultiPixelPackedSampleModel) factory.build();
+        var factory = new SampleModelFactory(DataType.INT, size(), 1, 
bitsPerSample, false);
+        final var model = (MultiPixelPackedSampleModel) factory.build();
 
         assertEquals(bitsPerSample, model.getPixelBitStride());
         assertEquals(WIDTH / (Integer.SIZE / bitsPerSample), 
model.getScanlineStride());
diff --git 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/BandedSampleConverterTest.java
 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/BandedSampleConverterTest.java
index 07d1957a2f..42ffbd71c8 100644
--- 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/BandedSampleConverterTest.java
+++ 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/image/BandedSampleConverterTest.java
@@ -50,10 +50,10 @@ public final class BandedSampleConverterTest extends 
ImageTestCase {
      * The created image is assigned to the {@link #image} field.
      *
      * @param  sourceType  source data type as one of the {@link DataBuffer} 
constants.
-     * @param  targetType  target data type as one of the {@link DataBuffer} 
constants.
+     * @param  targetType  target data type.
      * @param  scale       the scale factor of the conversion to apply.
      */
-    private void createImage(final int sourceType, final int targetType, final 
double scale) {
+    private void createImage(final int sourceType, final DataType targetType, 
final double scale) {
         final Random random = TestUtilities.createRandomNumberGenerator();
         final TiledImageMock source = new TiledImageMock(
                 sourceType, 1,
@@ -106,7 +106,7 @@ public final class BandedSampleConverterTest extends 
ImageTestCase {
      */
     @Test
     public void testUShortToFloat() {
-        createImage(DataBuffer.TYPE_USHORT, DataBuffer.TYPE_FLOAT, 0.1);
+        createImage(DataBuffer.TYPE_USHORT, DataType.FLOAT, 0.1);
         assertValuesDivided();
     }
 
@@ -115,7 +115,7 @@ public final class BandedSampleConverterTest extends 
ImageTestCase {
      */
     @Test
     public void testFloatToUShort() {
-        createImage(DataBuffer.TYPE_FLOAT, DataBuffer.TYPE_USHORT, 10);
+        createImage(DataBuffer.TYPE_FLOAT, DataType.USHORT, 10);
         assertValuesMultiplied();
     }
 
@@ -124,7 +124,7 @@ public final class BandedSampleConverterTest extends 
ImageTestCase {
      */
     @Test
     public void testFloatToFloat() {
-        createImage(DataBuffer.TYPE_FLOAT, DataBuffer.TYPE_FLOAT, 0.1);
+        createImage(DataBuffer.TYPE_FLOAT, DataType.FLOAT, 0.1);
         assertValuesDivided();
     }
 
@@ -133,7 +133,7 @@ public final class BandedSampleConverterTest extends 
ImageTestCase {
      */
     @Test
     public void testUShortToUShort() {
-        createImage(DataBuffer.TYPE_USHORT, DataBuffer.TYPE_USHORT, 10);
+        createImage(DataBuffer.TYPE_USHORT, DataType.USHORT, 10);
         assertValuesMultiplied();
     }
 
@@ -142,7 +142,7 @@ public final class BandedSampleConverterTest extends 
ImageTestCase {
      */
     @Test
     public void testShortToInteger() {
-        createImage(DataBuffer.TYPE_SHORT, DataBuffer.TYPE_INT, 10);
+        createImage(DataBuffer.TYPE_SHORT, DataType.INT, 10);
         assertValuesMultiplied();
     }
 
@@ -151,7 +151,7 @@ public final class BandedSampleConverterTest extends 
ImageTestCase {
      */
     @Test
     public void testDoubleToInteger() {
-        createImage(DataBuffer.TYPE_DOUBLE, DataBuffer.TYPE_INT, 10);
+        createImage(DataBuffer.TYPE_DOUBLE, DataType.INT, 10);
         assertValuesMultiplied();
     }
 }
diff --git 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
index a5abf73b0d..23c8926929 100644
--- 
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
+++ 
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/ImageFileDirectory.java
@@ -25,6 +25,7 @@ import java.util.logging.Level;
 import java.util.logging.LogRecord;
 import java.nio.charset.Charset;
 import java.awt.Color;
+import java.awt.Dimension;
 import java.awt.image.ColorModel;
 import java.awt.image.SampleModel;
 import java.awt.image.SinglePixelPackedSampleModel;
@@ -1622,7 +1623,8 @@ final class ImageFileDirectory extends DataCube {
             RuntimeException error = null;
             final DataType type = getDataType();
             if (type != null) try {
-                sampleModel = new SampleModelFactory(type, tileWidth, 
tileHeight, samplesPerPixel, bitsPerSample, isPlanar).build();
+                var size = new Dimension(tileWidth, tileHeight);
+                sampleModel = new SampleModelFactory(type, size, 
samplesPerPixel, bitsPerSample, isPlanar).build();
             } catch (IllegalArgumentException | RasterFormatException e) {
                 error = e;
             }


Reply via email to