GDAL获取指定地理坐标像元值、获取指定地理范围影像数据

//GdalImage.h
#include "StructDef.h"

#include "gdal1.11.2/gdal_priv.h"
#include "gdal1.11.2/gdal.h"
//#ifdef __cplusplus
//extern "C" {
//#endif

struct stRasterInfo
{
	char fileName[255];
	GDALDataset* pDataset;
	XRECT<rtsDataTypeGeo> rasterRange;
	int nBandCount;
};

struct stBitmapInfo
{
	char fileName[255];
	bool isInters;//是否有相交部分
	BYTE* pBuf;
	int nBandCount;

	int xStart;
	int yStart;
	int xEnd;
	int yEnd;

	int xSize;
	int ySize;
	stBitmapInfo():isInters(false), pBuf(NULL), nBandCount(0), xStart(0),yStart(0),xEnd(0),yEnd(0), xSize(0), ySize(0){}
	~stBitmapInfo()
	{
		if( pBuf )
		{
			free( pBuf );
			pBuf = NULL;
		}
	}
};

static char g_szRasterPath[255] = {0};	//栅格影像所在文件夹全路径路径
static int g_screenWidth = 0;	//屏幕分辨率,宽
static int g_screenHeight = 0;	//屏幕分辨率,高

//由地理坐标得到图像行列号
bool Projection2ImageRowCol(double *adfGeoTransform, double dProjX, double dProjY, int &iCol, int &iRow);

//根据地理位置获得指定点的像元值2015.3.5
//cszRasterPath[IN]:影像文件绝对路径	GeoX, GeoY[IN]:地理位置	pBuf[OUT]:存放读取到的像元值,为NULL读取失败
//nBandCOunt[OUT]:存放波段数	xSize, ySize[IN]:要获取像元值的范围,宽和高默认为1
void GetPixValByGeoPos( const char *cszRasterPath, const double GeoX, const double GeoY,
	int *&pBuf, int &nBandCount, int xSize, int ySize);// = 1  = 1

//初始化路径及分辨率
void InitVariable( const char *szRasterPath, const int screenWidth, const int screenHeight );

//获取影像对象
void GetBuf( const XRECT<rtsDataTypeGeo> showRange, stBitmapInfo *&pBitmap, int& nSize );

//#ifdef __cplusplus
//}
//#endif

//  GdalImage.cpp
#include <vector>
#include <dirent.h>
//#include <io.h>
#include <string.h>
#include "StructDef.h"
#include "DRECT.h"

#include "GdalImage.h"
#include "gdal1.11.2/gdal_priv.h"
#include "gdal1.11.2/gdal.h"
#include <iostream>
#include "mapWndBase.h"

//const int DirCharMAXLEN = 1024; //定义最大目录长度
static vector<stRasterInfo> g_vecRI;	//初始化时存放指定文件夹下所有tif,bmp,img信息

