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

7

77

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?

Deenadeenya answered 23/3, 2010 at 9:54 Comment(0)
F
125

Try the following from the docs: https://pillow.readthedocs.io/en/stable/reference/ImageOps.html

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."

Fawne answered 23/3, 2010 at 10:1 Comment(3)
Oh, it seems I've missed that module. Thanks.Deenadeenya
yes but several PIL implementations will fail on images with modes other than RGB and L (i.e. RGBA, CMYK, 1), in which case you have to use workarounds that convert the source image's bands into L images, then invert these and then merge them back together (see below).Coenobite
module 'PIL' has no attribute 'ImageOps'Akanke
T
40

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')
Trug answered 14/10, 2012 at 6:57 Comment(2)
Alright, but this does NOT include the alpha channel for inversion. What if I want to invert the alpha channel as well?Overstuffed
Such an old answer and still works like a charm. Thanks man!Birkle
D
31

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')
Deign answered 14/7, 2016 at 15:53 Comment(1)
I wish there was a way to just tell other methods that use things like masks to invert, instead of this sort of workaround... but oh well, it works for now!Jellify
E
2

now ImageOps must be:

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

note that this works for me in python 3.8.5

Etiquette answered 30/10, 2021 at 12:35 Comment(0)
P
1

Of course ImageOps does its job well, but unfortunately it can't work with some modes like 'RGBA'. This code will solve this problem.

def invert(image: Image.Image) -> Image.Image:
    drawer = ImageDraw.Draw(image)
    pixels = image.load()
    for x in range(image.size[0]):
        for y in range(image.size[1]):
            data = pixels[x, y]
            if data != (0, 0, 0, 0) and isinstance(data, tuple):
                drawer.point((x, y), (255 - data[0], 255 - data[1], 255 - data[2], data[3]))

    return image
Postscript answered 19/9, 2022 at 16:30 Comment(0)
C
0

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()])
Coenobite answered 8/6, 2018 at 10:37 Comment(0)
V
-1
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()

`

Vitiated answered 9/7, 2018 at 1:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.