/* * Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) * any later version. * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see http://www.gnu.org/licenses/ */ package org.esa.snap.rcp.imgfilter; import org.esa.snap.core.datamodel.Band; import org.esa.snap.core.datamodel.ConvolutionFilterBand; import org.esa.snap.core.datamodel.FilterBand; import org.esa.snap.core.datamodel.GeneralFilterBand; import org.esa.snap.core.datamodel.Kernel; import org.esa.snap.core.datamodel.Product; import org.esa.snap.core.datamodel.ProductNode; import org.esa.snap.core.datamodel.RasterDataNode; import org.esa.snap.core.util.ProductUtils; import org.esa.snap.rcp.SnapApp; import org.esa.snap.rcp.actions.window.OpenImageViewAction; import org.esa.snap.rcp.imgfilter.model.Filter; import org.esa.snap.ui.ModalDialog; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; import org.openide.awt.ActionReferences; import org.openide.awt.ActionRegistration; import org.openide.util.ContextAwareAction; import org.openide.util.Lookup; import org.openide.util.LookupEvent; import org.openide.util.LookupListener; import org.openide.util.NbBundle; import org.openide.util.Utilities; import org.openide.util.WeakListeners; import javax.swing.AbstractAction; import javax.swing.Action; import java.awt.event.ActionEvent; import static org.esa.snap.rcp.SnapApp.SelectionSourceHint.*; @ActionID( category = "Tools", id = "FilteredBandAction" ) @ActionRegistration( displayName = "#CTL_FilteredBandAction_MenuText", popupText = "#CTL_FilteredBandAction_MenuText", lazy = false ) @ActionReferences({ @ActionReference(path = "Menu/Raster", position = 10), @ActionReference(path = "Context/Product/RasterDataNode", position = 40,separatorAfter = 45) }) @NbBundle.Messages({ "CTL_FilteredBandAction_MenuText=Filtered Band...", "CTL_FilteredBandAction_ShortDescription=Applies a filter to the currently selected band and adds it as a new band." }) public class FilteredBandAction extends AbstractAction implements LookupListener, ContextAwareAction { private Lookup lookup; private Lookup.Result<RasterDataNode> result; public FilteredBandAction() { this(Utilities.actionsGlobalContext()); } public FilteredBandAction(Lookup lookup){ super(Bundle.CTL_FilteredBandAction_MenuText()); this.lookup = lookup; result = lookup.lookupResult(RasterDataNode.class); result.addLookupListener(WeakListeners.create(LookupListener.class, this, result)); updateEnableState(this.lookup.lookup(RasterDataNode.class)); } @Override public Action createContextAwareInstance(Lookup actionContext) { return new FilteredBandAction(actionContext); } @Override public void resultChanged(LookupEvent ev) { updateEnableState(this.lookup.lookup(RasterDataNode.class)); } private void updateEnableState(RasterDataNode node) { //todo [multisize_products] compare scenerastertransform rather than size setEnabled(node != null); } @Override public void actionPerformed(ActionEvent e) { createFilteredBand(); } static GeneralFilterBand.OpType getOpType(Filter.Operation operation) { if (operation == Filter.Operation.OPEN) { return GeneralFilterBand.OpType.OPENING; } else if (operation == Filter.Operation.CLOSE) { return GeneralFilterBand.OpType.CLOSING; } else if (operation == Filter.Operation.ERODE) { return GeneralFilterBand.OpType.EROSION; } else if (operation == Filter.Operation.DILATE) { return GeneralFilterBand.OpType.DILATION; } else if (operation == Filter.Operation.MIN) { return GeneralFilterBand.OpType.MIN; } else if (operation == Filter.Operation.MAX) { return GeneralFilterBand.OpType.MAX; } else if (operation == Filter.Operation.MEAN) { return GeneralFilterBand.OpType.MEAN; } else if (operation == Filter.Operation.MEDIAN) { return GeneralFilterBand.OpType.MEDIAN; } else if (operation == Filter.Operation.STDDEV) { return GeneralFilterBand.OpType.STDDEV; } else { throw new IllegalArgumentException("illegal operation: " + operation); } } private void createFilteredBand() { RasterDataNode node = lookup.lookup(RasterDataNode.class); final CreateFilteredBandDialog.DialogData dialogData = promptForFilter(); if (dialogData == null) { return; } final FilterBand filterBand = getFilterBand(node, dialogData.getBandName(), dialogData.getFilter(), dialogData.getIterationCount()); OpenImageViewAction.openImageView(filterBand); } private static FilterBand getFilterBand(RasterDataNode sourceRaster, String bandName, Filter filter, int iterationCount) { FilterBand targetBand; Product targetProduct = sourceRaster.getProduct(); if (filter.getOperation() == Filter.Operation.CONVOLVE) { targetBand = new ConvolutionFilterBand(bandName, sourceRaster, getKernel(filter), iterationCount); if (sourceRaster instanceof Band) { ProductUtils.copySpectralBandProperties((Band) sourceRaster, targetBand); } } else { GeneralFilterBand.OpType opType = getOpType(filter.getOperation()); targetBand = new GeneralFilterBand(bandName, sourceRaster, opType, getKernel(filter), iterationCount); if (sourceRaster instanceof Band) { ProductUtils.copySpectralBandProperties((Band) sourceRaster, targetBand); } } targetBand.setDescription(String.format("Filter '%s' (=%s) applied to '%s'", filter.getName(), filter.getOperation(), sourceRaster.getName())); if (sourceRaster instanceof Band) { ProductUtils.copySpectralBandProperties((Band) sourceRaster, targetBand); } targetProduct.addBand(targetBand); ProductUtils.copyImageGeometry(sourceRaster, targetBand, false); targetBand.fireProductNodeDataChanged(); return targetBand; } private static Kernel getKernel(Filter filter) { return new Kernel(filter.getKernelWidth(), filter.getKernelHeight(), filter.getKernelOffsetX(), filter.getKernelOffsetY(), 1.0 / filter.getKernelQuotient(), filter.getKernelElements()); } private CreateFilteredBandDialog.DialogData promptForFilter() { final ProductNode selectedNode = SnapApp.getDefault().getSelectedProductNode(EXPLORER); final Product product = selectedNode.getProduct(); final CreateFilteredBandDialog dialog = new CreateFilteredBandDialog(product, selectedNode.getName(), "createFilteredBand"); if (dialog.show() == ModalDialog.ID_OK) { return dialog.getDialogData(); } return null; } }