I have some rendered or processed pixel data in a bgl.Buffer() object and need it in a numpy array but that proccess seems to take very long. Here is what I have tried so far:
buffer = bgl.Buffer(bgl.GL_BYTE, WIDTH * HEIGHT * 4)
# render something into it
imageDataNp = np.empty(WIDTH * HEIGHT * 4, dtype=np.float32)
# now some benchmarks
imageDataNp = np.array(buffer, dtype=np.float32) # 7.05s
imageDataNp = np.asarray(buffer, dtype=np.float32) # 7.00s
imageDataNp = np.fromiter(buffer, dtype=np.float32) # 3.29s
imageDataNp = np.array(buffer.to_list(), dtype=np.float32) # 4.69s
imageDataNp = np.asarray(buffer.to_list(), dtype=np.float32) # 4.71s
imageDataNp = np.fromiter(buffer.to_list(), dtype=np.float32) # 2.80s
# create an image datablock as secondary buffer
if not IMAGE_NAME in bpy.data.images:
bpy.data.images.new(IMAGE_NAME, WIDTH, HEIGHT, float_buffer=True)
image = bpy.data.images[IMAGE_NAME]
image.scale(WIDTH, HEIGHT)
image.pixels.foreach_set(buffer)
image.pixels.foreach_get(imageDataNp) # both lines together take only 2.05s
# answer from stackexchange by Sanoronas
buffer_list = bytes(buffer.to_list())
imageDataNp = np.frombuffer(buffer_list, dtype=np.float32) # both lines together take 1.28s
It appears like even setting and getting to and from a Blender image datablock as a "secondary" buffer ist faster than going directly from bgl.Buffer() to a numpy array.
One possible reason I can think about is that bgl.Buffer() is at the time of 2.92 still not supporting the numpy buffer proctocol as described in this post.
Is there a way to achieve something similar using only Python? I see that the Cookie Cutter addon by CG Cookie ships with an file bgl_ext.py which includes a function def np_array_as_bgl_Buffer(array) which appears to do exactly the complement to what I am trying to achieve.
An example file with the full code from above can be found here.