//由地理坐标得到图像行列号
bool Projection2ImageRowCol(double *adfGeoTransform, double dProjX, double dProjY, int &iCol, int &iRow)
{
	try
	{
		double dTemp = adfGeoTransform[1]*adfGeoTransform[5] - adfGeoTransform[2]*adfGeoTransform[4];
		double dCol = 0.0, dRow = 0.0;
		dCol = (adfGeoTransform[5]*(dProjX - adfGeoTransform[0]) -
			adfGeoTransform[2]*(dProjY - adfGeoTransform[3])) / dTemp + 0.5;
		dRow = (adfGeoTransform[1]*(dProjY - adfGeoTransform[3]) -
			adfGeoTransform[4]*(dProjX - adfGeoTransform[0])) / dTemp + 0.5;

		iCol = int(dCol);
		iRow = int(dRow);
		return true;
	}
	catch(...)
	{
		return false;
	}
}
//根据地理位置获得指定点的像元值2015.3.5
//cszRasterPath[IN]:影像文件绝对路径	GeoX, GeoY[IN]:地理位置	pBuf[OUT]:存放读取到的像元值,为NULL读取失败
//nBandCOunt[OUT]:存放波段数	xSize, ySize[IN]:要获取像元值的范围,宽和高默认为1
void GetPixValByGeoPos( const char *cszRasterPath, const double GeoX, const double GeoY,
	int *&pBuf, int &nBandCount, int xSize = 1, int ySize = 1 )
{
	try
	{
		//GDALAllRegister();
		GDALDataset *pDataset = (GDALDataset*)GDALOpen( cszRasterPath, GA_ReadOnly );
		double GT[6];
		//得到仿射变换模型
		pDataset->GetGeoTransform( GT );
		//得到影像宽和高
		int rasterXSize = pDataset->GetRasterXSize();
		int rasterYSize = pDataset->GetRasterYSize();
		//得到影像波段数
		nBandCount = pDataset->GetRasterCount();
		int iCol, iRow;
		//地理位置转换为影像行列位置
		if( !Projection2ImageRowCol( GT, GeoY, GeoX, iCol, iRow ) )
			throw 0;
		//地理位置转换结果是否超出影像范围
		if( iCol < 0 || iCol > rasterXSize || iRow < 0 || iRow > rasterYSize )
		{
			pBuf = NULL;
		}
		else
		{
			pBuf = new int[nBandCount*xSize*ySize];
			int *panBandMap= new int[nBandCount];
			for( int i = 0; i < nBandCount; ++i )
				panBandMap[i] = i+1;
			//获取指定行列位置每个波段的像元值,存入pBuf
			pDataset->RasterIO( GF_Read, iCol, iRow, xSize, ySize, pBuf, xSize,
				ySize, GDT_CInt32, nBandCount, panBandMap, 4, 0, 0 );

			delete[] panBandMap;
			panBandMap = NULL;
		}
	}
	catch(...)
	{
		if( pBuf )
			delete[] pBuf;
		pBuf = NULL;
	}

	return;
}

//Linux下使用
void GetFileList( const char* szPath, vector<string>& vecFile )
{
	DIR* dp = opendir (szPath);
	if (! dp)
		return;

	if (chdir (szPath) == -1)
		 return;

	struct dirent* de;
	for (de = readdir (dp); de; de = readdir (dp))
	{
		if ( (de -> d_type != DT_DIR) )
		{
			string strName(de->d_name);
			string strFormat = strName.substr(strName.length()-3, 3);
			if( "tif"==strFormat || "img"==strFormat || "bmp"==strFormat )
				vecFile.push_back( strName );
		}
	}
	closedir (dp);
	return ;
}
//windows下使用
//void GetFileList( const char* szPath, vector<string>& vecFile )
//{
//	_finddata_t fdata; //定义文件查找结构对象
//	long done;
//	char tempdir[DirCharMAXLEN] = {0}; //定义一个临时字符数组
//	strcat(tempdir, szPath); //连接字符串
//	strcat(tempdir, "\\*.*"); //连接字符串(搜索所有文件)
//	done = _findfirst(tempdir, &fdata); //开始查找文件
//
//	if(done != -1) //是否查找成功
//	{
//		int ret = 0;
//		while(ret != -1) //定义一个循环
//		{
//			if(fdata.attrib != _A_SUBDIR) //判断文件属性
//			{
//				//cout << fdata.name << endl;
//				if(strcmp(fdata.name, "...")!=0 &&
//					strcmp(fdata.name, "..") != 0 &&
//					strcmp(fdata.name, ".") != 0) //过滤
//				{
//					char dir[DirCharMAXLEN] = {0}; //定义字符数组
//					strcat(dir, szPath); //连接字符串
//					strcat(dir, "\\");
//					strcat(dir, fdata.name);
//					vecFile.push_back(string(dir));
//				}
//			}
//			ret = _findnext(done, &fdata); //查找下一个文件
//		}
//	}
//}

