user11380394
user11380394

Reputation:

Convert multiples images into its negative with PIL

I want to read all the images in a folder and convert them into negatives of the same image

# Import library to work with Images
from PIL import Image

# Make negative pixel
def negatePixel(pixel):
    return tuple([255-x for x in pixel])

#img_dir = "" # Enter Directory of all images 

for i in range(1,130):
    # Original Image
    img = []
    img = Image.open(str(i) + '.jpg')
    # New clear image
    new_img = Image.new('RGB', img.size)

    # Get pixels from Image
    data = img.getdata()
    # Create map object consists of negative pixels
    new_data = map(negatePixel, data)

    # Put negative pixels into the new image
    new_img.putdata(list(new_data))
    # Save negative Image
    new_img.save(str(i) + 'neg.jpg')

    print ('saved image' + str(i))

I'm getting this error :

Traceback (most recent call last):
  File "2.py", line 23, in <module>
    new_img.putdata(list(new_data))
  File "2.py", line 6, in negatePixel
    return tuple([255-x for x in pixel])
TypeError: 'int' object is not iterable

I wrote the above programme to perform what I wanted it to, but it is striking an error. I'm new to programming and is there any idea how to solve this?

Upvotes: 3

Views: 924

Answers (1)

Mark Setchell
Mark Setchell

Reputation: 207465

Your approach is not ideal. Firstly, you can do that much more simply with ImageMagick which is included in most Linux distros and is available for macOS and Windows. Just in Terminal, this will invert all files in the current directory:

magick mogrify -negate *.jpg

Or, if you want them saved in a directory called results:

mkdir results
magick mogrify -path results -negate *.jpg

If you want to stick to Python and PIL/Pillow, there is already a invert() function in its ImageOps module here:

#!/usr/local/bin/python3

from PIL import Image, ImageOps

# Load image 
im = Image.open('image.jpg')

# Invert
result = ImageOps.invert(im)

# Save
result.save('result.jpg')

If you don't want to use the built-in invert(), you will be much better off using the point() function here:

#!/usr/local/bin/python3

from PIL import Image

# Load image 
im = Image.open('image.jpg')

# Negate
result = im.point(lambda p: 255 -p)

# Save
result.save('result.jpg')

Note: In general, as soon as you start using a for loop, or getdata() with an image in Python, you have probably already gone wrong. You should use built-in library functions or Numpy really, else everything will be slo-o-o-o-o-o-w.

Upvotes: 4

Related Questions