Imagine Python

Quite a cryptic title, but if you haven’t guessed, were talking about Images. This being a Python article that’s what we’re using! If you’ve never thought about it, or — even better — if you didn’t know it was possible then you’re in for a nice surprise; not only can Python do this but it’s pretty good at it, too. Actually, Python works well with graphics in general, but for now we’re sticking to the 2D kind.

Why would anyone want to do this with a language like Python?

Fortunately this is not a question I’ve had to ask myself since the answer seems pretty obvious to me. But basically that’s what this article is all about. Over the next few pages we’ll be looking at some of the different places you could use Python to automate and generally play with your images.

You will need to have at least basic knowledge of these subjects, so if you’re new to Python you should probably read Vikram Vaswani’s “Python 101″ first and come back later!

Essentially when you do anything to an image what you’re actually doing is writing/moving bytes around. You can do this manually, but when you have an excellent third party module like PIL (Python Imaging Library), why bother?

So let’s add a little extra image processing power to Python! You can get the latest version of PIL from www.pythonware.com

Windows users should download the windows installer (.exe). Those installing PIL from source should probably take a look through “Installing Python Modules” in the Python docs, if only out of interest.

On to the Fun Stuff

Ok, now that we have the “basics” out of the way, it’s time for the fun stuff! Something like converting a JPEG image to a GIF maybe. In most cases all you should have to do is open the image and save it with a different file extension and PIL will do the rest!

[code]
>>> import Image
>>> image = Image.open('sample.jpg')
>>> image.save('sample.gif')
>>>
[/code]

If this didn’t work for you, don’t worry; chances are all you have to do is add another line before saving.
 
[code]
>>> import Image
>>> image = Image.open('sample.jpg')
>>> image.convert('RGB')
>>> image.save('sample.gif')
>>>
[/code]

{mospagebreak title=Batch Processing}

Who ever said programming had to be hard work? With a little help from the OS module we can turn this into a nice piece of batch processing!

[code]
#!/usr/bin/env python

 

import os, Image

 

def convert(path, format):
 for each in os.listdir(path):
  if each.endswith(format[0]):
   try:
    name = os.path.join(path, each)
    save = os.path.splitext(name)
    Image.open(name).save(save[0] + format[1])
   except IOError: None

 

if __name__ == '__main__':
 

 convert('', ('.jpg', '.gif'))
[/code]

Ok, possibly a little scary at first glance but all this actually does is read a list of names from a given directory and loops over them performing some action. convert() just checks if ‘each’ ends with the extension we want before joining ‘path’ and ‘each’ together and splitting the extension from end. It then attempts to convert the image using PIL.

And no, you’re not limited to converting images between formats, or PIL would be pretty useless wouldn’t it! Actually one of the things I like most about PIL is that it hides a lot of the complexities that pop up when you’re working with images. That said let’s have a look at some of the other things we can do!

[code]
>>> import Image
>>> image = Image.open('sample.jpg')
>>> image.size
(200, 200)
>>> image.format
'JPEG'
>>> image.mode
'RGB'
>>> image.show()
>>> image.resize((100, 100))
>>> image.show()
>>> image.crop((0, 0, 50, 50))
>>> image.show()
>>> image.rotate(180)
>>> image.show()
>>>
[/code]

This shows off some nice features i.e. retrieving the image size, actual format, resizing, etc. The next part (after image.mode) does the actual work: resizing, cropping and rotating the image.

{mospagebreak title=Image.Show}

You’re probably wondering what all the image.show() calls are about; show() just creates a temporary image and opens it. This way we can see what’s happening to our image step by step!

Anyway let’s just slip off topic for a second here and imagine that you’re in charge of some online art gallery/community where members can upload images and have them displayed for the world to see. As part of the site’s design every image has a square thumbnail that links to the full-sized image.

We can think of this as a few steps:

  1. Loading the image and passing it to our function.
  2. Cropping our image so we end up with a square.
  3. Resizing (100 x 100) and saving our thumbnail.

