use of org.geotoolkit.processing.coverage.resample.ResampleProcess in project geotoolkit by Geomatys.
the class KmzContextInterpreter method writeCoverageMapLayer.
/**
* Transforms a CoverageMapLayer into KML GroundOverlay.
*/
private Feature writeCoverageMapLayer(MapLayer coverageMapLayer) throws Exception {
final Feature groundOverlay = KML_FACTORY.createGroundOverlay();
final CoordinateReferenceSystem targetCrs = CommonCRS.WGS84.normalizedGeographic();
final GridCoverageResource ref = (GridCoverageResource) coverageMapLayer.getData();
final GridCoverage coverage = ref.read(null);
final GridCoverage targetCoverage = new ResampleProcess(coverage, targetCrs, null, InterpolationCase.NEIGHBOR, null).executeNow();
final Envelope envelope = targetCoverage.getGridGeometry().getEnvelope();
final CharSequence name = CoverageUtilities.getName(targetCoverage);
// Creating image file and Writting referenced image into.
final Path img = filesDirectory.resolve(name.toString() + ".png");
try (OutputStream outputStream = Files.newOutputStream(img, CREATE, WRITE, TRUNCATE_EXISTING)) {
ImageIO.write(targetCoverage.render(null), "png", outputStream);
}
final Icon image = KML_FACTORY.createIcon(KML_FACTORY.createLink());
image.setHref(filesDirectory.getFileName().toString() + File.separator + name);
groundOverlay.setPropertyValue(KmlConstants.TAG_NAME, name.toString());
groundOverlay.setPropertyValue(KmlConstants.TAG_ICON, image);
groundOverlay.setPropertyValue(KmlConstants.TAG_ALTITUDE, 1.0);
groundOverlay.setPropertyValue(KmlConstants.TAG_ALTITUDE_MODE, EnumAltitudeMode.CLAMP_TO_GROUND);
final LatLonBox latLonBox = KML_FACTORY.createLatLonBox();
latLonBox.setNorth(envelope.getMaximum(1));
latLonBox.setSouth(envelope.getMinimum(1));
latLonBox.setEast(envelope.getMaximum(0));
latLonBox.setWest(envelope.getMinimum(0));
groundOverlay.setPropertyValue(KmlConstants.TAG_LAT_LON_BOX, latLonBox);
return groundOverlay;
}
use of org.geotoolkit.processing.coverage.resample.ResampleProcess in project geotoolkit by Geomatys.
the class StraightenProcess method execute.
/**
* {@inheritDoc}
*/
@Override
protected void execute() throws ProcessException {
final GridCoverage candidate = inputParameters.getValue(StraightenDescriptor.COVERAGE_IN);
// resample coverage, we want it to be 'straight', no rotation or different axe scale.
final GridGeometry gridgeom = candidate.getGridGeometry();
final CoordinateReferenceSystem crs = gridgeom.getCoordinateReferenceSystem();
final GridExtent gridenv = gridgeom.getExtent();
final MathTransform gridToCRS = gridgeom.getGridToCRS(PixelInCell.CELL_CORNER);
try {
final double[] coords = new double[2 * 5];
coords[0] = gridenv.getLow(0);
coords[1] = gridenv.getLow(1);
coords[2] = gridenv.getLow(0);
coords[3] = gridenv.getHigh(1) + 1;
coords[4] = gridenv.getHigh(0) + 1;
coords[5] = gridenv.getHigh(1) + 1;
coords[6] = gridenv.getHigh(0) + 1;
coords[7] = gridenv.getLow(1);
coords[8] = gridenv.getHigh(0) + 2;
coords[9] = gridenv.getHigh(1) + 2;
gridToCRS.transform(coords, 0, coords, 0, 5);
double minX = Math.min(Math.min(coords[0], coords[2]), Math.min(coords[4], coords[6]));
double maxX = Math.max(Math.max(coords[0], coords[2]), Math.max(coords[4], coords[6]));
double minY = Math.min(Math.min(coords[1], coords[3]), Math.min(coords[5], coords[7]));
double maxY = Math.max(Math.max(coords[1], coords[3]), Math.max(coords[5], coords[7]));
double spanX = maxX - minX;
double spanY = maxY - minY;
double scaleX = spanX / gridenv.getSize(0);
double scaleY = spanY / gridenv.getSize(1);
double scale = Math.min(scaleX, scaleY);
if (coords[0] > coords[6]) {
// x axe flip
minX = Math.min(minX, coords[8]);
}
if (coords[1] < coords[3]) {
// y axe flip
maxY = Math.max(maxY, coords[9]);
}
final AffineTransform2D outGridToCRS = new AffineTransform2D(scale, 0, 0, -scale, minX, maxY);
final GridExtent gridEnv = new GridExtent((long) (spanX / scale), (long) (spanY / scale));
final GridGeometry outgridGeom = new GridGeometry(gridEnv, PixelInCell.CELL_CORNER, outGridToCRS, crs);
final GridCoverage outCoverage = new ResampleProcess(candidate, outgridGeom.getCoordinateReferenceSystem(), outgridGeom, InterpolationCase.NEIGHBOR, null).executeNow();
outputParameters.getOrCreate(StraightenDescriptor.COVERAGE_OUT).setValue(outCoverage);
} catch (TransformException ex) {
throw new ProcessException(ex.getMessage(), this, ex);
}
}
use of org.geotoolkit.processing.coverage.resample.ResampleProcess in project geotoolkit by Geomatys.
the class AbstractCoverageSymbolizerRenderer method getObjectiveCoverage.
/**
* Returns expected {@linkplain GridCoverage elevation coverage} or {@linkplain GridCoverage coverage}
* from given {@link ProjectedCoverage}.
*
* TODO: add a margin or interpolation parameter. To properly interpolate border on output canvas, we need extra
* lines/columns on source image. Their number depends on applied interpolation (bilinear, bicubic, etc.).
*
* @param ref coverage resource
* @param canvasGrid Rendering canvas grid geometry
* @param isElevation {@code true} if we want elevation coverage, else ({@code false}) for features coverage.
* @param sourceBands coverage source bands to features
* @return expected {@linkplain GridCoverage elevation coverage} or {@linkplain GridCoverage coverage}
* @throws org.geotoolkit.coverage.io.CoverageStoreException if problem during coverage reading.
* @throws org.opengis.referencing.operation.TransformException if problem during {@link Envelope} transformation.
* @throws org.opengis.util.FactoryException if problem during {@link Envelope} study.
* @throws org.geotoolkit.process.ProcessException if problem during resampling processing.
* @see ProjectedCoverage#getElevationCoverage(org.geotoolkit.coverage.io.GridCoverageReadParam)
* @see ProjectedCoverage#getCoverage(org.geotoolkit.coverage.io.GridCoverageReadParam)
*/
protected GridCoverage getObjectiveCoverage(final GridCoverageResource ref, GridGeometry canvasGrid, final boolean isElevation, int[] sourceBands) throws DataStoreException, TransformException, FactoryException, ProcessException {
ArgumentChecks.ensureNonNull("projectedCoverage", ref);
final InterpolationCase interpolation = InterpolationCase.BILINEAR;
final GridGeometry refGG = ref.getGridGeometry();
// fast envelope intersection in 2D
if (refGG.isDefined(GridGeometry.ENVELOPE)) {
Envelope bbox = renderingContext.getCanvasObjectiveBounds2D();
Envelope refEnv = Envelopes.transform(refGG.getEnvelope(), bbox.getCoordinateReferenceSystem());
if (!AbstractEnvelope.castOrCopy(bbox).intersects(refEnv, true)) {
throw new DisjointExtentException("Coverage resource envelope do not intersect canvas");
}
}
final GridGeometry baseGG = trySubGrid(refGG, canvasGrid);
final GridGeometry slice = extractSlice(baseGG, canvasGrid, computeMargin2D(interpolation), true);
if (sourceBands != null && sourceBands.length < 1)
sourceBands = null;
GridCoverage coverage = ref.read(slice, sourceBands);
if (coverage instanceof GridCoverageStack) {
Logger.getLogger("org.geotoolkit.display2d.primitive").log(Level.WARNING, "Coverage reader return more than one slice.");
}
while (coverage instanceof GridCoverageStack) {
// pick the first slice
coverage = ((GridCoverageStack) coverage).coverageAtIndex(0);
}
// we remove all other dimension to simplify any following operation
if (coverage.getCoordinateReferenceSystem().getCoordinateSystem().getDimension() > 2) {
coverage = new ReducedGridCoverage(coverage, 0, 1);
}
final CoordinateReferenceSystem crs2d = CRS.getHorizontalComponent(canvasGrid.getCoordinateReferenceSystem());
if (Utilities.equalsIgnoreMetadata(crs2d, coverage.getCoordinateReferenceSystem())) {
return coverage;
} else {
coverage = prepareCoverageToResampling(coverage, symbol);
// resample
final double[] fill = new double[coverage.getSampleDimensions().size()];
Arrays.fill(fill, Double.NaN);
// ///// HACK FOR 0/360 /////////////////////////////////////////
GeneralEnvelope ge = new GeneralEnvelope(coverage.getGridGeometry().getEnvelope());
try {
GeneralEnvelope cdt = GeneralEnvelope.castOrCopy(Envelopes.transform(coverage.getGridGeometry().getEnvelope(), CommonCRS.WGS84.normalizedGeographic()));
cdt.normalize();
if (!cdt.isEmpty()) {
ge = cdt;
}
} catch (ProjectionException ex) {
LOGGER.log(Level.INFO, ex.getMessage(), ex);
}
GridGeometry resampleGrid = canvasGrid;
try {
resampleGrid = resampleGrid.derive().rounding(GridRoundingMode.ENCLOSING).subgrid(ge).build().reduce(0, 1);
} catch (DisjointExtentException ex) {
// don't log, still continue
} catch (IllegalGridGeometryException ex) {
LOGGER.log(Level.INFO, ex.getMessage(), ex);
}
resampleGrid = CoverageUtilities.forceLowerToZero(resampleGrid);
// ///// HACK FOR 0/360 /////////////////////////////////////////
final MathTransform gridToCRS = coverage.getGridGeometry().getGridToCRS(PixelInCell.CELL_CENTER);
if (isNonLinear(gridToCRS)) {
final GridGeometry slice2 = extractSlice(refGG, canvasGrid, computeMargin2D(interpolation), false);
coverage = ref.read(slice2, sourceBands);
// we remove all other dimension to simplify any following operation
if (coverage.getCoordinateReferenceSystem().getCoordinateSystem().getDimension() > 2) {
coverage = new ReducedGridCoverage(coverage, 0, 1);
}
return forwardResample(coverage, resampleGrid);
} else {
ResampleProcess process = new ResampleProcess(coverage, crs2d, resampleGrid, interpolation, fill);
// do not extrapolate values, can cause large areas of incorrect values
process.getInput().parameter(ResampleDescriptor.IN_BORDER_COMPORTEMENT_TYPE.getName().getCode()).setValue(ResampleBorderComportement.FILL_VALUE);
return process.executeNow();
}
}
}
use of org.geotoolkit.processing.coverage.resample.ResampleProcess in project geotoolkit by Geomatys.
the class PatternRenderer method presentations.
@Override
public Stream<Presentation> presentations(MapLayer layer, Resource resource) {
if (!(resource instanceof GridCoverageResource)) {
return Stream.empty();
}
final GridCoverageResource gcr = (GridCoverageResource) resource;
GridCoverage dataCoverage;
try {
dataCoverage = gcr.read(renderingContext.getGridGeometry());
} catch (NoSuchDataException ex) {
return Stream.empty();
} catch (DataStoreException ex) {
ExceptionPresentation ep = new ExceptionPresentation(ex);
ep.setLayer(layer);
ep.setResource(resource);
return Stream.of(ep);
}
if (!Utilities.equalsIgnoreMetadata(CRS.getHorizontalComponent(dataCoverage.getCoordinateReferenceSystem()), renderingContext.getObjectiveCRS())) {
// coverage is not in objective crs, resample it
try {
// we resample the native view of the coverage only, the style will be applied later.
dataCoverage = new ResampleProcess(dataCoverage, renderingContext.getObjectiveCRS(), null, InterpolationCase.NEIGHBOR, null).executeNow();
} catch (Exception ex) {
LOGGER.log(Level.WARNING, "ERROR resample in raster symbolizer renderer", ex);
}
}
final Map.Entry<FeatureSet, MutableStyle> entry;
try {
entry = symbol.getMasks(dataCoverage);
} catch (IOException | TransformException ex) {
ExceptionPresentation ep = new ExceptionPresentation(ex);
ep.setLayer(layer);
ep.setResource(resource);
return Stream.of(ep);
}
final MapLayer subLayer = MapBuilder.createLayer(entry.getKey());
subLayer.setStyle(entry.getValue());
return DefaultPortrayalService.present(subLayer, entry.getKey(), renderingContext);
}
use of org.geotoolkit.processing.coverage.resample.ResampleProcess in project geotoolkit by Geomatys.
the class RasterPresentation method renderCoverage.
private boolean renderCoverage(RenderingContext2D renderingContext, org.apache.sis.coverage.grid.GridCoverage coverage, MathTransform trs2D) throws PortrayalException {
final Graphics2D g2d = renderingContext.getGraphics();
final CanvasMonitor monitor = renderingContext.getMonitor();
boolean dataRendered = false;
RenderedImage img = coverage.render(null);
/*
* Try to prefetch image before rendering
* resampled image or mosaic have deferred tiles
* java2d render tiles one by one which can be slow when working with
* computed coverages or distant services like WMTS or TMS
*/
if ((img.getWidth() * img.getHeight()) < 5000 * 5000) {
ImageProcessor processor = new ImageProcessor();
processor.setExecutionMode(ImageProcessor.Mode.PARALLEL);
img = processor.prefetch(img, null);
}
final InterpolationCase interpolationCase = (InterpolationCase) renderingContext.getRenderingHints().get(GO2Hints.KEY_INTERPOLATION);
if (interpolationCase != null) {
switch(interpolationCase) {
case NEIGHBOR:
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
break;
case BILINEAR:
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
break;
case BICUBIC:
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
break;
default:
// resample image ourself
try {
GridCoverage cov = new ResampleProcess(coverage, renderingContext.getGridGeometry().getCoordinateReferenceSystem(), renderingContext.getGridGeometry2D(), interpolationCase, null).executeNow();
trs2D = renderingTransform(cov.getGridGeometry());
img = cov.render(null);
} catch (ProcessException ex) {
throw new PortrayalException(ex);
}
break;
}
}
if (trs2D instanceof AffineTransform) {
try {
g2d.drawRenderedImage(RenderingWorkaround.wrap(img), (AffineTransform) trs2D);
dataRendered = true;
} catch (Exception ex) {
final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter(sw);
ex.printStackTrace(pw);
if (ex instanceof ArrayIndexOutOfBoundsException) {
// we can recover when it's an inapropriate componentcolormodel
final StackTraceElement[] eles = ex.getStackTrace();
if (eles.length > 0 && ComponentColorModel.class.getName().equalsIgnoreCase(eles[0].getClassName())) {
try {
final Map<String, Object> analyze = StatisticOp.analyze(img);
final double[] minArray = (double[]) analyze.get(StatisticOp.MINIMUM);
final double[] maxArray = (double[]) analyze.get(StatisticOp.MAXIMUM);
final double min = findExtremum(minArray, true);
final double max = findExtremum(maxArray, false);
final List<InterpolationPoint> values = new ArrayList<>();
values.add(new DefaultInterpolationPoint(Double.NaN, GO2Utilities.STYLE_FACTORY.literal(new Color(0, 0, 0, 0))));
values.add(new DefaultInterpolationPoint(min, GO2Utilities.STYLE_FACTORY.literal(Color.BLACK)));
values.add(new DefaultInterpolationPoint(max, GO2Utilities.STYLE_FACTORY.literal(Color.WHITE)));
final Literal lookup = StyleConstants.DEFAULT_CATEGORIZE_LOOKUP;
final Literal fallback = StyleConstants.DEFAULT_FALLBACK;
final Expression function = GO2Utilities.STYLE_FACTORY.interpolateFunction(lookup, values, Method.COLOR, Mode.LINEAR, fallback);
final CompatibleColorModel model = new CompatibleColorModel(img.getColorModel().getPixelSize(), function);
final ImageLayout layout = new ImageLayout().setColorModel(model);
img = new NullOpImage(img, layout, null, OpImage.OP_COMPUTE_BOUND);
g2d.drawRenderedImage(RenderingWorkaround.wrap(img), (AffineTransform) trs2D);
dataRendered = true;
} catch (Exception e) {
// plenty of errors can happen when painting an image
monitor.exceptionOccured(e, Level.WARNING);
// raise the original error
monitor.exceptionOccured(ex, Level.WARNING);
}
} else {
// plenty of errors can happen when painting an image
monitor.exceptionOccured(ex, Level.WARNING);
}
} else {
// plenty of errors can happen when painting an image
monitor.exceptionOccured(ex, Level.WARNING);
}
}
} else if (trs2D instanceof LinearTransform) {
final LinearTransform lt = (LinearTransform) trs2D;
final int col = lt.getMatrix().getNumCol();
final int row = lt.getMatrix().getNumRow();
// TODO using only the first parameters of the linear transform
throw new PortrayalException("Could not render image, GridToCRS is a not an AffineTransform, found a " + trs2D.getClass());
} else {
throw new PortrayalException("Could not render image, GridToCRS is a not an AffineTransform, found a " + trs2D.getClass());
}
return dataRendered;
}
Aggregations