bool ImageRowCol2Projection(double *adfGeoTransform, int iCol, int iRow, double &dProjX, double &dProjY)
{
	//adfGeoTransform[6]  数组adfGeoTransform保存的是仿射变换中的一些参数,分别含义见下
	//adfGeoTransform[0]  左上角x坐标
	//adfGeoTransform[1]  东西方向分辨率
	//adfGeoTransform[2]  旋转角度, 0表示图像 "北方朝上"
	//adfGeoTransform[3]  左上角y坐标
	//adfGeoTransform[4]  旋转角度, 0表示图像 "北方朝上"
	//adfGeoTransform[5]  南北方向分辨率
	try
	{
		dProjX = adfGeoTransform[0] + adfGeoTransform[1] * iCol + adfGeoTransform[2] * iRow;
		dProjY = adfGeoTransform[3] + adfGeoTransform[4] * iCol + adfGeoTransform[5] * iRow;
		return true;
	}
	catch(...)
	{
		return false;
	}
}

bool GetRasterInfo( vector<stRasterInfo>& vecRI )
{
	if( !g_szRasterPath )
		return false;
	vector<string> vecFile;
	GetFileList( g_szRasterPath, vecFile );

	try
	{
		//GDALAllRegister();
		for( int i = 0; i < vecFile.size(); ++i )
		{
			GDALDataset *pDataset = (GDALDataset*)GDALOpen( vecFile[i].c_str(), GA_ReadOnly );
			double GT[6];
			//得到仿射变换模型
			pDataset->GetGeoTransform( GT );
			//得到影像宽和高
			int rasterXSize = pDataset->GetRasterXSize();
			int rasterYSize = pDataset->GetRasterYSize();
			//得到影像波段数
			int nBandCount = pDataset->GetRasterCount();
			GDALClose(pDataset);
			pDataset = NULL;
			double dProjX, dProjY;
			if( !ImageRowCol2Projection(GT, rasterXSize, rasterYSize, dProjX, dProjY) )
				throw 0;

			stRasterInfo RI;
			RI.pDataset = NULL;
			RI.nBandCount = nBandCount;
			strcpy( RI.fileName, vecFile[i].c_str() );
			RI.rasterRange.m_left = GT[0];
			RI.rasterRange.m_right = dProjX;
			RI.rasterRange.m_top = GT[3];
			RI.rasterRange.m_bottom = dProjY;
			vecRI.push_back(RI);
		}
	}
	catch(...)
	{
		return false;
	}
	return true;
}

void InitVariable( const char *szRasterPath, const int screenWidth, const int screenHeight )
{
	if( !szRasterPath || screenWidth <= 0 || screenHeight <= 0 )
		return;
	strcpy( g_szRasterPath, szRasterPath );
	g_screenWidth = screenWidth;
	g_screenHeight = screenHeight;
	if( !g_vecRI.empty() )
 		g_vecRI.clear();
 	GetRasterInfo( g_vecRI );
	return;
}

