gdal可以说是GIS数据处理比较好的工具之一,虽然也提供了Java API,但是官方文档确实太过简单,用起来确实太难受,每次都需要去参考对应的C++api,然后在对应使用。

因此小编决定从这篇文章开始,将自己以前以及今后用到的API,都记录下,以帮助更多从事java GIS服务开发者。

今天主要来记录栅格数据的裁剪功能,gdal中提供了多种裁剪方法,今天主要介绍以下两种:

第一中是通过gdal自身的Warp方法,其实现有以下几个接口;

public static int Warp(Dataset dstDS, Dataset[] object_list_count, WarpOptions warpAppOptions, ProgressCallback callback);

public static int Warp(Dataset dstDS, Dataset[] object_list_count, WarpOptions warpAppOptions);

public static Dataset Warp(String dest, Dataset[] object_list_count, WarpOptions warpAppOptions, ProgressCallback callback);

public static Dataset Warp(String dest, Dataset[] object_list_count, WarpOptions warpAppOptions);

其实这个几个接口基本差不多

1、dstDs/dest 其实就是目标数据,两种方式,要么传入目标路径,要么是目标Dataset

2、object_list_count 这个是源数据的Dataset 数据

3、warpAppOptions 这个参数很重要,是我们裁剪需要传递的重要参数,后面代码会专门解释

4、callback 处理进度

下面我们结合最后一个方法,来处理一个栅格裁剪

private static void cutTif() throws FactoryException, IOException, ParseException {
Dataset dataSet = gdal.Open("E:\\数据\\影像数据\\tiff\\xian18.tif");
//通过最大最小经纬度生成一个面矢量
createCutShapeRegion(108.583740,33.928528,108.883740,34.260242);
Vector vector = new Vector();
vector.add("-cutline");
vector.add("D:\\data\\cut2.shp");
vector.add("-crop_to_cutline");
Dataset ds = gdal.Warp("D:\\data\\xian18_1.tif",new Dataset[]{dataSet},new WarpOptions(vector));
if (ds != null){
System.out.println("成功!");
}
}
createCutShapeRegion是用通过bbox来生成shape数据的,我这边是用矩形来裁剪的,当然你也可以用多边形,通过传入多边形的顶点来生层一个面矢量,记住一定是面矢量,
D:\\data\\cut2.shp是createCutShapeRegion生成的矢量文件,最主要的两个参数一个是-cutline 一个是-crop_to_cutline,其中-cutline后面跟裁剪的矢量文件,-crop_to_cutline不需要具体值,这些具体参数可参考gdal的warp的参数介绍,其实和安装版gdalwarp的参数是基本一致的。

但是这里说明下,并不是gdalwarp的所有参数都在gdal的java api中进行了适配,就比如gdalwarp这个命令中除了上面使用shp作为裁剪之外,还有一个-te参数,这个参数后面跟一个经纬度的范围
主要作用就是将原始数据裁剪为制定的范围,就比如我们使用安装的gdal中可以这样调用裁剪
gdalwarp.exe -te 108.583740 33.928528 108.883740 34.260242  E:\\数据\\影像数据\\tiff\\xian18.tif D:\\data\\xian18_2.tif
然而这个-te参数如果使用代码来调用,就会报没有-te这个option,就比如下面的这个例子其实是跑不通的
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException, FactoryException, IOException, ParseException {
gdal.AllRegister();
Dataset dataSet = gdal.Open("E:\\数据\\影像数据\\tiff\\xian18.tif");
Vector vector = new Vector();
vector.add("-te");
vector.add("108.583740 33.928528 108.883740 34.260242"); //裁剪范围
vector.add("-crop_to_cutline");
Dataset ds = gdal.Warp("D:\\data\\xian18_1.tif",new Dataset[]{dataSet},new WarpOptions(vector));
}

上述代码是跑不通的,虽然安装板的gdalwarp可以使用-te来裁剪,而且效率比上面使用shp要更快,但是java代码的api却没有集成这个-te参数,当然我不知道是我调用的问题,还是确实没有适配

如果有了解的朋友,麻烦告知一声。

除了上述使用gdalwarp的接口外,我们还可以通过使用driver来快速裁剪出一个tif,具体代码如下

