golang GDAL地理空间数据处理插件库godal的使用
Golang GDAL地理空间数据处理插件库godal的使用
目标
Godal旨在为GDAL库提供符合Go语言习惯的封装:
- 函数调用返回结果和错误。如果没有错误返回,结果将是有效的。错误信息将包含错误发生的根本原因
- 为了减少Go和原生库之间的调用开销,godal不严格暴露GDAL的API,而是将常用调用分组到单个cgo函数中
使用示例
基本文件操作
// 打开文件(只读模式)
hDS, err := godal.Open(filename)
if err != nil {
panic(err)
}
// 获取数据集结构信息
structure := hDS.Structure()
fmt.Printf("dataset size: %dx%dx%d\n", structure.SizeX, structure.SizeY, structure.NBands)
// 遍历所有波段及其概览
for _, band := range hDS.Bands() {
for o, ovr := range band.Overviews() {
bstruct := ovr.Structure()
fmt.Printf("overview %d size: %dx%d\n", o, bstruct.SizeX, bstruct.SizeY)
}
}
读写模式选项
// 只读模式打开文件
ds, err := godal.Open(filename)
// 读写模式打开文件
ds, err := godal.Open(filename, godal.Update())
创建新数据集
// 创建新的GeoTIFF文件
driver := godal.GTiff
ds, err := driver.Create("output.tif", godal.GTiffOptions{
Width: 512,
Height: 512,
NBands: 3,
DataType: godal.Byte,
CreationOptions: []string{"COMPRESS=DEFLATE"},
})
if err != nil {
panic(err)
}
defer ds.Close()
// 写入数据
band := ds.Bands()[0]
data := make([]byte, 512*512)
err = band.Write(0, 0, data, 512, 512)
if err != nil {
panic(err)
}
波段操作
// 获取波段信息
band := ds.Bands()[0]
fmt.Printf("Band data type: %v\n", band.DataType())
// 读取波段数据
data := make([]byte, 100*100)
err = band.Read(10, 10, data, 100, 100)
if err != nil {
panic(err)
}
// 获取波段统计信息
stats, err := band.ComputeStatistics(false)
if err != nil {
panic(err)
}
fmt.Printf("Min: %v, Max: %v, Mean: %v, StdDev: %v\n",
stats.Min, stats.Max, stats.Mean, stats.StdDev)
安装要求
Godal需要GDAL 3.0以上版本。确保系统上安装了GDAL头文件。如果GDAL安装在非标准位置,可以设置PKG_CONFIG_PATH
环境变量,例如:
export PKG_CONFIG_PATH=/opt/include/pkgconfig
当前状态
- 栅格数据处理功能接近完成且保持稳定
- 矢量和空间参考功能尚不完整,API可能会有不兼容的变更
许可证
Godal采用Apache License 2.0许可证。
更多关于golang GDAL地理空间数据处理插件库godal的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang GDAL地理空间数据处理插件库godal的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用godal进行地理空间数据处理
godal是Go语言对GDAL(Geospatial Data Abstraction Library)的绑定,用于处理各种栅格和矢量地理空间数据格式。下面我将介绍godal的基本用法和示例代码。
安装
首先需要安装GDAL库,然后安装godal:
# Ubuntu/Debian
sudo apt-get install gdal-bin libgdal-dev
# macOS
brew install gdal
# 然后安装godal
go get -u github.com/airbusgeo/godal
基本用法
1. 打开和读取栅格数据
package main
import (
"fmt"
"github.com/airbusgeo/godal"
)
func main() {
// 初始化GDAL
godal.RegisterAll()
// 打开栅格文件
ds, err := godal.Open("example.tif")
if err != nil {
panic(err)
}
defer ds.Close()
// 获取栅格信息
fmt.Printf("Raster size: %dx%d\n", ds.RasterXSize(), ds.RasterYSize())
fmt.Printf("Number of bands: %d\n", ds.RasterCount())
// 读取第一个波段
band := ds.Bands()[0]
blockX, blockY := band.BlockSize()
fmt.Printf("Band block size: %dx%d\n", blockX, blockY)
fmt.Printf("Data type: %s\n", band.DataType().Name())
}
2. 读取矢量数据
package main
import (
"fmt"
"github.com/airbusgeo/godal"
)
func main() {
godal.RegisterAll()
// 打开矢量文件
ds, err := godal.Open("example.shp")
if err != nil {
panic(err)
}
defer ds.Close()
// 获取图层
layer := ds.Layers()[0]
fmt.Printf("Layer name: %s\n", layer.Name())
fmt.Printf("Feature count: %d\n", layer.FeatureCount())
// 遍历要素
layer.ResetReading()
for {
feature := layer.NextFeature()
if feature == nil {
break
}
geom := feature.Geometry()
if geom != nil {
fmt.Printf("Geometry type: %s\n", geom.Type().Name())
}
}
}
3. 创建和写入栅格数据
package main
import (
"github.com/airbusgeo/godal"
)
func main() {
godal.RegisterAll()
// 创建驱动
driver, err := godal.GetDriverByName("GTiff")
if err != nil {
panic(err)
}
// 创建新数据集
ds, err := driver.Create("output.tif", 100, 100, 1, godal.Byte, nil)
if err != nil {
panic(err)
}
defer ds.Close()
// 设置地理变换和投影
transform := [6]float64{440720.0, 60.0, 0.0, 3751320.0, 0.0, -60.0}
ds.SetGeoTransform(transform[:])
ds.SetProjection(`PROJCS["NAD27 / UTM zone 11N",GEOGCS["NAD27",DATUM["North_American_Datum_1927",SPHEROID["Clarke 1866",6378206.4,294.9786982138982,AUTHORITY["EPSG","7008"]],AUTHORITY["EPSG","6267"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4267"]],PROJECTION["Transverse_Mercator"],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",-117],PARAMETER["scale_factor",0.9996],PARAMETER["false_easting",500000],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["EPSG","26711"]]`)
// 写入数据
band := ds.Bands()[0]
data := make([]byte, 100*100)
for i := range data {
data[i] = byte(i % 256)
}
err = band.IO(godal.Write, 0, 0, 100, 100, data, 100, 100)
if err != nil {
panic(err)
}
}
4. 栅格数据处理示例
package main
import (
"fmt"
"github.com/airbusgeo/godal"
)
func main() {
godal.RegisterAll()
// 打开输入文件
srcDS, err := godal.Open("input.tif")
if err != nil {
panic(err)
}
defer srcDS.Close()
// 创建输出文件
driver, _ := godal.GetDriverByName("GTiff")
dstDS, err := driver.Create("output.tif", srcDS.RasterXSize(), srcDS.RasterYSize(), srcDS.RasterCount(), srcDS.Bands()[0].DataType(), nil)
if err != nil {
panic(err)
}
defer dstDS.Close()
// 复制地理信息
gt := srcDS.GeoTransform()
dstDS.SetGeoTransform(gt[:])
dstDS.SetProjection(srcDS.Projection())
// 处理每个波段
for i := 1; i <= srcDS.RasterCount(); i++ {
srcBand := srcDS.Bands()[i-1]
dstBand := dstDS.Bands()[i-1]
// 读取数据
data := make([]float32, srcDS.RasterXSize()*srcDS.RasterYSize())
err = srcBand.IO(godal.Read, 0, 0, srcDS.RasterXSize(), srcDS.RasterYSize(), data, srcDS.RasterXSize(), srcDS.RasterYSize())
if err != nil {
panic(err)
}
// 简单处理数据 - 这里示例乘以2
for j := range data {
data[j] *= 2
}
// 写入数据
err = dstBand.IO(godal.Write, 0, 0, srcDS.RasterXSize(), srcDS.RasterYSize(), data, srcDS.RasterXSize(), srcDS.RasterYSize())
if err != nil {
panic(err)
}
}
fmt.Println("Processing completed!")
}
高级功能
1. 重投影
package main
import (
"github.com/airbusgeo/godal"
)
func main() {
godal.RegisterAll()
// 打开源数据集
srcDS, err := godal.Open("input.tif")
if err != nil {
panic(err)
}
defer srcDS.Close()
// 定义目标投影 (WGS84)
dstSRS := godal.NewSpatialReference()
dstSRS.FromEPSG(4326)
// 创建重投影选项
options := []string{
"RESAMPLING=NEAREST",
"COMPRESS=DEFLATE",
}
// 执行重投影
err = godal.Warp("output.tif", []godal.Dataset{srcDS}, options, dstSRS)
if err != nil {
panic(err)
}
}
2. 栅格计算
package main
import (
"github.com/airbusgeo/godal"
)
func main() {
godal.RegisterAll()
// 打开两个输入栅格
ds1, err := godal.Open("input1.tif")
if err != nil {
panic(err)
}
defer ds1.Close()
ds2, err := godal.Open("input2.tif")
if err != nil {
panic(err)
}
defer ds2.Close()
// 创建计算选项
options := []string{
"FORMAT=GTiff",
"OUTPUT_TYPE=Float32",
"NO_DATA=-9999",
}
// 执行栅格计算 (这里示例相加)
err = godal.Calc("output.tif", []godal.Dataset{ds1, ds2}, "A+B", options)
if err != nil {
panic(err)
}
}
注意事项
- 确保在使用前调用
godal.RegisterAll()
注册所有驱动 - 记得关闭数据集(
defer ds.Close()
) - 处理大数据时注意内存使用,可以使用分块处理
- 错误处理很重要,GDAL操作可能会因为各种原因失败
godal提供了对GDAL功能的全面访问,可以处理几乎所有常见的地理空间数据格式。更多高级功能可以参考GDAL官方文档和godal的API文档。