I have an application that receives a pointer to JPEG data from a camera API wrapped with ctypes, converts it to a wx.Image, and displays the images as a movie.
One of required features is to set two of the components of a pixel equal to the third. E.g, my pixel in RGB format is (100,200,255), I want to set the the R and B values equal to the G, or (200,200,200). I need to do t his for every pixel in the image whilst maintaining a decent framerate.
I can access the RGB values from my wx.Image by calling the Image.GetData, which returns a string containing the pixel values in the following format: RGBRGBRGB ... I have implemented the feature naively by iterating through this RGBRGBRGB string.
However, this naive approach is far too slow to achieve a decent FPS because (I think):
a) I am iterating through every pixel in the image.
b) I am doing too much data copying.
I have considered converting my RGB data to numpy, performing the operation (I assume numpy would have a faster way of doing this sort of thing), and then converting back to wx.Image. Unfortunately I cannot convert straight from the raw data to numpy as the data comes as a JPEG, not in as a RGB bitmap. So I would need to go from data->wx.Image->numpy array->wx.Image.
I have also considered implementing my own python buffer which will return, for example, the G pixel value instead of the R and B values when being read. I think this would be the ideal solution, as it requires no data copying or excessive iterations, but I have no idea how to go about doing this. Will I need to write this buffer in C? Is it possible to implement buffers in pure python and still manipulate raw memory?
So SO, how do you think I should go about improving my performance? Should I attempt the numpy or buffer solution, or is there an easier solution that I am missing?
I am mainly looking for ideas/links to relevant documentation or examples, but if someones wants to write some code then that's fine :)
Thanks
You could try using the Python Imaging Library (PIL) - this is a library for manipulating images.
You can find information about converting between a wxPython image and a PIL image here, or you can load the jpeg directly into a PIL image.
Once you have converted your wx image into a PIL image I think this will do what you want (but I have not tested it):
r, g, b = im.split() # split the image into separate color planes
im = Image.merge("RGB", (g, g, g)) # merge them back, using the green plane for each
Then convert it back to a wxPython image.
This should be orders of magnitude faster than doing it in Python, since PIL is implemented in C and optimised for image processing.