如何通过 GDAL 从位于 RAM 中的 geotiff 创建数据集
How to create dataset from geotiff located in RAM by GDAL
打开文件的 Gdal 函数使用文件名读取数据,如下所示:
GDALOpen (const char *pszFilename, GDALAccess eAccess)
但我的文件位于内存中。我使用下一个代码创建指向文件的指针:
FILE *stream;
stream = fmemopen(buf, lengthOfArray, "r");
是否可以通过某种方式通过指向文件的指针创建 GDALDataset?
有什么技巧和窍门吗?
GDAL 可以选择从缓冲区创建内存文件。参见:
http://gdal.org/cpl__vsi_8h.html#a86b6b1c37bb19d954ee3c4a7e910120c
我没有使用 C++ 的经验,但在 Python 中它看起来像:
with open('myfile.tif', mode='rb') as f:
gdal.FileFromMemBuffer('/vsimem/some_memfile', f.read())
然后您可以像打开普通文件一样打开该虚拟位置:
ds = gdal.Open('/vsimem/some_memfile')
当您处理完该文件后,请务必取消链接,否则它会一直存在。
ds = None
gdal.Unlink('/vsimem/some_memfile')
这是在 linux 上使用 jni 处理来自 java bytearray 的 geotiff 文件的完整 C++ 示例:
#include <jni.h>
#include "gdal_priv.h"
#include "cpl_string.h"
#include "cpl_conv.h"
#include "gdalwarper.h"
#include "cpl_vsi.h"
JNIEXPORT void JNICALL Java_com_box_processing_GEOTransform_run(JNIEnv *env, jobject obj, jbyteArray array) {
GDALAllRegister();
jboolean isCopy;
jbyte* buf = env->GetByteArrayElements(array, &isCopy);
jsize lengthOfArray = env->GetArrayLength(array);
const char *pszFormat = "GTiff";
GDALDriver *poDriver;
poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
VSILFILE* fpMem = VSIFileFromMemBuffer ("/vsimem/temp.tif", (GByte*) buf, (vsi_l_offset) lengthOfArray, FALSE );
VSIFCloseL(fpMem);
GDALDataset *poSrcDS = (GDALDataset *) GDALOpen( "/vsimem/temp.tif", GA_ReadOnly );
GDALDataset *poDstDS;
const char *pszSrcWKT = NULL;
pszSrcWKT=GDALGetProjectionRef(poSrcDS);
double error_threshold = 0.125;
GDALResampleAlg resampling = GRA_Cubic;
char* pszDstWKT = NULL;
GDALDataset * tmpDS = (GDALDataset*)(GDALDataset*)GDALAutoCreateWarpedVRT(poSrcDS, pszSrcWKT, pszDstWKT, resampling, error_threshold, NULL);
poDstDS = poDriver->CreateCopy( "/some/folder/example1.tif", (GDALDataset*)tmpDS, FALSE, NULL, NULL, NULL );
GDALClose( (GDALDatasetH) poDstDS );
GDALClose( (GDALDatasetH) poSrcDS );
VSIUnlink( "/vsimem/temp.tif" );
}
打开文件的 Gdal 函数使用文件名读取数据,如下所示:
GDALOpen (const char *pszFilename, GDALAccess eAccess)
但我的文件位于内存中。我使用下一个代码创建指向文件的指针:
FILE *stream;
stream = fmemopen(buf, lengthOfArray, "r");
是否可以通过某种方式通过指向文件的指针创建 GDALDataset?
有什么技巧和窍门吗?
GDAL 可以选择从缓冲区创建内存文件。参见:
http://gdal.org/cpl__vsi_8h.html#a86b6b1c37bb19d954ee3c4a7e910120c
我没有使用 C++ 的经验,但在 Python 中它看起来像:
with open('myfile.tif', mode='rb') as f:
gdal.FileFromMemBuffer('/vsimem/some_memfile', f.read())
然后您可以像打开普通文件一样打开该虚拟位置:
ds = gdal.Open('/vsimem/some_memfile')
当您处理完该文件后,请务必取消链接,否则它会一直存在。
ds = None
gdal.Unlink('/vsimem/some_memfile')
这是在 linux 上使用 jni 处理来自 java bytearray 的 geotiff 文件的完整 C++ 示例:
#include <jni.h>
#include "gdal_priv.h"
#include "cpl_string.h"
#include "cpl_conv.h"
#include "gdalwarper.h"
#include "cpl_vsi.h"
JNIEXPORT void JNICALL Java_com_box_processing_GEOTransform_run(JNIEnv *env, jobject obj, jbyteArray array) {
GDALAllRegister();
jboolean isCopy;
jbyte* buf = env->GetByteArrayElements(array, &isCopy);
jsize lengthOfArray = env->GetArrayLength(array);
const char *pszFormat = "GTiff";
GDALDriver *poDriver;
poDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
VSILFILE* fpMem = VSIFileFromMemBuffer ("/vsimem/temp.tif", (GByte*) buf, (vsi_l_offset) lengthOfArray, FALSE );
VSIFCloseL(fpMem);
GDALDataset *poSrcDS = (GDALDataset *) GDALOpen( "/vsimem/temp.tif", GA_ReadOnly );
GDALDataset *poDstDS;
const char *pszSrcWKT = NULL;
pszSrcWKT=GDALGetProjectionRef(poSrcDS);
double error_threshold = 0.125;
GDALResampleAlg resampling = GRA_Cubic;
char* pszDstWKT = NULL;
GDALDataset * tmpDS = (GDALDataset*)(GDALDataset*)GDALAutoCreateWarpedVRT(poSrcDS, pszSrcWKT, pszDstWKT, resampling, error_threshold, NULL);
poDstDS = poDriver->CreateCopy( "/some/folder/example1.tif", (GDALDataset*)tmpDS, FALSE, NULL, NULL, NULL );
GDALClose( (GDALDatasetH) poDstDS );
GDALClose( (GDALDatasetH) poSrcDS );
VSIUnlink( "/vsimem/temp.tif" );
}