[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