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 3974735 Allow selection of interpolation method.
3974735 is described below
commit 39747356392aace3e8db46e4fab81d54a3786212
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Mon May 18 13:03:28 2020 +0200
Allow selection of interpolation method.
---
.../java/org/apache/sis/gui/coverage/Controls.java | 24 +++++-
.../apache/sis/gui/coverage/CoverageCanvas.java | 54 ++++++++++--
.../apache/sis/gui/coverage/CoverageControls.java | 95 +++++++++++++++++++---
.../org/apache/sis/gui/coverage/GridControls.java | 11 +--
.../org/apache/sis/gui/coverage/RenderingData.java | 11 +++
.../org/apache/sis/gui/referencing/CRSChooser.java | 2 +-
.../java/org/apache/sis/internal/gui/Styles.java | 5 +-
.../org/apache/sis/util/resources/Vocabulary.java | 15 ++++
.../sis/util/resources/Vocabulary.properties | 3 +
.../sis/util/resources/Vocabulary_fr.properties | 3 +
10 files changed, 191 insertions(+), 32 deletions(-)
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/Controls.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/Controls.java
index 00764a8..be38dee 100644
---
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/Controls.java
+++
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/Controls.java
@@ -48,7 +48,7 @@ abstract class Controls {
/**
* Margin to keep around captions after the first one.
*/
- static final Insets NEXT_CAPTION_MARGIN = new Insets(30, 0, 9, 0);
+ private static final Insets NEXT_CAPTION_MARGIN = new Insets(30, 0, 9, 0);
/**
* The border to use for grouping some controls together.
@@ -73,11 +73,13 @@ abstract class Controls {
* The controls must be associated to the given labels by {@link
Label#getLabelFor()}.
* If a label is {@code null}, then no row is created for that label.
*
+ * @param row index of the first row. If different than 0, then it
is caller responsibility
+ * to provide controls for all rows before the specified
index.
* @param controls (label, control) pairs to layout in rows.
* @return a pane with each (label, control) pair on a row.
*/
- static GridPane createControlGrid(final Label... controls) {
- final GridPane gp = Styles.createControlGrid(controls);
+ static GridPane createControlGrid(final int row, final Label... controls) {
+ final GridPane gp = Styles.createControlGrid(row, controls);
Styles.setAllRowToSameHeight(gp);
gp.setBorder(GROUP_BORDER);
return gp;
@@ -103,6 +105,22 @@ abstract class Controls {
}
/**
+ * Creates a label with the specified text associated to the given group
of controls.
+ *
+ * @param vocabulary the resources from which to get the text.
+ * @param key {@code vocabulary} key of the text to put in the
label.
+ * @param group the group of controls to associate to the label.
+ * @param isFirst whether the given group is the first group in the
pane.
+ * @return label associated to the given group of controls.
+ */
+ static Label labelOfGroup(final Vocabulary vocabulary, final short key,
final Region group, final boolean isFirst) {
+ final Label label = new Label(vocabulary.getLabel(key));
+ label.setPadding(isFirst ? CAPTION_MARGIN : NEXT_CAPTION_MARGIN);
+ label.setLabelFor(group);
+ return label;
+ }
+
+ /**
* Returns the main component, which is showing coverage data or image.
* This is the component to shown on the right (largest) part of the split
pane.
*/
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageCanvas.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageCanvas.java
index aeb414d..d76cf16 100644
---
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageCanvas.java
+++
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageCanvas.java
@@ -44,6 +44,7 @@ import
org.apache.sis.referencing.operation.transform.LinearTransform;
import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.geometry.Envelope2D;
import org.apache.sis.image.PlanarImage;
+import org.apache.sis.image.Interpolation;
import org.apache.sis.gui.map.MapCanvas;
import org.apache.sis.gui.map.MapCanvasAWT;
import org.apache.sis.internal.gui.Resources;
@@ -84,6 +85,14 @@ public class CoverageCanvas extends MapCanvasAWT {
public final ObjectProperty<GridExtent> sliceExtentProperty;
/**
+ * The interpolation method to use for resampling the image.
+ *
+ * @see #getInterpolation()
+ * @see #setInterpolation(Interpolation)
+ */
+ public final ObjectProperty<Interpolation> interpolationProperty;
+
+ /**
* The {@code RenderedImage} to draw together with transform from pixel
coordinates to display coordinates.
* Shall never be {@code null} but may be {@linkplain
RenderingData#isEmpty() empty}. This instance shall be
* read and modified in JavaFX thread only and cloned if those data needed
by a background thread.
@@ -104,12 +113,14 @@ public class CoverageCanvas extends MapCanvasAWT {
*/
public CoverageCanvas() {
super(Locale.getDefault());
- coverageProperty = new SimpleObjectProperty<>(this, "coverage");
- sliceExtentProperty = new SimpleObjectProperty<>(this, "sliceExtent");
- resampledImages = new EnumMap<>(Stretching.class);
- data = new RenderingData();
- coverageProperty .addListener((p,o,n) -> onImageSpecified());
- sliceExtentProperty.addListener((p,o,n) -> onImageSpecified());
+ data = new RenderingData();
+ resampledImages = new EnumMap<>(Stretching.class);
+ coverageProperty = new SimpleObjectProperty<>(this, "coverage");
+ sliceExtentProperty = new SimpleObjectProperty<>(this,
"sliceExtent");
+ interpolationProperty = new SimpleObjectProperty<>(this,
"interpolation", data.getInterpolation());
+ coverageProperty .addListener((p,o,n) -> onImageSpecified());
+ sliceExtentProperty .addListener((p,o,n) -> onImageSpecified());
+ interpolationProperty.addListener((p,o,n) ->
onInterpolationSpecified(n));
}
/**
@@ -173,6 +184,28 @@ public class CoverageCanvas extends MapCanvasAWT {
}
/**
+ * Gets the interpolation method used during resample operations.
+ *
+ * @return the current interpolation method.
+ *
+ * @see #interpolationProperty
+ */
+ public final Interpolation getInterpolation() {
+ return interpolationProperty.get();
+ }
+
+ /**
+ * Sets the interpolation method to use during resample operations.
+ *
+ * @param interpolation the new interpolation method.
+ *
+ * @see #interpolationProperty
+ */
+ public final void setInterpolation(final Interpolation interpolation) {
+ interpolationProperty.set(interpolation);
+ }
+
+ /**
* Sets the background, as a color for now but more patterns may be
allowed in a future version.
*/
final void setBackground(final Color color) {
@@ -247,6 +280,15 @@ public class CoverageCanvas extends MapCanvasAWT {
}
/**
+ * Invoked when a new interpolation has been specified.
+ */
+ private void onInterpolationSpecified(final Interpolation interpolation) {
+ data.setInterpolation(interpolation);
+ resampledImages.clear();
+ requestRepaint();
+ }
+
+ /**
* Invoked in JavaFX thread for creating a renderer to be executed in a
background thread.
* This method prepares the information needed but does not start the
rendering itself.
* The rendering will be done later by a call to {@link
Renderer#paint(Graphics2D)}.
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageControls.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageControls.java
index 91b0284..a5103fc 100644
---
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageControls.java
+++
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/CoverageControls.java
@@ -16,12 +16,13 @@
*/
package org.apache.sis.gui.coverage;
+import java.util.Locale;
+import java.util.Objects;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javafx.scene.control.Accordion;
import javafx.scene.control.ColorPicker;
import javafx.scene.control.Control;
-import javafx.scene.control.Label;
import javafx.scene.control.TitledPane;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
@@ -30,11 +31,13 @@ import javafx.scene.layout.VBox;
import javafx.beans.property.ObjectProperty;
import javafx.scene.control.ChoiceBox;
import javafx.scene.paint.Color;
+import javafx.util.StringConverter;
import org.opengis.referencing.ReferenceSystem;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.apache.sis.coverage.grid.GridCoverage;
import org.apache.sis.gui.referencing.RecentReferenceSystems;
import org.apache.sis.gui.map.StatusBar;
+import org.apache.sis.image.Interpolation;
import org.apache.sis.util.resources.Vocabulary;
@@ -87,29 +90,32 @@ final class CoverageControls extends Controls implements
PropertyChangeListener
/*
* "Display" section with the following controls:
* - Coordinate reference system
+ * - Interpolation
* - Color stretching
* - Background color
*/
final VBox displayPane;
{ // Block for making variables locale to this scope.
- final ChoiceBox<ReferenceSystem> systems =
referenceSystems.createChoiceBox((p,o,n) -> {
+ final GridPane referencing = createControlGrid(1,
+ label(vocabulary, Vocabulary.Keys.Interpolation,
createInterpolationButton(vocabulary.getLocale()))
+ );
+ final ChoiceBox<ReferenceSystem> systemChoices =
referenceSystems.createChoiceBox((p,o,n) -> {
if (n instanceof CoordinateReferenceSystem) {
view.setObjectiveCRS((CoordinateReferenceSystem) n, p);
}
});
- systems.setMaxWidth(Double.POSITIVE_INFINITY);
- referenceSystem = systems.valueProperty();
- final Label systemLabel = new
Label(vocabulary.getLabel(Vocabulary.Keys.ReferenceSystem));
- systemLabel.setPadding(CAPTION_MARGIN);
- systemLabel.setLabelFor(systems);
- final GridPane gp = createControlGrid(
+ systemChoices.setMaxWidth(Double.POSITIVE_INFINITY);
+ GridPane.setConstraints(systemChoices, 0, 0, 2, 1); // First
row and column, span 2 columns.
+ referencing.getChildren().add(systemChoices);
+ referenceSystem = systemChoices.valueProperty();
+
+ final GridPane colors = createControlGrid(0,
label(vocabulary, Vocabulary.Keys.Stretching,
Stretching.createButton((p,o,n) -> view.setStretching(n))),
label(vocabulary, Vocabulary.Keys.Background,
createBackgroundButton(background))
);
- final Label label = new
Label(vocabulary.getLabel(Vocabulary.Keys.Colors));
- label.setPadding(NEXT_CAPTION_MARGIN);
- label.setLabelFor(gp);
- displayPane = new VBox(systemLabel, systems, label, gp);
+ displayPane = new VBox(
+ labelOfGroup(vocabulary, Vocabulary.Keys.ReferenceSystem,
referencing, true), referencing,
+ labelOfGroup(vocabulary, Vocabulary.Keys.Colors,
colors, false), colors);
}
/*
* Put all sections together and have the first one expanded by
default.
@@ -124,6 +130,71 @@ final class CoverageControls extends Controls implements
PropertyChangeListener
}
/**
+ * Creates the controls for choosing an interpolation method.
+ */
+ private ChoiceBox<Interpolation> createInterpolationButton(final Locale
locale) {
+ final ChoiceBox<Interpolation> b = new ChoiceBox<>();
+ b.setConverter(new InterpolationConverter(locale));
+ b.getItems().setAll(InterpolationConverter.INTERPOLATIONS);
+ b.getSelectionModel().select(view.getInterpolation());
+
view.interpolationProperty.bind(b.getSelectionModel().selectedItemProperty());
+ return b;
+ }
+
+ /**
+ * Gives a localized {@link String} instance for a given {@link
Interpolation} and conversely.
+ */
+ private static final class InterpolationConverter extends
StringConverter<Interpolation> {
+ /** The interpolation supported by this converter. */
+ static final Interpolation[] INTERPOLATIONS = {
+ Interpolation.NEAREST, Interpolation.BILINEAR,
Interpolation.LANCZOS
+ };
+
+ /** Keys of localized names for each {@link #INTERPOLATIONS} element.
*/
+ private static final short[] VOCABULARIES = {
+ Vocabulary.Keys.NearestNeighbor, Vocabulary.Keys.Bilinear, 0
+ };
+
+ /** The locale to use for string representation. */
+ private final Locale locale;
+
+ /** Creates a new converter for the given locale. */
+ InterpolationConverter(final Locale locale) {
+ this.locale = locale;
+ }
+
+ /** Returns a string representation of the given item. */
+ @Override public String toString(final Interpolation item) {
+ for (int i=0; i<INTERPOLATIONS.length; i++) {
+ if (INTERPOLATIONS[i].equals(item)) {
+ final short key = VOCABULARIES[i];
+ if (key != 0) {
+ return Vocabulary.getResources(locale).getString(key);
+ } else if (item == Interpolation.LANCZOS) {
+ return "Lanczos";
+ }
+ }
+ }
+ return Objects.toString(item);
+ }
+
+ /** Returns the interpolation for the given text. */
+ @Override public Interpolation fromString(final String text) {
+ final Vocabulary vocabulary = Vocabulary.getResources(locale);
+ for (int i=0; i<VOCABULARIES.length; i++) {
+ final short key = VOCABULARIES[i];
+ final Interpolation item = INTERPOLATIONS[i];
+ if ((key != 0 &&
vocabulary.getString(key).equalsIgnoreCase(text))
+ ||
item.toString().equalsIgnoreCase(text))
+ {
+ return item;
+ }
+ }
+ return null;
+ }
+ }
+
+ /**
* Creates the button for selecting a background color.
*/
private ColorPicker createBackgroundButton(final Color background) {
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridControls.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridControls.java
index f569356..260a21b 100644
---
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridControls.java
+++
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/GridControls.java
@@ -75,9 +75,7 @@ final class GridControls extends Controls {
*/
final VBox coveragePane;
{ // Block for making variables locale to this scope.
- final Label label = new
Label(vocabulary.getLabel(Vocabulary.Keys.SampleDimensions));
- label.setPadding(CAPTION_MARGIN);
- label.setLabelFor(sampleDimensions);
+ final Label label = labelOfGroup(vocabulary,
Vocabulary.Keys.SampleDimensions, sampleDimensions, true);
coveragePane = new VBox(label, sampleDimensions);
}
/*
@@ -87,15 +85,12 @@ final class GridControls extends Controls {
*/
final VBox displayPane;
{ // Block for making variables locale to this scope.
- final GridPane gp = createControlGrid(
+ final GridPane gp = createControlGrid(0,
label(vocabulary, Vocabulary.Keys.Width,
createSlider(view.cellWidth, 30, 200)),
label(vocabulary, Vocabulary.Keys.Height,
createSlider(view.cellHeight, 10, 50)),
label(vocabulary, Vocabulary.Keys.Format,
view.cellFormat.createEditor())
);
- final Label label = new
Label(vocabulary.getLabel(Vocabulary.Keys.Cells));
- label.setPadding(CAPTION_MARGIN);
- label.setLabelFor(gp);
- displayPane = new VBox(label, gp);
+ displayPane = new VBox(labelOfGroup(vocabulary,
Vocabulary.Keys.Cells, gp, true), gp);
}
/*
* Put all sections together and have the first one expanded by
default.
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/RenderingData.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/RenderingData.java
index 8de11f5..1ef639e 100644
---
a/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/RenderingData.java
+++
b/application/sis-javafx/src/main/java/org/apache/sis/gui/coverage/RenderingData.java
@@ -195,7 +195,18 @@ final class RenderingData implements Cloneable {
}
/**
+ * Gets the interpolation method to use during resample operations.
+ *
+ * @see CoverageCanvas#getInterpolation()
+ */
+ final Interpolation getInterpolation() {
+ return processor.getInterpolation();
+ }
+
+ /**
* Sets the interpolation method to use during resample operations.
+ *
+ * @see CoverageCanvas#setInterpolation(Interpolation)
*/
final void setInterpolation(final Interpolation newValue) {
processor = processor.clone(); // Previous processor may be
in use by background thread.
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/gui/referencing/CRSChooser.java
b/application/sis-javafx/src/main/java/org/apache/sis/gui/referencing/CRSChooser.java
index 1a26e67..8ff7d95 100644
---
a/application/sis-javafx/src/main/java/org/apache/sis/gui/referencing/CRSChooser.java
+++
b/application/sis-javafx/src/main/java/org/apache/sis/gui/referencing/CRSChooser.java
@@ -224,7 +224,7 @@ public class CRSChooser extends
Dialog<CoordinateReferenceSystem> {
final Label ld = new
Label(vocabulary.getLabel(Vocabulary.Keys.Domain));
lt.setLabelFor(type = new Label());
ld.setLabelFor(domain = new Label());
- summary = Styles.createControlGrid(lt, ld);
+ summary = Styles.createControlGrid(0, lt, ld);
final Tooltip tp = new Tooltip();
tp.setShowDelay(Duration.seconds(0.5));
tp.setShowDuration(Duration.minutes(1));
diff --git
a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Styles.java
b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Styles.java
index 225d50e..d681eeb 100644
---
a/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Styles.java
+++
b/application/sis-javafx/src/main/java/org/apache/sis/internal/gui/Styles.java
@@ -165,10 +165,12 @@ public final class Styles extends Static {
* The controls must be associated to the given labels by {@link
Label#getLabelFor()}.
* If a label is {@code null}, then no row is created for that label.
*
+ * @param row index of the first row. If different than 0, then it
is caller responsibility
+ * to provide controls for all rows before the specified
index.
* @param controls (label, control) pairs to layout in rows.
* @return a pane with each (label, control) pair on a row.
*/
- public static GridPane createControlGrid(final Label... controls) {
+ public static GridPane createControlGrid(int row, final Label... controls)
{
final GridPane gp = new GridPane();
final ColumnConstraints labelColumn = new ColumnConstraints();
final ColumnConstraints controlColumn = new ColumnConstraints();
@@ -194,7 +196,6 @@ public final class Styles extends Static {
gp.setPadding(FORM_INSETS);
gp.setVgap(9);
gp.setHgap(9);
- int row = 0;
for (final Label label : controls) {
if (label != null) {
final Node control = label.getLabelFor();
diff --git
a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
index d670e6a..3e97eb0 100644
---
a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
+++
b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
@@ -135,6 +135,11 @@ public final class Vocabulary extends
IndexedResourceBundle {
public static final short BarometricAltitude = 16;
/**
+ * Bilinear
+ */
+ public static final short Bilinear = 230;
+
+ /**
* Black
*/
public static final short Black = 17;
@@ -590,6 +595,11 @@ public final class Vocabulary extends
IndexedResourceBundle {
public static final short Index = 106;
/**
+ * Interpolation
+ */
+ public static final short Interpolation = 231;
+
+ /**
* Invalid
*/
public static final short Invalid = 107;
@@ -755,6 +765,11 @@ public final class Vocabulary extends
IndexedResourceBundle {
public static final short Name = 139;
/**
+ * Nearest neighbor
+ */
+ public static final short NearestNeighbor = 232;
+
+ /**
* No data
*/
public static final short Nodata = 140;
diff --git
a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
index c3a53b0..6b157c2 100644
---
a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
+++
b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
@@ -30,6 +30,7 @@ Azimuth = Azimuth
Background = Background
Band_1 = Band {0}
BarometricAltitude = Barometric altitude
+Bilinear = Bilinear
Black = Black
Blue = Blue
Cardinality = Cardinality
@@ -121,6 +122,7 @@ ImageLayout = Image layout
Implementation = Implementation
InBetweenWords = \u2002in\u2002
Index = Index
+Interpolation = Interpolation
Invalid = Invalid
InverseOperation = Inverse operation
JavaExtensions = Java extensions
@@ -154,6 +156,7 @@ ModifiedJulian = Modified Julian
More_1 = \u2026 {0} more\u2026
Multiplicity = Multiplicity
Name = Name
+NearestNeighbor = Nearest neighbor
Nodata = No data
None = None
Note = Note
diff --git
a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
index f2eeb0e..0c89b49 100644
---
a/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
+++
b/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
@@ -37,6 +37,7 @@ Azimuth = Azimut
Background = Arri\u00e8re plan
Band_1 = Bande {0}
BarometricAltitude = Altitude barom\u00e9trique
+Bilinear = Bilin\u00e9aire
Black = Noir
Blue = Bleu
Cardinality = Cardinalit\u00e9
@@ -128,6 +129,7 @@ ImageLayout = Agencement de l\u2019image
Implementation = Impl\u00e9mentation
InBetweenWords = \u2002dans\u2002
Index = Index
+Interpolation = Interpolation
Invalid = Invalide
InverseOperation = Op\u00e9ration inverse
JavaExtensions = Extensions du Java
@@ -161,6 +163,7 @@ ModifiedJulian = Julien modifi\u00e9
More_1 = \u2026 {0} de plus\u2026
Multiplicity = Multiplicit\u00e9
Name = Nom
+NearestNeighbor = Plus proche voisin
Nodata = Absence de donn\u00e9es
None = Aucun
Note = Note