How to invert colors of image with PIL (Python-Imaging)?

PythonPython Imaging-Library

Python Problem Overview


I need to convert series of images drawn as white on black background letters to images where white and black are inverted (as negative). How can I achieve this using PIL?

Python Solutions


Solution 1 - Python

Try the following from the docs: http://effbot.org/imagingbook/imageops.htm

from PIL import Image
import PIL.ImageOps    

image = Image.open('your_image.png')

inverted_image = PIL.ImageOps.invert(image)

inverted_image.save('new_name.png')

Note: "The ImageOps module contains a number of 'ready-made' image processing operations. This module is somewhat experimental, and most operators only work on L and RGB images."

Solution 2 - Python

If the image is RGBA transparent this will fail... This should work though:

from PIL import Image
import PIL.ImageOps    

image = Image.open('your_image.png')
if image.mode == 'RGBA':
	r,g,b,a = image.split()
	rgb_image = Image.merge('RGB', (r,g,b))
	
	inverted_image = PIL.ImageOps.invert(rgb_image)
	
	r2,g2,b2 = inverted_image.split()
	
	final_transparent_image = Image.merge('RGBA', (r2,g2,b2,a))
	
	final_transparent_image.save('new_file.png')
	
else:
	inverted_image = PIL.ImageOps.invert(image)
	inverted_image.save('new_name.png')

Solution 3 - Python

For anyone working with an image in "1" mode (i.e., 1-bit pixels, black and white, stored with one pixel per byte -- see docs), you need to convert it into "L" mode before calling PIL.ImageOps.invert.

Thus:

im = im.convert('L')
im = ImageOps.invert(im)
im = im.convert('1')

Solution 4 - Python

now ImageOps must be:

PIL.ImageChops.invert(PIL.Image.open(imagepath))

note that this works for me in python 3.8.5

Solution 5 - Python

In case someone is inverting a CMYK image, the current implementations of PIL and Pillow don't seem to support this and throw an error. You can, however, easily circumvent this problem by inverting your image's individual bands using this handy function (essentially an extension of Greg Sadetsky's post above):

def CMYKInvert(img) :
	return Image.merge(img.mode, [ImageOps.invert(b.convert('L')) for b in img.split()])

Solution 6 - Python

from PIL import Image

img = Image.open("archive.extension") 

pixels = img.load()

for i in range(img.size[0]):
    for j in range(img.size[1]):
        x,y,z = pixels[i,j][0],pixels[i,j][1],pixels[i,j][2]
        x,y,z = abs(x-255), abs(y-255), abs(z-255)
        pixels[i,j] = (x,y,z)
		
img.show()

`

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbialixView Question on Stackoverflow
Solution 1 - PythonGary KerrView Answer on Stackoverflow
Solution 2 - PythonDaveView Answer on Stackoverflow
Solution 3 - PythonGreg SadetskyView Answer on Stackoverflow
Solution 4 - PythonAliView Answer on Stackoverflow
Solution 5 - PythonmxlView Answer on Stackoverflow
Solution 6 - PythonzilgoView Answer on Stackoverflow