/* (c) 2014 - 2016 Open Source Geospatial Foundation - all rights reserved
* (c) 2001 - 2013 OpenPlans
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wms.map;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.awt.image.ColorModel;
import java.awt.image.RenderedImage;
import java.awt.image.SampleModel;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.xml.namespace.QName;
import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CatalogBuilder;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.catalog.CoverageStoreInfo;
import org.geoserver.catalog.CoverageView;
import org.geoserver.catalog.CoverageView.CompositionType;
import org.geoserver.catalog.CoverageView.CoverageBand;
import org.geoserver.catalog.CoverageView.InputCoverageBand;
import org.geoserver.data.test.MockData;
import org.geoserver.data.test.SystemTestData;
import org.geoserver.data.test.SystemTestData.LayerProperty;
import org.geoserver.data.test.TestData;
import org.geoserver.wms.CachedGridReaderLayer;
import org.geoserver.wms.GetMapRequest;
import org.geoserver.wms.WMSMapContent;
import org.geoserver.wms.WMSTestSupport;
import org.geoserver.wms.map.RenderedImageMapOutputFormatTest.DummyRasterMapProducer;
import org.geotools.coverage.grid.io.GridCoverage2DReader;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.filter.IllegalFilterException;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.map.Layer;
import org.geotools.styling.NamedLayer;
import org.geotools.styling.SLDParser;
import org.geotools.styling.Style;
import org.geotools.styling.StyledLayerDescriptor;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletResponse;
/**
* @author Nicola Lagomarsini
*/
public class RenderedImageMapOutputFormatExtendedTest extends WMSTestSupport {
private static final QName MOSAIC_HOLES = new QName(MockData.SF_URI, "mosaic_holes",
MockData.SF_PREFIX);
private static final String RGB_IR_VIEW = "RgbIrView";
private static final QName IR_RGB = new QName(MockData.SF_URI, "ir-rgb", MockData.SF_PREFIX);
private RenderedImageMapOutputFormat rasterMapProducer;
@Before
public void setRasterMapProducer() throws Exception {
this.rasterMapProducer = getProducerInstance();
}
protected RenderedImageMapOutputFormat getProducerInstance() {
return new DummyRasterMapProducer(getWMS());
}
@After
public void unsetRasterMapProducer() throws Exception {
this.rasterMapProducer = null;
}
@BeforeClass
public static void setup() {
System.setProperty("ENABLE_ADVANCED_PROJECTION", "false");
}
@Override
protected void onSetUp(SystemTestData testData) throws Exception {
super.onSetUp(testData);
Map properties = new HashMap();
properties.put(LayerProperty.STYLE, "raster");
final Catalog cat = getCatalog();
testData.addRasterLayer(MOSAIC_HOLES, "mosaic_holes.zip", null, properties,
RenderedImageMapOutputFormatExtendedTest.class, cat);
testData.addRasterLayer(IR_RGB, "ir-rgb.zip", null, null, TestData.class, cat);
// setup the coverage view
final CoverageStoreInfo storeInfo = cat.getCoverageStoreByName("ir-rgb");
final CoverageView coverageView = buildRgbIRView();
final CatalogBuilder builder = new CatalogBuilder(cat);
builder.setStore(storeInfo);
final CoverageInfo coverageInfo = coverageView.createCoverageInfo(RGB_IR_VIEW, storeInfo,
builder);
coverageInfo.getParameters().put("USE_JAI_IMAGEREAD", "false");
coverageInfo.getDimensions().get(0).setName("Red");
coverageInfo.getDimensions().get(1).setName("Green");
coverageInfo.getDimensions().get(2).setName("Blue");
coverageInfo.getDimensions().get(3).setName("Infrared");
cat.add(coverageInfo);
}
private CoverageView buildRgbIRView() {
final CoverageBand rBand = new CoverageBand(
Arrays.asList(new InputCoverageBand("rgb", "0")), "rband", 0,
CompositionType.BAND_SELECT);
final CoverageBand gBand = new CoverageBand(
Arrays.asList(new InputCoverageBand("rgb", "1")), "gband", 1,
CompositionType.BAND_SELECT);
final CoverageBand bBand = new CoverageBand(
Arrays.asList(new InputCoverageBand("rgb", "2")), "bband", 2,
CompositionType.BAND_SELECT);
final CoverageBand irBand = new CoverageBand(
Collections.singletonList(new InputCoverageBand("ir", "0")), "irband", 3,
CompositionType.BAND_SELECT);
final CoverageView coverageView = new CoverageView(RGB_IR_VIEW,
Arrays.asList(rBand, gBand, bBand, irBand));
return coverageView;
}
/**
* Test to check that a channel selection after a renderingTransformation involving
* an optimized read with underlying BANDS selection will not thrown an exception,
* by updating the band select accordingly
*/
@Test
public void testRenderingTransformationChannelsSelectionFromCoverageView() throws Exception {
final Catalog catalog = getCatalog();
// Get the RGB-IR View which is combining an RGB GeoTIFF and an IR GeoTIFF
final CoverageInfo ci = catalog.getCoverageByName(RGB_IR_VIEW);
final GridCoverage2DReader reader = (GridCoverage2DReader) ci.getGridCoverageReader(null, null);
final ReferencedEnvelope bbox = new ReferencedEnvelope(reader.getOriginalEnvelope());
final GetMapRequest request = new GetMapRequest();
request.setBbox(bbox);
request.setSRS("urn:x-ogc:def:crs:EPSG:32632");
request.setFormat("image/png");
final WMSMapContent map = new WMSMapContent(request);
map.setMapWidth(20);
map.setMapHeight(20);
map.setTransparent(false);
map.getViewport().setBounds(bbox);
// Setup a style
final SLDParser parser = new SLDParser(CommonFactoryFinder.getStyleFactory());
parser.setInput(RasterSymbolizerVisitorTest.class.getResource("CropTransformAndChannelSelect.sld"));
final StyledLayerDescriptor sld = parser.parseSLD();
final NamedLayer ul = (NamedLayer) sld.getStyledLayers()[0];
final Style style = ul.getStyles()[0];
final Layer dl = new CachedGridReaderLayer(reader, style);
map.addLayer(dl);
// Without the symbolizer update fix, the rendering would have thrown a
// "java.lang.IllegalArgumentException: Band number 4 is not valid."
// trying to do a band select on the 4th element to setup the gray channel.
// However, the optimized read performed through the BANDS parameter
// returned the IR image only so the channel selection
// should have been updated with a proper index (as part of the fix)
// as already made in the path not involving a RenderingTransformation.
RenderedImageMap dstImageMap = this.rasterMapProducer.produceMap(map);
RenderedImage destImage = dstImageMap.getImage();
assertNotNull(destImage);
ColorModel cm = destImage.getColorModel();
SampleModel sm = destImage.getSampleModel();
assertTrue(cm.getColorSpace().getNumComponents() == 1);
assertTrue(sm.getNumBands() == 1);
dstImageMap.dispose();
map.dispose();
}
/**
* Test to check that disabling ADVANCED PROJECTION HANDLING will not return a blank image
*/
@Test
public void testMosaicNoProjection() throws IOException, IllegalFilterException, Exception {
// Request
MockHttpServletResponse response = getAsServletResponse("wms?BBOX=6.40284375,36.385494140625,12.189662109375,42.444494140625"
+ "&styles=&layers=sf:mosaic_holes&Format=image/png"
+ "&request=GetMap"
+ "&width=550" + "&height=250" + "&srs=EPSG:4326");
checkImage(response);
}
@AfterClass
public static void after() {
System.setProperty("ENABLE_ADVANCED_PROJECTION", "true");
}
}