[gdal-dev] GDAL C# bindings, read from /vsimem/
Atle Frenvik Sveen
atle at frenviksveen.net
Thu Jul 12 02:05:39 PDT 2018
Hi list, first time poster here.
I'm using the GDAL C# bindings in .net core via the Gdal.Core Nuget package (https://www.nuget.org/packages/Gdal.Core/)
Everyting seems to work fine, apart from the fact that I have to touch the file system in order to get my created GeoTiff as a memory stream
Sample code:
var outputRasterFileName = $"{Path.GetTempPath()}{Guid.NewGuid()}.tiff";
var driver = Gdal.GetDriverByName("GTiff");
var ds = driver.Create(outputRasterFileName, resolution.X, resolution.Y, 1, DataType.GDT_Byte, null);
SetSrsFromLayer(ds, layer);
var arg = new[] { envelope.MinX, pixelSize, 0, envelope.MinY, 0, pixelSize };
ds.SetGeoTransform(arg);
var band = ds.GetRasterBand(1);
band.SetNoDataValue(noDataValue);
band.FlushCache();
var rasterizeOptions = new[] { "ALL_TOUCHED=TRUE" };
Gdal.RasterizeLayer(ds, 1, new[] { 1 }, layer, IntPtr.Zero, IntPtr.Zero, 1, new[] { 10.0 }, rasterizeOptions, null, null);
ds.FlushCache();
var destination = new MemoryStream();
using (var source = File.Open(outputRasterFileName, FileMode.Open))
{
source.CopyTo(destination);
destination.Position = 0;
return destination;
}
This works, but I do not like the idea of writing to disk when I don't have to. I then found these threads:
http://osgeo-org.1560.x6.nabble.com/gdal-dev-NET-and-OGR-writing-to-stream-td3744067.html#a3744070
https://lists.osgeo.org/pipermail/gdal-dev/2016-August/045030.html
Which says I can use the memory file system handler, and the python sample code provided by Even seems easy enough to translate:
# Read /vsimem/output.png
f = gdal.VSIFOpenL('/vsimem/output.png', 'rb')
gdal.VSIFSeekL(f, 0, 2) # seek to end
size = gdal.VSIFTellL(f)
gdal.VSIFSeekL(f, 0, 0) # seek to beginning
data = gdal.VSIFReadL(1, size, f)
gdal.VSIFCloseL(f)
# Cleanup
gdal.Unlink('/vsimem/output.png')
However, the C# bindings does not seem to include VSIFReadL, although Maksim Sestic seems to indicate that they are.
Is this an issue with the Nuget-package?
I then tried using C# Marshal.Copy, but this fails:
var bufPtr = Gdal.VSIFOpenL(outputRasterFileName, "rb"); //outputRasterFileName is now "/vsimem/file.tiff"
Gdal.VSIFSeekL(bufPtr, 0, 2); // seek to end
var size = Gdal.VSIFTellL(bufPtr);
Gdal.VSIFSeekL(bufPtr, 0, 0); // seek to beginning
Gdal.VSIFCloseL(bufPtr);
var data = new byte[size];
Marshal.Copy(bufPtr, data, 0, size);
Gdal.Unlink(outputRasterFileName);
I am by no means a C# expert, but I cannot see any reason this should fail? Given a memory pointer and size, read bytes, right?
As a last alternative I've tried to use the examples provided here: https://trac.osgeo.org/gdal/browser/trunk/gdal/swig/csharp/apps/GDALReadDirect.cs
This lets me read the bitmap of my raster, but all geotiff-metadata is lost. This also seems a bit overkill, as the actual GeoTiff is created and exists in memory!
So, to sum up a large mail:
1. Should Gdal.VSIFReadL be available in the C# bindings? If so, how do I get them?
2. If not 1, Should I be able to use Marshal.Copy in the manner described above? Or are there any other ways of getting these bytes?
3. If not 2, is using the sample code in https://trac.osgeo.org/gdal/browser/trunk/gdal/swig/csharp/apps/GDALReadDirect.cs a feasible way to create a stream of a geotiff-file`?
Thanks in advance for your replies, and thanks for a great library!
-a
--
Atle Frenvik Sveen
atle at frenviksveen.net
45278689
atlefren.net
More information about the gdal-dev
mailing list