一组关联的栅格波段,通常来自一个文件。
封装一个或多个栅格波段的数据集
在GDAL中,GDALDataset类并没有直接封装打开文件的方法。相反,您需要使用GDALOpen或其他相关函数来打开数据源,并将其返回为一个新的GDALDataset对象。
使用 GDALOpen() 或 GDALOpenShared() 为命名文件创建 GDALDataset,或使用 GDALDriver::Create() 或 GDALDriver::CreateCopy() 创建新数据集。
GDALOpen()是默认函数,它将数据集加载到应用程序的内存中,并阻止其他应用程序打开同一数据集。这通常称为独占访问(exclusive access)
poDataset = (GDALDataset *) GDALOpen( "filenema.tif", GA_ReadOnly );
加载数据时有GA_Update和GA_ReadOnly两种模式
(GDALDataset *)GDALOpen()的详细解释:http://t.csdn.cn/PFmc6
GDALOpenShared()允许多个应用程序共享数据集,因此它允许在同一时间内打开多个实例。这通常称为共享访问(shared access)
如果您的应用程序需要同时打开并读取或写入多个数据集,则每个数据集都应该使用GDALOpenShared()打开,以避免竞争条件或进程崩溃,但如果您可以确保每个数据集只被一个应用程序或线程访问,那么GDALOpen()是一个合适的选择
GDALDataset* dataset1 = (GDALDataset*) GDALOpenShared("filename1", GA_ReadOnly);
GDALDataset* dataset2 = (GDALDataset*) GDALOpenShared("filename2", GA_ReadOnly);
如果之前已经有线程打开了这个数据集,则它会返回一个指向相同数据集的指针,避免重复打开数据集而浪费资源。这也使得多个线程可以同时访问同一个数据集,提高了程序的效率
注:
GDALOpenShared()函数可以利用已经建立的缓存,是因为在打开数据集时,它会检查内存中是否已经有缓存了该数据集的信息。如果有,则使用已有的缓存而不是重新从硬盘读取数据集。这种缓存机制可以减少程序读取硬盘数据的次数,提高读取效率
通过对数据集进行缓存,GDALOpenShared()函数减少了读取硬盘数据集的次数,节省了系统资源,提高了程序效率,对于处理多个数据集的任务尤为重要
如果使用GDALOpen()函数分别打开多个不同的数据集,会占用较多的缓存和内存,导致程序效率低下,甚至引起内存不足的问题
参数:要删除的数据集的名称
返回值: 成功 CE_None 失败 CE_Failure
关闭 GDAL 数据集并解除分配与其关联的所有资源的公认方法
关闭GDAL数据集,并且释放与数据集相关的所有资源,以便于操作系统回收该数据集所占用的空间
// 打开数据集
dataset = (GDALDataset*)GDALOpen("filename.tif", GA_ReadOnly);
// 关闭数据集
GDALClose(dataset);
GDALDataset的析构方法
GDALAllRegister();
GDALDataset* dataset = (GDALDataset*) GDALOpen("my_data.tif", GA_ReadOnly);
GDALClose(dataset); //关闭数据集
dataset = (GDALDataset*) GDALOpen("my_data2.tif", GA_ReadOnly);
delete dataset; //销毁对象
GDALClose(dataset),它关闭了数据集并释放占用的资源,但是对象dataset并没有被摧毁,可以继续使用打开新的数据集
delete dataset,直接销毁对象,并在此过程中调用析构函数,释放该对象所占用的所有资源
对于 Windows 用户,不建议对数据集对象使用 delete 运算符,因为在跨模块边界分配和释放内存时存在已知问题。调用GDALClose()是一个更好的选择
获取栅格宽度(以像素为单位) 相当于 C 函数 GDALGetRasterXSize()
参数:无参
返回值:int
获取栅格高度(以像素为单位) 相当于 C 函数 GDALGetRasterYSize()
参数:无参
返回值:int
关于GetRasterXSize和GetXSize的理解:
https://blog.csdn.net/qq_69574549/article/details/129896322
获取此数据集上的栅格波段数 与 C 函数 GDALGetRasterCount() 相同
参数:无参
返回值:int
GDALDataset * dataset = (GDALDataset *)GDALOpen("1.jpeg" , GA_ReadOnly);
cout<GetRasterXSize()<GetRasterYSize()<GetRasterCount()<
700
700
3
GDALRasterBand *GetRasterBand (int) 获取数据集的波段对象
相当于 C 函数 GDALGetRasterBand()。
参数: nBandId – 要获取的波段的索引号,从 1 到 GetRasterCount()。
返回: nBandId 第 n 波段对象
后面有GDALRasterBand的API,但是我们也提前了解下:http://t.csdn.cn/0nS96
将所有写入缓存数据刷新到磁盘 此方法与 C 函数 GDALFlushCache() 相同
参数: bAtClosing – 这是否从 GDALDataset 析构函数调用
返回: 成功情况下CE_None
GDALDataset *ds = (GDALDataset *) GDALOpen("example.tif", GA_Update);
// 读取栅格数据
GDALRasterBand *band = ds->GetRasterBand(1);
int xsize = band->GetXSize();
int ysize = band->GetYSize();
float *data = new float[xsize * ysize];
band->RasterIO(GF_Read, 0, 0, xsize, ysize, data, xsize, ysize, GDT_Float32, 0, 0);
// 修改栅格数据
for (int i = 0; i < xsize * ysize; i++) {
data[i] += 1.0;
}
// 写入修改后的栅格数据
band->RasterIO(GF_Write, 0, 0, xsize, ysize, data, xsize, ysize, GDT_Float32, 0, 0);
// 刷新缓存,将修改写入文件
band->FlushCache();
delete [] data;
// 关闭栅格文件
GDALClose(ds);
中间暂时看不懂没关系,只需要知道中间部分是修改了example.tif的band1的数据,每个数据都+1了
bool bAtClosesing
bool bAtClosesing参数表示是否在文件关闭时自动刷新缓存。如果设置为true,则在调用GDALClose()函数关闭文件时会自动调用FlushCache()函数,将缓存中的修改写入文件中。如果设置为false,则在文件关闭时不会自动刷新缓存,需要在程序中手动调用FlushCache()函数来刷新缓存
需要注意的是,当bAtClosing为true时,FlushCache()函数的调用并不会直接关闭文件,而是将缓存中的修改写入文件后保持文件处于打开状态。在程序结束时,应该手动调用GDALClose()函数来关闭文件。如果程序异常退出或崩溃,未刷新的数据将会丢失。
一般来说,如果不需要频繁地修改文件,建议将bAtClosesing参数设置为true,确保数据在文件关闭前都被写入文件中。如果需要频繁地修改文件,可以将bAtClosing设置为false,并在必要的时候手动调用FlushCache()函数来刷新缓存
返回此数据集的固有 RAM 使用情况
返回: RAM 使用率(以字节为单位),如果未知,则为 -1(默认实现返回 -1)
意义
用于估算当前数据集占用内存的函数。它的作用是计算打开当前数据集所需的内存大小,包括数据集的元数据、波段数据、缓存等。
在数据处理中,我们通常需要在内存中进行数据的计算和处理,因此需要知道当前数据集占用的内存大小,以便预估程序运行的内存需求,避免程序因内存不足而崩溃或运行缓慢。GetEstimatedRAMUsage()函数可以帮助我们计算当前数据集所需的内存大小,从而更好地管理程序的内存使用
virtual const OGRSpatialReference *GetSpatialRef() const
与 C 函数 GDALGetSpatialRef() 相同
获取此数据集的空间参考
返回: poSRS –空间参考系统对象 当投影定义不可用时,将返回 null
poSRS是一个OGRSpatialReference对象的指针
OGRSpatialReference
OGRSpatialReference是GDAL/OGR库中用于处理空间参考系统的类。它可以表示和操作不同的空间参考系统,如经纬度、投影坐标系等。通过OGRSpatialReference类,可以获取和设置空间参考系统的各种属性,如坐标系名称、投影方法、椭球体参数等。同时,OGRSpatialReference类也提供了与EPSG和PROJ.4等标准的互操作性,使得用户可以方便地使用已有的空间参考系统定义
函数返回的是一个指向内部静态缓冲区的指针,因此该指针指向的字符串应该被视为只读字符串,不应该被修改。如果尝试修改该指针指向的字符串,可能会导致不可预测的行为
后面有很多类似的获取(Get)类型的方法,一般都是const类型的,需要注意
virtual CPLErr SetSpatialRef(const OGRSpatialReference *poSRS)
此方法与 C GDALSetSpatialRef() 函数相同。
设置此数据集的空间参考系统
参数:poSRS – 空间参考系统对象
返回:如果发生错误,CE_Failure,否则CE_None。
取消空间参考系统
当需要取消数据集的空间参考信息时,可以将nullptr(空指针)作为参数传递给SetSpatialRef()函数,以表示当前数据集不再具有空间参考信息。
需要注意的是,并非所有的GDAL驱动程序都支持取消数据集的空间参考信息。因此,在使用SetSpatialRef()函数取消数据集的空间参考信息之前,需要确认当前驱动程序是否支持该操作。可以通过调用GDALDriver类的GetMetadataItem()方法,并传递参数“DCAP_UNSETTABLESRS”,来查询当前驱动程序是否支持取消数据集的空间参考信息。如果返回值为“YES”,则表示当前驱动程序支持取消数据集的空间参考信息
举例
GDALAllRegister();
GDALDriverManager* poDriverManager = GetGDALDriverManager();
const char* pszDriverName = "GTiff"; // 替换成所需的驱动名称
GDALDriver* poDriver = poDriverManager->GetDriverByName(pszDriverName);
if (poDriver->GetMetadataItem("DCAP_UNSETTABLESRS") != NULL) {
cout << "支持取消数据集的空间参考信息." << endl;
} else {
cout << "不支持取消数据集的空间参考信息" << endl;
}
由此可见,GTiff并不支持取消数据集的空间参考信息
但是,不同版本的GDAL驱动程序可能会有不同的功能和支持,因此某些驱动程序可能会支持取消数据集的空间参考信息,而另一些则不支持。因此,在使用某个GDAL驱动程序之前,最好查看该驱动程序的文档以及GDAL版本的兼容性信息,以确定它支持哪些功能和选项
const char *GetProjectionRef(void) const 与 C 函数 GDALGetProjectionRef() 相同
提取此数据集的投影定义字符串
参数:无参
返回:当投影定义不可用时,将返回空(但不是 NULL)字符串
GDALDataset *dataset = (GDALDataset *) GDALOpen("filename.tif", GA_ReadOnly);
const char *projection = dataset->GetProjectionRef();
GEOGCS["NAD83",DATUM["North_American_Datum_1983",SPHEROID["GRS 1980",6378137,298.257222101004,AUTHORITY["EPSG","7019"]],AUTHORITY["EPSG","6269"]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AXIS["Latitude",NORTH],AXIS["Longitude",EAST],AUTHORITY["EPSG","4269"]]
CPLErr SetProjection(const char *pszProjection) 此方法与 C GDALSetProjection() 函数相同
设置此数据集的投影参考字符串
参数:psz投影 – 投影引用字符串 字符串应采用 OGC WKT 或 PROJ.4 格式
返回:如果发生错误,CE_Failure,否则CE_None
OGC WKT 示例:
// 设置 WGS84 地理坐标系
SetProjection("GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]]");
// 设置 UTM 投影坐标系
SetProjection("PROJCS[\"WGS 84 / UTM zone 18N\",GEOGCS[\"WGS 84\",DATUM[\"WGS_1984\",SPHEROID[\"WGS 84\",6378137,298.257223563]],PRIMEM[\"Greenwich\",0],UNIT[\"degree\",0.0174532925199433]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",-75],PARAMETER[\"scale_factor\",0.9996],PARAMETER[\"false_easting\",500000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1]]");
PROJ.4 示例:
// 设置 WGS84 地理坐标系
SetProjection("+proj=longlat +datum=WGS84 +no_defs");
// 设置 UTM 投影坐标系
SetProjection("+proj=utm +zone=18 +datum=WGS84 +units=m +no_defs");
OGC WKT 太麻烦了,我选择PROJ [doge]
不过,OGC WKT 格式作为一种标准格式,在某些应用场景中也有其优势,例如与其他标准格式的互操作性更好,可读性更强等。具体使用哪种格式还需要根据具体应用场景和需求来进行选择
可以通过将projection参数设置为NULL或空字符串来取消空间参考
代码:
GDALAllRegister();
GDALDataset *dataset = (GDALDataset *) GDALOpen("USGS_1_n33w096_20211124.tif", GA_Update);
const char * projection = dataset->GetProjectionRef(); //打印原来的投影定义字符串
cout<SetProjection(NULL); //取消空间参考系统
//dataset->SetProjection("");
projection = dataset->GetProjectionRef(); //再次打印投影定义字符串
cout<
结果:无论是使用NULL还是"",都会显示格局被破坏了,取消空间参考可能导致元数据信息与实际数据不一致,所有一般还是不要取消空间参考,没了参考,数据其实就没有是使用价值了
在使用取消空间参考系统前,一定要提前备份好数据
Warning 1: USGS_1_n33w096_20211124.tif: The IFD has been rewritten at the end of the file, which breaks COG layout.
GDALDataset 的东西一篇写完太多了,今天就到这了
持续补充、修改、更新。。。。。