/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2015, Geomatys * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotoolkit.gui.javafx.style.dynamicrange; import java.awt.image.RenderedImage; import java.util.List; import java.util.logging.Level; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.scene.control.ChoiceBox; import org.geotoolkit.coverage.GridSampleDimension; import org.geotoolkit.coverage.grid.GeneralGridGeometry; import org.geotoolkit.coverage.grid.GridCoverage2D; import org.geotoolkit.coverage.io.CoverageStoreException; import org.geotoolkit.coverage.io.GridCoverageReadParam; import org.geotoolkit.coverage.io.GridCoverageReader; import org.geotoolkit.display2d.ext.dynamicrange.DynamicRangeSymbolizer; import org.geotoolkit.gui.javafx.style.FXStyleElementController; import org.geotoolkit.map.CoverageMapLayer; import org.geotoolkit.map.MapLayer; import org.geotoolkit.storage.coverage.CoverageReference; import org.opengis.geometry.Envelope; import org.apache.sis.util.logging.Logging; import org.geotoolkit.display2d.GO2Utilities; /** * * @author Johann Sorel (Geomatys) */ public class FXDRChannel extends FXStyleElementController<DynamicRangeSymbolizer.DRChannel> { @FXML private ChoiceBox<String> uiBands; @FXML private ChoiceBox<String> uiCsComponent; @FXML private FXDRBound uiLower; @FXML private FXDRBound uiUpper; @Override public Class<DynamicRangeSymbolizer.DRChannel> getEditedClass() { return DynamicRangeSymbolizer.DRChannel.class; } public void lock(String csc){ uiCsComponent.valueProperty().setValue(csc); uiCsComponent.setDisable(true); } @Override public DynamicRangeSymbolizer.DRChannel newValue() { return new DynamicRangeSymbolizer.DRChannel(); } @Override public void initialize() { super.initialize(); uiCsComponent.setItems(FXCollections.observableArrayList( DynamicRangeSymbolizer.DRChannel.BAND_RED, DynamicRangeSymbolizer.DRChannel.BAND_GREEN, DynamicRangeSymbolizer.DRChannel.BAND_BLUE, DynamicRangeSymbolizer.DRChannel.BAND_ALPHA )); valueProperty().set(new DynamicRangeSymbolizer.DRChannel()); final ChangeListener changeListener = (ChangeListener) (ObservableValue observable, Object oldValue, Object newValue) -> { if(updating) return; final DynamicRangeSymbolizer.DRChannel element = new DynamicRangeSymbolizer.DRChannel(); element.setBand(uiBands.valueProperty().get()); element.setColorSpaceComponent(uiCsComponent.valueProperty().get()); element.setLower(uiLower.valueProperty().get()); element.setUpper(uiUpper.valueProperty().get()); value.set(element); }; uiBands.valueProperty().addListener(changeListener); uiCsComponent.valueProperty().addListener(changeListener); uiLower.valueProperty().addListener(changeListener); uiUpper.valueProperty().addListener(changeListener); } @Override protected void updateEditor(DynamicRangeSymbolizer.DRChannel styleElement) { if(styleElement!=null){ uiBands.valueProperty().setValue(styleElement.getBand()); uiCsComponent.valueProperty().setValue(styleElement.getColorSpaceComponent()); uiLower.valueProperty().setValue(styleElement.getLower()); uiUpper.valueProperty().setValue(styleElement.getUpper()); } } @Override public void setLayer(MapLayer layer) { super.setLayer(layer); uiLower.setLayer(layer); uiUpper.setLayer(layer); if(layer instanceof CoverageMapLayer){ final CoverageMapLayer cml = (CoverageMapLayer) layer; final CoverageReference ref = cml.getCoverageReference(); GridCoverageReader reader = null; try { reader = ref.acquireReader(); final List<GridSampleDimension> dims = reader.getSampleDimensions(ref.getImageIndex()); final int nbdim; if(dims==null){ //read a very low resolution image to extract bands from it final GeneralGridGeometry gg = reader.getGridGeometry(ref.getImageIndex()); final Envelope env = gg.getEnvelope(); final double[] res = gg.getResolution(); for(int i=0;i<res.length;i++){ res[i] = env.getSpan(i); } final GridCoverageReadParam params = new GridCoverageReadParam(); params.setEnvelope(env); params.setResolution(res); final GridCoverage2D cov = (GridCoverage2D) reader.read(ref.getImageIndex(), params); final RenderedImage ri = cov.getRenderedImage(); nbdim = ri.getSampleModel().getNumBands(); }else{ nbdim = dims.size(); } final ObservableList<String> bvals = FXCollections.observableArrayList(); bvals.add("none"); for(int i=0;i<nbdim;i++){ bvals.add(""+i); } uiBands.setItems(bvals); ref.recycle(reader); } catch (CoverageStoreException ex) { Logging.getLogger("org.geotoolkit.gui.javafx.style.dynamicrange").log(Level.SEVERE, null, ex); } finally{ if(reader!=null) ref.recycle(reader); } } } /** * Try to find best values for band and min/max. */ public void fitToData(){ final MapLayer cml = getLayer(); if(cml instanceof CoverageMapLayer){ final CoverageReference ref = ((CoverageMapLayer)cml).getCoverageReference(); GridCoverageReader reader = null; try { reader = ref.acquireReader(); List<GridSampleDimension> dims = reader.getSampleDimensions(ref.getImageIndex()); final int nbdim; if(dims==null){ //read a very low resolution image to extract bands from it final GeneralGridGeometry gg = reader.getGridGeometry(ref.getImageIndex()); final Envelope env = gg.getEnvelope(); final double[] res = gg.getResolution(); for(int i=0;i<res.length;i++){ res[i] = env.getSpan(i); } final GridCoverageReadParam params = new GridCoverageReadParam(); params.setEnvelope(env); params.setResolution(res); final GridCoverage2D cov = (GridCoverage2D) reader.read(ref.getImageIndex(), params); final RenderedImage ri = cov.getRenderedImage(); nbdim = ri.getSampleModel().getNumBands(); }else{ nbdim = dims.size(); } //find best match band index int index = 0; switch (uiCsComponent.getValue()) { case DynamicRangeSymbolizer.DRChannel.BAND_RED: index = 0; break; case DynamicRangeSymbolizer.DRChannel.BAND_GREEN: index = 1; break; case DynamicRangeSymbolizer.DRChannel.BAND_BLUE: index = 2; break; case DynamicRangeSymbolizer.DRChannel.BAND_ALPHA: index = 3; break; } if(index>=nbdim) index = 0; uiBands.setValue(""+index); //extract band min/max double min = 0; double max = 255; if(dims!=null){ final GridSampleDimension sd = dims.get(index); min = sd.getMinimumValue(); max = sd.getMaximumValue(); } final DynamicRangeSymbolizer.DRBound boundMin = new DynamicRangeSymbolizer.DRBound(); boundMin.setMode(DynamicRangeSymbolizer.DRBound.MODE_EXPRESSION); boundMin.setValue(GO2Utilities.FILTER_FACTORY.literal(min)); valueProperty().get().setLower(boundMin); uiLower.valueProperty().setValue(boundMin); final DynamicRangeSymbolizer.DRBound boundMax = new DynamicRangeSymbolizer.DRBound(); boundMax.setMode(DynamicRangeSymbolizer.DRBound.MODE_EXPRESSION); boundMax.setValue(GO2Utilities.FILTER_FACTORY.literal(max)); valueProperty().get().setUpper(boundMax); uiUpper.valueProperty().setValue(boundMax); } catch (CoverageStoreException ex) { Logging.getLogger("org.geotoolkit.gui.javafx.style.dynamicrange").log(Level.SEVERE, null, ex); } finally{ if(reader!=null) ref.recycle(reader); } } } }