/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2004-2015, 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.renderer.lite; import static org.hamcrest.CoreMatchers.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.awt.image.ComponentColorModel; import java.awt.image.RenderedImage; import java.io.File; import java.io.IOException; import java.net.URL; import java.text.ParseException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.imageio.ImageIO; import javax.media.jai.Interpolation; import javax.media.jai.ROI; import org.geotools.TestData; import org.geotools.coverage.CoverageFactoryFinder; import org.geotools.coverage.GridSampleDimension; import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.coverage.grid.GridCoverageFactory; import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader; import org.geotools.coverage.grid.io.AbstractGridFormat; import org.geotools.coverage.grid.io.GridCoverage2DReader; import org.geotools.coverage.grid.io.imageio.GeoToolsWriteParams; import org.geotools.coverage.processing.CoverageProcessor; import org.geotools.coverage.processing.operation.Crop; import org.geotools.data.DataUtilities; import org.geotools.factory.GeoTools; import org.geotools.factory.Hints; import org.geotools.filter.function.EnvFunction; import org.geotools.gce.arcgrid.ArcGridReader; import org.geotools.gce.geotiff.GeoTiffFormat; import org.geotools.gce.geotiff.GeoTiffReader; import org.geotools.gce.geotiff.GeoTiffWriteParams; import org.geotools.gce.geotiff.GeoTiffWriter; import org.geotools.geometry.GeneralEnvelope; import org.geotools.geometry.jts.JTS; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.image.ImageWorker; import org.geotools.image.test.ImageAssert; import org.geotools.map.DefaultMapContext; import org.geotools.map.GridReaderLayer; import org.geotools.map.Layer; import org.geotools.map.MapContent; import org.geotools.map.MapContext; import org.geotools.parameter.DefaultParameterDescriptorGroup; import org.geotools.parameter.ParameterGroup; import org.geotools.referencing.CRS; import org.geotools.referencing.crs.DefaultGeographicCRS; import org.geotools.referencing.crs.DefaultProjectedCRS; import org.geotools.referencing.cs.DefaultCartesianCS; import org.geotools.referencing.operation.DefaultMathTransformFactory; import org.geotools.referencing.operation.projection.MapProjection; import org.geotools.renderer.lite.gridcoverage2d.GridCoverageRenderer; import org.geotools.resources.image.ImageUtilities; import org.geotools.styling.ColorMap; import org.geotools.styling.ContrastEnhancement; import org.geotools.styling.RasterSymbolizer; import org.geotools.styling.SelectedChannelType; import org.geotools.styling.Style; import org.geotools.styling.StyleBuilder; import org.geotools.styling.StyleFactory; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.opengis.coverage.grid.Format; import org.opengis.coverage.grid.GridCoverage; import org.opengis.coverage.grid.GridCoverageWriter; import org.opengis.parameter.GeneralParameterDescriptor; import org.opengis.parameter.GeneralParameterValue; import org.opengis.parameter.ParameterValue; import org.opengis.parameter.ParameterValueGroup; import org.opengis.referencing.FactoryException; import org.opengis.referencing.NoSuchIdentifierException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.crs.GeographicCRS; import org.opengis.referencing.datum.Ellipsoid; import org.opengis.referencing.operation.MathTransform; import com.vividsolutions.jts.geom.Envelope; import it.geosolutions.jaiext.JAIExt; /** * @author Simone Giannecchini * * * @source $URL$ */ public class GridCoverageRendererTest { private static final String AFRICA_EQUIDISTANT_CONIC_WKT = "PROJCS[\"Africa_Equidistant_Conic\"," + "GEOGCS[\"GCS_WGS_1984\"," + "DATUM[\"WGS_1984\"," + "SPHEROID[\"WGS_1984\",6378137,298.257223563]]," + "PRIMEM[\"Greenwich\",0]," + "UNIT[\"Degree\",0.017453292519943295]]," + "PROJECTION[\"Equidistant_Conic\"]," + "PARAMETER[\"False_Easting\",0]," + "PARAMETER[\"False_Northing\",0]," + "PARAMETER[\"Central_Meridian\",25]," + "PARAMETER[\"Standard_Parallel_1\",20]," + "PARAMETER[\"Standard_Parallel_2\",-23]," + "PARAMETER[\"Latitude_Of_Origin\",0]," + "UNIT[\"Meter\",1]," + "AUTHORITY[\"EPSG\",\"102023\"]]"; String FILENAME = "TestGridCoverage.jpg"; private GridCoverage2DReader worldReader; private GridCoverage2DReader rainReader; private GridCoverage2DReader worldPaletteReader; private GeoTiffReader worldReader_0_360; private GeoTiffReader worldRoiReader; private GeoTiffReader sampleGribReader; // @BeforeClass // public static void enableJaiExt() { // final String JAIEXT_ENABLED_KEY = "org.geotools.coverage.jaiext.enabled"; // System.setProperty(JAIEXT_ENABLED_KEY, "true"); // }j @Before public void disableJaiExt() { JAIExt.initJAIEXT(false); } @Before public void getData() throws IOException { MapProjection.SKIP_SANITY_CHECKS = true; File coverageFile = TestData.copy(this, "geotiff/world.tiff"); assertTrue(coverageFile.exists()); worldReader = new GeoTiffReader(coverageFile); coverageFile = TestData.copy(this, "geotiff/world_0_360.tiff"); assertTrue(coverageFile.exists()); worldReader_0_360 = new GeoTiffReader(coverageFile); coverageFile = TestData.copy(this, "geotiff/worldPalette.tiff"); assertTrue(coverageFile.exists()); worldPaletteReader = new GeoTiffReader(coverageFile); // grab also the global precipitation File file = TestData.copy(this, "arcgrid/arcgrid.zip"); assertTrue(file.exists()); // unzip it TestData.unzipFile(this, "arcgrid/arcgrid.zip"); URL rainURL = GridCoverageRendererTest.class .getResource("test-data/arcgrid/precip30min.asc"); File rainFile = DataUtilities.urlToFile(rainURL); rainReader = new ArcGridReader(rainFile); // read a image with a roi (mask) coverageFile = TestData.copy(this, "geotiff/world-roi.tiff"); assertTrue(coverageFile.exists()); worldRoiReader = new GeoTiffReader(coverageFile); // sampleGrib.tif has longitudes from 302 to 308 degrees East coverageFile = DataUtilities .urlToFile(GridCoverageRendererTest.class.getResource("test-data/sampleGrib.tif")); assertTrue(coverageFile.exists()); sampleGribReader = new GeoTiffReader(coverageFile); } @After public void close() throws IOException { MapProjection.SKIP_SANITY_CHECKS = false; worldReader.dispose(); EnvFunction.clearLocalValues(); } /** * Returns a {@link GridCoverage} which may be used as a "real world" * example. * * @param number * The example number. Numbers are numeroted from 0 to * {@link #getNumExamples()} exclusive. * @return The "real world" grid coverage. * @throws IOException * if an I/O operation was needed and failed. * @throws ParseException * @throws IllegalArgumentException */ private final GridCoverage2D getGC() throws IOException, IllegalArgumentException, ParseException { final String path; final Rectangle2D bounds; // unit = "°C"; path = "TestGridCoverage.tif"; final CoordinateReferenceSystem crs = DefaultGeographicCRS.WGS84; // 41°S - 5°N ; 35°E - 80°E (450 x 460 pixels) bounds = new Rectangle2D.Double(35, -41, 45, 46); final GeneralEnvelope envelope = new GeneralEnvelope(bounds); final RenderedImage image = ImageIO.read(TestData.getResource(this,path)); final int numBands = image.getSampleModel().getNumBands(); final GridSampleDimension[] bands = new GridSampleDimension[numBands]; // setting bands names. for (int i = 0; i < numBands; i++) { bands[i] = new GridSampleDimension("band " + i); } final String filename = new File(path).getName(); final GridCoverageFactory factory = org.geotools.coverage.CoverageFactoryFinder.getGridCoverageFactory(GeoTools.getDefaultHints()); envelope.setCoordinateReferenceSystem(crs); return factory.create(filename, image, envelope,bands, null, null); } /** * Returns a projected CRS for test purpose. */ private static CoordinateReferenceSystem getProjectedCRS( final GridCoverage2D coverage) { try { final GeographicCRS base = (GeographicCRS) coverage.getCoordinateReferenceSystem(); final Ellipsoid ellipsoid = base.getDatum().getEllipsoid(); final DefaultMathTransformFactory factory = new DefaultMathTransformFactory(); final ParameterValueGroup parameters = factory.getDefaultParameters("Oblique_Stereographic"); parameters.parameter("semi_major").setValue(ellipsoid.getSemiMajorAxis()); parameters.parameter("semi_minor").setValue(ellipsoid.getSemiMinorAxis()); parameters.parameter("central_meridian").setValue(5); parameters.parameter("latitude_of_origin").setValue(-5); final MathTransform mt; try { mt = factory.createParameterizedTransform(parameters); } catch (FactoryException exception) { fail(exception.getLocalizedMessage()); return null; } //create the projected crs return new DefaultProjectedCRS( java.util.Collections.singletonMap("name", "Stereographic"), base, mt, DefaultCartesianCS.PROJECTED); } catch (NoSuchIdentifierException exception) { fail(exception.getLocalizedMessage()); return null; } } @Test public void paint() throws Exception { // // ///////////////////////////////////////////////////////////////// // // CREATING A GRID COVERAGE // // // ///////////////////////////////////////////////////////////////// final GridCoverage2D gc = getGC(); // // // ///////////////////////////////////////////////////////////////// // // MAP CONTEXT // // // ///////////////////////////////////////////////////////////////// final MapContext context = new DefaultMapContext(DefaultGeographicCRS.WGS84); final Style style = getStyle(); context.addLayer(gc, style); // ///////////////////////////////////////////////////////////////// // // Streaming renderer // // // /////////////////////////////////////////////////////////////// final StreamingRenderer renderer = new StreamingRenderer(); renderer.setContext(context); RendererBaseTest.showRender("testGridCoverage", renderer, 1000, context.getLayerBounds()); } /** * Tests what happens when the grid coverage is associated with a broken style with * no symbolizers inside. It should just render nothing, a NPE was reported instead * in GEOT-2543. * @throws Exception */ @Test public void paintWrongStyle() throws Exception { final GridCoverage2D gc = getGC(); final MapContext context = new DefaultMapContext(DefaultGeographicCRS.WGS84); // final Style style = new StyleBuilder().createStyle((Symbolizer) null); final Style style = RendererBaseTest.loadStyle(this, "empty.sld"); context.addLayer(gc, style); final StreamingRenderer renderer = new StreamingRenderer(); CountingRenderListener counter = new CountingRenderListener(); renderer.addRenderListener(counter); renderer.setContext(context); BufferedImage image = new BufferedImage(300, 300, BufferedImage.TYPE_4BYTE_ABGR); Graphics2D g2d = (Graphics2D) image.getGraphics(); renderer.paint(g2d, new Rectangle(0,0,300,300), context.getLayerBounds()); g2d.dispose(); // make sure no errors and no features assertEquals(0, counter.errors); assertEquals(0, counter.features); } @Test public void reproject() throws Exception { // /////////////////////////////////////////////////////////////////// // // CREATING A GRID COVERAGE // // // // ///////////////////////////////////////////////////////////////// final GridCoverage2D coverage = getGC(); // // /////////////////////////////////////////////////////////////////// // // MAP CONTEXT // We want to show the context in a different CRS // // // ///////////////////////////////////////////////////////////////// final MapContext context = new DefaultMapContext(DefaultGeographicCRS.WGS84); final Style style = getStyle(); context.addLayer(coverage, style); // transform to a new crs final CoordinateReferenceSystem destCRS = getProjectedCRS(coverage); // /////////////////////////////////////////////////////////////////// // // Streaming renderer // // ///////////////////////////////////////////////////////////////// final StreamingRenderer renderer = new StreamingRenderer(); renderer.setContext(context); ReferencedEnvelope env = context.getLayerBounds(); env = new ReferencedEnvelope(env.getMinX(), env.getMaxX(), env.getMinY(), env.getMaxY(), DefaultGeographicCRS.WGS84); final ReferencedEnvelope newbounds = env.transform(destCRS, true); RendererBaseTest.showRender("testGridCoverageReprojection", renderer, 1000, newbounds); } @Test public void testRenderingBuffer() throws Exception { // prepare the layer MapContent content = new MapContent(); final Style style = getStyle(); content.addLayer(new GridReaderLayer(worldReader, style)); final StreamingRenderer renderer = new StreamingRenderer(); renderer.setMapContent(content); renderer.setRendererHints(Collections.singletonMap("renderingBuffer", 1024)); BufferedImage image = RendererBaseTest.showRender("testGridCoverageReprojection", renderer, 1000, content.getViewport().getBounds()); ImageAssert.assertEquals(new File("src/test/resources/org/geotools/renderer/lite/rescaled.png"), image, 1000); } @Test public void testInterpolationBicubic() throws Exception { CoordinateReferenceSystem googleMercator = CRS.decode("EPSG:3857"); ReferencedEnvelope mapExtent = new ReferencedEnvelope(-20037508.34, 20037508.34, -20037508.34, 20037508.34, googleMercator); Rectangle screenSize = new Rectangle(200, (int) (mapExtent.getHeight() / mapExtent.getWidth() * 200)); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer(googleMercator, mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); GridCoverage2D coverage = worldReader.read(null); RenderedImage image = renderer.renderImage(coverage, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_BICUBIC), Color.RED, 256, 256); File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/googleMercatorBicubic.png"); ImageAssert.assertEquals(reference, image, 0); } @Test public void testInvertedColors() throws Exception { MapContent content = new MapContent(); content.getViewport().setBounds( new ReferencedEnvelope(-179.9997834892, 180.00025801626, -89.999828389438, 270.00021311603, DefaultGeographicCRS.WGS84)); RasterSymbolizer rs = buildRainColorMap(); final Style style = new StyleBuilder().createStyle(rs); content.addLayer(new GridReaderLayer(rainReader, style)); final StreamingRenderer renderer = new StreamingRenderer(); renderer.setMapContent(content); Map<Object, Object> rendererParams = new HashMap<Object, Object>(); rendererParams.put(StreamingRenderer.ADVANCED_PROJECTION_HANDLING_KEY, true); rendererParams.put(StreamingRenderer.CONTINUOUS_MAP_WRAPPING, true); renderer.setRendererHints(rendererParams); BufferedImage image = RendererBaseTest.showRender("testGridCoverageReprojection", renderer, 1000, content.getViewport().getBounds()); ImageAssert.assertEquals(new File( "src/test/resources/org/geotools/renderer/lite/inverted.png"), image, 1000); } private static Style getStyle() { StyleBuilder sb = new StyleBuilder(); Style rasterstyle = sb.createStyle(); RasterSymbolizer raster = sb.createRasterSymbolizer(); rasterstyle.featureTypeStyles().add(sb.createFeatureTypeStyle(raster)); rasterstyle.featureTypeStyles().get(0).setName("GridCoverage"); return rasterstyle; } @Test public void testReprojectBuffer() throws Exception { // create a solid color 1m coverage in EPSG:26915 BufferedImage bi = new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY); Graphics2D graphics = bi.createGraphics(); graphics.setColor(Color.DARK_GRAY); graphics.fillRect(0, 0, bi.getWidth(), bi.getHeight()); graphics.dispose(); double baseX = 529687; double baseY = 3374773; CoordinateReferenceSystem nativeCrs = CRS.decode("EPSG:26915", true); GridCoverage2D coverage = CoverageFactoryFinder.getGridCoverageFactory(null).create("test", bi, new ReferencedEnvelope(baseX, baseX + bi.getWidth(), baseY, baseY + bi.getHeight(), nativeCrs)); // write out as geotiff File testFile = new File("./target/testReprojection.tiff"); GeoTiffWriter writer = new GeoTiffWriter(testFile); writer.write(coverage, null); // setup to read only a block 50x50 in the middle MathTransform r2m = coverage.getGridGeometry().getGridToCRS(); Envelope env = new Envelope(25, 75, 25, 75); ReferencedEnvelope read26915 = new ReferencedEnvelope(JTS.transform(env, r2m), nativeCrs); CoordinateReferenceSystem mapCRS = CRS.decode("EPSG:3857", true); ReferencedEnvelope read3857 = read26915.transform(mapCRS, true); // setup map content StyleBuilder sb = new StyleBuilder(); Layer layer = new GridReaderLayer(new GeoTiffReader(testFile), sb.createStyle(sb.createRasterSymbolizer())); MapContent mc = new MapContent(); mc.getViewport().setBounds(read3857); mc.addLayer(layer); StreamingRenderer sr = new StreamingRenderer(); sr.setMapContent(mc); BufferedImage result = RendererBaseTest.showRender("testGridCoverageBoundsReprojection", sr, 1000, read3857); // there used to be a white triangle in the lower right corner of the output ImageAssert.assertEquals( new File("src/test/resources/org/geotools/renderer/lite/reprojectBuffer.png"), result, 0); } @Test public void testReprojectGoogleMercator() throws Exception { CoordinateReferenceSystem googleMercator = CRS.decode("EPSG:3857"); ReferencedEnvelope mapExtent = new ReferencedEnvelope(-20037508.34, 20037508.34, -20037508.34, 20037508.34, googleMercator); Rectangle screenSize = new Rectangle(200, (int) (mapExtent.getHeight() / mapExtent.getWidth() * 200)); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer(googleMercator, mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); GridCoverage2D coverage = worldReader.read(null); RenderedImage image = renderer.renderImage(coverage, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.RED, 256, 256); // always set ROI on reprojection assertThat(image.getProperty("roi"), instanceOf(ROI.class)); File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/googleMercator.png"); ImageAssert.assertEquals(reference, image, 0); } @Test public void testReprojectGoogleMercatorLargerThanWorld() throws Exception { CoordinateReferenceSystem googleMercator = CRS.decode("EPSG:3857"); ReferencedEnvelope mapExtent = new ReferencedEnvelope(-38448446.580832, 38448446.580832, -44138127.016561, 44138127.016561, googleMercator); Rectangle screenSize = new Rectangle(400, (int) (mapExtent.getHeight() / mapExtent.getWidth() * 400)); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer(googleMercator, mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); RenderedImage image = renderer.renderImage(worldReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.RED, 256, 256); File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/googleMercatorLargerThanWorld.png"); ImageAssert.assertEquals(reference, image, 0); } @Test public void testReprojectGoogleMercatorBlackLine() throws Exception { CoordinateReferenceSystem googleMercator = CRS.decode("EPSG:3857"); ReferencedEnvelope mapExtent = new ReferencedEnvelope(-70650900.64528, 32797834.549784, -25517354.68145, 26207012.916082, googleMercator); Rectangle screenSize = new Rectangle(600, 300); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer(googleMercator, mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); RenderedImage image = renderer.renderImage(worldReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.RED, 256, 256); // always set ROI on reprojection assertThat(image.getProperty("roi"), instanceOf(ROI.class)); File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/googleMercatorBlackLine.png"); ImageAssert.assertEquals(reference, image, 5); } @Test public void testReprojectGoogleMercatorTouchDateline() throws Exception { CoordinateReferenceSystem googleMercator = CRS.decode("EPSG:3857"); ReferencedEnvelope mapExtent = new ReferencedEnvelope(20037508.34, 40075016.68, 0, 20037508.34, googleMercator); Rectangle screenSize = new Rectangle(256, 256); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer(googleMercator, mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); RenderedImage image = renderer.renderImage(worldReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.RED, 256, 256); File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/googleMercatorTouchDateline.png"); ImageAssert.assertEquals(reference, image, 10); } @Test public void testAcrossDatelineBilinear() throws Exception { ReferencedEnvelope mapExtent = new ReferencedEnvelope(10, 350, -90, 90, DefaultGeographicCRS.WGS84); Rectangle screenSize = new Rectangle(500, (int) (mapExtent.getHeight() / mapExtent.getWidth() * 500)); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer(DefaultGeographicCRS.WGS84, mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); RenderedImage image = renderer.renderImage(worldReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.RED, 256, 256); File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/wrapDatelineNearest.png"); ImageAssert.assertEquals(reference, image, 20); } @Test public void testNoProjectionHandlerSet() throws Exception { // Request crossing dateline should not contain wrapped data ReferencedEnvelope mapExtent = new ReferencedEnvelope(10, 500, -90, 90, DefaultGeographicCRS.WGS84); Rectangle screenSize = new Rectangle(500, (int) (mapExtent.getHeight() / mapExtent.getWidth() * 500)); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer(DefaultGeographicCRS.WGS84, mapExtent, screenSize, w2s); // Setting No projectionHandler renderer.setAdvancedProjectionHandlingEnabled(false); RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); RenderedImage image = renderer.renderImage(worldReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.RED, 256, 256); File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/noProjectionHandlerSet.png"); ImageAssert.assertEquals(reference, image, 0); } public void testCrashOutsideValidArea() throws Exception { ReferencedEnvelope mapExtent = new ReferencedEnvelope(0.00023726353151687, 180.00025801626, -269.99984914217, -89.999828389438, DefaultGeographicCRS.WGS84); Rectangle screenSize = new Rectangle(256, 256); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer(DefaultGeographicCRS.WGS84, mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); RenderedImage image = renderer.renderImage(worldReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.RED, 256, 256); assertNull(image); } private void assertNull(RenderedImage image) { // TODO Auto-generated method stub } @Test public void testAcrossDatelineBicubic() throws Exception { ReferencedEnvelope mapExtent = new ReferencedEnvelope(10, 350, -90, 90, DefaultGeographicCRS.WGS84); Rectangle screenSize = new Rectangle(500, (int) (mapExtent.getHeight() / mapExtent.getWidth() * 500)); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer(DefaultGeographicCRS.WGS84, mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); RenderedImage image = renderer.renderImage(worldReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_BICUBIC), Color.RED, 256, 256); File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/wrapDatelineBicubic.png"); ImageAssert.assertEquals(reference, image, 0); } @Test public void testUTM() throws Exception { CoordinateReferenceSystem crs = CRS.decode("EPSG:32632", true); ReferencedEnvelope mapExtent = new ReferencedEnvelope(-6e6, 6e6, 0, 5.3e6, crs); // System.out.println(mapExtent.transform(DefaultGeographicCRS.WGS84, true)); // System.out.println(mapExtent.transform(DefaultGeographicCRS.WGS84, true).transform(crs, // true)); Rectangle screenSize = new Rectangle(400, (int) (mapExtent.getHeight() / mapExtent.getWidth() * 400)); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer( mapExtent.getCoordinateReferenceSystem(), mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); RenderedImage image = renderer.renderImage(worldReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_BICUBIC), Color.RED, 256, 256); assertNotNull(image); File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/utm.png"); ImageAssert.assertEquals(reference, image, 0); } @Test public void testSouthPolar() throws Exception { CoordinateReferenceSystem crs = CRS.decode("EPSG:3031", true); // across the dateline, not including the pole ReferencedEnvelope mapExtent = new ReferencedEnvelope(-6000000, 6000000, -8000000, -1000000, crs); Rectangle screenSize = new Rectangle(400, (int) (mapExtent.getHeight() / mapExtent.getWidth() * 400)); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer( mapExtent.getCoordinateReferenceSystem(), mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); RenderedImage image = renderer.renderImage(worldReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.RED, 256, 256); assertNotNull(image); File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/south_polar.png"); ImageAssert.assertEquals(reference, image, 0); } @Test public void testNorthPolar() throws Exception { CoordinateReferenceSystem crs = CRS.decode("EPSG:3995", true); // across the dateline, not including the pole ReferencedEnvelope mapExtent = new ReferencedEnvelope(-6000000, 6000000, 8000000, 1000000, crs); Rectangle screenSize = new Rectangle(400, (int) (mapExtent.getHeight() / mapExtent.getWidth() * 400)); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer( mapExtent.getCoordinateReferenceSystem(), mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); RenderedImage image = renderer.renderImage(worldReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.RED, 256, 256); assertNotNull(image); File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/north_polar.png"); ImageAssert.assertEquals(reference, image, 40); } @Test public void testIndexedWithNoBackground() throws Exception { CoordinateReferenceSystem googleMercator = CRS.decode("EPSG:3857"); ReferencedEnvelope mapExtent = new ReferencedEnvelope(-20037508.34, 20037508.34, -20037508.34, 20037508.34, googleMercator); Rectangle screenSize = new Rectangle(200, (int) (mapExtent.getHeight() / mapExtent.getWidth() * 200)); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer(googleMercator, mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); RenderedImage image = renderer.renderImage(worldPaletteReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_BICUBIC), null, 256, 256); assertNotNull(image); } @Test public void testPolarCutLowCorner() throws Exception { // we request a small area, oversampling, and the output has some white pixels in a corner CoordinateReferenceSystem crs = CRS.decode("EPSG:3031", true); // across the dateline, not including the pole ReferencedEnvelope mapExtent = new ReferencedEnvelope(-2500000, -1250000, -10000000, -8750000, crs); Rectangle screenSize = new Rectangle(256, 256); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer( mapExtent.getCoordinateReferenceSystem(), mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = buildRainColorMap(); RenderedImage image = renderer.renderImage(rainReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.RED, 256, 256); assertNotNull(image); File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/polar_whitecorner.png"); ImageAssert.assertEquals(reference, image, 0); } private RasterSymbolizer buildRainColorMap() { StyleBuilder sb = new StyleBuilder(); ColorMap colorMap = sb .createColorMap(new String[] { "1", "2", "3", "4" }, new double[] { 0, 100, 2000, 5000 }, new Color[] { Color.RED, Color.WHITE, Color.GREEN, Color.BLUE }, ColorMap.TYPE_RAMP); RasterSymbolizer rasterSymbolizer = sb.createRasterSymbolizer(colorMap, 1d); return rasterSymbolizer; } @Test public void testPolarCutUpperCorner() throws Exception { // We request a small area, oversampling, and the output has some white pixels in the up // corner CoordinateReferenceSystem crs = CRS.decode("EPSG:3031", true); ReferencedEnvelope mapExtent = new ReferencedEnvelope(-625000, 0, -10000000, -9375000, crs); Rectangle screenSize = new Rectangle(256, 256); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer( mapExtent.getCoordinateReferenceSystem(), mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = buildRainColorMap(); RenderedImage image = renderer.renderImage(rainReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.RED, 256, 256); assertNotNull(image); File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/polar_whitecorner_up.png"); ImageAssert.assertEquals(reference, image, 0); } @Test public void testPolarTouchDateline() throws Exception { // we request a small area, oversampling, and the output has some white pixels in a corner CoordinateReferenceSystem crs = CRS.decode("EPSG:3031", true); // across the dateline, not including the pole ReferencedEnvelope mapExtent = new ReferencedEnvelope(-1250000, 0, -10000000, -8750000, crs); Rectangle screenSize = new Rectangle(256, 256); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer( mapExtent.getCoordinateReferenceSystem(), mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = buildRainColorMap(); RenderedImage image = renderer.renderImage(rainReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.RED, 256, 256); assertNotNull(image); File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/polar_touchdateline.png"); ImageAssert.assertEquals(reference, image, 0); } @Test public void testAfricaEquidistantConic() throws Exception { CoordinateReferenceSystem crs = CRS.parseWKT(AFRICA_EQUIDISTANT_CONIC_WKT); // across the dateline ReferencedEnvelope mapExtent = new ReferencedEnvelope(-15814047.554122284, 24919762.252195686, -14112074.925190449, 11688610.748676982, crs); // Setting Screen size Rectangle screenSize = new Rectangle(400, (int) (mapExtent.getHeight() / mapExtent.getWidth() * 400)); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer( mapExtent.getCoordinateReferenceSystem(), mapExtent, screenSize, w2s); // Apply the symbolizer RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); // Render the image RenderedImage image = renderer.renderImage(worldReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.RED, 256, 256); assertNotNull(image); // Check the image File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/africa-conic.png"); ImageAssert.assertEquals(reference, image, 0); } @Test public void testAfricaEquidistantConicIndexed() throws Exception { CoordinateReferenceSystem crs = CRS.parseWKT(AFRICA_EQUIDISTANT_CONIC_WKT); // across the dateline ReferencedEnvelope mapExtent = new ReferencedEnvelope(-15814047.554122284, 24919762.252195686, -14112074.925190449, 11688610.748676982, crs); // Setting Screen size Rectangle screenSize = new Rectangle(400, (int) (mapExtent.getHeight() / mapExtent.getWidth() * 400)); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer( mapExtent.getCoordinateReferenceSystem(), mapExtent, screenSize, w2s); // Apply the symbolizer RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); // Get the reader File coverageFile = TestData.copy(this, "geotiff/worldPalette.tiff"); assertTrue(coverageFile.exists()); GridCoverage2DReader reader = new GeoTiffReader(coverageFile); // Render the image RenderedImage image = renderer.renderImage(reader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.RED, 256, 256); assertNotNull(image); // we have performed color expansion to allow for red background (it's not in the palette) assertTrue(image.getColorModel() instanceof ComponentColorModel); // Check the image File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/africa-conic-palette.png"); ImageAssert.assertEquals(reference, image, 10); } @Test public void testAfricaEquidistantConicRoi() throws Exception { JAIExt.initJAIEXT(true); CoordinateReferenceSystem crs = CRS.parseWKT(AFRICA_EQUIDISTANT_CONIC_WKT); // across the dateline ReferencedEnvelope mapExtent = new ReferencedEnvelope(-15814047.554122284, 24919762.252195686, -14112074.925190449, 11688610.748676982, crs); // Setting Screen size Rectangle screenSize = new Rectangle(400, (int) (mapExtent.getHeight() / mapExtent.getWidth() * 400)); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer( mapExtent.getCoordinateReferenceSystem(), mapExtent, screenSize, w2s); // Apply the symbolizer RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); // Get the reader // Render the image RenderedImage image = renderer.renderImage(worldRoiReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.RED, 256, 256); assertNotNull(image); // Check the image File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/africa-conic-roi.png"); ImageAssert.assertEquals(reference, image, 10); } @Test public void testFlippedAffine() throws Exception { // get the source data File coverageFile = TestData.copy(this, "geotiff/float64.tif"); assertTrue(coverageFile.exists()); GridCoverage2DReader reader = new GeoTiffReader(coverageFile); // Apply the symbolizer Style style = RendererBaseTest.loadStyle(this, "float64.sld"); RasterSymbolizer rasterSymbolizer = (RasterSymbolizer) style.featureTypeStyles().get(0) .rules().get(0).symbolizers().get(0); // Render, used to return a white image ReferencedEnvelope mapExtent = ReferencedEnvelope.reference(reader.getOriginalEnvelope()); Rectangle screenSize = new Rectangle(50, 50); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer( reader.getCoordinateReferenceSystem(), mapExtent, screenSize, w2s); RenderedImage image = renderer.renderImage(reader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.RED, 256, 256); assertNotNull(image); // Check the image File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/flippedAffine.png"); ImageAssert.assertEquals(reference, image, 2); } @Test public void testEnvFunctionInColorMap() throws Exception { EnvFunction.setLocalValue("low", "-0.001"); EnvFunction.setLocalValue("lowColor", "#000000"); // get the source data File coverageFile = TestData.copy(this, "geotiff/float64.tif"); assertTrue(coverageFile.exists()); GridCoverage2DReader reader = new GeoTiffReader(coverageFile); // Apply the symbolizer Style style = RendererBaseTest.loadStyle(this, "float64.sld"); final MapContent mc = new MapContent(); mc.addLayer(new GridReaderLayer(reader, style)); StreamingRenderer renderer = new StreamingRenderer(); renderer.setMapContent(mc); BufferedImage image = RendererBaseTest.renderImage(renderer, mc.getViewport().getBounds(), null, 50, 50); // Check the image File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/flippedAffineParametric.png"); ImageAssert.assertEquals(reference, image, 2); } @Test public void testCoverage_0_360() throws Exception { CoordinateReferenceSystem crs = CRS.decode("EPSG:4326", true); ReferencedEnvelope mapExtent = new ReferencedEnvelope(100, 260, -90, 90, crs); Rectangle screenSize = new Rectangle(400, (int) (mapExtent.getHeight() / mapExtent.getWidth() * 400)); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer( mapExtent.getCoordinateReferenceSystem(), mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); RenderedImage image = renderer.renderImage(worldReader_0_360, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.BLACK, 256, 256); assertNotNull(image); File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/world_0_360.png"); ImageAssert.assertEquals(reference, image, 10); } /** * Test rendering of sampleGrib.tif on its native longitude bounds (302,308). */ @Test public void testSampleGrib() throws Exception { CoordinateReferenceSystem crs = CRS.decode("EPSG:4326", true); ReferencedEnvelope mapExtent = new ReferencedEnvelope(302, 308, 2, 10, crs); Rectangle screenSize = new Rectangle(400, (int) (mapExtent.getHeight() / mapExtent.getWidth() * 400)); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer( mapExtent.getCoordinateReferenceSystem(), mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); RenderedImage image = renderer.renderImage(sampleGribReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.GRAY, 256, 256); assertNotNull(image); File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/sampleGrib.png"); ImageAssert.assertEquals(reference, image, 0); } /** * Test that rendering of sampleGrib.tif on longitude (304,310) results in cropping. */ @Test public void testSampleGribCropLongitude() throws Exception { CoordinateReferenceSystem crs = CRS.decode("EPSG:4326", true); ReferencedEnvelope mapExtent = new ReferencedEnvelope(304, 310, 2, 10, crs); Rectangle screenSize = new Rectangle(400, (int) (mapExtent.getHeight() / mapExtent.getWidth() * 400)); AffineTransform w2s = RendererUtilities.worldToScreenTransform(mapExtent, screenSize); GridCoverageRenderer renderer = new GridCoverageRenderer( mapExtent.getCoordinateReferenceSystem(), mapExtent, screenSize, w2s); RasterSymbolizer rasterSymbolizer = new StyleBuilder().createRasterSymbolizer(); RenderedImage image = renderer.renderImage(sampleGribReader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.GRAY, 256, 256); assertNotNull(image); File reference = new File( "src/test/resources/org/geotools/renderer/lite/gridcoverage2d/sampleGribCropLongitude.png"); ImageAssert.assertEquals(reference, image, 0); } /** * Test to check the case where band selection cannot be pushed down to the reader, but needs to be run in memory */ @Test public void testBandSelectionOnNonSupportingReader() throws Exception { // Create a solid color coverage BufferedImage bi = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB); Graphics2D graphics = bi.createGraphics(); graphics.setColor(Color.BLUE); graphics.fillRect(0, 0, bi.getWidth(), bi.getHeight()); graphics.dispose(); CoordinateReferenceSystem nativeCrs = CRS.decode("EPSG:4326", true); ReferencedEnvelope mapExtent = new ReferencedEnvelope(0, 90, 0, 90, nativeCrs); GridCoverage2D coverage = CoverageFactoryFinder.getGridCoverageFactory(null).create("test", bi, new ReferencedEnvelope(0, 90, 0, 90, nativeCrs)); assertEquals(coverage.getNumSampleDimensions(), 3); // Write out as a geotiff File coverageFile = new File("./target/blue.tiff"); GeoTiffWriter writer = new GeoTiffWriter(coverageFile); final GeoTiffFormat format = new GeoTiffFormat(); final GeoTiffWriteParams wp = new GeoTiffWriteParams(); // setting compression to LZW wp.setCompressionMode(GeoTiffWriteParams.MODE_EXPLICIT); wp.setCompressionType("LZW"); wp.setCompressionQuality(0.75F); final ParameterValueGroup params = format.getWriteParameters(); List<GeneralParameterValue> paramsValues = params.values(); writer.write(coverage, params.values().toArray(new GeneralParameterValue[paramsValues.size()])); // Get the reader, read with band selection assertTrue(coverageFile.exists()); GridCoverage2DReader reader = new GeoTiffReader(coverageFile); // Render the image selecting blue GridCoverageRenderer renderer = new GridCoverageRenderer(nativeCrs, mapExtent, new Rectangle(0, 0, 100, 100), null); RenderedImage image = renderer.renderImage(reader, null, buildChannelSelectingSymbolizer(3), Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.BLACK, 256, 256); assertEquals(1, image.getSampleModel().getNumBands()); assertEquals(255, new ImageWorker(image).getMinimums()[0], 0d); ImageUtilities.disposeImage(image); // Render again selecting red image = renderer.renderImage(reader, null, buildChannelSelectingSymbolizer(1), Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.BLACK, 256, 256); assertEquals(1, image.getSampleModel().getNumBands()); assertEquals(0, new ImageWorker(image).getMaximums()[0], 0d); ImageUtilities.disposeImage(image); } @Test public void testBandSelectionSupportingReader() throws Exception { ReferencedEnvelope mapExtent = new ReferencedEnvelope(0, 90, 0, 90, DefaultGeographicCRS.WGS84); GridCoverage2DReader reader = new TestSingleBandReader(2); GridCoverageRenderer renderer = new GridCoverageRenderer(DefaultGeographicCRS.WGS84, mapExtent, new Rectangle(0, 0, 100, 100), null); // keeping a reference to the raster symbolizer so we can check we has not altered // during the band setup the raster symbolizer channel selection needs to be rearranged // but the original raster symbolizer should not be altered RasterSymbolizer rasterSymbolizer = buildChannelSelectingSymbolizer(3); RenderedImage image = renderer.renderImage(reader, null, rasterSymbolizer, Interpolation.getInstance(Interpolation.INTERP_NEAREST), Color.BLACK, 256, 256); assertEquals(1, image.getSampleModel().getNumBands()); assertEquals(255, new ImageWorker(image).getMinimums()[0], 0d); // test that raster symbolizer was not altered RasterSymbolizer expectedRasterSymbolizer = buildChannelSelectingSymbolizer(3); // during the copy method contrast enhancement NULL options are converted to an empty HashMap expectedRasterSymbolizer.getContrastEnhancement().setOptions(Collections.emptyMap()); assertEquals(rasterSymbolizer, expectedRasterSymbolizer); ImageUtilities.disposeImage(image); } @Test public void testReprojectTransparency() throws Exception { ReferencedEnvelope re = new ReferencedEnvelope(0, 20, 20, 40, DefaultGeographicCRS.WGS84); CoordinateReferenceSystem utm32n = CRS.decode("EPSG:32632", true); ReferencedEnvelope mapExtent = re.transform(utm32n, true); // get a subset of the coverage GridCoverage2D global = worldReader.read(null); CoverageProcessor processor = CoverageProcessor.getInstance(new Hints(Hints.LENIENT_DATUM_SHIFT, Boolean.TRUE)); final ParameterValueGroup param = processor.getOperation("CoverageCrop").getParameters().clone(); param.parameter("source").setValue(global); param.parameter("Envelope").setValue(re); GridCoverage2D cropped = (GridCoverage2D) ((Crop)processor.getOperation("CoverageCrop")).doOperation(param, null); // render with reprojection, the ROI should be used to create transparent pixels BufferedImage bi = new BufferedImage(100, 100, BufferedImage.TYPE_4BYTE_ABGR); Graphics2D graphics = bi.createGraphics(); GridCoverageRenderer renderer = new GridCoverageRenderer(utm32n, mapExtent, new Rectangle(0, 0, 100, 100), null); renderer.paint(graphics, cropped, new StyleBuilder().createRasterSymbolizer()); graphics.dispose(); // top left and top right corners must be transparent now, the UTM shrinks towards the pole assertPixelIsTransparent(bi, 0, 0); assertPixelIsTransparent(bi, bi.getWidth() - 1, 0); } @Test public void testRenderOutsideBounds() throws Exception { ReferencedEnvelope re = new ReferencedEnvelope(0, 20, 20, 40, DefaultGeographicCRS.WGS84); // get a subset of the coverage GridCoverage2D global = worldReader.read(null); CoverageProcessor processor = CoverageProcessor.getInstance(new Hints(Hints.LENIENT_DATUM_SHIFT, Boolean.TRUE)); final ParameterValueGroup param = processor.getOperation("CoverageCrop").getParameters().clone(); param.parameter("source").setValue(global); param.parameter("Envelope").setValue(re); GridCoverage2D cropped = (GridCoverage2D) ((Crop)processor.getOperation("CoverageCrop")).doOperation(param, null); ReferencedEnvelope reOutside = new ReferencedEnvelope(40, 60, 20, 40, DefaultGeographicCRS.WGS84); GridCoverageRenderer renderer = new GridCoverageRenderer(DefaultGeographicCRS.WGS84, reOutside, new Rectangle(0, 0, 100, 100), null); RasterSymbolizer symbolizer = new StyleBuilder().createRasterSymbolizer(); Interpolation interpolation = Interpolation.getInstance(Interpolation.INTERP_NEAREST); RenderedImage image = renderer.renderImage(cropped, symbolizer, interpolation, null, 256, 256); // outside coverage bounds, just return null but don't NPE assertNull(image); } /** * Checks the pixel i/j is fully transparent * @param image * @param i * @param j */ protected void assertPixelIsTransparent(BufferedImage image, int i, int j) { int pixel = image.getRGB(i,j); assertEquals(true, (pixel>>24) == 0x00); } private RasterSymbolizer buildChannelSelectingSymbolizer(int band) { StyleBuilder sb = new StyleBuilder(); RasterSymbolizer symbolizer = sb.createRasterSymbolizer(); StyleFactory sf = sb.getStyleFactory(); symbolizer.setChannelSelection(sf.createChannelSelection(new SelectedChannelType[] {sf.createSelectedChannelType(String.valueOf(band), (ContrastEnhancement) null)})); return symbolizer; } /** * Mock reader checking the expected band was requested */ private static class TestSingleBandReader extends AbstractGridCoverage2DReader { int[] expectedBands; public TestSingleBandReader(int... expectedBands) { this.expectedBands = expectedBands; this.originalEnvelope = new GeneralEnvelope(new ReferencedEnvelope(0, 90, 0, 90, DefaultGeographicCRS.WGS84)); this.crs = DefaultGeographicCRS.WGS84; } @Override public Format getFormat() { return new AbstractGridFormat() { @Override public GridCoverageWriter getWriter(Object destination, Hints hints) { throw new UnsupportedOperationException(); } @Override public GridCoverageWriter getWriter(Object destination) { throw new UnsupportedOperationException(); } @Override public AbstractGridCoverage2DReader getReader(Object source, Hints hints) { throw new UnsupportedOperationException(); } @Override public AbstractGridCoverage2DReader getReader(Object source) { throw new UnsupportedOperationException(); } @Override public GeoToolsWriteParams getDefaultImageIOWriteParameters() { // TODO Auto-generated method stub return null; } @Override public boolean accepts(Object source, Hints hints) { throw new UnsupportedOperationException(); } @Override public ParameterValueGroup getReadParameters() { HashMap<String, String> info = new HashMap<String, String>(); info.put("name", "bandTester"); info.put("description", "desc"); info.put("vendor", "vendor"); info.put("docURL", "http://www.geotools.org"); info.put("version", "1.0"); List<GeneralParameterDescriptor> params = new ArrayList<GeneralParameterDescriptor>(); params.add(AbstractGridFormat.BANDS); return new ParameterGroup(new DefaultParameterDescriptorGroup(info, params.toArray(new GeneralParameterDescriptor[params.size()]))); } }; } @Override public GridCoverage2D read(GeneralParameterValue[] parameters) throws IllegalArgumentException, IOException { assertTrue(Arrays.stream(parameters).anyMatch(p -> "Bands".equals(p.getDescriptor().getName().toString()) && Arrays.equals(expectedBands, (int[]) ((ParameterValue) p).getValue()))); // Create a solid color single band coverage BufferedImage bi = new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY); Graphics2D graphics = bi.createGraphics(); graphics.setColor(Color.WHITE); graphics.fillRect(0, 0, bi.getWidth(), bi.getHeight()); graphics.dispose(); GridCoverage2D coverage = CoverageFactoryFinder.getGridCoverageFactory(null).create("test", bi, getOriginalEnvelope()); return coverage; } } }