I am using Cython to grab images from a USB camera and convert them into a PIL image that is returned to the caller.
The data for the image is in a character array pointed at by the “convert_buffer” member of the structure returned by the image grabbing function:
struct FlyCaptureImage:
/// stuff
char * convert_buffer
/// more stuff
Right now, I am doing this to turn it into a PIL image:
cdef unsigned char *convert_buffer
cdef Py_ssize_t byte_length
cdef bytes py_string
// get the number of bytes into a Py_ssize_t type
byte_length = count
// slice the char array so it looks like a Python str type
py_string = convert_buffer[:byte_length]
// create the PIL image from the python string
pil_image = PILImage.fromstring('RGB', (width, height), py_string)
That procedure of converting the data into a python string takes 2ms for what sounds like it could be a zero-copy event. Is it possible to get PIL to create my image just from the char * image data pointer that the camera API provided?
As of PIL 1.1.4, the
Image.frombuffermethod supports zero-copy:The problem is that your camera data appears to be 24-bit RGB, where PIL wants 32-bit RGBA/RGBX. Can you control the pixel format coming from the camera API?
If not, there still may be an advantage to usingImage.frombuffer, since it will accept abufferinstead of requiring you to build a python string from the pixel data.Edit: looking at the source for
frombuffer, it is a light wrapper onfromstring, and zero-copy requires a pixel format in theImage._MAPMODESlist (i.e. RGBX). At a minimum, you would have to copy/convert the RGB data to an RGBX buffer to get a zero-copy compatible pixel format.I don’t have a better way to get the raw bytes into PIL, but here are some interesting references: