OGR python : write binary data in layer
An answer to this question on the GIS Stack Exchange.
Question
I'm trying to create a memory layer with gdal/ogr python that contains a Binary Field.
But I didn't succeed, where am I wrong?
from osgeo import ogr
# create layer
driver = ogr.GetDriverByName('Memory')
data_source = driver.CreateDataSource('foo')
layer = data_source.CreateLayer('bar')
# create binary field
field_name = 'bin_field'
binary_field = ogr.FieldDefn(field_name, ogr.OFTBinary)
layer.CreateField(binary_field)
# add feature that contains binary value
bytes_value = bytes(b'hello world')
feature = ogr.Feature(layer.GetLayerDefn())
feature.SetField(field_name, bytes_value)
layer.CreateFeature(feature)
Error message :
feature.SetField(field_name, bytes_value)
File "/usr/lib/python3/dist-packages/osgeo/ogr.py", line 4321, in SetField
return _ogr.Feature_SetField(self, *args)
TypeError: Wrong number or type of arguments for overloaded function 'Feature_SetField'.
Possible C/C++ prototypes are:
OGRFeatureShadow::SetField(int,char const *)
OGRFeatureShadow::SetField(char const *,char const *)
OGRFeatureShadow::SetField(int,double)
OGRFeatureShadow::SetField(char const *,double)
OGRFeatureShadow::SetField(int,int,int,int,int,int,float,int)
OGRFeatureShadow::SetField(char const *,int,int,int,int,int,float,int)
Answer
The warning returned by the compiler hints at what the problem is. Since field_name is a string, your code must conform to one of three patterns:
OGRFeatureShadow::SetField(char const *,char const *)
OGRFeatureShadow::SetField(char const *,double)
OGRFeatureShadow::SetField(char const *,int,int,int,int,int,float,int)
The first one is the one you want. From this it's clear that bytes_value is not getting automagically converted into a char const * type.
If we instead define:
bytes_value = 'hello world'
then things appear to work.
Alternatively, we could use:
bytes_value = bytes(b'hello world').decode('ascii')
You'll have to build unit tests in your application to determine whether either of those solutions allow you to correctly pass data around. Alternatively, you could get ahold of the GDAL folks to see if a new conversion method is possible.
Update, Even Rouault suggests:
binary_as_hex_string = binascii.hexlify(b'hello world')
f.SetFieldBinaryFromHexString(field_name, binary_as_hex_string)