3

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

I am continuously getting the 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:121)
at com.qedrix.map.maplotr.Demo1.main(Demo1.java:229)

when the code tries to read the WMS image.

My code looks like this:

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);
        }

        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);

        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>

Somewhere I read that it could a GDAL issue. But I couldn't figure out how to resolve it. I am using eclipse on 64 JDK 1.6 and Win 7 amd64.

Please help, someone..

Just tested the image file using gdalinfo.exe found in the GDAL native libraries path. Here's the report:

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

FURTHER UPDATES

I just tried and changed the out format for WMS from images/png to images/geotiff and this now works partially ( the final image that is generated by geotools is Black & White). Why this is happening? And why it didn't work with PNG?

john_science
  • 6,325
  • 6
  • 43
  • 60
Qedrix
  • 453
  • 1
  • 8
  • 15
  • Can you print out the url of the request and then check it works in a browser. try opening the image on disk using a browser too. It is possible that you are getting an error not an image back. – Ian Turton Nov 03 '12 at 07:46
  • This is the URL and the image looks OK to me [link] (http://184.106.187.247:8080/geoserver/rg/wms?SERVICE=WMS&LAYERS=rg%3Aparcels&ISBASELAYER=false&FORMAT=image%2Fpng&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) – Qedrix Nov 03 '12 at 12:39

1 Answers1

4

Check that you have JAI and ImageIO avaialble. Either via maven dependency, or by installing them as Java Extensions as outlined in the Quickstart.

Update:

I was able to catch up on the GeoTools IRC channel and confirm this is an environment issue. In class works for me fashion I was able to connect using the WMSLab tutorial example to the WMS in question and display results.

So lets check out "problem" environment::

System.out.println( GeoTools.getAboutInfo() );

Result::

GeoTools version 9-SNAPSHOT (built from ree5a6830d2c774ee9a4eb9e024d989c2a1bcdfe3) Java version: 1.7.0_09 Operating system: Windows 7 6.1 GeoTools jars on classpath:

A couple ideas:

  • Check out the ImageLab to confirm JAI / ImageIO is availble?

This worked!

  • Save the image retrieved from the browser and try loading it using straight up Java

Example from WorldImageReader::

File input = ...
ImageInputStreamSpi inStreamSPI= ImageIOExt.getImageInputStreamSPI( input );
if (inStreamSPI == null) throw new IllegalStateException("Unsuppported");

Apparently this was not successful?

  • GeoTools has not gone through QA on Java 7 yet, downgrade to Java 6?

Recently a Java 7 build box has been volunteered. When GeoTools works in Java 7 the release notes and tutorials will be updated.

  • Especially on windows the implementation of PNG support is suspect.

The following code from the uDig project disables the native implementation allowing the pure Java implementation to have a crack at it::

 if (Platform.getOS().equals(Platform.OS_WIN32)) {
        try {
            // PNG native support is not very good .. this turns it off
            ImageUtilities.allowNativeCodec("png", ImageReaderSpi.class, false); //$NON-NLS-1$
        } catch (Throwable t) {
            // we should not die if JAI is missing; we have a warning for that...
            System.out.println("Difficulty turnning windows native PNG support (which will result in scrambled images from WMS servers)"); //$NON-NLS-1$
            t.printStackTrace();
        }
    }
Jody Garnett
  • 503
  • 3
  • 10
  • I tried running the java file again using JDK 1.6 x86 and also use the code 'if(System.getProperty("os.arch").toLowerCase().equals("x86")){ System.out.println("---"); ImageUtilities.allowNativeCodec("png", ImageReaderSpi.class, false); //$NON-NLS-1$ }' to disable native implemention. Didn't work - same error message. – Qedrix Nov 04 '12 at 10:03
  • I also observed a few things. When I try to read a jpg file which has an accompanying .jgw file in the same folder (i picked these up from the sample files), my code works perfect. When I try to run the code without a .jgw file, the same error is thrown. Why do we need this .jgw file? how am I supposed to create one with WMS image? – Qedrix Nov 04 '12 at 10:34
  • @Qedrix Asking within comments is strongly discouraged. Please post it on a separate question so others can learn from your experience, too. – R.K. Nov 05 '12 at 01:12