GDAL介绍:
GDAL(Geospatial Data Abstraction Library)是一个开源栅格空间数据转换库。它利用抽象数据模型来表达所支持的各种文件格式。它还有一系列命令行工具来进行数据转换和处理。
GDAL使用C++开发,因此要在Java环境下使用GDAL库,要用JNI(Java跨平台调用的一种方式)的方法调用dll库。所以,我们可以下载GDAL的源码,依照官网教程,通过Visual Studio编译出可用dll。但是最简单的做法就是使用已经编译生成好的符合JNI标准的动态dll库和jar包了,推荐这个网址:http://www.gisinternals.com/archive.php,下载合适的文件。
例如我下载的是release-1800-x64-gdal-2-2-3-mapserver-7-0-7,里面包含了编译好的GDAL以及jar包。
下面以Eclipse的配置为例,示范如何在Java环境中调用GDAL库(此时假设所有GDAL的dll都已经编译好,或是从上面写的网址下载下来了):
1.将下载下来的压缩包解压至合适位置,内容列表如下:
2. 打开Eclipse,新建一个普通的java工程。
3.将下载下来的压缩包bin/gdal/java目录下的gdal.jar、gdalconstjni.dll、gdaljni.dll、ogrjni.dll、osrjni.dll文件拷贝到刚才新建的java工程目录下,如下图,和src目录同级。
4.右键gdal.jar,在弹出的菜单中选择Build Path -> Add to Build Path,将gdal.jar引入到工程环境中
这时候写代码,Eclipse编译不会有错误,但是运行程序时会报错,于是还要进行下一步:
5.将下载下来的压缩包bin目录下的所有dll文件(这些文件是GDAL相关的dll文件,是GDAL_Java的dll需要调用的)拷贝至正确的位置,有很多地方可选:
1)java工程目录下(我用的是这种方法,让dll文件跟着项目一块)。
2){JAVA_HOME}jre/bin,也可以采用这种做法,将这些dll拷贝至jdk安装目录下的jre下的bin目录下。
3)网上有人说拷贝至{windir}system32目录下,此方法没有检验过
6. 新建一个HelloGDAL类来执行转换,代码如下:
package com.ysq.gdal;
import org.gdal.gdal.Band;
import org.gdal.gdal.Dataset;
import org.gdal.gdal.Driver;
import org.gdal.gdal.gdal;
import org.gdal.gdalconst.gdalconstConstants;
import org.gdal.ogr.DataSource;
//import org.gdal.ogr.Driver;
import org.gdal.ogr.ogr;
public class HelloGDAL {
public static void main(String[] args) {
//此处换成自己文件的位置的路径
//readGDAL("E:\\xxxxxxx.tif");
getElevationFromTif("E:\\xxxxxxx.tif");
}
/**
* 读取tif文件的相关信息
* @param fileName
*/
public static void readGDAL(String fileName) {
gdal.AllRegister();
//读取影像数据
Dataset dataset = gdal.Open(fileName,gdalconstConstants.GA_ReadOnly);
if(dataset == null){
System.err.println("GDALOpen failed - "+gdal.GetLastErrorNo());
System.err.println(gdal.GetLastErrorMsg());
System.exit(1);
}
Driver driver = dataset.GetDriver();
System.out.println("Driver:"+driver.getShortName()+"/"+driver.getLongName());
//读取影像信息
int xSize = dataset.getRasterXSize();
int ySize = dataset.getRasterYSize();
int bandCount = dataset.GetRasterCount();
System.out.println("size is "+xSize+","+ySize+",光带数:"+bandCount);
Band band = dataset.GetRasterBand(1);
int type = band.GetRasterDataType();
//type为1,代表的是Eight bit unsigned integer
System.out.println(type);
dataset.delete();
gdal.GDALDestroyDriverManager();
}
/**
* shp转换geojson
* @param shpFileName
* @param geojsonFileName
*/
public static void shpToGeojson(String shpFileName,String geojsonFileName) {
// 注册所有的驱动
ogr.RegisterAll();
// 为了支持中文路径,请添加下面这句代码
gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8","YES");
// 为了使属性表字段支持中文,请添加下面这句
gdal.SetConfigOption("SHAPE_ENCODING","");
//shp文件所在的位置
//String strVectorFile = "D:\\sichuan\\sichuanPointALL.shp";
//打开数据
DataSource ds = ogr.Open(shpFileName,0);
if (ds == null)
{
System.out.println("打开文件失败!" );
return;
}
System.out.println("打开文件成功!" );
org.gdal.ogr.Driver dv = ogr.GetDriverByName("GeoJSON");
if (dv == null)
{
System.out.println("打开驱动失败!" );
return;
}
System.out.println("打开驱动成功!" );
//输出geojson的位置及文件名
//String geojsonFileName = "D:\\data\\sichuan.geojson";
dv.CopyDataSource(ds, geojsonFileName);
System.out.println("转换成功!");
}
/**
* 获取每个点的高程值
* @param fileName_tif
*/
public static void getElevationFromTif(String fileName_tif) {
gdal.AllRegister();
Dataset hDataset = gdal.Open(fileName_tif, gdalconstConstants.GA_ReadOnly);
if (hDataset == null)
{
System.err.println("GDALOpen failed - " + gdal.GetLastErrorNo());
System.err.println(gdal.GetLastErrorMsg());
System.exit(1);
}
Driver hDriver = hDataset.GetDriver();
System.out.println("Driver: " + hDriver.getShortName() + "/" + hDriver.getLongName());
int iXSize = hDataset.getRasterXSize();
int iYSize = hDataset.getRasterYSize();
System.out.println("Size is " + iXSize + ", " + iYSize);
Band band = hDataset.GetRasterBand(1);
//这里是DEM数据,所以声明一个int数组来存储,如果是其他数据类型,声明相应的类型即可
int buf[] = new int[iXSize];
for(int i=0; i<50/*iYSize*/; i++)
{
band.ReadRaster(0, i, iXSize, 1, buf); //读取一行数据
// 下面是输出像元值,为了方便,我只输出了左上角 10×10的范围内的数据
for(int j=0; j<50/*iXSize*/; j++){
System.out.print(buf[j] + ", ");
}
System.out.println("\n");
}
hDataset.delete();
// 可选
gdal.GDALDestroyDriverManager();
}
}
执行结果示例:
PS:运行java工程时可能的报错:
1. 工程中只引用了gdal.jar包,没有任何gdal_java的dll
Native library load failed.
java.lang.UnsatisfiedLinkError: no gdaljni in java.library.path
Exception in thread "main" java.lang.UnsatisfiedLinkError: org.gdal.gdal.gdalJNI.AllRegister()V
at org.gdal.gdal.gdalJNI.AllRegister(Native Method)
at org.gdal.gdal.gdal.AllRegister(gdal.java:519)
at com.ysq.gdal.HelloGDAL.getElevationFromTif(HelloGDAL.java:91)
at com.ysq.gdal.HelloGDAL.main(HelloGDAL.java:17)
2. 有引用了gdal.jar包 ,也将releasegdal_java的dll文件拷贝到正确位置,但是缺少GDAL本身的dll(即release-1800-gdal/bin下的众多dll文件)