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后接三个英文冒号(:::),解析来由一系列的选项=值的方式来组成,具体选项和说明如下:
下面是一个简单的示例代码,主要作用就是从一个大图像中读取512*512的大小的图像,然后将读取出来的图像构造一个MEM文件,并将该文件存储为一个PNG图像出来。
首先看看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为单位。选填项
下面是一个简单的示例代码,主要作用就是从一个大图像中读取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,比较方便,不需要复杂的代码即可完成工作;同时对于某些算法需要将数据做成一个临时文件放到磁盘上,然后再处理的情况,可以考虑使用这种方式,即不将数据写入磁盘,所有的数据都在内存中进行处理,可以很大程度上提高算法的效率。