/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2016, 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.gce.imagemosaic.egr; import java.awt.Rectangle; import java.awt.image.RenderedImage; import java.util.ArrayList; import java.util.List; import javax.media.jai.ROI; import javax.media.jai.ROIShape; import org.geotools.gce.imagemosaic.GranuleDescriptor; import org.geotools.gce.imagemosaic.GranuleDescriptor.GranuleLoadingResult; import org.geotools.geometry.jts.JTS; import org.geotools.referencing.CRS; import org.opengis.referencing.crs.CoordinateReferenceSystem; /** * Support class helping to remove images not contributing pixels to the final mosaic based on the image ROIs (thus, working in raster space after the * images are read) * * @author Andrea Aime - GeoSolutions * */ public class ROIExcessGranuleRemover { /** * Default size for excess granule removal tiles */ public static final int DEFAULT_TILE_SIZE = 256; Binarizator binarizator; Rectangle rasterBounds; int tileWidth; int tileHeight; CoordinateReferenceSystem targetCRS; /** * Holds the granule loading results until it becomes evident actual geometric computation is needed */ List<ROI> roiBuffer = new ArrayList<ROI>(); public ROIExcessGranuleRemover(Rectangle rasterBounds, int tileWidth, int tileHeight, CoordinateReferenceSystem targetCRS) { this.rasterBounds = rasterBounds; this.tileWidth = tileWidth; this.tileHeight = tileHeight; this.targetCRS = targetCRS; } public boolean addGranule(GranuleLoadingResult result) { // check we are working in the uniform CRS case CoordinateReferenceSystem granuleCRS = result.getGranuleDescriptor().getGranuleEnvelope() .getCoordinateReferenceSystem(); if (granuleCRS != null && targetCRS != null && !CRS.equalsIgnoreMetadata(granuleCRS, targetCRS)) { throw new UnsupportedOperationException( "Excess granule removal not yet supported with heterogeneous CRS"); } // early bail out if possible if (binarizator != null && binarizator.isComplete()) { return false; } // get the ROI ROI roi = result.getFootprint(); if (roi == null) { // TODO: check if the image has some form transparency (alpha band, palette // with fully transparent pixels), binarize it and use it as a ROI? final RenderedImage raster = result.getRaster(); Rectangle bounds = new Rectangle(raster.getMinX(), raster.getMinY(), raster.getWidth(), raster.getHeight()); roi = new ROIShape(bounds); } boolean essential; if (!roi.getBounds().intersects(rasterBounds)) { essential = false; } else { if (binarizator == null) { binarizator = new Binarizator(JTS.toPolygon(rasterBounds), rasterBounds.width, rasterBounds.height, tileWidth, tileHeight); } essential = binarizator.add(roi); } return essential; } /** * Returns true if the rendering area is complete * * @return */ public boolean isRenderingAreaComplete() { // TODO: handle case in which the binarization is not yet generated? Like single tile // covering everything? return binarizator != null && binarizator.isComplete(); } }