GeoTiff及GDAL切图(java)

9 篇文章 5 订阅

一、GeoTiff

GeoTiff是很常见的一种遥感影像数据格式,它是一种栅格数据,这种数据是以像素点矩阵的形式存储的。

TIF文件中的空间信息包括投影信息和仿射变换信息。其中,仿射变换(经纬度等)的信息分别为:左上角的坐标(经度和维度)、东西和南北方向的像素分辨率(也就是每个像素点的经纬度偏移量)以及图像的旋转系数(正北方向时为零)。这样,每个像素点的坐标就可以通过它与左上角的偏移量和每个像素的分辨率值计算出来。

切图产生的新图的投影信息是不变的,但仿射信息会发生变化,因为左上角的原点可能跟原图不一样了。因此,需要重新计算仿射信息并设置(投影信息也需要设置,但不需要重新计算)。

二、波段

波段又称为波谱段或波谱带,在遥感技术中,通常把电磁波谱划分为大大小小的段落,大的成为波段区,如可见区、红外区等;中等的如近红外、远红外等;小的称为波段。

影像数据根据波段的多少可以分为单波段影像和多波段影像两种,单波段影像一般用黑白色的灰度图来描述,多波段常用RGB 合成象素值的彩色图来描述,就是将三个波段的数据分别通过红、绿、蓝三个通道加载,从而渲染出。

将多波段影像数据添加到地图中之后,可使用多波段栅格数据集中的任意三个可用波段的组合来创建 RGB 合成图。与仅处理一个波段相比,通过将多个波段共同显示为RGB 合成图通常可从数据集收集到更多信息。
在这里插入图片描述

三、GDAL切图

  1. Tif文件的读取

  2. 根据Tif文件中的波段数量,读取相应的波段(Band)。

  3. 根据裁剪的起始点和矩形框的大小,并读取相应的数据

  4. 获取创建文件并创建新的目标文件

  5. 计算新图的仿射信息,并设置投影和仿射信息

  6. 将提取出来的数据写入新文件并刷新缓存到磁盘

  7. 释放文件句柄资源

源码如下:

import org.gdal.gdal.Dataset;
import org.gdal.gdal.Driver;
import org.gdal.gdal.gdal;
import org.gdal.gdalconst.gdalconstConstants;

public class GDALClip {

    public static void clip(String srcFile, String dstFile, int offsetX, int offsetY, int sizeX, int sizeY) {
        // 读取要切的原图
        Dataset srcDs = gdal.Open(srcFile, gdalconstConstants.GA_ReadOnly);
        if (srcDs == null) {
            System.err.println("GDALOpen failed - " + gdal.GetLastErrorNo());
            System.err.println(gdal.GetLastErrorMsg());
            return;
        }

        int rasterCount = srcDs.GetRasterCount();
        System.out.println("波段数 = " + rasterCount);
        if (rasterCount < 1) {
            System.err.println("异常:没有波段。");
            return;
        }

        // 获取Tif的驱动,为创建切出来的图文件做准备
        Driver GTIFFDiver = gdal.GetDriverByName("GTIFF");
        // 创建切出来的要存的文件
        Dataset dstDs = GTIFFDiver.Create(dstFile, sizeX, sizeY, rasterCount, srcDs.GetRasterBand(1).getDataType());
        if (dstDs == null) {
            System.err.println("Create failed - " + gdal.GetLastErrorNo());
            System.err.println(gdal.GetLastErrorMsg());
            return;
        }

        // 复制每个波段的数据
        for (int index = 1; index <= rasterCount; index++) {
            copyData(srcDs, dstDs, index, offsetX, offsetY, sizeX, sizeY);
        }

        // 仿射变换系数,即6个参数,左上角地理坐标,纵横方向上的分辨率,以及旋转系数。
        // GeoTransform[0] /* 左上角x坐标  */
		// GeoTransform[1] /* 东西方向分辨率resolution */
	   	// GeoTransform[2] /* 旋转角度, 0表示图像 "北方朝上" */
   		// GeoTransform[3] /* 左上角y坐标 */
	   	// GeoTransform[4] /* 旋转角度, 0表示图像 "北方朝上" */
	    // GeoTransform[5] /* 南北方向分辨率resolution */ 
	    // 获取原图的原点坐标信息
        double[] srcTransform = srcDs.GetGeoTransform();
        System.out.println("原点坐标   = " + srcTransform[0] + "," + srcTransform[3]);
        System.out.println("像素坐标差 = " + srcTransform[1] + "," + srcTransform[5]);

        // 根据反射变换参数计算新图的原点坐标
        double top_left_x = srcTransform[0] + offsetX * srcTransform[1];
        double top_left_y = srcTransform[3] + offsetY * srcTransform[5];
        // 将计算后的值组装为一个元组
        double[] dstTransform = {top_left_x, srcTransform[1], srcTransform[2], top_left_y, srcTransform[4], srcTransform[5]};
        // 设置裁剪出来图的原点坐标
        dstDs.SetGeoTransform(dstTransform);

        // 设置SRS属性(投影信息)
        // System.out.println("Projection = " + srcDs.GetProjection());
        dstDs.SetProjection(srcDs.GetProjection());

        // 将缓存写入磁盘
        dstDs.FlushCache();

        dstDs.delete();
        srcDs.delete();
    }

    private static void copyData(Dataset srcDs, Dataset dstDs, int bandNum, int offsetX, int offsetY, int sizeX, int sizeY) {
        int bufR[] = new int[sizeX * sizeY];

        //从波段中切需要的矩形框内的数据(注意读取的矩形框不能超过原图大小)
        srcDs.GetRasterBand(bandNum).ReadRaster(offsetX, offsetY, sizeX, sizeY, bufR);

        // 写入目标文件
        dstDs.GetRasterBand(bandNum).WriteRaster(0, 0, sizeX, sizeY, bufR);
    }

    public static void main(String[] args) {
        gdal.AllRegister();
        GDALClip.clip("D:\\test\\cut_img.tif", "D:\\test\\clip.tif", 0, 0, 100, 100);
        gdal.GDALDestroyDriverManager();
    }
}

  • 8
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值