You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sis.apache.org by de...@apache.org on 2021/12/08 14:52:45 UTC
[sis] 04/04: Fix a problem of incompatible (SampleModel, ColorModel) pair when `Visualization` determined that it can not apply interpolations.
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 <ma...@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;
+ }
}
/**