/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2017, Open Source Geospatial Foundation (OSGeo) * * 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.geotools.process.raster; import java.awt.RenderingHints; import java.awt.image.RenderedImage; import javax.media.jai.RenderedOp; import javax.media.jai.operator.ExtremaDescriptor; import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.coverage.processing.CoverageProcessor; import org.geotools.process.ProcessException; import org.geotools.process.factory.DescribeParameter; import org.geotools.process.factory.DescribeProcess; import org.geotools.process.factory.DescribeResult; import org.geotools.renderer.i18n.Errors; import org.geotools.resources.i18n.ErrorKeys; import org.geotools.resources.image.ImageUtilities; import org.opengis.parameter.ParameterValueGroup; import org.opengis.util.ProgressListener; /** * A transparency holes-dashes filling process * * @author Daniele Romagnoli - GeoSolutions * * @source $URL$ */ @DescribeProcess(title = "TransparencyFill", description = "Fill transparent pixels") public class TransparencyFillProcess implements RasterProcess { private static final CoverageProcessor PROCESSOR = CoverageProcessor.getInstance(); @DescribeResult(name = "result", description = "The processed coverage") public GridCoverage2D execute( @DescribeParameter(name = "data", description = "Input coverage") GridCoverage2D coverage, // @DescribeParameter(name = "type", description = "Type of filling algorithm", min = 0) FillType type, ProgressListener listener) throws ProcessException { if (coverage == null) { throw new ProcessException(Errors.format(ErrorKeys.NULL_ARGUMENT_$1, "coverage")); } RenderedImage ri = coverage.getRenderedImage(); // If no transparency is involved, no need to do the checks boolean hasTransparency = ri != null ? ri.getColorModel().hasAlpha() : false; if (!hasTransparency) { return coverage; } int numBands = ri.getSampleModel().getNumBands(); RenderingHints renderingHints = null; if (numBands == 4 || numBands == 2) { // Looking for statistics on alpha channel renderingHints = ImageUtilities.getRenderingHints(ri); RenderedOp extremaOp = ExtremaDescriptor.create(ri, null, 1, 1, false, 1, renderingHints); double[][] extrema = (double[][]) extremaOp.getProperty("Extrema"); double[] mins = extrema[0]; // check if alpha is 255 on every pixel (fully opaque) hasTransparency = !(mins[mins.length - 1] == 255); // fully opaque } if (!hasTransparency) { return coverage; } // Do the transparency fill operation final ParameterValueGroup param = PROCESSOR.getOperation("TransparencyFill") .getParameters(); param.parameter("source").setValue(coverage); // if (type != null && type instanceof FillType) { // param.parameter("type").setValue(type); // } return (GridCoverage2D) PROCESSOR.doOperation(param); } }