美文网首页GIS加油站
Java实现地图的导出

Java实现地图的导出

作者: 牛老师讲webgis | 来源:发表于2021-11-17 22:42 被阅读0次

    概述

    前文讲了在前端实现地图的导出,本文简单的通过java实现一下后端地图的导出。

    实现效果

    实现效果

    实现代码

    package com.lzugis.image;
    
    import sun.misc.BASE64Decoder;
    import javax.imageio.ImageIO;
    import java.awt.*;
    import java.awt.image.BufferedImage;
    import java.io.ByteArrayInputStream;
    import java.io.File;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.util.Date;
    
    public class MapPrint {
    
        static int TILE_SIZE = 256;
        static double RES_ZERO = 156543.03392804097;
        static double[] resolutions = new double[19];
        static int ZOOM = 4;
    
        public static void main(String[] args) {
            long start = new Date().getTime();
            System.out.println("开始出图。。。");
            double res = RES_ZERO;
            for (int i = 0; i < 19; i++) {
                resolutions[i] = res;
                res = res / 2;
            }
            double[] extent = {4816313.49458338, 1168266.6364252055, 19000980.555761307, 7826564.13063698};
            int[] rowCol = getTileRowCol(extent);
    
            int xmin = rowCol[0];
            int xmax = rowCol[1];
            int ymin = rowCol[2];
            int ymax = rowCol[3];
    
            int width = (xmax - xmin) * TILE_SIZE;
            int height = (ymax - ymin) * TILE_SIZE;
            try {
                BufferedImage mergeImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
                Graphics2D graphics2D = mergeImage.createGraphics();
                for (int i = xmin; i <= xmax ; i++) {
                    for (int j = ymin; j <= ymax ; j++) {
                        String destUrl = "http://webrd01.is.autonavi.com/appmaptile?x="+i+"&y="+j+"&z="+ZOOM+"&lang=zh_cn&size=1&scale=1&style=8";
                        BufferedImage tile = getBufferedImageDestUrl(destUrl);
                        int x = (i - xmin) * TILE_SIZE;
                        int y = (j -ymin) * TILE_SIZE;
                        graphics2D.drawImage(tile, x, y, TILE_SIZE, TILE_SIZE, null);
                    }
                }
    
                // 添加wms图层
                String extentStr = extent[0]+"," + extent[1]+"," + extent[2]+"," + extent[3];
                String wmsUrl = "http://localhost:8081/geoserver/ecodrought/wms?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&FORMAT=image%2Fpng&TRANSPARENT=true&LAYERS=ecodrought%3Apaddy-rice&CRS=EPSG%3A3857&SRS=EPSG%3A3857&WIDTH="+width+"&HEIGHT="+height+"&STYLES=&BBOX="+extentStr;
                BufferedImage wms = getBufferedImageDestUrl(wmsUrl);
                System.out.println(wmsUrl);
                graphics2D.drawImage(wms, 0, 0, width, height, null);
    
                // 添加地图标题
                String mapTitle = "地图导出测试";
                graphics2D.setColor(new Color(255,0,0,255));
    
                Font font = new Font("微软雅黑", Font.BOLD, 24);
                graphics2D.setFont(font);
                int length = graphics2D.getFontMetrics(graphics2D.getFont()).charsWidth(mapTitle.toCharArray(), 0, mapTitle.length());
                int posx = 60, posy = 80, offest = 15;
                graphics2D.drawString(mapTitle, posx, posy);
                graphics2D.setStroke(new BasicStroke(2.0f));
                int x1 = posx - offest, y1 = posy - offest - 18, x2 = posx + length + offest, y2 = posy + offest + 6;
                graphics2D.drawLine(x1, y1, x2, y1);
                graphics2D.drawLine(x2, y1, x2, y2);
                graphics2D.drawLine(x2, y2, x1, y2);
                graphics2D.drawLine(x1, y2, x1, y1);
    
                // 添加指北针
                String base64 = "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";
                int w =50, h = 50, x = width - w - posx;
                graphics2D.drawImage(base64ToBufferedImage(base64), x , posx, w, h, null);
    
                // 保存图片
                generateSaveFile(mergeImage, "merge.png");
    
                long end = new Date().getTime();
                System.out.println(String.format("出图结束,耗时%sms", end - start));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * 获取切片行列号
         * @param {double[]} extent - 出图四至,格式为[xmin, ymin, xmax, ymax]
         * @return {int[]} - 切片的行列号范围
         */
        public static int[] getTileRowCol (double[] extent) {
            if(extent.length != 4) return new int[]{};
            double originY = RES_ZERO * TILE_SIZE / 2;
            double originX = -originY;
            double res = resolutions[ZOOM] * TILE_SIZE;
            int xmin = (int) Math.floor((extent[0] - originX) / res);
            int xmax = (int) Math.ceil((extent[2] - originX) / res);
            int ymax = (int) Math.ceil((originY - extent[1]) / res);
            int ymin = (int) Math.floor((originY - extent[3]) / res);
            // 往周围扩充一圈
            return new int[]{ xmin + 1, xmax - 1, ymin + 1, ymax - 1 };
        }
    
        /**
         * 远程图片转BufferedImage
         * @return {BufferedImage} - 返回图片BufferedImage
         */
        public static BufferedImage getBufferedImageDestUrl(String destUrl) {
            HttpURLConnection conn = null;
            BufferedImage image = null;
            try {
                URL url = new URL(destUrl);
                conn = (HttpURLConnection) url.openConnection();
                if (conn.getResponseCode() == 200) {
                    image = ImageIO.read(conn.getInputStream());
                    return image;
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                conn.disconnect();
            }
            return image;
        }
    
        /**
         * base64转BufferedImage
         * @param {String} base64
         * @return {BufferedImage}
         * @throws Exception
         */
        public static BufferedImage base64ToBufferedImage(String base64) throws Exception {
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] result = decoder.decodeBuffer(base64);
            InputStream stream = new ByteArrayInputStream(result);
            BufferedImage bufferedImage = ImageIO.read(stream);
            return bufferedImage;
        }
    
        /**
         * 输出图片
         * @param buffImg  图像拼接叠加之后的BufferedImage对象
         * @param savePath 图像拼接叠加之后的保存路径
         */
        public static void generateSaveFile(BufferedImage buffImg, String savePath) {
            int temp = savePath.lastIndexOf(".") + 1;
            try {
                File outFile = new File(savePath);
                if(!outFile.exists()){
                    outFile.createNewFile();
                }
                ImageIO.write(buffImg, savePath.substring(temp), outFile);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    

    实现分析

    上面的实现中,实现了两类图层的叠加:底图切片和WMS图层的加载。底图切片的核心加载逻辑是通过传入的四至和地图级别计算需要叠加的切片的x和y的范围,并计算合并后的图片的大小,wms加载的逻辑是通过传入的四至和计算好的图片大小,再通过参数url和layers获取对应的图层的图片,再将两个图片合并。

    相关文章

      网友评论

        本文标题:Java实现地图的导出

        本文链接:https://www.haomeiwen.com/subject/yfvrtrtx.html