GDAL中MEM格式的简单使用示例

GDAL库中提供了一种内存文件格式——MEM。如何使用MEM文件格式,主要有两种,一种是通过别的文件使用CreateCopy方法来创建一个MEM;另外一种是图像数据都已经存储在内存中了,然后使用内存数据块来构造一个MEM。第一种方式比较简单,这里主要说明下第二种方式。
首先看看MEM的说明文档,地址为:www.gdal.org/frmt_mem.html。从里面我们可以看到MEM文件支持几乎所有的空间数据信息,包括投影,坐标,GCP,元数据等信息。下面就主要看看怎么从一个内存数据块来构造一个MEM文件。MEM文件的数据名称如下:
MEM:::option=value[,option=value…]
例如:
MEM:::DATAPOINTER=342343408,PIXELS=100,LINES=100,BANDS=3,DATATYPE=Byte,PIXELOFFSET=3,LINEOFFSET=300,BANDOFFSET=1
可以看到MEM文件名开头有MEM后接三个英文冒号(:::),解析来由一系列的选项=值的方式来组成,具体选项和说明如下:

  • DATAPOINTER:内存数据块的指针地址,指针地址使用长整形来进行表示。注意:指针地址与32位或者64位系统有关系,要注意对应关系。必填项
  • PIXELS:图像宽度。必填项
  • LINES:图像高度,行数。必填项
  • BANDS:波段数,默认为1。选填项
  • DATATYPE:数据类型的名称(如Byte,Int16等),可以通过函数GDALGetDataTypeName()来获取,默认为Byte。选填项
  • PIXELOFFSET:像素偏移量,以Byte为单位。选填项
  • LINEOFFSET:行偏移量,以Byte为单位。选填项
  • BANDOFFSET:波段偏移量,以Byte为单位。选填项

其中前三项为必填项,必须指定,其余五项为选填项,最后三项和RasterIO函数的最后三个参数的意思相同。
下面是一个简单的示例代码,主要作用就是从一个大图像中读取512*512的大小的图像,然后将读取出来的图像构造一个MEM文件,并将该文件存储为一个PNG图像出来。

void GDAL_MEM_Test()
{
	GDALAllRegister();
	
	// 打开原始图像
	GDALDataset *pSrcDS = (GDALDataset*) GDALOpen("D:\\Data\\landsat\\p139r26_5t19900902_nn2.tif", GA_ReadOnly);
	GDALRasterBand *pBand = pSrcDS->GetRasterBand(1);


	// 申请512*512大小的内存,用于存放像素值
	unsigned char *pData = new unsigned char[512*512];
	memset(pData, 0, 512*512);


	// 从2500,2500开始宽高均读取256个像素
	pBand->RasterIO(GF_Read, 2500, 2500, 512, 512, pData, 512, 512, GDT_Byte, 0, 0);


	//使用读取出来的pData构造一个MEM数据集
	//"MEM:::DATAPOINTER=342343408,PIXELS=100,LINES=100,BANDS=3,DATATYPE=Byte,PIXELOFFSET=3,LINEOFFSET=300,BANDOFFSET=1"
	char aMemString[256] ={0};
	//构造MEM的文件名
	sprintf_s(aMemString, 256, "MEM:::DATAPOINTER=%d,PIXELS=%d,LINES=%d", pData, 512, 512);


	//打开MEM文件
	GDALDataset *pMemDS = (GDALDataset*) GDALOpen(aMemString, GA_ReadOnly);
	
	GDALDriver *pDriver = GetGDALDriverManager()->GetDriverByName("PNG");
	GDALDataset *pOutDS = pDriver->CreateCopy("D:\\Data\\landsat\\p139r26_5t19900902_nn2_sub.png", pMemDS, FALSE, NULL, NULL, NULL);


	GDALClose((GDALDatasetH) pSrcDS);
	GDALClose((GDALDatasetH) pMemDS);
	GDALClose((GDALDatasetH) pOutDS);

	delete []pData;
}

裁切的原始图像如下图所示,图中的红色区域大致为代码中读取出来的区域,右下角为鹰眼图。

 

下图是构造的MEM并输出的结果,可以看出图像的区域与上图中的红色区域中的一样。对于需要从图像中裁切一块数据除了使用RasterIO和Cereate方式之外,还可以使用MEM,比较方便,不需要复杂的代码即可完成工作;同时对于某些算法需要将数据做成一个临时文件放到磁盘上,然后再处理的情况,可以考虑使用这种方式,即不将数据写入磁盘,所有的数据都在内存中进行处理,可以很大程度上提高算法的效率。


需要注意的是,MEM文件大小是和你的系统内存大小有关系。如果使用32位程序的话,处理的数据保守估计不会超过2GB,如果是64位程序的话,只和你机器的内存大小有关系了。
转载自:https://blog.csdn.net/liminlu0314/article/details/19633849

You may also like...