gdal读取正射影像数据

gdal 读取tif文件,与opencv操作图像的思路不一样,不能照搬,切不可逐个像素的调用 RasterIO 函数,操作非常耗时,最简单的方式就是全部读取,再逐个赋值。

以下是经过反复测试后的代码,可以供大家借鉴:

GDALAllRegister();		// 注册数据集
GDALDataset *poDataset;	//  创建数据集

poDataset = (GDALDataset *)GDALOpen(orthoFile, GA_ReadOnly);	//  打开影像
if (poDataset == NULL)
{
	emit sendMsg(tr("Error: Can't open photo!\t") + orthoFile);
	continue;
}

int orthoWidth = poDataset->GetRasterXSize();	//  获取影像宽度和高度
int orthoHeight = poDataset->GetRasterYSize();

double adfGeoTransform[6];
poDataset->GetGeoTransform(adfGeoTransform);	//  获取影像坐标信息

if (fabs(adfGeoTransform[0]) < 1 || fabs(adfGeoTransform[3]) < 1)	//  如果影像中未记录坐标系,则查找tfw文件,如果也不存在,终止程序
{
	QString tfwFileName = QFileInfo(orthoList[j]).baseName() + ".tfw";
	if (!QFileInfo(tfwFileName).exists())
	{
		return 1;
	}

	FILE *fp;
	fopen_s(&fp, tfwFileName.toLocal8Bit().data(), "r");
	if (!fp)
	{
		return 1;
	}

	int n = 0;
	double tfwData[6];

	while (!feof(fp))
	{
		char line[128];
		if (!fgets(line, 128, fp))
		{
			break;
		}

		sscanf(line, "%lf", &tfwData[n++]);
		if (n >= 6)
		{
			break;
		}
	}

	adfGeoTransform[0] = tfwData[4];
	adfGeoTransform[1] = tfwData[0];
	adfGeoTransform[2] = tfwData[1];
	adfGeoTransform[3] = tfwData[5];
	adfGeoTransform[4] = tfwData[2];
	adfGeoTransform[5] = tfwData[3];

	fclose(fp);
}

int bandCount = poDataset->GetRasterCount();			//  获取波段数
GDALRasterBand *band = poDataset->GetRasterBand(1);		//  获取第一个波段数据:目的是用来获取数据类型及数据宽度

GDALDataType datatype = band->GetRasterDataType();		//  获取数据类型
if (datatype == 0 || datatype == 12 || bandCount < 3)	//  如类型未定义及波段数据小于3则退出
{
	emit sendMsg(tr("Error: The file is error!") + orthoList[j]);
	return 1;
}

int nXBuffSize = orthoWidth;	//  读取缓存的宽度和高度,可根据需要对影像进行缩放
int nYBuffSize = orthoHeight;
int depth = GDALGetDataTypeSize(band->GetRasterDataType());		//  获取数据宽度
int nchar = depth / 8;			//  数据类型的字节数

size_t imgBufNum = (size_t)nXBuffSize * nYBuffSize * bandCount;	//  计算缓存空间大小

MEMORYSTATUS ms;
::GlobalMemoryStatus(&ms);					//  获取系统内存使用情况

if (imgBufNum * 32 > ms.dwAvailPhys * 0.8)	//  如果内存不够,则退出
{
	emit sendMsg(tr("Error: Insufficient remaining memory, please check!"));
	return 1;
}

int bandMap[3] = { 1, 2, 3 };		//  读取波段的次序,可设定,比如:RGB BGR 等
float *imgBuf = new float[imgBufNum];	//  开辟缓存空间,此处定义位float,以兼容 byte short ushort int uint
poDataset->RasterIO(GF_Read, 0, 0, orthoWidth, orthoHeight, //  获取的图像区域大小 起始坐标(x,y),宽度、高度(width,height                           
	imgBuf, nXBuffSize, nYBuffSize,	//  缓存地址,缓存的宽度和高度                            
	GDT_Float32,					//  缓存的数据类型,不是影像的数据类型,gdal会自动把影像的数据类型转为指定的数据类型                            
	3,								//  要获取的波段数,此处设为3                           
	bandMap,						//  获取的波段次序,此处设为 RGB 次序                          
	3 * 4,							//  缓存中相邻波段间隔,比如 RGB RGB,第一个R与第二个R相隔三个float,也就是 3 * 4(字节)                          
	nXBuffSize * 3 * 4,				//  缓存中相邻行的间距                           
	4);								//  缓存中两个波段的间距,R与G相邻,间隔是一个float,也就是 4(字节)

  

posted @ 2019-11-24 11:40  尘世俗人  阅读(1828)  评论(0编辑  收藏  举报