对于网络数据源,调度中可以把数据写入本地,然后读取本地数据格式进行影像的解析(地形有时候也用tif等格式)。
此种方式会每次调度进行不必要的IO开销和时间花费。
GDAL提供了相应的接口,直接从内存中解析数据,避免了磁盘写入和读取操作。具体步骤是:
(1)利用内存中的二进制数据流创建对应的内存文件 即 从 Buffer 创建 memory "file",这里的内存文件路径是位于GDAL自定义的虚拟文件目录 /vsimem/下。
(2)和解析本地文件一样,利用GDALOpen 读取内存文件。
//通过读取本地文件,产生二进制数据流 buffer、size FILE* pFile = fopen("D:\\data\\1.tif","rb"); fseek(pFile,0,SEEK_END); int size = ftell(pFile); rewind(pFile); GByte * buffer = new GByte [size]; fread(buffer,1,size,pFile); fclose(pFile); //利用二进制流创建内存文件 VSIFCloseL(VSIFileFromMemBuffer("/vsimem/work",buffer,size,FALSE)); //像打开本地文件一样,利用GDALopen 打开内存文件 GDALAllRegister(); GDALDataset* readDS = (GDALDataset*)GDALOpen("/vsimem/work",GA_ReadOnly); //释放 内存文件 VSIUnlink("/vsimem/work"); int width = readDS->GetRasterXSize(); int height = readDS->GetRasterYSize(); int bandCount = readDS->GetRasterCount(); float* data = new float[width*height*bandCount]; if (readDS->RasterIO(GDALRWFlag::GF_Read,0,0,width,height,data,width,height,GDT_Float32,bandCount,NULL,0,0,0)==CE_Failure) { GDALClose(readDS); //释放二进制数据流 delete[] buffer; buffer = NULL; delete[] data; data = NULL; } GDALClose(readDS); delete[] buffer; buffer = NULL; //现在只需操纵data就好,用完释放 delete[] data; data = NULL;
这里需注意,内存中二进制数据流 buffer 的释放是 在数据读取结束才能做,否则会出现RasterIO 失败。
这也正好说明,创建的内存文件 "/vsimem/work" 没有重新分配内存保存图像数据块,而是指向二进制数据流 buffer。
参考:
http://cryolite.iteye.com/blog/358929
http://blog.csdn.net/liminlu0314/article/details/40209357
http://www.gdal.org/cpl__vsi_8h.html#af9c1b931449d423e7a80bacb75ff0717