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 5c39a4340e635a95fecb86fc271027ade5303223
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Wed Dec 8 15:29:16 2021 +0100

    Fix a problem of incompatible (SampleModel, ColorModel) pair when 
`Visualization` determined that it can not apply interpolations.
---
 .../java/org/apache/sis/image/Interpolation.java   | 26 ++++++++++++++++++++++
 .../java/org/apache/sis/image/ResampledImage.java  | 12 +---------
 .../java/org/apache/sis/image/Visualization.java   | 20 +++++------------
 3 files changed, 33 insertions(+), 25 deletions(-)

diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/image/Interpolation.java 
b/core/sis-feature/src/main/java/org/apache/sis/image/Interpolation.java
index 9943dc0..63ef0bd 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/Interpolation.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/Interpolation.java
@@ -17,6 +17,8 @@
 package org.apache.sis.image;
 
 import java.awt.Dimension;
+import java.awt.image.RenderedImage;
+import java.awt.image.IndexColorModel;
 import java.nio.DoubleBuffer;
 
 
@@ -106,6 +108,25 @@ public abstract class Interpolation {
     public abstract void interpolate(DoubleBuffer source, int numBands, double 
xfrac, double yfrac, double[] writeTo, int writeToOffset);
 
     /**
+     * Returns {@link #NEAREST} if interpolations on the given image should be 
restricted to nearest-neighbor.
+     * If the given image uses an index color model, interpolating the indexed 
values does not produce the
+     * expected colors. Safest approach is to disable completely 
interpolations in that case.
+     *
+     * <div class="note"><b>Note:</b>
+     * we could interpolate if we knew that all index values, without 
exception (i.e. no index for missing values),
+     * are related to measurements by a linear function. In practice it rarely 
happens, because there is usually
+     * at least one index value reserved for missing values. Scientific data 
in SIS are usually stored as floating
+     * point type (with missing values mapped to NaN), which can not be 
associated to {@link IndexColorModel}.
+     * For now we do not try to perform a more sophisticated detection of 
which interpolations are allowed,
+     * but a future SIS version may revisit this policy if needed.</div>
+     *
+     * @return {@link #NEAREST} if interpolations should be restricted to 
nearest-neighbor, or {@code this} otherwise.
+     */
+    Interpolation toCompatible(final RenderedImage source) {
+        return (source.getColorModel() instanceof IndexColorModel) ? NEAREST : 
this;
+    }
+
+    /**
      * A nearest-neighbor interpolation using 1×1 pixel.
      */
     public static final Interpolation NEAREST = new Interpolation() {
@@ -128,6 +149,11 @@ public abstract class Interpolation {
             source.get(writeTo, writeToOffset, numBands);
             source.reset();
         }
+
+        /** This interpolation never need to be disabled. */
+        @Override Interpolation toCompatible(final RenderedImage source) {
+            return this;
+        }
     };
 
     /**
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/image/ResampledImage.java 
b/core/sis-feature/src/main/java/org/apache/sis/image/ResampledImage.java
index 9f8ded6..ec3107e 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/ResampledImage.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/ResampledImage.java
@@ -24,7 +24,6 @@ import java.awt.Dimension;
 import java.awt.Rectangle;
 import java.awt.geom.Rectangle2D;
 import java.awt.image.ColorModel;
-import java.awt.image.IndexColorModel;
 import java.awt.image.Raster;
 import java.awt.image.RenderedImage;
 import java.awt.image.WritableRaster;
@@ -245,17 +244,8 @@ public class ResampledImage extends ComputedImage {
         /*
          * If the image uses an index color model, interpolating the indexed 
values does not produce
          * the expected colors. Safest approach is to disable completely 
interpolations in that case.
-         *
-         * Note: we could interpolate if we knew that all index values, 
without exception (i.e. no index for
-         * missing values), are related to measurements by a linear function. 
It practice it rarely happens,
-         * because there is usually at least one index value reserved for 
missing values. Scientific data in
-         * SIS are usually stored as floating point type (with missing values 
mapped to NaN), which can not
-         * be associated to `IndexColorModel`. For now we don't try to perform 
a more sophisticated detection
-         * of which interpolations are allowed, but a future SIS version may 
revisit this policy if needed.
          */
-        if (source.getColorModel() instanceof IndexColorModel) {
-            interpolation = Interpolation.NEAREST;
-        }
+        interpolation = interpolation.toCompatible(source);
         /*
          * If the interpolation requires more than 2×2 pixels, we will need to 
shift the transform
          * to source image. For example if the interpolation requires 4×4 
pixels, the interpolation
diff --git 
a/core/sis-feature/src/main/java/org/apache/sis/image/Visualization.java 
b/core/sis-feature/src/main/java/org/apache/sis/image/Visualization.java
index 110aed7..393f65f 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/Visualization.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/Visualization.java
@@ -30,7 +30,6 @@ import java.awt.image.SampleModel;
 import java.awt.image.Raster;
 import java.awt.image.WritableRaster;
 import java.awt.image.RenderedImage;
-import java.awt.image.DataBuffer;
 import java.nio.DoubleBuffer;
 import javax.measure.Quantity;
 import org.apache.sis.coverage.Category;
@@ -250,18 +249,6 @@ final class Visualization extends ResampledImage {
                 colorizer.initialize(statistics.minimum(), 
statistics.maximum());
             }
             /*
-             * At this point we finished to configure the colorizer; we are 
ready to build the `ColorModel`.
-             * If the source image uses unsigned integer types and there is no 
resampling operation, we can
-             * update the color model without changing sample values. This is 
much cheaper and as accurate.
-             */
-            final int dataType = source.getSampleModel().getDataType();
-            if (dataType == DataBuffer.TYPE_BYTE || dataType == 
DataBuffer.TYPE_USHORT) {
-                if (toSource != null && !toSource.isIdentity()) {
-                    source = processor.resample(source, bounds, toSource);
-                }
-                return RecoloredImage.create(source, 
colorizer.createColorModel(dataType, NUM_BANDS, VISIBLE_BAND));
-            }
-            /*
              * If we reach this point, sample values need to be converted to 
integers in [0 … 255] range.
              * Skip any previous `RecoloredImage` since we are replacing the 
`ColorModel` by a new one.
              */
@@ -284,7 +271,7 @@ final class Visualization extends ResampledImage {
                 layout        = ImageLayout.fixedSize(source);
                 interpolation = Interpolation.NEAREST;
             } else {
-                interpolation = combine(interpolation, converters);
+                interpolation = combine(interpolation.toCompatible(source), 
converters);
                 converters    = null;
             }
             /*
@@ -365,6 +352,11 @@ final class Visualization extends ResampledImage {
                 throw new BackingStoreException(e);     // Will be unwrapped 
by computeTile(…).
             }
         }
+
+        /** This interpolation never need to be disabled. */
+        @Override Interpolation toCompatible(final RenderedImage source) {
+            return this;
+        }
     }
 
     /**

Reply via email to