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
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new 9aa776c7af Last adjustements on the `Colorizer` work and addition of a
convenience `GridcoverageProcessor.visualize(GridCoverage, …)` method.
9aa776c7af is described below
commit 9aa776c7afbc577dd398dfa8335618af819e7e33
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Thu Mar 30 15:47:10 2023 +0200
Last adjustements on the `Colorizer` work and addition of a convenience
`GridcoverageProcessor.visualize(GridCoverage, …)` method.
---
.../org/apache/sis/coverage/grid/GridCoverage.java | 4 +-
.../sis/coverage/grid/GridCoverageBuilder.java | 2 +
.../sis/coverage/grid/GridCoverageProcessor.java | 83 +++++++++++++++++++++-
.../apache/sis/coverage/grid/ImageRenderer.java | 6 +-
.../apache/sis/coverage/grid/SliceGeometry.java | 2 +
.../apache/sis/image/BandedSampleConverter.java | 6 +-
.../java/org/apache/sis/image/ImageProcessor.java | 18 +++--
.../java/org/apache/sis/image/Visualization.java | 27 ++++---
.../sis/internal/coverage/SampleDimensions.java | 31 ++++++--
.../sis/internal/map/coverage/RenderingData.java | 24 ++-----
10 files changed, 155 insertions(+), 48 deletions(-)
diff --git
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverage.java
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverage.java
index fbea3ecdb7..bb4c8d5e25 100644
---
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverage.java
+++
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverage.java
@@ -314,10 +314,10 @@ public abstract class GridCoverage extends BandedCoverage
{
final MathTransform1D[] converters, final ImageProcessor processor)
{
try {
- SampleDimensions.CONVERTED_BANDS.set(sampleDimensions);
+ SampleDimensions.IMAGE_PROCESSOR_ARGUMENT.set(sampleDimensions);
return processor.convert(source, getRanges(), converters,
bandType);
} finally {
- SampleDimensions.CONVERTED_BANDS.remove();
+ SampleDimensions.IMAGE_PROCESSOR_ARGUMENT.remove();
}
}
diff --git
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverageBuilder.java
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverageBuilder.java
index ca04e9a09e..15a52e41ad 100644
---
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverageBuilder.java
+++
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverageBuilder.java
@@ -483,6 +483,8 @@ public class GridCoverageBuilder {
*/
if (bands != null) {
properties.put(PlanarImage.SAMPLE_DIMENSIONS_KEY,
bands.toArray(SampleDimension[]::new));
+ } else {
+ properties.remove(PlanarImage.SAMPLE_DIMENSIONS_KEY);
}
if (raster instanceof WritableRaster) {
final WritableRaster wr = (WritableRaster) raster;
diff --git
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverageProcessor.java
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverageProcessor.java
index b915d36752..a57a73b479 100644
---
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverageProcessor.java
+++
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridCoverageProcessor.java
@@ -23,7 +23,6 @@ import java.util.Objects;
import java.util.function.Function;
import java.awt.Shape;
import java.awt.Rectangle;
-import java.awt.image.ColorModel;
import java.awt.image.RenderedImage;
import javax.measure.Quantity;
import org.opengis.util.FactoryException;
@@ -39,6 +38,7 @@ import org.apache.sis.image.DataType;
import org.apache.sis.image.Colorizer;
import org.apache.sis.image.ImageProcessor;
import org.apache.sis.image.Interpolation;
+import org.apache.sis.internal.coverage.SampleDimensions;
import org.apache.sis.internal.coverage.MultiSourcesArgument;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.logging.Logging;
@@ -220,6 +220,7 @@ public class GridCoverageProcessor implements Cloneable {
* @param colorizer colorization algorithm to apply on computed image, or
{@code null} for default.
*
* @see ImageProcessor#setColorizer(Colorizer)
+ * @see #visualize(GridCoverage, GridExtent)
*
* @since 1.4
*/
@@ -328,6 +329,12 @@ public class GridCoverageProcessor implements Cloneable {
* If {@code maskInside} is {@code false}, then the mask is reversed:
* the pixels set to fill values are the ones outside the ROI.
*
+ * <h4>Properties used</h4>
+ * This operation uses the following properties in addition to method
parameters:
+ * <ul>
+ * <li>{@linkplain #getFillValues() Fill values} values to assign to
pixels inside/outside the region of interest.</li>
+ * </ul>
+ *
* @param source the coverage on which to apply a mask.
* @param mask region (in arbitrary CRS) of the mask.
* @param maskInside {@code true} for masking pixels inside the shape,
or {@code false} for masking outside.
@@ -369,13 +376,19 @@ public class GridCoverageProcessor implements Cloneable {
* If the source coverage is backed by a {@link
java.awt.image.WritableRenderedImage},
* then changes in the source coverage are reflected in the returned
coverage and conversely.
*
+ * <h4>Properties used</h4>
+ * This operation uses the following properties in addition to method
parameters:
+ * <ul>
+ * <li>{@linkplain #getColorizer() Colorizer} for customizing the
rendered image color model.</li>
+ * </ul>
+ *
* @param source the coverage for which to convert sample values.
* @param converters the transfer functions to apply on each sample
dimension of the source coverage.
* @param sampleDimensionModifier a callback for modifying the {@link
SampleDimension.Builder} default
* configuration for each sample dimension of the target coverage,
or {@code null} if none.
* @return the coverage which computes converted values from the given
source.
*
- * @see ImageProcessor#convert(RenderedImage, NumberRange<?>[],
MathTransform1D[], DataType, ColorModel)
+ * @see ImageProcessor#convert(RenderedImage, NumberRange<?>[],
MathTransform1D[], DataType)
*
* @since 1.3
*/
@@ -430,6 +443,12 @@ public class GridCoverageProcessor implements Cloneable {
* of this {@code translate(…)} method into a single
translation.</li>
* </ul>
*
+ * <h4>Properties used</h4>
+ * This operation uses the following properties in addition to method
parameters:
+ * <ul>
+ * <li>(none)</li>
+ * </ul>
+ *
* @param source the grid coverage to translate.
* @param translation translation to apply on each grid axis in order.
* @return a grid coverage whose grid coordinates (both low and high ones)
and
@@ -488,6 +507,15 @@ public class GridCoverageProcessor implements Cloneable {
* by {@code translate(…)} when possible.</li>
* </ul>
*
+ * <h4>Properties used</h4>
+ * This operation uses the following properties in addition to method
parameters:
+ * <ul>
+ * <li>{@linkplain #getInterpolation() Interpolation method} (nearest
neighbor, bilinear, <i>etc</i>).</li>
+ * <li>{@linkplain #getFillValues() Fill values} for pixels outside
source image.</li>
+ * <li>{@linkplain #getPositionalAccuracyHints() Positional accuracy
hints}
+ * for enabling faster resampling at the cost of lower
precision.</li>
+ * </ul>
+ *
* @param source the grid coverage to resample.
* @param target the desired geometry of returned grid coverage. May be
incomplete.
* @return a grid coverage with the characteristics specified in the given
grid geometry.
@@ -742,6 +770,57 @@ public class GridCoverageProcessor implements Cloneable {
return new BandAggregateGridCoverage(aggregate, snapshot());
}
+ /**
+ * Renders the given grid coverage as an image suitable for displaying
purpose.
+ * The resulting image is for visualization only and should not be used
for computational purposes.
+ * There is no guarantee about the number of bands in returned image or
about which formula is used
+ * for converting floating point values to integer values.
+ *
+ * <h4>How to specify colors</h4>
+ * The image colors can be controlled by the {@link Colorizer} set on this
coverage processor.
+ * The recommended way is to associate colors to {@linkplain
Category#getName() category names},
+ * {@linkplain org.apache.sis.measure.MeasurementRange#unit() units of
measurement}
+ * or other category properties. Example:
+ *
+ * {@snippet lang="java" :
+ * Map<String,Color[]> colors = Map.of(
+ * "Temperature", new Color[] {Color.BLUE, Color.MAGENTA,
Color.RED},
+ * "Wind speed", new Color[] {Color.GREEN, Color.CYAN,
Color.BLUE});
+ *
+ * processor.setColorizer(Colorizer.forCategories((category) ->
+ * colors.get(category.getName().toString(Locale.ENGLISH))));
+ *
+ * RenderedImage visualization = processor.visualize(source, slice);
+ * }
+ *
+ * <h4>Properties used</h4>
+ * This operation uses the following properties in addition to method
parameters:
+ * <ul>
+ * <li>{@linkplain #getColorizer() Colorizer} for customizing the
rendered image color model.</li>
+ * </ul>
+ *
+ * @param source the grid coverage to visualize.
+ * @param slice the slice and extent to render, or {@code null} for the
whole coverage.
+ * @return rendered image for visualization purposes only.
+ * @throws IllegalArgumentException if the given extent does not have the
same number of dimensions
+ * than the specified coverage or does not intersect.
+ *
+ * @see ImageProcessor#visualize(RenderedImage)
+ *
+ * @since 1.4
+ */
+ public RenderedImage visualize(final GridCoverage source, final GridExtent
slice) {
+ ArgumentChecks.ensureNonNull("source", source);
+ final SampleDimension[] bands =
source.getSampleDimensions().toArray(SampleDimension[]::new);
+ final RenderedImage image = source.render(slice);
+ try {
+ SampleDimensions.IMAGE_PROCESSOR_ARGUMENT.set(bands);
+ return imageProcessor.visualize(image);
+ } finally {
+ SampleDimensions.IMAGE_PROCESSOR_ARGUMENT.remove();
+ }
+ }
+
/**
* Invoked when an ignorable exception occurred.
*
diff --git
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ImageRenderer.java
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ImageRenderer.java
index 9fde21c79b..b9005bd109 100644
---
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ImageRenderer.java
+++
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/ImageRenderer.java
@@ -447,7 +447,7 @@ public class ImageRenderer {
public GridGeometry getImageGeometry(final int dimCRS) {
GridGeometry ig = imageGeometry;
if (ig == null || dimCRS != GridCoverage2D.BIDIMENSIONAL) {
- if (isSameGeometry(dimCRS)) {
+ if (imageUseSameGeometry(dimCRS)) {
ig = geometry;
} else try {
ig = new SliceGeometry(geometry, sliceExtent, gridDimensions,
mtFactory)
@@ -515,7 +515,7 @@ public class ImageRenderer {
* can return {@link #geometry} directly. This common case avoids the need
for more costly computation with
* {@link SliceGeometry}.
*/
- private boolean isSameGeometry(final int dimCRS) {
+ private boolean imageUseSameGeometry(final int dimCRS) {
final int tgtDim = geometry.getTargetDimension();
ArgumentChecks.ensureBetween("dimCRS", GridCoverage2D.BIDIMENSIONAL,
tgtDim, dimCRS);
if (tgtDim == dimCRS && geometry.getDimension() ==
gridDimensions.length) {
@@ -762,7 +762,7 @@ public class ImageRenderer {
}
SliceGeometry supplier = null;
if (imageGeometry == null) {
- if (isSameGeometry(GridCoverage2D.BIDIMENSIONAL)) {
+ if (imageUseSameGeometry(GridCoverage2D.BIDIMENSIONAL)) {
imageGeometry = geometry;
} else {
supplier = new SliceGeometry(geometry, sliceExtent,
gridDimensions, mtFactory);
diff --git
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/SliceGeometry.java
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/SliceGeometry.java
index dc57a98663..26efeb3bac 100644
---
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/SliceGeometry.java
+++
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/SliceGeometry.java
@@ -59,6 +59,7 @@ final class SliceGeometry implements Function<RenderedImage,
GridGeometry> {
/**
* Extents of the slice to take in the {@linkplain #geometry}.
+ * May be {@code null} if unknown.
*/
private final GridExtent sliceExtent;
@@ -189,6 +190,7 @@ final class SliceGeometry implements
Function<RenderedImage, GridGeometry> {
}
GeneralEnvelope subArea = null;
if (useSubExtent && cornerToCRS != null) try {
+ // `extent` is non-null if `useSubExtent` is true.
subArea = extent.toEnvelope(cornerToCRS, gridToCRS, null);
} catch (TransformException e) {
// GridGeometry.reduce(…) is the public method invoking indirectly
this method.
diff --git
a/core/sis-feature/src/main/java/org/apache/sis/image/BandedSampleConverter.java
b/core/sis-feature/src/main/java/org/apache/sis/image/BandedSampleConverter.java
index baab75fe89..8cc2527aa5 100644
---
a/core/sis-feature/src/main/java/org/apache/sis/image/BandedSampleConverter.java
+++
b/core/sis-feature/src/main/java/org/apache/sis/image/BandedSampleConverter.java
@@ -99,8 +99,8 @@ class BandedSampleConverter extends ComputedImage {
/**
* Description of bands, or {@code null} if unknown.
* Not used by this class, but provided as a {@value
#SAMPLE_DIMENSIONS_KEY} property.
- * The value is fetched from {@link SampleDimensions#CONVERTED_BANDS} for
avoiding to
- * expose a {@code SampleDimension[]} argument in public {@link
ImageProcessor} API.
+ * The value is fetched from {@link
SampleDimensions#IMAGE_PROCESSOR_ARGUMENT} for avoiding
+ * to expose a {@code SampleDimension[]} argument in public {@link
ImageProcessor} API.
*
* @see #getProperty(String)
*/
@@ -221,7 +221,7 @@ class BandedSampleConverter extends ComputedImage {
}
final int numBands = converters.length;
final BandedSampleModel sampleModel =
layout.createBandedSampleModel(targetType, numBands, source, null);
- final SampleDimension[] sampleDimensions =
SampleDimensions.CONVERTED_BANDS.get();
+ final SampleDimension[] sampleDimensions =
SampleDimensions.IMAGE_PROCESSOR_ARGUMENT.get();
final int visibleBand = ImageUtilities.getVisibleBand(source);
ColorModel colorModel = ColorModelBuilder.NULL_COLOR_MODEL;
if (colorizer != null) {
diff --git
a/core/sis-feature/src/main/java/org/apache/sis/image/ImageProcessor.java
b/core/sis-feature/src/main/java/org/apache/sis/image/ImageProcessor.java
index e0ca82b6cc..dea9f52adf 100644
--- a/core/sis-feature/src/main/java/org/apache/sis/image/ImageProcessor.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/image/ImageProcessor.java
@@ -993,6 +993,12 @@ public class ImageProcessor implements Cloneable {
* If {@code maskInside} is {@code false}, then the mask is reversed:
* the pixels set to fill values are the ones outside the shape.
*
+ * <h4>Properties used</h4>
+ * This operation uses the following properties in addition to method
parameters:
+ * <ul>
+ * <li>{@linkplain #getFillValues() Fill values} values to assign to
pixels inside/outside the shape.</li>
+ * </ul>
+ *
* @param source the image on which to apply a mask.
* @param mask geometric area (in pixel coordinates) of the mask.
* @param maskInside {@code true} for masking pixels inside the shape,
or {@code false} for masking outside.
@@ -1037,7 +1043,7 @@ public class ImageProcessor implements Cloneable {
* <h4>Properties used</h4>
* This operation uses the following properties in addition to method
parameters:
* <ul>
- * <li>{@linkplain #getColorizer() Colorizer}.</li>
+ * <li>{@linkplain #getColorizer() Colorizer} for customizing the
rendered image color model.</li>
* </ul>
*
* <h4>Result relationship with source</h4>
@@ -1135,7 +1141,7 @@ public class ImageProcessor implements Cloneable {
* @param source the image to be resampled.
* @param bounds domain of pixel coordinates of resampled image to
create.
* Updated by this method if {@link Resizing#EXPAND}
policy is applied.
- * @param toSource conversion of pixel coordinates from resampled image
to {@code source} image.
+ * @param toSource conversion of pixel center coordinates from resampled
image to {@code source} image.
* @return resampled image (may be {@code source}).
*
* @see GridCoverageProcessor#resample(GridCoverage, GridGeometry)
@@ -1362,7 +1368,7 @@ public class ImageProcessor implements Cloneable {
* <h4>Properties used</h4>
* This operation uses the following properties in addition to method
parameters:
* <ul>
- * <li>{@linkplain #getColorizer() Colorizer}.</li>
+ * <li>{@linkplain #getColorizer() Colorizer} for customizing the
rendered image color model.</li>
* </ul>
*
* @param source the image to recolor for visualization purposes.
@@ -1406,15 +1412,17 @@ public class ImageProcessor implements Cloneable {
* if {@code bounds} size is not divisible by a tile size.</li>
* <li>{@linkplain #getPositionalAccuracyHints() Positional accuracy
hints}
* for enabling faster resampling at the cost of lower
precision.</li>
- * <li>{@linkplain #getColorizer() Colorizer}.</li>
+ * <li>{@linkplain #getColorizer() Colorizer} for customizing the
rendered image color model.</li>
* </ul>
*
* @param source the image to be resampled and recolored.
* @param bounds domain of pixel coordinates of resampled image to
create.
* Updated by this method if {@link Resizing#EXPAND}
policy is applied.
- * @param toSource conversion of pixel coordinates from resampled image
to {@code source} image.
+ * @param toSource conversion of pixel center coordinates from resampled
image to {@code source} image.
* @return resampled and recolored image for visualization purposes only.
*
+ * @see #resample(RenderedImage, Rectangle, MathTransform)
+ *
* @since 1.4
*/
public RenderedImage visualize(final RenderedImage source, final Rectangle
bounds, final MathTransform toSource) {
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 35229898d1..7237500a48 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
@@ -197,9 +197,12 @@ final class Visualization extends ResampledImage {
this.bounds = bounds;
this.source = source;
this.toSource = toSource;
- Object ranges = source.getProperty(SAMPLE_DIMENSIONS_KEY);
- if (ranges instanceof SampleDimension[]) {
- sampleDimensions = (SampleDimension[]) ranges;
+ sampleDimensions = SampleDimensions.IMAGE_PROCESSOR_ARGUMENT.get();
+ if (sampleDimensions == null) {
+ Object ranges = source.getProperty(SAMPLE_DIMENSIONS_KEY);
+ if (ranges instanceof SampleDimension[]) {
+ sampleDimensions = (SampleDimension[]) ranges;
+ }
}
}
@@ -247,8 +250,19 @@ final class Visualization extends ResampledImage {
* Keep only the band to make visible in order to reduce the
amount of calculation during
* resampling and for saving memory.
*/
- while (source instanceof ImageAdapter) {
- source = ((ImageAdapter) source).source;
+ if (toSource == null) {
+ toSource = MathTransforms.identity(BIDIMENSIONAL);
+ }
+ for (;;) {
+ if (source instanceof ImageAdapter) {
+ source = ((ImageAdapter) source).source;
+ } else if (source instanceof ResampledImage) {
+ final ResampledImage r = (ResampledImage) source;
+ toSource = MathTransforms.concatenate(toSource,
r.toSource);
+ source = r.getSource();
+ } else {
+ break;
+ }
}
source = BandSelectImage.create(source, new int[] {visibleBand});
final SampleDimension visibleSD = (sampleDimensions != null &&
visibleBand < sampleDimensions.length)
@@ -259,9 +273,6 @@ 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.
*/
- if (toSource == null) {
- toSource = MathTransforms.identity(BIDIMENSIONAL);
- }
final boolean shortcut = toSource.isIdentity() && (bounds == null
|| ImageUtilities.getBounds(source).contains(bounds));
if (shortcut) {
layout = ImageLayout.fixedSize(source);
diff --git
a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/SampleDimensions.java
b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/SampleDimensions.java
index d896643025..a8dcb60a16 100644
---
a/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/SampleDimensions.java
+++
b/core/sis-feature/src/main/java/org/apache/sis/internal/coverage/SampleDimensions.java
@@ -37,14 +37,33 @@ import org.apache.sis.util.Static;
*/
public final class SampleDimensions extends Static {
/**
- * The sample dimensions of a {@link
org.apache.sis.image.BandedSampleConverter} image.
- * We use this thread-local variable as an internal workaround for an
parameter that we
- * do not expose in the public API of {@link ImageProcessor}.
+ * A hidden argument passed to some {@link ImageProcessor} operations.
+ * Used for a parameter that we do not want to expose in the public API,
+ * because {@link ImageProcessor} is not supposed to know grid coverages.
+ * We may revisit in future Apache SIS version if we find a better way to
+ * pass this information.
*
- * <p>The content of the array in this thread-local variable shall not be
modified,
- * because it may be a direct reference to an internal array (not a
clone).</p>
+ * This is used in:
+ * <ul>
+ * <li>The <em>target</em> sample dimensions of a {@link
org.apache.sis.image.BandedSampleConverter} image.</li>
+ * <li>The <em>source</em> sample dimensions of a {@link
org.apache.sis.image.Visualization} image.</li>
+ * </ul>
+ *
+ * Usage pattern:
+ *
+ * {@snippet lang="java" :
+ * try {
+ * SampleDimensions.IMAGE_PROCESSOR_ARGUMENT.set(dataRanges);
+ * return imageProcessor.doSomeStuff(...);
+ * } finally {
+ * SampleDimensions.IMAGE_PROCESSOR_ARGUMENT.remove();
+ * }
+ * }
+ *
+ * The content of the array in this thread-local variable shall not be
modified,
+ * because it may be a direct reference to an internal array (not a clone).
*/
- public static final ThreadLocal<SampleDimension[]> CONVERTED_BANDS = new
ThreadLocal<>();
+ public static final ThreadLocal<SampleDimension[]>
IMAGE_PROCESSOR_ARGUMENT = new ThreadLocal<>();
/**
* Do not allow instantiation of this class.
diff --git
a/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/coverage/RenderingData.java
b/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/coverage/RenderingData.java
index bea3a65a64..6c51dd0946 100644
---
a/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/coverage/RenderingData.java
+++
b/core/sis-portrayal/src/main/java/org/apache/sis/internal/map/coverage/RenderingData.java
@@ -662,30 +662,16 @@ public class RenderingData implements Cloneable {
*/
if (CREATE_INDEX_COLOR_MODEL) {
final ColorModelType ct =
ColorModelType.find(recoloredImage.getColorModel());
- if (ct.isSlow || (ct.useColorRamp && processor.getColorizer() !=
null)) {
- return
processor.visualize(withSampleDimensions(recoloredImage), bounds,
displayToCenter);
+ if (ct.isSlow || (ct.useColorRamp && processor.getColorizer() !=
null)) try {
+ SampleDimensions.IMAGE_PROCESSOR_ARGUMENT.set(dataRanges);
+ return processor.visualize(recoloredImage, bounds,
displayToCenter);
+ } finally {
+ SampleDimensions.IMAGE_PROCESSOR_ARGUMENT.remove();
}
}
return processor.resample(recoloredImage, bounds, displayToCenter);
}
- /**
- * Returns an image augmented with the sample dimensions if not already
present.
- * If the property is present but with a different value, the {@link
#dataRanges}
- * will overwrite the image property value.
- *
- * @param image the image for which to add a property if not already
present.
- * @return image augmented with the given property.
- */
- private RenderedImage withSampleDimensions(RenderedImage image) {
- final String key = PlanarImage.SAMPLE_DIMENSIONS_KEY;
- final SampleDimension[] value = dataRanges;
- if (!Objects.deepEquals(image.getProperty(key), value)) {
- image = processor.addUserProperties(image, Map.of(key, value));
- }
- return image;
- }
-
/**
* Conversion or transformation from {@linkplain
PlanarCanvas#getObjectiveCRS() objective CRS} to
* {@linkplain #data} CRS. This transform will include {@code
WraparoundTransform} steps if needed.