[GIS] How to overlay a Shapefile on a WMS layer using Geotools

eclipsegeotoolsshapefilewms

I am trying to overlay a shp file on wms layer using the example http://docs.geotools.org/latest/userguide/tutorial/raster/image.html.

Each time I want to read the format of the file to get a reader I get this error :

Exception in thread "main" java.lang.UnsupportedOperationException: Trying to get a reader from an unknown format.
at org.geotools.coverage.grid.io.UnknownFormat.getReader(UnknownFormat.java:62)
at com.qedrix.map.maplotr.Demo1.displayLayers(Demo1.java:127)
at com.qedrix.map.maplotr.Demo1.main(Demo1.java:260)

My code follows:

public class Demo1 {

private AbstractGridCoverage2DReader reader = null;

private StyleFactory sf = CommonFactoryFinder.getStyleFactory();
private FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2();

/**
 * This method examines the names of the sample dimensions in the provided
 * coverage looking for "red...", "green..." and "blue..." (case insensitive
 * match). If these names are not found it uses bands 1, 2, and 3 for the
 * red, green and blue channels. It then sets up a raster symbolizer and
 * returns this wrapped in a Style.
 * 
 * @return a new Style object containing a raster symbolizer set up for RGB
 *         image
 */
private Style createRGBStyle() {
    GridCoverage2D cov = null;
    try {
        cov = reader.read(null);
    } catch (IOException giveUp) {
        throw new RuntimeException(giveUp);
    }
    // We need at least three bands to create an RGB style
    int numBands = cov.getNumSampleDimensions();
    if (numBands < 3) {
        return null;
    }
    // Get the names of the bands
    String[] sampleDimensionNames = new String[numBands];
    for (int i = 0; i < numBands; i++) {
        GridSampleDimension dim = cov.getSampleDimension(i);
        sampleDimensionNames[i] = dim.getDescription().toString();
    }
    final int RED = 0, GREEN = 1, BLUE = 2;
    int[] channelNum = { -1, -1, -1 };
    // We examine the band names looking for "red...", "green...",
    // "blue...".
    // Note that the channel numbers we record are indexed from 1, not 0.
    for (int i = 0; i < numBands; i++) {
        String name = sampleDimensionNames[i].toLowerCase();
        if (name != null) {
            if (name.matches("red.*")) {
                channelNum[RED] = i + 1;
            } else if (name.matches("green.*")) {
                channelNum[GREEN] = i + 1;
            } else if (name.matches("blue.*")) {
                channelNum[BLUE] = i + 1;
            }
        }
    }
    // If we didn't find named bands "red...", "green...", "blue..."
    // we fall back to using the first three bands in order
    if (channelNum[RED] < 0 || channelNum[GREEN] < 0 || channelNum[BLUE] < 0) {
        channelNum[RED] = 1;
        channelNum[GREEN] = 2;
        channelNum[BLUE] = 3;
    }
    // Now we create a RasterSymbolizer using the selected channels
    SelectedChannelType[] sct = new SelectedChannelType[cov.getNumSampleDimensions()];
    ContrastEnhancement ce = sf.contrastEnhancement(ff.literal(1.0), ContrastMethod.NORMALIZE);
    for (int i = 0; i < 3; i++) {
        sct[i] = sf.createSelectedChannelType(String.valueOf(channelNum[i]), ce);
    }
    RasterSymbolizer sym = sf.getDefaultRasterSymbolizer();
    ChannelSelection sel = sf.channelSelection(sct[RED], sct[GREEN], sct[BLUE]);
    sym.setChannelSelection(sel);

    return SLD.wrapSymbolizers(sym);
}

public void displayLayers() {

    File rasterFile = fetchWmsImage();

    AbstractGridFormat format = GridFormatFinder.findFormat(rasterFile);

    this.reader = format.getReader(rasterFile);

    // Initially display the raster in greyscale using the
    // data from the first image band
    Style rasterStyle = createRGBStyle();

    // Create a basic style with yellow lines and no fill
    Style shpStyle = SLD.createPointStyle("point", Color.YELLOW, Color.GRAY, 0.0f, 1.5f);

    MapContent map = new MapContent();
    map.setTitle("ImageLab");

    MapViewport vp = new MapViewport();

    org.geotools.map.Layer rasterLayer = new GridReaderLayer(reader, rasterStyle);
    map.addLayer(rasterLayer);

    saveImage(map, "final.jpeg", 583);

}

public File fetchWmsImage() {

    URL url = null;
    try {
        url = new URL("http://184.106.187.247:8080/geoserver/rg/wms?version=1.1.0");
    } catch (MalformedURLException e) {
        // will not happen
    }

    WebMapServer wms = null;
    try {
        wms = new WebMapServer(url);

        WMSCapabilities capabilities = wms.getCapabilities();
        Layer[] layers = WMSUtils.getNamedLayers(capabilities);

        GetMapRequest request = wms.createGetMapRequest();

        request.setFormat("image/png");
        request.setDimensions("583", "420");
        request.setTransparent(true);
        request.setSRS("EPSG:900913");
        request.setBBox("-13019428.542822,3922163.1648461,-13013051.407366,3929863.8567165");
        //request.setProperty("isBaseLayer", "false");
        //request.setProperty("opacity", ".2");

        for (Layer layer : WMSUtils.getNamedLayers(capabilities)) {
            if (layer.getName().equals("rg:parcels"))
                request.addLayer(layer);
        }

        System.out.println(request.getFinalURL());

        GetMapResponse response = (GetMapResponse) wms.issueRequest(request);
        BufferedImage image = ImageIO.read(response.getInputStream());

        File rasterFile = new File("C:\\Users\\samabhik\\Workspace\\MAP\\data\\out.png");
        ImageIO.write(image, "png", rasterFile);

        try{
            Thread.sleep(2000);
        }catch(InterruptedException e){}

        return rasterFile;

    } catch (ServiceException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } finally {

    }

    return null;
}

public void saveImage(final MapContent map, final String file, final int imageWidth) {

    GTRenderer renderer = new StreamingRenderer();
    renderer.setMapContent(map);

    Rectangle imageBounds = null;
    ReferencedEnvelope mapBounds = null;
    try {
        mapBounds = map.getMaxBounds();
        double heightToWidth = mapBounds.getSpan(1) / mapBounds.getSpan(0);
        imageBounds = new Rectangle(0, 0, imageWidth, (int) Math.round(imageWidth * heightToWidth));

    } catch (Exception e) {
        // failed to access map layers
        throw new RuntimeException(e);
    }

    BufferedImage image = new BufferedImage(imageBounds.width, imageBounds.height, BufferedImage.TYPE_INT_RGB);

    Graphics2D gr = image.createGraphics();
    gr.setPaint(Color.WHITE);
    gr.fill(imageBounds);

    try {
        renderer.paint(gr, imageBounds, mapBounds);
        File fileToSave = new File(file);
        ImageIO.write(image, "jpeg", fileToSave);

    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

public static void main(String[] args) {

    Demo1 demo = new Demo1();
    demo.displayLayers();
}

}

My pom dependency looks like this:

<dependency>
        <groupId>org.geotools</groupId>
        <artifactId>gt-shapefile</artifactId>
        <version>${geotools.version}</version>
    </dependency>
    <dependency>
        <groupId>org.geotools</groupId>
        <artifactId>gt-swing</artifactId>
        <version>${geotools.version}</version>
    </dependency>
    <dependency>
        <groupId>org.geotools</groupId>
        <artifactId>gt-epsg-hsql</artifactId>
        <version>${geotools.version}</version>
    </dependency>
    <dependency>
        <groupId>org.geotools</groupId>
        <artifactId>gt-geotiff</artifactId>
        <version>${geotools.version}</version>
    </dependency>
    <dependency>
        <groupId>org.geotools</groupId>
        <artifactId>gt-image</artifactId>
        <version>${geotools.version}</version>
    </dependency>
    <dependency>
        <groupId>org.geotools</groupId>
        <artifactId>gt-wms</artifactId>
        <version>${geotools.version}</version>
    </dependency>
    <dependency>
        <groupId>org.geotools</groupId>
        <artifactId>gt-coverage</artifactId>
        <version>${geotools.version}</version>
    </dependency>
    <dependency>
        <groupId>org.geotools</groupId>
        <artifactId>gt-imageio-ext-gdal</artifactId>
        <version>${geotools.version}</version>
    </dependency>

I am using geotools version 9-SNAPSHOT

I have added the native libraries from gdal in java classpath in eclipse.

I am totally stuck and don't know what's wrong.

I even tested the geoserver WMS URL and it works:

http://184.106.187.247:8080/geoserver/rg/wms?SERVICE=WMS&LAYERS=rg:parcels&ISBASELAYER=false&FORMAT=image/png&OPACITY=.2&HEIGHT=420&TRANSPARENT=TRUE&REQUEST=GetMap&BBOX=-13019428.542822,3922163.1648461,-13013051.407366,3929863.8567165&WIDTH=583&STYLES=&SRS=EPSG:900913&VERSION=1.1.1

Just ran gdalinfo.exe to read the image content and it follows:

Driver: PNG/Portable Network Graphics
Files: ..\..\Workspace\MAP\data\out2.png
Size is 583, 420
Coordinate System is `'
Image Structure Metadata:
  INTERLEAVE=PIXEL
Corner Coordinates:
Upper Left  (    0.0,    0.0)
Lower Left  (    0.0,  420.0)
Upper Right (  583.0,    0.0)
Lower Right (  583.0,  420.0)
Center      (  291.5,  210.0)
Band 1 Block=583x1 Type=Byte, ColorInterp=Red
  Mask Flags: PER_DATASET ALPHA
Band 2 Block=583x1 Type=Byte, ColorInterp=Green
  Mask Flags: PER_DATASET ALPHA
Band 3 Block=583x1 Type=Byte, ColorInterp=Blue
  Mask Flags: PER_DATASET ALPHA
Band 4 Block=583x1 Type=Byte, ColorInterp=Alpha

Best Answer

I think the answer is to use a WMSMapLayer instead of saving the map to disk and trying to reload it.

    MapContext mapcontext = new DefaultMapContext();
    mapcontext.setTitle( wms.getCapabilities().getService().getTitle() );

    for( Layer wmsLayer : wmsLayers ){
        WMSMapLayer displayLayer = new WMSMapLayer(wms, wmsLayer );
        mapcontext.addLayer( displayLayer );
    }
    // Now display the map
    JMapFrame.showMap(mapcontext);

See this tutorial for more details.

Related Question