diff --git a/src/wms/src/main/java/org/geoserver/wms/map/DirectRasterRenderer.java b/src/wms/src/main/java/org/geoserver/wms/map/DirectRasterRenderer.java index 014ebcd421d..3c7fa486f81 100644 --- a/src/wms/src/main/java/org/geoserver/wms/map/DirectRasterRenderer.java +++ b/src/wms/src/main/java/org/geoserver/wms/map/DirectRasterRenderer.java @@ -4,7 +4,10 @@ */ package org.geoserver.wms.map; +import static org.geoserver.wms.map.RenderedImageMapOutputFormat.ADV_PROJECTION_HANDLING_FORMAT_OPTION; +import static org.geoserver.wms.map.RenderedImageMapOutputFormat.MAP_WRAPPING_FORMAT_OPTION; import static org.geoserver.wms.map.RenderedImageMapOutputFormat.getConfiguredLayerInterpolation; +import static org.geoserver.wms.map.RenderedImageMapOutputFormat.getFormatOptionAsBoolean; import static org.geoserver.wms.map.RenderedImageMapOutputFormat.toInterpolationObject; import static org.geotools.renderer.lite.gridcoverage2d.ChannelSelectionUpdateStyleVisitor.getBandIndicesFromSelectionChannels; @@ -243,7 +246,11 @@ public RenderedImage render() throws FactoryException { try { final Color readerBgColor = transparent ? null : bgColor; CoordinateReferenceSystem mapCRS = mapEnvelope.getCoordinateReferenceSystem(); - if (transformation == null && wms.isAdvancedProjectionHandlingEnabled()) { + boolean advancedProjectionHandling = + wms.isAdvancedProjectionHandlingEnabled() + && getFormatOptionAsBoolean( + mapContent.getRequest(), ADV_PROJECTION_HANDLING_FORMAT_OPTION); + if (transformation == null && advancedProjectionHandling) { image = readWithProjectionHandling(interpolationHints, readerBgColor, mapCRS); } else { // @@ -623,12 +630,21 @@ private Object readAndTransform( CoordinateReferenceSystem coverageCRS, GridGeometry2D readGG) throws IOException, SchemaException, TransformException, FactoryException { + + boolean advancedProjectionHandling = + wms.isAdvancedProjectionHandlingEnabled() + && getFormatOptionAsBoolean( + mapContent.getRequest(), ADV_PROJECTION_HANDLING_FORMAT_OPTION); + boolean continuousMapWrapping = + wms.isContinuousMapWrappingEnabled() + && getFormatOptionAsBoolean( + mapContent.getRequest(), MAP_WRAPPING_FORMAT_OPTION); RenderingTransformationHelper helper = new GCRRenderingTransformationHelper( mapContent, interpolation, - wms.isAdvancedProjectionHandlingEnabled(), - wms.isContinuousMapWrappingEnabled()); + advancedProjectionHandling, + continuousMapWrapping); Object result = helper.applyRenderingTransformation( transformation, @@ -716,7 +732,11 @@ private RenderedImage readWithProjectionHandling( new GridCoverageRenderer( mapCRS, mapEnvelope, mapRasterArea, worldToScreen, interpolationHints); gcr.setAdvancedProjectionHandlingEnabled(true); - gcr.setWrapEnabled(wms.isContinuousMapWrappingEnabled()); + boolean continuousMapWrappingEnabled = + wms.isContinuousMapWrappingEnabled() + && getFormatOptionAsBoolean( + mapContent.getRequest(), MAP_WRAPPING_FORMAT_OPTION); + gcr.setWrapEnabled(continuousMapWrappingEnabled); // use null background here, background color is handled afterwards RenderedImage image = gcr.renderImage( diff --git a/src/wms/src/main/java/org/geoserver/wms/map/RenderedImageMapOutputFormat.java b/src/wms/src/main/java/org/geoserver/wms/map/RenderedImageMapOutputFormat.java index 7a66b2ec98f..6a2ff99dc95 100644 --- a/src/wms/src/main/java/org/geoserver/wms/map/RenderedImageMapOutputFormat.java +++ b/src/wms/src/main/java/org/geoserver/wms/map/RenderedImageMapOutputFormat.java @@ -96,9 +96,8 @@ public class RenderedImageMapOutputFormat extends AbstractMapOutputFormat { private static final List AA_SETTINGS = Arrays.asList(AA_NONE, AA_TEXT, AA_FULL); - private static final String MAP_WRAPPING_FORMAT_OPTION = "mapWrapping"; - private static final String ADV_PROJECTION_HANDLING_FORMAT_OPTION = - "advancedProjectionHandling"; + public static final String MAP_WRAPPING_FORMAT_OPTION = "mapWrapping"; + public static final String ADV_PROJECTION_HANDLING_FORMAT_OPTION = "advancedProjectionHandling"; private static final String ADV_PROJECTION_DENSIFICATION_FORMAT_OPTION = "advancedProjectionHandlingDensification"; private static final String DISABLE_DATELINE_WRAPPING_HEURISTIC_FORMAT_OPTION = @@ -638,7 +637,7 @@ protected StreamingRenderer buildRenderer() { return new StreamingRenderer(); } - private boolean getFormatOptionAsBoolean( + public static boolean getFormatOptionAsBoolean( final GetMapRequest request, final String formatOptionKey) { if (request.getFormatOptions().get(formatOptionKey) != null) { String formatOptionValue = (String) request.getFormatOptions().get(formatOptionKey); diff --git a/src/wms/src/test/java/org/geoserver/wms/map/RenderedImageMapOutputFormatTest.java b/src/wms/src/test/java/org/geoserver/wms/map/RenderedImageMapOutputFormatTest.java index 2ebcca5ac83..e89f4dae288 100644 --- a/src/wms/src/test/java/org/geoserver/wms/map/RenderedImageMapOutputFormatTest.java +++ b/src/wms/src/test/java/org/geoserver/wms/map/RenderedImageMapOutputFormatTest.java @@ -102,6 +102,7 @@ import org.geotools.geometry.GeneralBounds; import org.geotools.geometry.jts.LiteShape2; import org.geotools.geometry.jts.ReferencedEnvelope; +import org.geotools.image.ImageWorker; import org.geotools.image.test.ImageAssert; import org.geotools.image.util.ImageUtilities; import org.geotools.map.FeatureLayer; @@ -685,12 +686,87 @@ public void testDirectVsNonDirectRasterRender() throws Exception { RenderedImageMap imageMap = this.rasterMapProducer.produceMap(map); ImageAssert.assertEquals( - new File("src/test/resources/org/geoserver/wms/map/direct-raster-expected.tif"), + new File("src/test/resources/org/geoserver/wms/map/direct-raster-expected.png"), imageMap.getImage(), 0); imageMap.dispose(); } + @Test + public void testDirectRasterRenderRespectingFormatOptions() throws Exception { + Catalog catalog = getCatalog(); + CoverageInfo ci = + catalog.getCoverageByName( + SystemTestData.WORLD.getPrefix(), SystemTestData.WORLD.getLocalPart()); + + CoordinateReferenceSystem crs = DefaultGeographicCRS.WGS84; + + // Request an area going over the dateline + ReferencedEnvelope bbox = + new ReferencedEnvelope(new Envelope(115.0, 315.0, -60.0, 60.0), crs); + + GetMapRequest request = new GetMapRequest(); + request.setBbox(bbox); + request.setSRS("urn:x-ogc:def:crs:EPSG:4326"); + request.setFormat("image/png"); + + testWithFormatOptions(ci, request, bbox, false); + testWithFormatOptions(ci, request, bbox, true); + } + + private void testWithFormatOptions( + CoverageInfo ci, + GetMapRequest request, + ReferencedEnvelope bbox, + boolean formatOptionsEnabled) + throws IOException { + request.getFormatOptions().put("mapWrapping", Boolean.toString(formatOptionsEnabled)); + request.getFormatOptions() + .put("advancedProjectionHandling", Boolean.toString(formatOptionsEnabled)); + + final WMSMapContent map = new WMSMapContent(request); + final float width = 400; + map.setMapWidth((int) width); + map.setMapHeight(240); + map.setBgColor(Color.red); + map.setTransparent(false); + map.getViewport().setBounds(bbox); + + StyleBuilder builder = new StyleBuilder(); + GridCoverage2DReader reader = (GridCoverage2DReader) ci.getGridCoverageReader(null, null); + reader.getCoordinateReferenceSystem(); + Layer l = + new CachedGridReaderLayer( + reader, builder.createStyle(builder.createRasterSymbolizer())); + map.addLayer(l); + + RenderedImageMap imageMap = this.rasterMapProducer.produceMap(map); + RenderedImage image = imageMap.getImage(); + float xOffset = 150; + ImageWorker worker = + new ImageWorker(image) + .crop(xOffset, 0, width - xOffset, 240) + .translate(-xOffset, 0, null); + + if (formatOptionsEnabled) { + // We have enabled continuous map wrapping. + // So cropping over the dateline we will see again + // North and South America + ImageAssert.assertEquals( + new File( + "src/test/resources/org/geoserver/wms/map/direct-raster-format-options-expected.png"), + worker.getRenderedImage(), + 10); + } else { + // We have disabled the continuous map wrapping format option. + // So cropping over the dateline we will only see RED background color + // filling the image + // Assert that we get everything red + assertArrayEquals(new double[] {255, 0, 0}, worker.getMinimums(), 1E-6); + assertArrayEquals(new double[] {255, 0, 0}, worker.getMaximums(), 1E-6); + } + } + @Test public void testTimeoutOption() throws Exception { Catalog catalog = getCatalog(); @@ -1497,7 +1573,7 @@ public void testBandSelectionToNormalCoverage() throws Exception { RenderedImageMap imageMap = this.rasterMapProducer.produceMap(map); ImageAssert.assertEquals( - new File("src/test/resources/org/geoserver/wms/map/direct-raster-expected.tif"), + new File("src/test/resources/org/geoserver/wms/map/direct-raster-expected.png"), imageMap.getImage(), 0); imageMap.dispose(); diff --git a/src/wms/src/test/resources/org/geoserver/wms/map/direct-raster-expected.tif b/src/wms/src/test/resources/org/geoserver/wms/map/direct-raster-expected.png similarity index 100% rename from src/wms/src/test/resources/org/geoserver/wms/map/direct-raster-expected.tif rename to src/wms/src/test/resources/org/geoserver/wms/map/direct-raster-expected.png diff --git a/src/wms/src/test/resources/org/geoserver/wms/map/direct-raster-format-options-expected.png b/src/wms/src/test/resources/org/geoserver/wms/map/direct-raster-format-options-expected.png new file mode 100644 index 00000000000..48c5d83f93d Binary files /dev/null and b/src/wms/src/test/resources/org/geoserver/wms/map/direct-raster-format-options-expected.png differ