gdal java 无法获取坐标_Java版gdal 初探

本文介绍了如何在Java中使用GDAL库进行影像读取、基本信息查看、影像裁切以及重投影。详细讲解了GDAL的部署、影像读取的基本API,包括六参数信息的获取,以及如何利用GDAL进行影像裁切。此外,还探讨了使用Spark进行分布式影像规整裁切的方法,涉及元数据整合、格网构建以及影像裁剪的实现逻辑。
摘要由CSDN通过智能技术生成

最新更新:2019.11.08:四.Spark并行化规整裁切

刚看了没几天的geotrellis就被叫去看gdal了,还好以前有一丢丢基础,借着这个机会复习一下。

一. gdal部署

部署方法可以参见另外两篇文章:windows下java版gdal部署和linux下java版gdal部署。

其中,在windows的部署文章中提到,要复制gdalconstjni.dll、gdaljni.dll、ogrjni.dll、osrjni.dll这四个dll,但本文使用的gdal版本是2.3.2,这四个dll已经被整合成了一个gdalalljni.dll。

二 .影像读取及基本信息查看

首先扔一个gdal的java API文档,该文档适用于gdal 1.7.0或以上版本。

首先是所有gdal程序都需要的注册语句:

gdal.AllRegister();

之前的版本还需要加这句话来支持中文路径:

gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8","YES");

但在2.3.2中,我没有加这句话,也能正常地在中文路径下读写影像。读取影像基本信息的代码如下:

//读取影像

Dataset rds = gdal.Open("影像路径", gdalconst.GA_ReadOnly);

//宽、高、波段数

int x = rds.getRasterXSize();

int y = rds.getRasterYSize();

int b = rds.getRasterCount();

//六参数信息

double[] geoTransform = rds.GetGeoTransform();

//影像左上角投影坐标

double[] ulCoord = new double[2];

ulCoord[0] = geoTransform[0];

ulCoord[1] = geoTransform[3];

//影像右下角投影坐标

double[] brCoord = new double[2];

brCoord[0] = geoTransform[0] + x * geoTransform[1] + y * geoTransform[2];

brCoord[1] = geoTransform[3] + x * geoTransform[4] + y * geoTransform[5];

//影像投影信息

String proj = rds.GetProjection();

这里有个数组geoTransform,容量为6,代表的是仿射变换六参数,其含义如下:

geoTransform[0]:左上角x坐标

geoTransform[1]:东西方向空间分辨率

geoTransform[2]:x方向旋转角

geoTransform[3]:左上角y坐标

geoTransform[4]:y方向旋转角

geoTransform[5]:南北方向空间分辨率

影像中任意一个像素的坐标可以用下式计算:

c25f9360459f

任意像素的坐标计算公式

其中六参数分别为{dx, a11, a12, dy, a21, a22},正常的影像,正北方向朝上,两个旋转角的值都是0。

三. 影像裁切

在gdal中,影像裁切的基本思想,是把原始影像中想要保留的部分进行另存为。因此这部分要做的事情,就是在定好要裁切的部分后,读取相应的部分并保存即可,其中涉及到一些简单的位置计算。代码如下:

gdal.AllRegister();

Dataset rds = gdal.Open("影像路径", gdalconst.GA_ReadOnly);

//宽、高、波段数

int b = rds.getRasterCount();

//从波段中获取影像的数据类型,gdal中波段索引从1开始

int dataType = rds.GetRasterBand(1).GetRasterDataType();

//六参数信息

double[] geoTransform = rds.GetGeoTransform();

//设置要裁剪的起始像元位置,以及各方向的像元数

//这里表示从像元(5000, 5000)开始,x方向和y方向各裁剪1000个像元

//最终结果就是一幅1000*1000的影像

int startX = 5000;

int startY = 5000;

int clipX = 1000;

int clipY = 1000;

//计算裁剪后的左上角坐标

geoTransform[0] = geoTransform[0] + startX * geoTransform[1] + startY * geoTransform[2];

geoTransform[3] = geoTransform[3] + startX * geoTransform[4] + startY * geoTransform[5];

//创建结果图像

Driver driver = gdal.GetDriverByName("GTIFF");

Dataset outputDs = driver.Create("D:\\Javaworkspace\\gdal\\output\\clip1.tif", clipX, clipY, b, dataType);

outputDs.SetGeoTransform(geoTransform);

outputDs.SetProjection(rds.GetProjection());

//按band读取

for(int i = 0; i < clipY; i++){

//按行读取

for(int j = 1; j <= b; j++){

Band orgBand = rds.GetRasterBand(j);

int[] cache = new int[clipX];

//从位置x开始,只读一行

orgBand.ReadRaster(startX, startY + i, clipX, 1, cache);

Band desBand = outputDs.GetRasterBand(j);

//从左上角开始,只写一行

desBand.WriteRaster(0, i, clipX, 1, cache);

desBand.FlushCache();

}

}

//释放资源

rds.delete();

outputDs.delete();

除了Band对象中的ReadRaster和WriteRaster接口外,Dataset对象也有ReadRaster和WriteRaster的接口,但是用法有所不同。要使用Dataset中的接口,需要先构建波段数组,表示在读写过程中对哪些波段进行操作。

int[] bands = new int[]{1};

然后在实例化cache数组的时候,数组容量就不是简单的要读写的影像窗口的x*y,而是x*y*b,b表示波段数。而数组的类型也需要根据影像的数据类型进行调整。gdal中的数据类型以常量的形式存放在org.gdal.gdalconst这个类中。从接口文档中能查到有这么些个:

c25f9360459f

gdal数据类型

正常来讲,可以使用位数更高的数据类型的数组来读取位数较低的数据。比如在我自己的影像中,datatype的值为2,对应的数据类型为GDT_UInt16,即无符号16位整型,但我在使用int类型数组来读数据的时候,报了数据类型不匹配的错(仅限Dataset的接口),但是输出的影像好像没有问题。报错信息如下:

ERROR 1: Java array type is not compatible with GDAL data type

当我改用short类型的数组来读写数据后,这个报错就消失了,不是很懂gdal的这一波操作。最后利用Dataset对象读写数据的代码如下,也是按行来执行:

int[] bands = new int[]{1};

for (int i = 0; i < clipY; i++)

{

short[] cache = new short[clipX * b];

rds.ReadRaster(startX, startY +

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值