A pointer to buffer of type POINTER(c_ubyte)
is returned by the C function (the image_data
variable in the following code). I want this data to be managed by Python, so I want to copy it into a bytearray
. Here's the function call
image_data = stb_image.stbi_load(filename_cstr, byref(width),
byref(height), byref(num_channels),
c_int(expected_num_channels))
We get to know the width
and height
of the image only after that call, so can't pre-allocate a bytearray
.
I would have used
array_type = c.c_ubyte * (num_channels.value * width.value * height.value)
image_data_bytearray = bytearray(cast(image_data, array_type))
But the type to cast
to must be a pointer, not array, so I get an error.
TypeError: cast() argument 2 must be a pointer type, not c_ubyte_Array_262144
What should I do?
OK, reading the answer to the question linked to in the comments (thanks, @"John Zwinck" and @"eryksun"), there are two ways of storing the data, either in a bytearray
or a numpy.array
. In all these snippets, image_data
is of type POINTER(c_ubyte)
, and we have array_type
defined as -
array_type = c_ubyte * num_channels * width * height
We can create a bytearray first and then loop over and set the bytes
arr_bytes = bytearray(array_size)
for i in range(array_size):
arr_bytes[i] = image_data[i]
Or a better way is to create a C array instance using from_address
and then initialize a bytearray
with it -
image_data_carray = array_type.from_address(addressof(image_data.contents))
# Copy into bytearray
image_data_bytearray = bytearray(image_data_carray)
And during writing the image (didn't ask this question, just sharing for completeness), we can obtain pointer to the bytearray data like this and give it to stbi_write_png
image_data_carray = array_type.from_buffer(image_data_bytearray)
image_data = cast(image_data_carray, POINTER(c_ubyte))
The numpy
based way of doing it is as answered in the linked question
address = addressof(image_data.contents)
image_data_ptr = np.ctypeslib.as_array(array_type.from_address(address))
This alone however only points to the memory returned by the C function, doesn't copy into a Python-managed array object. We can copy by creating a numpy array as
image_data = np.array(image_data_ptr)
To confirm I have done an assert all(arr_np == arr_bytes)
there. And arr_np.dtype
is uint8
.
And during writing the image, we can obtain a pointer to the numpy array's data like this
image_data = image_data_numpy.ctypes.data_as(POINTER(c_ubyte))
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments