1、头文件
#include<gdal.h>
#include<gdal_priv.h>
#include<gdalwarper.h>
2、注册驱动+设置中文路径+加载数据
//注册所有的驱动GDALAllRegister();//设置支持中文路径和文件名CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO"); //加载tif数据string file_path_name = "test.tif";//std::cout << "请输入图片路径:" << std::endl;//std::cin >> file_path_name;//将数据读入poDataset数据集GDALDataset* poDataset = (GDALDataset*)GDALOpen(file_path_name.c_str(),GA_ReadOnly);if (poDataset == NULL){std::cout << "指定的文件不能打开!" << std::endl;return 0;}
注意:GDALOpen中参数分为GA_Update(写数据),GA_ReadOnly(仅仅读数据)
3、获取图像的尺寸
int nImgSizeX = poDataset->GetRasterXSize();int nImgSizeY = poDataset->GetRasterYSize();
注意:此处得Xsize指的是有多少列(即宽度),Ysize指的是有多少行(即高度)。如下图

4、 获取图像的通道数
int bandCount = poDataset->GetRasterCount();
5、获取特定波段
GDALRasterBand* poBand1 = poDataset->GetRasterBand(1);
注意:此处得波段数是从1计数,不是从0;
6、获取数据类型
GDALDataType g_type = GDALDataType(poBand1->GetRasterDataType());
注意:Gdal总共有12中数据类型,具体如下
- GDT_Unknown : 未知数据类型
- GDT_Byte : 8bit正整型 (C++中对应unsigned char)
- GDT_UInt16 : 16bit正整型 (C++中对应 unsigned short)
- GDT_Int16 : 16bit整型 (C++中对应 short 或 short int)
- GDT_UInt32 : 32bit 正整型 (C++中对应unsigned long)
- GDT_Int32 : 32bit整型 (C++中对应int 或 long 或 long int)
- GDT_Float32 : 32bit 浮点型 (C++中对应float)
- GDT_Float64 : 64bit 浮点型 (C++中对应double)
- GDT_CInt16 : 16bit复整型 (?)
- GDT_CInt32 : 32bit复整型 (?)
- GDT_CFloat32 : 32bit复浮点型 (?)
- GDT_CFloat64 : 64bit复浮点型 (?)
7、读写GDAL数据
(1)读取Gdal数据
poDataset->GetRasterBand(2)->RasterIO(GF_Read, 0, 0, nImgSizeX, nImgSizeY, data, nImgSizeX, nImgSizeY, g_type, 0, 0);
参数解释:
1、GF_Read:代表是读取tif文件数据。
2、3:代表初始位置(a,b),注意第二个参数a指的是X方向,即多少列。第三个参数b指的是Y方向,即多少行。原点在左上角。如下图所示。

4,5指的是偏移量(X,Y)。X代表距离参数(a,b)的水平平移量和竖直偏移量。即宽和高。
如下图所示

6、中data用来将读取到的影像数据进行存储。想到于读到缓存中。data是一个数组指针类型,数据类型需要和GDAL通过GetRasterDataType获取的数据类型一致。创建格式如下
数组的大小要能存放下计划读入缓存的数据。如果是读取图像,那么读取出来的图像像素值就存储在这个Data中,如果是写入图像,那么这个Data中的数据会被写入到图像上指定的位置中去
unsigned short* data_ref = new unsigned short[100 * nRows];
7、8 表示data数据的大小。比如4、5设置读取图像的范围是300×200,如果我要读取图像中的原始数据,那么这两个参数分别应该设置为nImgSizeX=300和nImgSizeY = 200。如果设置比这个小或者大就会进行重采样生成放大或者缩小的图像。
9、gtype标记data 的数据类型。此时用的是GDAL格式的数据类型。
10、11默认0即可。具体不再阐述。
(2)写数据
写数据需要在加载数据的时候改为GA_Update,然后用以下代码写入
poDataset->GetRasterBand(2)->RasterIO(GF_Write, 0, 0, nImgSizeX, nImgSizeY, data, nImgSizeX, nImgSizeY, g_type, 0, 0);
指的是将data中的数据写入打开的tiff文件指定位置
注意:data中的数据是一行,和影像对应的关系如下图

(3)GDAL与OPENCV联动
注意:cv::Mat创建时,是(height,width)的格式,与GDAL的(width,height)刚好相反。
如以下代码所示
pDataset->GetRasterBand(1)->RasterIO(GF_Read, 0, 0, ncols, nrows, data, ncols, nrows, dataType, 0, 0);
Mat temp= (Mat(nrows, ncols, dataType, data)).clone();
也可以直接读取数据到mat中
cv::Mat gdal_mat1(nImgSizeY, nImgSizeX, CV_8UC1, Scalar(0));poDataset->GetRasterBand(1)->RasterIO(GF_Read, 0, 0, nImgSizeX, nImgSizeY, gdal_mat1.data, nImgSizeX, nImgSizeY, g_type, 0, 0);
8、Gdal复制影像
//加载原始影像数据GDALDataset* poSrcDS = (GDALDataset*)GDALOpen(file_path_name.c_str(), GA_ReadOnly);//创建要存储的数据集GDALDataset* pDatasetc;//注册create的驱动GDALDriver* poDriver;//设置驱动格式const char* pszFormat = "GTiff";//接下来的两步是完成复制,file_path_nameout是输出位置+文件名,poSrcDS是原始影像数据集poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);pDatasetc = poDriver->CreateCopy(file_path_nameout.c_str(), poSrcDS, FALSE, NULL, NULL, NULL);//判断复制后的影像是不是空的,是不是都关闭数据集。if (pDatasetc != NULL) {GDALClose((GDALDatasetH)pDatasetc);}GDALClose((GDALDatasetH)poSrcDS);
注意:这段程序只需要修改输入文件:file_path_name,和输出位置文件:file_path_nameout,即可直接复制运行。
9、Gdal地理信息
影像左上角横坐标(经度):geoTransform[0]
影像左上角纵坐标(纬度):geoTransform[3]
遥感图像的水平空间分辨率为geoTransform[1]
遥感图像的垂直空间分辨率为geoTransform[5]
通常geoTransform[5] 与 geoTransform[1]相等
double dfTransform[6] = { 0 };//获取影像六参数
readDataset->GetGeoTransform(dfTransform);
cout << dfTransform[0] << endl;//获取起始经度
cout << dfTransform[3] << endl;//获取起始纬度
10、获取投影
char* Project = NULL;Project = const_cast<char*>(readDataset->GetProjectionRef());
11、获取影像转换参数
double dfTransform[6] = { 0 };readDataset->GetGeoTransform(dfTransform);
12、创建数据集并打开
GDALDriver* pDriver = GetGDALDriverManager()->GetDriverByName("GTiff");GDALDataset* pDDst = pDriver->Create(filepathChong.c_str(), nNewWidth, nNewHeight, nBandCount,g_type, NULL);if (pDDst == NULL){GDALClose((GDALDatasetH)readDataset);cout << "创建重采样文件失败" << endl;return -2;}
13、对创建的影像设置投影和六参数
pDDst->SetProjection(Project);//设置投影pDDst->SetGeoTransform(dfTransformnew);//设置6参数
14、遥感影像重采样
#include<iostream>
#include<string>
using namespace std;
#include<gdal.h>
#include<gdal_priv.h>
#include<gdalwarper.h>
#define PI 3.1415926535897932384626433832795int main(int argc, char* argv[])
{//读取设置参数GDALResampleAlg eResample; int method;if (argc < 4){method = 2;}else{sscanf(argv[3], "%d", &method);}switch (method){case 1:eResample = GRA_NearestNeighbour;//最邻近采样 速度最快break;case 2:eResample = GRA_Bilinear; //双线性内插采样break;case 3:eResample = GRA_Cubic;//三次立方卷积采样break;}double newscale;sscanf(argv[2], "%lf", &newscale);FileInfo file(argv[1]);string filepath = file.path +"/"+ file.name +"."+ file.format;string filepathChong = file.path + "/" + file.name + "-Resampling"+"." + file.format;//注册所有的驱动GDALAllRegister();CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO"); //设置支持中文路径和文件名GDALDataset* readDataset = (GDALDataset*)GDALOpen(filepath.c_str(), GA_ReadOnly);//加载tif原图if (readDataset == NULL){std::cout << "指定的文件不能打开!" << std::endl;return 0;}//获取影像分辨率double dfTransform[6] = { 0 };readDataset->GetGeoTransform(dfTransform);double resolution_lat = -dfTransform[5];double resolution_lon = dfTransform[1];double resolutiony = Latitude_difference_to_distance(resolution_lat);double resolutionx = Longitude_difference_to_distance(resolution_lon, dfTransform[3]);//double resolution = std::max(resolutionx, resolutiony);//获取影像大小int nImgSizeX = readDataset->GetRasterXSize();int nImgSizeY = readDataset->GetRasterYSize();//获取投影char* Project = NULL;Project = const_cast<char*>(readDataset->GetProjectionRef());//获取影像数据类型GDALDataType g_type = GDALDataType(readDataset->GetRasterBand(1)->GetRasterDataType());//获取通道数int nBandCount = readDataset->GetRasterCount();double dfTransformnew[6] = { 0 };dfTransformnew[0]= dfTransform[0];dfTransformnew[1]= distance_to_latitude_difference(newscale);dfTransformnew[2]= dfTransform[2];dfTransformnew[3]= dfTransform[3];dfTransformnew[4]= dfTransform[4];dfTransformnew[5]= -distance_to_longitude_difference(newscale, dfTransform[3]);double fResX = dfTransform[1] / dfTransformnew[1];//计算重采样前后的比例double fResY = dfTransform[5] / dfTransformnew[5];cout << dfTransform[0] << endl;int nNewWidth = static_cast<int>(nImgSizeX * fResX + 0.5);//计算重采样后的宽度int nNewHeight = static_cast<int>(nImgSizeY * fResY + 0.5);//计算重采样后的高度//创建结果数据集 GDALDriver* pDriver = GetGDALDriverManager()->GetDriverByName("GTiff");GDALDataset* pDDst = pDriver->Create(filepathChong.c_str(), nNewWidth, nNewHeight, nBandCount,g_type, NULL);if (pDDst == NULL){GDALClose((GDALDatasetH)readDataset);cout << "创建重采样文件失败" << endl;return -2;}pDDst->SetProjection(Project);//设置投影pDDst->SetGeoTransform(dfTransformnew);//设置6参数//重采样GDALWarpOptions* psWo = GDALCreateWarpOptions();psWo->eResampleAlg = eResample;//设置重采样方式psWo->eWorkingDataType = g_type;//设置数据格式psWo->hSrcDS = (GDALDatasetH)readDataset;//源数据psWo->hDstDS = (GDALDatasetH)pDDst;//设置目标数据psWo->pfnTransformer = GDALGenImgProjTransform;psWo->pTransformerArg = GDALCreateGenImgProjTransformer((GDALDatasetH)readDataset, Project, (GDALDatasetH)pDDst, Project, FALSE, 0.0, 1);;psWo->nBandCount = nBandCount;psWo->panSrcBands = (int*)CPLMalloc(nBandCount * sizeof(int));psWo->panDstBands = (int*)CPLMalloc(nBandCount * sizeof(int));for (int i = 0; i < nBandCount; i++){psWo->panSrcBands[i] = i + 1;psWo->panDstBands[i] = i + 1;}GDALWarpOperation oWo;if (oWo.Initialize(psWo) != CE_None){GDALClose((GDALDatasetH)readDataset);GDALClose((GDALDatasetH)pDDst);cout << "处理出错" << endl;return -3;}oWo.ChunkAndWarpImage(0, 0, nNewWidth, nNewHeight);GDALFlushCache(pDDst);GDALDestroyGenImgProjTransformer(psWo->pTransformerArg);GDALDestroyWarpOptions(psWo);GDALClose((GDALDatasetH)readDataset);GDALClose((GDALDatasetH)pDDst);cout << "重采样完成,生成文件地址为:" << filepathChong <<endl;return 0;
}
15、如果一直循环IO读取数据会导致大量缓存,可通过以下代码清楚缓存
ref.readDataset->FlushCache();src.readDataset->FlushCache();

