bool GetBitmapInfo( stRasterInfo stRI, int* panBandMap, const XRECT<rtsDataTypeGeo>& showRange,
	stBitmapInfo& stBitmap )
{
	int nBandCount;
	if( 7 == stRI.nBandCount )
		nBandCount = 3;
	else
		nBandCount = stRI.nBandCount;

	XRECT<rtsDataTypeGeo> rasterRange = stRI.rasterRange;
	try
	{
		//是否有相交范围,如果有取相交部分
		XRECT<rtsDataTypeGeo> interRect;
		if( !interRect.IntersectRect(showRange, rasterRange) )
		{
			strcpy( stBitmap.fileName, stRI.fileName );
			stBitmap.isInters = false;
			if( stRI.pDataset )
			{
				GDALClose( stRI.pDataset );
				stRI.pDataset = NULL;
			}
			return true;
		}
		if( !stRI.pDataset )
			stRI.pDataset = (GDALDataset*)GDALOpen( stRI.fileName, GA_ReadOnly );
		GDALDataset *pDataset = stRI.pDataset;
		//得到仿射变换模型
		double GT[6];
		pDataset->GetGeoTransform( GT );
		int iCol_L=0, iRow_B=0, iCol_R=0, iRow_T=0;//左,下,右,上 像元行列号
		if( !Projection2ImageRowCol(GT, interRect.m_left, interRect.m_bottom, iCol_L, iRow_B) )
			throw 0;
		if( !Projection2ImageRowCol(GT, interRect.m_right, interRect.m_top, iCol_R, iRow_T) )
			throw 0;
		//得到行列宽,高
		int xSize = abs(iCol_R-iCol_L);
		int ySize = abs(iRow_B-iRow_T);
		//缓冲区大小
		int const bufLen = nBandCount*g_screenWidth*g_screenHeight;
		BYTE *pBuf = new BYTE[bufLen];

		pDataset->RasterIO( GF_Read, iCol_L, iRow_T, xSize, ySize, pBuf, g_screenWidth,
			g_screenHeight, GDT_Byte, nBandCount, panBandMap, nBandCount, 0, 1 );

		//整理pBuf
		BYTE *pBufBack;
		if( 1 == nBandCount )//单波段
		{
			//pBufBack = new int[bufLen*4];
			pBufBack = (BYTE*)malloc( sizeof(int)*bufLen*4 );
			for( int i = 0; i < bufLen; ++i )
			{
				pBufBack[i*4] = pBuf[i];	pBufBack[i*4+1] = pBuf[i];
				pBufBack[i*4+2] = pBuf[i];	pBufBack[i*4+3] = 0;
			}
		}
		else if( 3==nBandCount || 7==nBandCount )//3波段
		{
			//pBufBack = new int[bufLen+bufLen/3];
			pBufBack = (BYTE*)malloc(sizeof(BYTE)*(bufLen+bufLen/3));
			for( int i = 0; i < bufLen/3; ++i )
			{
				pBufBack[i*4] = pBuf[i*3];	pBufBack[i*4+1] = pBuf[i*3+1];
				pBufBack[i*4+2] = pBuf[i*3+2];	pBufBack[i*4+3] = 0;
			}
		}
		else if( 4 == nBandCount )//4波段
		{
			//pBufBack = new int[bufLen];
			pBufBack = (BYTE*)malloc(bufLen*sizeof(int));
			for( int i = 0; i < bufLen; ++i )
			{
				if( 3 == (i%4) )
					pBufBack[i] = 0;
			}
		}
		delete[] pBuf;

		XRECT<rtsDataTypeDevice> bmpDevice;
		GeoToDevice(interRect,bmpDevice);

		strcpy( stBitmap.fileName, stRI.fileName );
		stBitmap.isInters = true;
		stBitmap.nBandCount = nBandCount;
		stBitmap.pBuf = pBufBack;

		stBitmap.xStart=bmpDevice.m_left;
		stBitmap.yStart=bmpDevice.m_top;
		stBitmap.xEnd=bmpDevice.m_right;
		stBitmap.yEnd=bmpDevice.m_bottom;

		stBitmap.xSize = g_screenWidth;
		stBitmap.ySize = g_screenHeight;
	}
	catch(...)
	{
		return false;
	}
	return true;
}

void DeleteBmpArray( stBitmapInfo *&pBitmap )
{
	delete[] pBitmap;
}

void GetBuf( const XRECT<rtsDataTypeGeo> showRange, stBitmapInfo *&pBitmap, int& nBitmap )
{
	nBitmap = 0;
	int nBandCount;//波段
	int *panBandMap;
	int nVecRI = g_vecRI.size();
 	pBitmap = new stBitmapInfo[nVecRI];
	for( int i = 0; i < nVecRI; ++i )
	{
		nBandCount = g_vecRI[i].nBandCount;
		//1波段 或 3波段
		if( 1==nBandCount || 3==nBandCount )
		{
			panBandMap = new int[nBandCount];
			for( int j = 0; j < nBandCount; ++j )
				panBandMap[j] = j+1;//nBandCount-j;
		}
		//如果是7波段
		else if( 7==nBandCount )
		{
			nBandCount = 3;
			panBandMap = new int[nBandCount];
			panBandMap[0] = 3;
			panBandMap[1] = 4;
			panBandMap[2] = 2;
		}
		if( GetBitmapInfo( g_vecRI[i], panBandMap, showRange, pBitmap[nBitmap] ) )
		{
			//只打开可显示的前4个
			if( (pBitmap[nBitmap].isInters) && (++nBitmap==4) )
			{
				//扫描其余RasterInfo,关闭打开的pDataset
				for( int j = i+1; j < nVecRI; ++j )
				{
					if( g_vecRI[j].pDataset )
					{
						GDALClose( g_vecRI[j].pDataset );
						g_vecRI[j].pDataset = NULL;
					}
				}
				break;
			}
		}
		delete[] panBandMap;
	}
	return;
}
时间: 2024-08-28 14:39:14

