1

I'am trying to print an OSM tiles in a given bounding box using geotools and the tile client,i have implemented a wms service that can read a wms request and render the image in a given boudning box, the OSM layer is used as a base layer,i have other layers that are vector layers that i can add later,vector layer are displayed correctly in the given bounding box but osm tiles are not displayed ,the Url used for sending the request to the osm server don't get any response ?i have the following error :

2020-05-27 16:03:00.291 ERROR 26094 --- [pool-6-thread-1] org.geotools.tile                        : Failed to load image: https://tile.openstreetmap.org/8/123/106.png

java.io.IOException: Can't create an ImageInputStream!
    at org.geotools.image.io.ImageIOExt.read(ImageIOExt.java:339) ~[gt-coverage-22.2.jar:na]
    at org.geotools.image.io.ImageIOExt.readBufferedImage(ImageIOExt.java:402) ~[gt-coverage-22.2.jar:na]
    at org.geotools.tile.Tile.loadImageTileImage(Tile.java:175) ~[gt-tile-client-22.2.jar:na]
    at org.geotools.tile.Tile.getBufferedImage(Tile.java:163) ~[gt-tile-client-22.2.jar:na]
    at org.geotools.tile.util.TileLayer.getTileImage(TileLayer.java:143) [gt-tile-client-22.2.jar:na]
    at org.geotools.tile.util.TileLayer.renderTile(TileLayer.java:131) [gt-tile-client-22.2.jar:na]
    at org.geotools.tile.util.TileLayer.renderTiles(TileLayer.java:125) [gt-tile-client-22.2.jar:na]
    at org.geotools.tile.util.TileLayer.draw(TileLayer.java:86) [gt-tile-client-22.2.jar:na]
    at org.geotools.renderer.lite.CompositingGroup$WrappingDirectLayer.draw(CompositingGroup.java:228) [gt-render-22.2.jar:na]
    at org.geotools.renderer.lite.StreamingRenderer$RenderDirectLayerRequest.execute(StreamingRenderer.java:3850) [gt-render-22.2.jar:na]
    at org.geotools.renderer.lite.StreamingRenderer$PainterThread.run(StreamingRenderer.java:3911) [gt-render-22.2.jar:na]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_232]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_232]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_232]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_232]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_232]

the image represent the result of a wms request send from postman with a fake layer to have only osm tiles

the second image show a polygon layer that is displayed in the given bounding box but osm tile layer from the background is not displayed

for the source code these is how i add the osm tile layer :

MapContent mapContent = new MapContent();
String baseURL = "https://tile.openstreetmap.org/";
TileService service = new OSMService("OSM", baseURL);
mapContent.addLayer(new TileLayer(service));

later i print it using gt-render :

StreamingRenderer renderer = new StreamingRenderer();
renderer.setMapContent(map);
ReferencedEnvelope mapBounds = mapRequest.getReferencedEnvelope();
Rectangle imageBounds = new Rectangle(0, 0, mapRequest.getWidth(), mapRequest.getHeight());

map.getViewport().setScreenArea(imageBounds);
map.getViewport().setBounds( mapBounds );

BufferedImage image = new BufferedImage(mapRequest.getWidth(), mapRequest.getHeight(),BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D gr = image.createGraphics();

gr.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));

int threads = Runtime.getRuntime().availableProcessors();
ExecutorService fixedPool = Executors.newFixedThreadPool(threads - 1);
        renderer.setThreadPool(fixedPool);

try {
        renderer.paint(gr, imageBounds, mapBounds);
        ImageIO.write(image, imageExtension, os);
    } 
catch (IOException e) {
            throw new RuntimeException(e);
    }

gr.dispose();
map.dispose();

i have a hard coded version of the source code to test it:

  public void test(OutputStream os) throws NoSuchAuthorityCodeException, FactoryException {

        MapContent map = new MapContent();

        String baseURL = "https://tile.openstreetmap.org/";
        TileService service = new OSMService("OSM", baseURL);
        map.addLayer(new TileLayer(service));

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

        CoordinateReferenceSystem crs = CRS.decode("EPSG:3857");

        ReferencedEnvelope mapBounds = new ReferencedEnvelope(-939258.203568246,-626172.1357121639,3130860.67856082,3443946.746416902,crs);
        Rectangle imageBounds = new Rectangle(0, 0, 256, 256);

        map.getViewport().setScreenArea(imageBounds);
        map.getViewport().setBounds( mapBounds );

        BufferedImage image = new BufferedImage(256, 256,
                BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D gr = image.createGraphics();

        gr.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));

        try {
            renderer.paint(gr, imageBounds, mapBounds);
            ImageIO.write(image, imageExtension, os);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        gr.dispose();
        map.dispose();
    }
  • what is your Java tempdir set to? – Ian Turton May 27 '20 at 16:05
  • I checked with System.out.println(System.getProperty("java.io.tmpdir")); it returns "/tmp" ,i'am under ubuntu linux – Achrouf Abdenour May 27 '20 at 16:15
  • That line is simply calling ImageIOExt.readBufferedImage(getUrl()); on the URL (which is a good one) - does your process have access to the internet? or do you need to set up a proxy gateway or something? – Ian Turton May 27 '20 at 16:21
  • Yes I'am connected to the internet and there is no proxy. – Achrouf Abdenour May 27 '20 at 16:24
  • Then I can't think what is happening. Can you add a minimum viable example and I'll try to have a quick look – Ian Turton May 27 '20 at 16:39
  • I updated the question with a hard coded source code to test ,i have given the bounding box and other paramters ,you only need to specify your output stream to test the image output format.I hope these can help.thank you. – Achrouf Abdenour May 27 '20 at 16:52

1 Answers1

1

The problem seems to be that OpenStreetMap will return an HTTP-429 error (Too Many Requests) if you don't set a valid User-Agent header in your requests.

I'm assuming this is a new requirement since the OSM tile code was last used or tested. Though looking at the test it may not actually fetch a tile to render.

I've raised a bug against gt-tile-client at the issue tracker and I have a PR to fix the issue, to add a header in as the WMTSTile implementation does.

It should be available in the master nightly build later today 30/5/2020.

Ian Turton
  • 10,018
  • 1
  • 28
  • 47