Skip to content

Commit

Permalink
[GEOT-5615] Make sure image mosaic does not generate raster images wi…
Browse files Browse the repository at this point in the history
…th very high raster coordinate values
  • Loading branch information
aaime committed Jan 16, 2017
1 parent 494428a commit d83e5d3
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 34 deletions.
Expand Up @@ -18,6 +18,7 @@

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.image.*;
import java.io.IOException;
import java.lang.reflect.Constructor;
Expand Down Expand Up @@ -720,23 +721,36 @@ private void initTransformations() throws Exception {
// compute final world to grid
// base grid to world for the center of pixels
final AffineTransform g2w;
final SpatialRequestHelper spatialRequestHelper = request.spatialRequestHelper;
if (!request.isHeterogeneousGranules()) {
final OverviewLevel baseLevel = rasterManager.overviewsController.resolutionsLevels
.get(0);
final OverviewLevel selectedLevel = rasterManager.overviewsController.resolutionsLevels
.get(imageChoice);
final double resX = baseLevel.resolutionX;
final double resY = baseLevel.resolutionY;
final double[] requestRes = request.spatialRequestHelper.getComputedResolution();

g2w = new AffineTransform((AffineTransform) baseGridToWorld);
final double[] requestRes = spatialRequestHelper.getComputedResolution();

BoundingBox computedBBox = spatialRequestHelper.getComputedBBox();
GeneralEnvelope requestedRasterArea = CRS.transform(baseGridToWorld.inverse(), computedBBox);
double minxRaster = Math.round(requestedRasterArea.getMinimum(0));
double minyRaster = Math.round(requestedRasterArea.getMinimum(1));

// rebase the grid to world location to a position close to the requested one to
// avoid JAI playing with very large raster coordinates
// This can be done because the final computation generates the coordinates of the
// output coverage based on the output raster bounds and this very transform
final AffineTransform at = (AffineTransform) baseGridToWorld;
Point2D src = new Point2D.Double(minxRaster, minyRaster);
Point2D dst = new Point2D.Double();
at.transform(src, dst);
g2w = new AffineTransform(at.getScaleX(), at.getShearX(), at.getShearY(), at.getScaleY(), dst.getX(), dst.getY());
g2w.concatenate(CoverageUtilities.CENTER_TO_CORNER);

if ((requestRes[0] < resX || requestRes[1] < resY)) {
// Using the best available resolution
oversampledRequest = true;
} else {

// SG going back to working on a per level basis to do the composition
// g2w = new AffineTransform(request.getRequestedGridToWorld());
g2w.concatenate(AffineTransform.getScaleInstance(selectedLevel.scaleFactor,
Expand All @@ -746,9 +760,7 @@ private void initTransformations() throws Exception {
baseReadParameters.getSourceYSubsampling()));
}
} else {
g2w = new AffineTransform(request.spatialRequestHelper.isNeedsReprojection()
? request.spatialRequestHelper.getComputedGridToWorld()
: request.spatialRequestHelper.getComputedGridToWorld());
g2w = new AffineTransform(spatialRequestHelper.getComputedGridToWorld());
g2w.concatenate(CoverageUtilities.CENTER_TO_CORNER);
}
// move it to the corner
Expand Down
Expand Up @@ -24,6 +24,7 @@
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.Transparency;
import java.awt.geom.Point2D;
import java.awt.image.Raster;
import java.awt.image.RenderedImage;
import java.io.File;
Expand Down Expand Up @@ -411,7 +412,7 @@ public void testInsetsFull() throws Exception {
// check the footprints have been applied by pocking the output image
pixel = new byte[4];
// Close to San Marino, black if we have the insets
coverage.evaluate(tr.transform(new DirectPosition2D(coverage.getRenderedImage().getMinX(),coverage.getRenderedImage().getMinY()),null), pixel);
coverage.evaluate(new DirectPosition2D(coverage.getEnvelope().getMinimum(0) + 1e-3, coverage.getEnvelope().getMinimum(1) + 1e-3), pixel);

assertEquals(0, pixel[0]);
assertEquals(0, pixel[1]);
Expand Down Expand Up @@ -467,7 +468,7 @@ public void testInsetsMargin() throws Exception {
jaiImageRead.setValue(false);
params[1] = jaiImageRead;

// GridGeometry, small aread at the upper right corner
// GridGeometry, small read at the upper right corner
final GridEnvelope2D ge2D= new GridEnvelope2D(
reader.getOriginalGridRange().getHigh(0)-3,
reader.getOriginalGridRange().getLow(1),
Expand All @@ -486,8 +487,7 @@ public void testInsetsMargin() throws Exception {
// check the footprints have been applied by pocking the output image
pixel = new byte[4];
// Close to San Marino, black if we have the insets
coverage.evaluate(tr.transform(new DirectPosition2D(coverage.getRenderedImage().getMinX(),coverage.getRenderedImage().getMinY()),null), pixel);
// RenderedImageBrowser.showChain(coverage.getRenderedImage());
coverage.evaluate(new DirectPosition2D(coverage.getEnvelope().getMinimum(0) + 1e-3 ,coverage.getEnvelope().getMinimum(1) + 1e-3), pixel);
assertEquals(0, pixel[0]);
assertEquals(0, pixel[1]);
assertEquals(0, pixel[2]);
Expand Down
Expand Up @@ -19,16 +19,11 @@
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.CoreMatchers.is;

import it.geosolutions.imageio.pam.PAMDataset;
import it.geosolutions.imageio.pam.PAMDataset.PAMRasterBand;
import it.geosolutions.imageio.pam.PAMParser;
import it.geosolutions.imageio.utilities.ImageIOUtilities;
import it.geosolutions.jaiext.JAIExt;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.color.ColorSpace;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
Expand Down Expand Up @@ -71,9 +66,6 @@
import javax.media.jai.RenderedOp;
import javax.swing.JFrame;

import junit.framework.JUnit4TestAdapter;
import junit.textui.TestRunner;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
Expand Down Expand Up @@ -106,6 +98,7 @@
import org.geotools.factory.Hints;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.filter.text.ecql.ECQL;
import org.geotools.gce.geotiff.GeoTiffWriter;
import org.geotools.gce.imagemosaic.Utils.Prop;
import org.geotools.gce.imagemosaic.catalog.GranuleCatalog;
import org.geotools.gce.imagemosaic.catalog.index.Indexer;
Expand Down Expand Up @@ -154,6 +147,14 @@
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LinearRing;

import it.geosolutions.imageio.pam.PAMDataset;
import it.geosolutions.imageio.pam.PAMDataset.PAMRasterBand;
import it.geosolutions.imageio.pam.PAMParser;
import it.geosolutions.imageio.utilities.ImageIOUtilities;
import it.geosolutions.jaiext.JAIExt;
import junit.framework.JUnit4TestAdapter;
import junit.textui.TestRunner;

/**
* Testing {@link ImageMosaicReader}.
*
Expand Down Expand Up @@ -1939,11 +1940,26 @@ private void imageMosaicCropTest(URL testURL, String title)
outTransp.setValue(Color.black);


// test the coverage
TestUtils.checkCoverage(reader, new GeneralParameterValue[] { gg, outTransp },title);

final double[] baseResolutions = reader.getResolutionLevels()[0];
// test the coverage
final double tolerance = Math.max(baseResolutions[0], baseResolutions[1]) * 10;
GridCoverage2D coverage = TestUtils.checkCoverage(reader,
new GeneralParameterValue[] { gg, outTransp }, title);
// the envelope is the requested one
assertEnvelope(coverage.getEnvelope(), cropEnvelope, tolerance);
// the raster space ordinates are not far away from the origin
RenderedImage ri = coverage.getRenderedImage();
assertEquals(0, ri.getMinX(), 10);
assertEquals(0, ri.getMinY(), 10);
}

void assertEnvelope(Envelope expected, Envelope actual, double tolerance) {
assertEquals(expected.getMinimum(0), actual.getMinimum(0), tolerance);
assertEquals(expected.getMaximum(0), actual.getMaximum(0), tolerance);
assertEquals(expected.getMinimum(1), actual.getMinimum(1), tolerance);
assertEquals(expected.getMaximum(1), actual.getMaximum(1), tolerance);
}

@Test
//@Ignore
public void testRequestInHole() throws Exception {
Expand All @@ -1968,10 +1984,8 @@ public void testRequestInHole() throws Exception {
assertTrue(coverage.getEnvelope2D().intersects((Rectangle2D) env));

// and that the color is the expected one given the background values provided
RenderedImage ri = coverage.getRenderedImage();
int[] pixel = new int[4];
Raster tile = ri.getTile(ri.getMinTileX(), ri.getMinTileY());
tile.getPixel(411, 87, pixel);
coverage.evaluate(new Point2D.Double(497987,3197819), pixel);
assertEquals(255, pixel[0]);
assertEquals(0, pixel[1]);
assertEquals(0, pixel[2]);
Expand Down Expand Up @@ -2000,14 +2014,12 @@ public void testRequestInOut() throws Exception {
// read and check we actually got a coverage in the requested area
GridCoverage2D coverage = reader.read(new GeneralParameterValue[] {ggp, bgp});
assertNotNull(coverage);
assertTrue(coverage.getEnvelope2D().contains((Rectangle2D) env));
final Envelope2D envelope2d = coverage.getEnvelope2D();
assertTrue(envelope2d.contains((Rectangle2D) env));

// and that the color is the expected one given the background values provided
RenderedImage ri = coverage.getRenderedImage();
int[] pixel = new int[4];
Raster tile = ri.getTile(ri.getMinTileX() + ri.getNumXTiles() - 1,
ri.getMinTileY() + ri.getNumYTiles() - 1);
tile.getPixel(410, 120, pixel);
coverage.evaluate(new Point2D.Double(430000, 2700000), pixel);
assertEquals(255, pixel[0]);
assertEquals(0, pixel[1]);
assertEquals(0, pixel[2]);
Expand Down Expand Up @@ -2035,16 +2047,15 @@ public void testRequestInAreaWithNoGranulesBecomesTransparent() throws Exception
// read and check we actually got a coverage in the requested area
GridCoverage2D coverage = reader.read(new GeneralParameterValue[] {ggp, transparent});
assertNotNull(coverage);
new GeoTiffWriter(new File("/tmp/test.tiff")).write(coverage, null);
assertTrue(coverage.getEnvelope2D().contains((Rectangle2D) env));

RenderedImage ri = coverage.getRenderedImage();
int[] pixel = new int[] { Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE,
Integer.MAX_VALUE };
ri.getData().getPixel(220, 15, pixel);
coverage.evaluate(new Point2D.Double(20, 45), pixel);
assertEquals(0, pixel[0]);
assertEquals(0, pixel[1]);
assertEquals(0, pixel[2]);

// We only have input RGB granules.
// The mosaic should have been added the alpha component.
// Moreover it should have been set to fully transparent (0)
Expand Down

0 comments on commit d83e5d3

Please sign in to comment.