GDAL从二进制数据流中构造数据集
目录
1. 概述
参看《从二进制数据流中构造GDAL可以读取的图像数据》这篇文章。这个问题的内涵在于,处理图像时都会将其读取成宽X高X波段的三维数组的内存Buffer,但是图像文件本身却会被压缩成各种各样的数据类型(jpg、png、tif等)。在某些直接获取到数据流的情况下,可以直接在内存中构建GDAL数据集并进行读写操作,这样就可以避免磁盘IO的性能。
以个人的实际经验来看,有两个地方用到了这个功能:
- 从远端(Web)访问数据,可以先一次性获取到内存Buffer,然后在内存中构建GDAL数据集。
- gltf的bin中内嵌了jpg/png图像文件,可以直接获取二进制文件流,然后在内存中构建GDAL数据集。
2. 实现
按照自己的使用习惯,试用了一下《从二进制数据流中构造GDAL可以读取的图像数据》的例子,基本没什么问题:
#include <iostream> #include <gdal_priv.h> using namespace std; GByte *GetStream(const char* pszFile, int &nSize) { FILE* pFile = fopen(pszFile, "rb"); fseek(pFile, 0, SEEK_END); nSize = ftell(pFile); fseek(pFile, 0, SEEK_SET); GByte *pBuffer = new GByte[nSize]; fread(pBuffer, nSize, 1, pFile); fclose(pFile); return pBuffer; } int main() { GDALAllRegister(); //GDAL所有操作都需要先注册格式 CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO"); //支持中文路径 // 为了构造内存文件,必须有一个内存文件名称,以/vsimem/开头,后面的随便啥都行 string osMemFileName = "/vsimem/00000000"; // 写了一个函数,读取二进制数据,也可以从数据库中或者网络啥的获取图像的二进制流存储在pabyData中 const char* imgPath = "D:/dst1.jpg"; int nDataSize = 0; GByte* pabyData = GetStream(imgPath, nDataSize); // 将二进制流构造到MEM文件中 VSIFCloseL(VSIFileFromMemBuffer(osMemFileName.c_str(), pabyData, nDataSize, FALSE)); GDALDataset* img = (GDALDataset *)GDALOpen(imgPath, GA_ReadOnly); if (!img) { cout << "Can't Open Image!" << endl; return 1; } // 处理结束后,将内存文件进行释放 VSIUnlink(osMemFileName.c_str()); delete[] pabyData; pabyData = nullptr; int imgWidth = img->GetRasterXSize(); //图像宽度 int imgHeight = img->GetRasterYSize(); //图像高度 int bandNum = img->GetRasterCount(); //波段数 int depth = GDALGetDataTypeSize(img->GetRasterBand(1)->GetRasterDataType()) / 8; //图像深度 cout << imgWidth << '\t' << imgHeight << '\t' << bandNum << '\t' << depth << endl; GDALClose(img); img = nullptr; }
读取到的宽、高、波段以及深度:
也可以进行进一步的读写操作。
分类: GDAL