private static void clipRaster(Dataset dataset, Envelope boundingBox){
//获取当前数据范围
ReferencedEnvelope originalEnvelope = (ReferencedEnvelope) GdalDataAnalysis.readBboxFromFile(dataset);
//判断是否相交,不想交则直接返回
if (!originalEnvelope.intersects(boundingBox)){
return;
}
//求请求与原始数据的范围
ReferencedEnvelope interEnvelope = originalEnvelope.intersection(boundingBox);
//原始数据上偏移位置
int offset_x = (int) ((interEnvelope.getMinX() - originalEnvelope.getMinX()) / GdalDataAnalysis.getResoulution(dataset,true));
int offset_y = (int) ((interEnvelope.getMaxY() - originalEnvelope.getMaxY()) / GdalDataAnalysis.getResoulution(dataset,false));
//需要多少个原始像素
int block_xsize = (int) ((interEnvelope.getMaxX() - interEnvelope.getMinX()) / GdalDataAnalysis.getResoulution(dataset,true));
int block_ysize = (int)Math.abs((interEnvelope.getMaxY() - interEnvelope.getMinY()) / GdalDataAnalysis.getResoulution(dataset,false));
//实际瓦片的长度,裁剪数据的分辨率和原始图像一致
int image_Xbuf = block_xsize;
int image_Ybuf = block_ysize;
//写入瓦片的偏移位置
int imageOffSetX = 0;
int imageOffSetY = 0;
//循环读写
Driver driver = gdal.GetDriverByName("GTiff");
int dataType = dataset.GetRasterBand(1).getDataType();
int bands = dataset.getRasterCount();
byte[] pixelArray = new byte[image_Xbuf*image_Ybuf];
Dataset dsDataset = driver.Create("D:\\data\\xian18_1.tif",image_Xbuf,image_Ybuf,bands, dataType);
for (int i = 1;i<=bands;i++){
Band band = dataset.GetRasterBand(i);
band.ReadRaster(offset_x,offset_y,block_xsize,block_ysize,image_Xbuf,image_Ybuf,dataType,pixelArray);
//写数据
dsDataset.GetRasterBand(i).WriteRaster(imageOffSetX,imageOffSetY,block_xsize,block_ysize,pixelArray);
//清理删除缓存
dsDataset.GetRasterBand(i).FlushCache();
dsDataset.GetRasterBand(i).delete();
}
dsDataset.SetProjection(dataset.GetProjection());
double[] rsGeoTransform = dataset.GetGeoTransform();
rsGeoTransform[0] = interEnvelope.getMinX();
rsGeoTransform[3] = interEnvelope.getMaxY();
dsDataset.SetGeoTransform(rsGeoTransform);
dsDataset.FlushCache();
dsDataset.delete();
}

这个函数中dataset是原始数据,boundingBox是裁剪矩形范围,当然这个方法,无法裁剪不规则多边形,也就是它只能裁剪矩形规则范围。

相比使用shape文件裁剪效率,这个直接拷贝像素的效率更高,当然这些裁剪方法中,还是直接使用gdalwarp.exe的-te参数效率最高,但是

奈何gdal的java api中好像没有适配这个参数,不知道为什么?

好了今天的内容就讲解到这里,如有问题,欢迎评论区讨论。

 




 





 

