Search code examples
javagisgeotools

save zoom image level to file


Let's say that I want to load an shp file, do my stuff on it and save the map as an image.

In order to save an image I am using:

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, "png", fileToSave);
      } catch (IOException e) {
          throw new RuntimeException(e);
      }
  }

But, let's say I am doing something like this:

...
MapContent map = new MapContent();
map.setTitle("TEST");
map.addLayer(layer);
map.addLayer(shpLayer);

// zoom into the line
MapViewport viewport = new MapViewport(featureCollection.getBounds());
map.setViewport(viewport);

saveImage(map, "/tmp/img.png", 800);

1) The problem is that the zoom level isn't saved on the image file.Is there a way to save it?

2) When I am doing MapViewport(featureCollection.getBounds()); is there a way to extend a little bit the boundaries in order to have a better visual representation?

...


Solution

  • The reason that you aren't saving the map at the current zoom level is that in your saveImage method you have the line:

    mapBounds = map.getMaxBounds();
    

    which always uses the full extent of the map, you can change this to

    mapBounds = map.getViewport().getBounds();
    

    You can expand a bounding box by something like:

        ReferencedEnvelope bounds = featureCollection.getBounds();
        double delta = bounds.getWidth()/20.0; //5% on each side
        bounds.expandBy(delta );
        MapViewport viewport = new MapViewport(bounds);
        map.setViewport(viewport );
    

    A quicker (and easier) way to save a map from the GUI is to use a method like this which just saves exactly what is on the screen:

    public void drawMapToImage(File outputFile, String outputType,
            JMapPane mapPane) {
        ImageOutputStream outputImageFile = null;
        FileOutputStream fileOutputStream = null;
        try {
            fileOutputStream = new FileOutputStream(outputFile);
            outputImageFile = ImageIO.createImageOutputStream(fileOutputStream);
            RenderedImage bufferedImage = mapPane.getBaseImage();
            ImageIO.write(bufferedImage, outputType, outputImageFile);
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (outputImageFile != null) {
                    outputImageFile.flush();
                    outputImageFile.close();
                    fileOutputStream.flush();
                    fileOutputStream.close();
                }
            } catch (IOException e) {// don't care now
            }
        }
    }