I have an image where the colors are BGR. How can I transform my PIL image to swap the B and R elements of each pixel in an efficient manner?
Adding a solution using the ellipsis
image = image[...,::-1]
In this case, the ellipsis ...
is equivalent to :,:
while ::-1
inverts the order of the last dimension (channels).
im = Image.frombuffer('RGB', (width, height), bgr_buf, 'raw', 'BGR', 0, 0)
Assuming no alpha band, isn't it as simple as this?
b, g, r = im.split()
im = Image.merge("RGB", (r, g, b))
Edit:
Hmm... It seems PIL has a few bugs in this regard... im.split()
doesn't seem to work with recent versions of PIL (1.1.7). It may (?) still work with 1.1.6, though...
Application of other solutions. Just for a temporary measure.
import numpy
im = Image.fromarray(numpy.array(im)[:,:,::-1])
Just a quick footnote for anyone writing code that might have to deal with 4-channel images, and discovering that the simple numpy answer seems to be eating their alpha channel.
np_image[:,:,[0,1,2]] = np_image[:,:,[2,1,0]]
will preserve the alpha data if there is a fourth channel, whereas
np_image = np_image[:,:,[2,1,0]]
will overwrite the 4-channel image with only reversed 3-channel data. (And the even simpler numpy answer, img = img[:,:,::-1], will give you ARGB data, which would be bad, too. :)
Using the ideas explained before... using numpy you could.
bgr_image_array = numpy.asarray(bgr_image)
B, G, R = bgr_image_array.T
rgb_image_array = np.array((R, G, B)).T
rgb_image = Image.fromarray(rgb_image_array, mode='RGB')
Additionally it can remove the Alpha channel.
assert bgra_image_array.shape == (image_height, image_width, 4)
B, G, R, _ = bgra_image_array.T
rgb_image_array = np.array((R, G, B)).T