GDAL获取指定地理坐标像元值、获取指定地理范围影像数据的相关文章

倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-如何获取标准驱动器扭矩值获取电流值

双击某个驱动器(以松下伺服驱动器为例),在Process Data中,注意默认显示了PDO mapping1的数据(Error code, status word等) ? 注意左侧,2和3分别表示了与驱动器的所有数据输入和输出,如果我选中2 Output之后,勾选四个选项,那么就会有PDO mapping1到4,当然如果3 Input只勾选了第一项,那么就只会有Receive PDO mapping1 ? 在PDO mapping2中可以找到Torque actual value ? 我们还是输

仅当使用了列的列表,并且 IDENTITY_INSERT 为 ON 时,才能在表中为标识列指定显式值问题

今天在处理数据库过程中碰到这样的问题在插入一条数据到表中 系统报这样的错误 仅当使用了列的列表,并且 IDENTITY_INSERT 为 ON 时,才能在表中为标识列指定显式值问题 表有一列是自增长的标识列 ”字段1“ 如果这样插入 SET IDENTITY_INSERT platform..as_userinfo ON INSERT INTO platform..As_UserInfo values('110','张飞','男',20120401,18,'团员',2008-3-1) SET I

如何从二维数组中的多个key中获取指定key的值?

精华 LOVEME96 2016-10-21 10:40:19 浏览(1512) 回答(3) 赞(0) 新手求教:二维数组中一般会有多个key,如果我们要获得指定key的值,应该怎么做? 问题标签: php 回答(3) TimberSwift 2016-10-21 第一种:最简单的方法: foreach遍历数组,代码: foreach ($arr as $key => $value) { $arr2[] = $value['name']; } 另一种方法:使用了array_map $arr2 =

读取页面元素的onclick属性值 禁止重定向 获取url重定向后Location头指定的重定向目标

(1) 读取页面元素的onclick属性值 html代码: <a id='linka' onclick="alert('ok');">链接</a> 取出item身上onclick属性的值:alert('ok'); 实现: IHTMLElement *item;// 已经找到该元素 CComQIPtr<IHTMLElement> spElem(item); VARIANT var; spElem->get_onclick(&var); C

获取一个类指定的属性值

/// <summary> /// 获取一个类指定的属性值 /// </summary> /// <param name="info">object对象</param> /// <param name="field">属性名称</param> /// <returns></returns> public static object GetPropertyValue(obj

jQuery如何获取指定type属性值的input元素

jQuery遍历input文本框并获取input的name属性值:因为input标签的type属性是多种多样的,例如text.radio.checkbox等,但是实际应用中往往需要获取某一类属性值的input元素,下面就通过实例简单介绍一下.代码实例如下: $("input:text", document.forms[0]).each(function(){alert(this.name)}); 以上代码可以获取type属性值为text的input元素,并且遍历弹出它们的name属性值

mustache 获取json数据内数组对象指定元素的方法

由于最近项目再用mustache,因此发现了这个问题,mustache无法获取json数据内数组键值的指定索引的元素 遂上网查资料总结一下两种方法 1,数据为数组对像 var obj = [{name: 'foo'}, {name: 'bar'}]; var tmp = '{{#1}}{{name}}{{/1}}'; console.log(Mustache.render(tmp, obj)); //bar 这种方法个人觉得有一定局限性 -----参照:http://stackoverflow.

从指定文件(字节数组)获取内容以及获取长度

package cn.felay.io; import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; /** * @author <a mailto:[email protected]>felayman</a> * @t

c# 判断字符是否是全角, 获取字符串的字节数 , 获取字符串指定长度字节数的字符串

1 Encoding.Default.GetByteCount(checkString);  =2 全角 =1 半角 /// <summary> /// 获取字符串的字节长度 /// </summary> /// <param name="str"></param> /// <returns></returns> public static int GetStringByteLength(this string s