[code]
#!/usr/bin/env python

 

import Image

 

def thumb(image):
 size = list(image.size)
 size.sort()
 image = image.crop((0, 0, size[0], size[0]))
 image = image.resize((100, 100), Image.ANTIALIAS)
 return image

 

if __name__ == '__main__':

 

 image = Image.open('sample1.jpg')
 image = thumb(image)
 image.save('sample2.jpg')
[/code]

This really just defines a new user function named thumb() which we can then use to create our thumbnails! It starts by converting the images size to a list and sorting it in place so we have the smallest dimension at the beginning of the list (this value is then used while cropping our image). The next part then crops and resizes our image using the ANTIALIAS filter (better quality) before returning the new image.

Watermarking

Next up we’re going to do some watermarking and paste a smaller graphic onto our image. Which as far as I know makes this the only example of watermarking with PIL, even though once again this is incredibly easy!

[code]
#!/usr/bin/env python

 

def watermark(image, thumb):
 imageX, imageY = image.size
 thumbX, thumbY = thumb.size
 if thumbX < imageX and thumbY < imageY:
  point1 = imageX - (thumbX + 10)
  point2 = imageY - (thumbY + 10)
  point3 = imageX - 10
  point4 = imageY - 10
  image.paste(thumb, (point1, point2, point3, point4))

if __name__ == '__main__':

 

 import Image

 

 image = Image.open('sample.jpg')
 thumb = Image.open('thumb.jpg')

 

 watermark(image, thumb)

 

 image.show()
[/code]

Quite proud of this for some reason; maybe because I’ve finally got my head around placing things where I want them on an image. Anyway what it is actually saying is that if ‘thumb’ is smaller than our image, then put it 10 pixels in from the bottom right hand corner of ‘image’ (since it would look pretty messed up in most cases otherwise).

{mospagebreak title=Lock It Down}

Last but not least: You may or may not have noticed those funky little images some websites use to stop automated signups and etc. No? Never mind if you haven’t because that’s what we’re about to do.

[code]
#!/usr/bin/env python

 

import Image, ImageDraw, ImageFont, random

 

def sample():
 ascii = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
 return ''.join(random.sample(ascii, 5))

 

def verify():
 image = Image.new('RGB', (125, 40), (255, 255, 255))
 font = ImageFont.truetype('Verdana.ttf', 25)
 draw = ImageDraw.Draw(image)
 draw.text((5, 5), sample(), font = font, fill = (0, 0, 0))
 image.save('verify.gif')

 

if __name__ == '__main__': verify()
[/code] 

There are a few differences between this example and the others we’ve talked about so far. Primarily the three modules ImageDraw, ImageFont and random and the two functions sample() and verify().

Why have two functions? We could have just as easily done this inside verify couldn’t we?

The thing is, sooner or later everyone ends up rewriting something they wrote for some other project. One of the nice things about using Python is it encourages you to write clean, reusable, modular code. Which is of course the main reason for the sample() function; since it just returns a string of random letters you could also use it to automate password generation!

Short and sweet, all sample() does is pick five letters at random from the string ‘ascii’ using random.sample() and returns them as a string.

verify() on the other hand has a little more going for it. This one unlike any of the other examples we’ve looked at starts off by creating a brand spanking new image instead of opening one! We’re going to write our random letters onto this in a second, but first we need to load the font we want to use, for this we’re using the ImageFont module. We then create a new instance of ImageDraw.Draw() which is used to draw the sample() string on the image!

Anyway it’s pretty safe to assume you have a good idea why this could be useful by now. You should also know enough to get started using PIL with your own images. Slap open up your Python shell and get playing!

Liked this article? Then you’ll probably find these links interesting too!

Python homepage
Python tutorial
Installing Python modules
PIL homepage
PIL tutorial
PIL documentation

Note: All the sample programs shown and discussed in this article where tested on Windows XP running Python 2.3 with PIL 1.4 and are meant only as examples.

[gp-comments width="770" linklove="off" ]
antalya escort bayan antalya escort bayan