[gdal-dev] Dataset's ReadRaster/WriteRaster throws exception on c#

Tamas Szekeres szekerest at gmail.com
Mon Nov 12 10:05:05 PST 2018


You did not count the band size when allocating memory for the buffer.
That should be:

byte[] readRaster = new byte[tileSize * tileSize * 4];

Or alternatively use Band.ReadRaster to read just a specific band.

Best regards,

Tamas




Gigas002 <gigas002 at yandex.ru> ezt írta (időpont: 2018. nov. 12., H, 17:34):

> Hi all.
> I've rewritten some python code from gdal2tiles.py on c#, using GDAL.NET
> nuget package (ver. 2.3.1). Here you can see the working python code:
>
> def create_overview_tiles(input_file, output_file):
>         tile_driver = 'PNG'
>         tile_size = 256
>         tilebands = 4
>         resampling = 'bilinear'
>
>         mem_driver = gdal.GetDriverByName('MEM')
>         out_driver = gdal.GetDriverByName(tile_driver)
>
>         dsquery = mem_driver.Create('', 2 * tile_size, 2 * tile_size,
> tilebands)
>         dstile = mem_driver.Create('', tile_size, tile_size, tilebands)
>         dsquerytile = gdal.Open(input_file, gdal.GA_ReadOnly)
>
>         dsquery.WriteRaster(0, 0, tile_size, tile_size,
> dsquerytile.ReadRaster(0,
> 0, tile_size, tile_size), band_list=list(range(1, tilebands + 1)))
>         scale_query_to_tile(dsquery, dstile, resampling)
>         out_driver.CreateCopy(output_file, dstile, strict=0)
>
>
> def scale_query_to_tile(dsquery, dstile, resampling):
>     querysize = dsquery.RasterXSize
>     tilesize = dstile.RasterXSize
>
>     if resampling == 'near':
>         gdal_resampling = gdal.GRA_NearestNeighbour
>
>     elif resampling == 'bilinear':
>                 gdal_resampling = gdal.GRA_Bilinear
>
>     elif resampling == 'cubic':
>         gdal_resampling = gdal.GRA_Cubic
>
>     elif resampling == 'cubicspline':
>         gdal_resampling = gdal.GRA_CubicSpline
>
>     dsquery.SetGeoTransform((0.0, tilesize / float(querysize), 0.0, 0.0,
> 0.0, tilesize / float(querysize)))
>     dstile.SetGeoTransform((0.0, 1.0, 0.0, 0.0, 0.0, 1.0))
>
>     gdal.ReprojectImage(dsquery, dstile, None, None, gdal_resampling)
>
>
> And here's rewritten code on c#:
>
>         private static void BuildOverview(string inputFile, string
> outputFile)
>         {
>             const string tileDriver = "PNG";
>             const int tileSize = 256;
>             const int tileBands = 4;
>             const string resampling = "bilinear";
>
>             Driver memDriver = Gdal.GetDriverByName("MEM");
>             Driver outDriver = Gdal.GetDriverByName(tileDriver);
>
>             Dataset dsQuery = memDriver.Create("", 2 * tileSize, 2 *
> tileSize, tileBands, DataType.GDT_Byte, null);
>             Dataset dsTile = memDriver.Create("", tileSize, tileSize,
> tileBands, DataType.GDT_Byte, null);
>             Dataset dsQueryTile = Gdal.Open(inputFile, Access.GA_ReadOnly);
>
>             byte[] readRaster = new byte[tileSize * tileSize];
>             dsQueryTile.ReadRaster(0, 0, tileSize, tileSize, readRaster,
> tileSize, tileSize,
>                 tileBands, Enumerable.Range(1, tileBands + 1).ToArray(), 0,
> 0, 0);
>             dsQuery.WriteRaster(0, 0, tileSize, tileSize, readRaster,
> tileSize, tileSize,
>                 tileBands, Enumerable.Range(1, tileBands + 1).ToArray(), 0,
> 0, 0);
>
>             ScaleQueryToTile(dsQuery, dsTile, resampling);
>             outDriver.CreateCopy(outputFile, dsTile, 0, null, null, null);
>         }
>
>         private static void ScaleQueryToTile(Dataset dsQuery, Dataset
> dsTile, string resampling)
>         {
>             int querySize = dsQuery.RasterXSize;
>             int tileSize = dsTile.RasterXSize;
>
>             ResampleAlg gdalResampling;
>             switch (resampling)
>             {
>                 case "near":
>                     gdalResampling = ResampleAlg.GRA_NearestNeighbour;
>                     break;
>                 case "bilinear":
>                     gdalResampling = ResampleAlg.GRA_Bilinear;
>                     break;
>                 case "cubicspline":
>                     gdalResampling = ResampleAlg.GRA_CubicSpline;
>                     break;
>                 default:
>                     gdalResampling = ResampleAlg.GRA_Cubic;
>                     break;
>             }
>
>             dsQuery.SetGeoTransform(new[] {0.0, tileSize / (float)
> querySize, 0, 0, 0, tileSize / (float) querySize});
>             dsTile.SetGeoTransform(new[] { 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 });
>
>             Gdal.ReprojectImage(dsQuery, dsTile, null, null,
> gdalResampling,
> 0, 0, null, null, null);
>         }
>
>
> I use these methods to create upper tile (in my case create 10 lvl tile
> from
> 11 lvl tile). Python version works without problem, but c#'s throws
> "System.AccessViolationException" (Additional information on exception from
> VS: Attempted to read or write protected memory. This is often an
> indication
> that other memory is corrupt) on "dsQueryTile.ReadRaster(..." line in
> runtime.
> I suppose the exception is thrown because ReadRaster try to create pointer
> to byte[] and somehow fails.
>
> I uploaded the 11 lvl png tile, named "z_x_y.png", and good 10 lvl tile,
> done by python. I'm using VS2017, Win10x64 and writing on .net framework
> 4.7.2.
> Hope anyone knows how to fix it!
>
> 11_2200_1621.png
> <http://osgeo-org.1560.x6.nabble.com/file/t384059/11_2200_1621.png>
> 10_1100_810.png
> <http://osgeo-org.1560.x6.nabble.com/file/t384059/10_1100_810.png>
>
>
>
> --
> Sent from: http://osgeo-org.1560.x6.nabble.com/GDAL-Dev-f3742093.html
> _______________________________________________
> gdal-dev mailing list
> gdal-dev at lists.osgeo.org
> https://lists.osgeo.org/mailman/listinfo/gdal-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/gdal-dev/attachments/20181112/23ef3ada/attachment-0001.html>


More information about the gdal-dev mailing list