Java 调用gdal API(二)——栅格裁剪的更多相关文章

  1. Java 调用Restful API接口的几种方式--HTTPS

    摘要:最近有一个需求,为客户提供一些Restful API 接口,QA使用postman进行测试,但是postman的测试接口与java调用的相似但并不相同,于是想自己写一个程序去测试Restful ...

  2. Java 调用 Rest api 设置经典 Linux 虚拟机的实例启停

    现象描述 用户可以通过 Rest API 设置经典 Linux 虚拟机实例的启停.在调用该 API 时需要通过 Azure Active Directory(下文简称 AAD) 获取 Token,但是 ...

  3. Java 调用 Hbase API 访问接口实现方案

    HBase是一个分布式的.面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文“Bigtable:一个结构化数据的分布式存储系统”.就像Bigtable利用了Google文件 ...

  4. JPush极光推送 Java调用服务器端API开发

       极光推送是:使得开发者可以即时地向其应用程序的用户推送通知或者消息,与用户保持互动,从而有效地提高留存率,提升用户体验.简单的说就是通过JPush后台管理网站进行app消息的推送.可以让用户及时 ...

  5. Java调用R(二)_JRI

    推荐使用.相比RServe更灵活,效率更高. 基本步骤 1.  R中需要安装rJava包. 2.  系统变量Path加上 C:\Program Files\R\R-3.0.1\bin\i386;C:\ ...

  6. Java调用Elasticsearch API查询及matchPhraseQuery和matchQuery的区别

    一.引入依赖 <!--Elasticsearch client--> <!-- https://mvnrepository.com/artifact/org.elasticsearc ...

  7. Java调用yahoo!API获取天气数据

    先把代码复制上来,以后再做补充 package com.weather.test; import java.io.InputStream; import java.net.URL; import ja ...

  8. Ant scp upload文件至linux server(用java调用Ant api)

    1.要准备的jar包:ant.jar,ant-jsch.jar code: package com.test.utils; import org.apache.tools.ant.Project; i ...

  9. java调用百度地图API依据地理位置中文获取经纬度

    百度地图api提供了非常多地图相关的免费接口,有利于地理位置相关的开发,百度地图api首页:http://developer.baidu.com/map/. 博主使用过依据地理依据地理位置中文获取经纬 ...

  10. Java 调用翻译软件实现英文文档翻译

    前言: 因最近要进行OCP的考试准备.看着大堆英文文档确实有些疼痛.又因文档内容有点大,又需要逐一去翻译 又很费时费力.于是 百度了一番,找到一些 可以使用Java来调用百度翻译软件的API( 注:( ...

随机推荐

  1. 云原生2.0网关API标准发展趋势

    摘要:Gateway API希望取代Ingress API. 本文分享自华为云社区<云原生2.0网关API标准发展趋势>,作者:华为云云原生团队 . 云原生网关API标准背景及发展现状 G ...

  2. javasec(一)java反射

    这篇文章介绍javasec基础知识--java反射. 0x01 反射是什么? 反射是一种机制,利用反射机制动态的实例化对象.读写属性.调用方法.构造函数. 在程序运行状态中,对于任意一个类或对象,都能 ...

  3. MAPPO学习笔记(1):从PPO算法开始

    由于这段时间的学习内容涉及到MAPPO算法,并且我对MAPPO算法这种多智能体算法的信息交互机制不甚了解,于是写了这个系列的笔记,目的是巩固知识,并且进行一些粗浅又滑稽的总结. 1.PPO算法的介绍 ...

  4. RTSP Server(LIVE555)源码分析(二)-服务器创建

    一. 设置RTSP服务器配置 步骤1.5:rtspServer_Init--->BasicTaskScheduler::createNew()时序图如下: 1)步骤1.54,BasicTaskS ...

  5. StarCoder: 最先进的代码大模型

    关于 BigCode BigCode 是由 Hugging Face 和 ServiceNow 共同领导的开放式科学合作项目,该项目致力于开发负责任的代码大模型. StarCoder 简介 StarC ...

  6. PaddlePaddle 自动求导

    自动求导 在 PaddlePaddle 中使用自动求导来计算导数. 要求:$ f(x)=\sin{x} $,绘制 \(f(x)\) 和 \(\dfrac{\mathrm{d}f(x)}{\mathrm ...

  7. vue中让嵌入的iframe完美自适应宽度、高度

    涉及到系统集成的时候,前端我们经常会用到iframe嵌入,但是嵌入的时候经常有不适应的情况,太长或太宽.滚动条... 下面的方法可以做到使嵌入的iframe自适应宽度.高度, 1.嵌入iframe,加 ...

  8. 2020-12-24:MQ中,如何保证消息不丢失?

    福哥答案2020-12-24: 生产者丢失消息:如网络传输中丢失消息.MQ 发生异常未成功接收消息等情况. 解决办法:主流的 MQ 都有确认或事务机制,可以保证生产者将消息送达到 MQ.如 Rabbi ...

  9. [MAUI程序设计]界面多态与实现

    目录 需求一:在不同设备上使用不同 UI 外观 定义控件 UI 外观 基于平台自定义配置 需求二:在不同数据类别中使用不同的 UI 外观 定义视图 UI 外观 创建数据模板 创建选择器 定义数据 需求 ...

  10. 使用umi+dva做一个demo

    最初只是使用react 进行开发项目,发现项目过大状态管理起来就相当困难,虽然有redux, mobx,但是使用起来还是相当繁琐,而目前umi有现成的轮子使用简单,当然愿意尝试了,趁现在假期有时间简单 ...