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

Gigas002 gigas002 at yandex.ru
Mon Nov 12 08:33:48 PST 2018


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


More information about the gdal-dev mailing list