[gdal-dev] Python Bindings - ReadArray direct to ctypes array?

Even Rouault even.rouault at mines-paris.org
Sat Jul 28 02:17:31 PDT 2012


Le samedi 28 juillet 2012 05:40:57, Jay L. a écrit :
> List,
> 
> I am working on a python script using the multiprocessing module with
> shared memory ctype arrays.
> 
> Currently the workflow is to open the dataset and grab the first band, as
> usual. I then read in the array, create an empty ctype array, and use
> memmove to move the numpy array to my ctypes array.
> 
> Is it possible, via python, to read the array direct to a ctypes array and
> bypass reading the array as an ndarray?

No, although it could certainly be extended to do so.

But with ctypes, you are able to bind all C functions of the GDAL API, so you 
can try the following snippet. Of course, due to the nature of ctypes 
bindings, you must be extra carefull of the value/size of arguments you use, 
otherwise crashes can easily happen.

from ctypes import *

def getlibgdal():
    import sys
    # Might need name tweaking depending on platfrom & version
    if sys.platform == 'win32':
        libgdal = windll.LoadLibrary("gdal19.dll")
    else:
        libgdal = cdll.LoadLibrary("libgdal.so.1")

    libgdal.GDALOpen.argtypes = [ c_char_p, c_int ]
    libgdal.GDALOpen.restype = c_void_p

    libgdal.GDALClose.argtypes = [ c_void_p ]

    libgdal.GDALGetRasterCount.argtypes = [ c_void_p ]
    libgdal.GDALGetRasterCount.res_type = c_int

    libgdal.GDALGetRasterXSize.argtypes = [ c_void_p ]
    libgdal.GDALGetRasterXSize.res_type = c_int

    libgdal.GDALGetRasterYSize.argtypes = [ c_void_p ]
    libgdal.GDALGetRasterYSize.res_type = c_int

    libgdal.GDALGetRasterBand.argtypes = [ c_void_p, c_int ]
    libgdal.GDALGetRasterBand.restype = c_void_p

    libgdal.GA_ReadOnly = 0
    libgdal.GA_Update = 1

    libgdal.GF_Read = 0
    libgdal.GF_Write = 1

    libgdal.GDT_Unknown = 0
    libgdal.GDT_Byte = 1
    libgdal.GDT_UInt16 = 2
    libgdal.GDT_Int16 = 3
    libgdal.GDT_UInt32 = 4
    libgdal.GDT_Int32 = 5
    libgdal.GDT_Float32 = 6
    libgdal.GDT_Float64 = 7
    libgdal.GDT_CInt16 = 8
    libgdal.GDT_CInt32 = 9
    libgdal.GDT_CFloat32 = 10
    libgdal.GDT_CFloat64 = 11

    libgdal.GDALRasterIO.argtypes = [
        c_void_p, # rasterband
        c_int, # eRWFlag
        c_int, # nXOff
        c_int, # nYOff
        c_int, # nXSize
        c_int, # nYSize
        c_void_p, # pData
        c_int, # nBufXSize
        c_int, # nBufYSize
        c_int, # eBufType
        c_int, # nPixelSpace
        c_int ] # nLineSpace
    libgdal.GDALRasterIO.res_type = c_int

    # Don't forget to register all drivers
    libgdal.GDALAllRegister()

    return libgdal

libgdal = getlibgdal()

ds = libgdal.GDALOpen("byte.tif", libgdal.GA_ReadOnly)
if ds is 0:
    import sys
    sys.exit(1)

xsize = libgdal.GDALGetRasterXSize(ds)
ysize = libgdal.GDALGetRasterYSize(ds)
band = libgdal.GDALGetRasterBand(ds, 1)
ar = (c_byte * (xsize * ysize))()

ret = libgdal.GDALRasterIO(band, libgdal.GF_Read,
                           0, 0, xsize, ysize,
                           cast(ar, c_void_p),
                           xsize, ysize, libgdal.GDT_Byte,
                           0, 0)
if ret == 0:
    print('success')

libgdal.GDALClose(ds)

> 
> Thanks,
> J


More information about the gdal-dev mailing list