/* * 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; import static org.geotools.referencing.crs.DefaultGeographicCRS.WGS84; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.awt.Color; import java.awt.image.RenderedImage; import java.io.File; import java.io.IOException; import java.net.URISyntaxException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import javax.media.jai.Interpolation; import org.apache.commons.io.FileUtils; import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.coverage.grid.io.AbstractGridFormat; import org.geotools.coverage.grid.io.footprint.FootprintBehavior; import org.geotools.factory.Hints; import org.geotools.geometry.GeneralEnvelope; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.image.test.ImageAssert; import org.geotools.referencing.CRS; import org.geotools.test.TestData; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.opengis.parameter.GeneralParameterValue; import org.opengis.parameter.ParameterValue; import org.opengis.referencing.FactoryException; import org.opengis.referencing.operation.TransformException; /** * Testing whether a simple mosaic correctly has its elements reprojected */ public class HeterogenousCRSTest { @Rule public TemporaryFolder crsMosaicFolder = new TemporaryFolder(); @Test public void testHeterogeneousCRS() throws IOException, URISyntaxException, TransformException, FactoryException { testMosaic("heterogeneous_crs", "location D, crs A", "red_blue_results/red_blue_heterogeneous_results.tiff", "EPSG:3587"); } @Test public void testDiffCRSSorting() throws IOException, URISyntaxException { testMosaic("diff_crs_sorting_test", "resolution D, crs A", "diff_crs_sorting_test_results/results.tiff", "EPSG:32610"); } @Test public void testWithInterpolation() throws IOException, URISyntaxException { ParameterValue<Interpolation> interpolationParam = AbstractGridFormat.INTERPOLATION.createValue(); interpolationParam.setValue(Interpolation.getInstance(Interpolation.INTERP_BILINEAR)); testMosaic("diff_crs_sorting_test", "resolution D, crs A", null, "EPSG:32610", interpolationParam); } @Test public void testUpdatingMosaic() throws IOException, URISyntaxException { File second = TestData.file(this, "heterogeneous_crs/zblue.tiff"); File indexer = TestData.file(this, "heterogeneous_crs/indexer.properties"); File first = TestData.file(this, "heterogeneous_crs/red.tiff"); File resultsImage = TestData.file(this, "red_blue_results/red_blue_update_test.tiff"); File testStoreDirectory = crsMosaicFolder.newFolder("updateTest"); FileUtils.copyFile(first, new File(testStoreDirectory, first.getName())); FileUtils.copyFile(indexer, new File(testStoreDirectory, indexer.getName())); ImageMosaicReader reader = new ImageMosaicReader(testStoreDirectory); File sfdemDest = new File(testStoreDirectory, second.getName()); FileUtils.copyFile(second, sfdemDest); reader.harvest(null, sfdemDest, null); GridCoverage2D gc2d = reader.read(new GeneralParameterValue[0]); RenderedImage renderImage = gc2d.getRenderedImage(); ImageAssert.assertEquals(resultsImage, renderImage, 1000); } private void testMosaic(String testLocation, String sortOrder, String resultLocation, String expectedCRS, GeneralParameterValue... params) throws URISyntaxException, IOException { URL storeUrl = TestData.url(this, testLocation); File testDataFolder = new File(storeUrl.toURI()); File testDirectory = crsMosaicFolder.newFolder(testLocation); FileUtils.copyDirectory(testDataFolder, testDirectory); Hints creationHints = new Hints(); ImageMosaicReader imReader = new ImageMosaicReader(testDirectory, creationHints); Assert.assertNotNull(imReader); //hack workaround for the store not being created with a consistent CRS in certain //environments. assertEquals(CRS.toSRS(imReader.getCoordinateReferenceSystem()), expectedCRS); Collection<GeneralParameterValue> finalParamsCollection = new ArrayList<>(Arrays.asList(params)); //Let's do a sort order to get the correct results ParameterValue<String> sortByParam = ImageMosaicFormat.SORT_BY.createValue(); sortByParam.setValue(sortOrder); finalParamsCollection.add(sortByParam); GridCoverage2D gc2d = imReader .read(finalParamsCollection.toArray(new GeneralParameterValue[]{})); assertEquals(CRS.toSRS(gc2d.getCoordinateReferenceSystem()), expectedCRS); if (resultLocation != null) { RenderedImage renderImage = gc2d.getRenderedImage(); File resultsFile = testFile(resultLocation); //number 1000 was a bit arbitrary for differences, should account for small differences in //interpolation and such, but not the reprojection of the blue tiff. Correct and incorrect //images will be pretty similar anyway ImageAssert.assertEquals(resultsFile, renderImage, 1000); } } @Test public void testHarvestHeteroUTM() throws Exception { File indexer = TestData.file(this, "hetero_utm/indexer.properties"); File utm32n = TestData.file(this, "hetero_utm/utm32n.tiff"); File utm33n = TestData.file(this, "hetero_utm/utm33n.tiff"); File utm32s = TestData.file(this, "hetero_utm/utm32s.tiff"); File utm33s = TestData.file(this, "hetero_utm/utm33s.tiff"); File testStoreDirectory = crsMosaicFolder.newFolder("harvestHeteroUtm"); FileUtils.copyFile(utm32n, new File(testStoreDirectory, utm32n.getName())); FileUtils.copyFile(indexer, new File(testStoreDirectory, indexer.getName())); // setup reader and check initial status ImageMosaicReader reader = new ImageMosaicReader(testStoreDirectory); Assert.assertNotNull(reader); assertExpectedBounds(new ReferencedEnvelope(11, 12, 0, 1, WGS84), reader); assertExpectedMosaic(reader, "hetero_utm_results/topleft.png"); // update and check assertEquals(1, reader.harvest(null, utm33n, null).size()); assertExpectedBounds(new ReferencedEnvelope(11, 13, 0, 1, WGS84), reader); assertExpectedMosaic(reader, "hetero_utm_results/top.png"); // update and check assertEquals(1, reader.harvest(null, utm32s, null).size()); assertExpectedBounds(new ReferencedEnvelope(11, 13, -1, 1, WGS84), reader); assertExpectedMosaic(reader, "hetero_utm_results/top_bottoleft.png"); // update and check assertEquals(1, reader.harvest(null, utm33s, null).size()); assertExpectedBounds(new ReferencedEnvelope(11, 13, -1, 1, WGS84), reader); assertExpectedMosaic(reader, "hetero_utm_results/full.png"); reader.dispose(); } @Test public void testHeteroUTM() throws Exception { String testLocation = "hetero_utm"; URL storeUrl = TestData.url(this, testLocation); File testDataFolder = new File(storeUrl.toURI()); File testDirectory = crsMosaicFolder.newFolder(testLocation); FileUtils.copyDirectory(testDataFolder, testDirectory); ImageMosaicReader imReader = new ImageMosaicReader(testDirectory, null); Assert.assertNotNull(imReader); // check we have the expected bounds and CRS assertExpectedBounds(new ReferencedEnvelope(11, 13, -1, 1, WGS84), imReader); // read a coverage and compare with expected image final String expectedResultLocation = "hetero_utm_results/full.png"; assertExpectedMosaic(imReader, expectedResultLocation); imReader.dispose(); } @Test public void testHeteroSentinel2() throws Exception { String testLocation = "hetero_s2"; URL storeUrl = TestData.url(this, testLocation); File testDataFolder = new File(storeUrl.toURI()); File testDirectory = crsMosaicFolder.newFolder(testLocation); FileUtils.copyDirectory(testDataFolder, testDirectory); ImageMosaicReader imReader = new ImageMosaicReader(testDirectory, null); Assert.assertNotNull(imReader); // read a coverage and compare with expected image final String expectedResultLocation = "hetero_s2_results/overlap.png"; ParameterValue<Color> inputTransparentColor = AbstractGridFormat.INPUT_TRANSPARENT_COLOR.createValue(); inputTransparentColor.setValue(Color.BLACK); ParameterValue<Color> outputTransparentColor = ImageMosaicFormat.OUTPUT_TRANSPARENT_COLOR.createValue(); outputTransparentColor.setValue(Color.BLACK); assertExpectedMosaic(imReader, expectedResultLocation, inputTransparentColor, outputTransparentColor); imReader.dispose(); } @Test public void testHeteroSentinel2Footprints() throws Exception { String testLocation = "hetero_s2_footprints"; URL storeUrl = TestData.url(this, testLocation); File testDataFolder = new File(storeUrl.toURI()); File testDirectory = crsMosaicFolder.newFolder(testLocation); FileUtils.copyDirectory(testDataFolder, testDirectory); ImageMosaicReader imReader = new ImageMosaicReader(testDirectory, null); Assert.assertNotNull(imReader); // read a coverage and compare with expected image final String expectedResultLocation = "hetero_s2_results/footprints.png"; ParameterValue<String> footprintBehavior = AbstractGridFormat.FOOTPRINT_BEHAVIOR.createValue(); footprintBehavior.setValue("Transparent"); assertExpectedMosaic(imReader, expectedResultLocation, footprintBehavior); imReader.dispose(); } private void assertExpectedBounds(ReferencedEnvelope expected, ImageMosaicReader imReader) { // the specified CRS has been honored assertTrue(CRS.equalsIgnoreMetadata(imReader.getCoordinateReferenceSystem(), expected.getCoordinateReferenceSystem())); // getting the expected bounds (more or less) double EPS = 0.5d / 110; // pixel size is 1km, use half a pixel tolerance GeneralEnvelope envelope = imReader.getOriginalEnvelope(); assertEquals(expected.getMinX(), envelope.getMinimum(0), EPS); assertEquals(expected.getMaxX(), envelope.getMaximum(0), EPS); assertEquals(expected.getMinY(), envelope.getMinimum(1), EPS); assertEquals(expected.getMaxY(), envelope.getMaximum(1), EPS); } private void assertExpectedMosaic(ImageMosaicReader imReader, final String expectedResultLocation, GeneralParameterValue... params) throws IOException { GridCoverage2D coverage = imReader.read(params); File resultsFile = testFile(expectedResultLocation); RenderedImage image = coverage.getRenderedImage(); ImageAssert.assertEquals(resultsFile, image, 1000); // cleanup coverage.dispose(true); } File testFile(String name) { return new File("src/test/resources/org/geotools/gce/imagemosaic/test-data/" + name); } }