在很多時候,我們的圖像數據往往都不是文件方式存儲在磁盤上,而是可能從網絡或者數據庫中獲取的是二進制的圖像數據流。最簡單的方式和最容易想到的方式就是將這個文件流保存到磁盤上形成一個文件,然後再使用GDAL來打開進行處理。但是這樣有一個不太好的地方就是需要生成一個磁盤的臨時文件,而且在磁盤上折騰了一圈後會增加不必要的系統開銷。
針對這個文件,GDAL庫裏面已經有現成的API來進行處理,下面就使用一個簡單的例子來進行說明,代碼如下:
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 StreamTest()
{
//爲了測試,從一個文件中將全部的數據讀取爲二進制流
const char* pszFile = "F:\\Data\\Test.tif";
// 爲了構造內存文件,必須有一個內存文件名稱,以/vsimem/開頭,後面的隨便啥都行,
// 這裏使用00000000這個來進行測試
string osMemFileName = "/vsimem/00000000";
// 寫了一個函數,讀取二進制數據,也可以從數據庫中或者網絡啥的獲取圖像的二進制流存儲在pabyData中
int nDataSize = 0;
GByte* pabyData = GetStream(pszFile, nDataSize);
// 將二進制流構造到MEM文件中
VSIFCloseL(VSIFileFromMemBuffer( osMemFileName.c_str(), pabyData, nDataSize, FALSE));
GDALAllRegister();
// 使用GDALOpen打開構造好的MEM文件
GDALDatasetH hDS = GDALOpen(osMemFileName.c_str(), GA_ReadOnly);
if (hDS == NULL)
{
// 打開失敗,將內存文件進行釋放
VSIUnlink(osMemFileName.c_str());
return FALSE;
}
// 下面就按照正常的圖像處理流程處理即可
printf("width = %d\nheight = %d\n", GDALGetRasterXSize(hDS), GDALGetRasterYSize(hDS));
// 關閉圖像
GDALClose(hDS);
// 處理結束後,將內存文件進行釋放
VSIUnlink(osMemFileName.c_str());
delete [] pabyData;
return TRUE;
}
上面GetStream函數用來讀取一個數據流。詳細的注視都在代碼裏面了。