How to invert image colors in pygame?

I have a pygame Surface and would like to invert the colors. Is there any way faster and more pythonic than this? This is pretty slow.

I know that subtracting a value from 255 is not the only definition for inverted color, but that is what I want now.

I am surprised that pygame has no such built-in!

Thank you for your help!

import pygame def invertImg(img): """Inverts the colors of a pygame Screen""" img.lock() for x in range(img.get_width()): for y in range(img.get_height()): RGBA = img.get_at((x,y)) for i in range(3): # Invert RGB, but not Alpha RGBA[i] = 255 - RGBA[i] img.set_at((x,y),RGBA) img.unlock() 
+7
source share
3 answers

Winston's answer is good, but for completeness, when you need to manipulate pixel by pixel in Python, you should avoid looping through each pixel, regardless of which image library is used. This processor intensity is due to the nature of the language and can rarely be used for real-time operation.

Fortunately, the excellent NumPy library can help you perform several scalar operations in byte streams, looping around each number in its own code, which is orders of magnitude higher than in Python. For this specific operation, if we use the xor operation with (2^32 - 1) , we can delegate the operation to the inner loop in native code.

This example, which you can paste directly into the Python console, instantly flips pixels to white (if you have NumPy installed):

 import pygame srf = pygame.display.set_mode((640,480)) pixels = pygame.surfarray.pixels2d(srf) pixels ^= 2 ** 32 - 1 del pixels pygame.display.flip() 

Without installing NumPy, the pygame.surfarray methods return regular Python arrays (from the stdlib array stdlib ), and you will have to look for another way to work with these numbers, since a regular Python array does not work with all elements when a string such as pixels ^= 2 ** 32 - 1 .

+6
source

Taken from: http://archives.seul.org/pygame/users/Sep-2008/msg00142.html

 def inverted(img): inv = pygame.Surface(img.get_rect().size, pygame.SRCALPHA) inv.fill((255,255,255,255)) inv.blit(img, (0,0), None, BLEND_RGB_SUB) return inv 

This may lead to the wrong alpha channel, but you should be able to work with additional settings.

+7
source

One approach that might be more efficient would be to use PIL as described here: How to invert image colors using PIL (Python-Imaging)?

It is easy to convert it to your own pygame image in memory, as described here: http://mail.python.org/pipermail/image-sig/2005-May/003315.html

+1
source

All Articles