Cropping An Image Using PIL

In one of our last post, we saw, how we can save a screenshot of a whole page. Since python provides quick and easy way to take a screenshot and save that, it seems pretty easy to take the screenshot.

However, there is a draw back to this method- it takes the screenshot of the whole web page. In many cases we don’t want the full web page, but the screenshot of a particular element- may be the one which is causing issues.

If you would use the JAVA jars for Selenium, the code is quick and doesn’t need anything to be imported externally. In python there is a caveat. You can’t directly use the image functions like cropping function.

So we would need to import an external library- the Python Image Library to deal with this.

Now, there are quite a few things to note here :

The Python Imaging Library (PIL) is not directly supported by Python 3.0 out of box. If you are using Python 2.7 on your system, then you can use the PIL library directly, but not on 3.0

Instead of PIL, we would install a fork of the original PIL library, called Pillow. Pillow is a friendly fork, created by Alex Clark and contributors, while the original PIL library was created by Fredrik Lundh and contributors.
So you would need to externally install this on your system and then start using it.

 

Installing PIL/Pillow

 

There are many ways of installing it, as given in the original installation documentation here.

 

As mentioned in the installation documentation :

 

Many of Pillow’s features require external libraries:

  • libjpeg provides JPEG functionality.
    • Pillow has been tested with libjpeg versions 6b, 8, and 9 and libjpeg-turbo version 8.
    • Starting with Pillow 3.0.0, libjpeg is required by default, but may be disabled with the--disable-jpeg flag.
  • zlib provides access to compressed PNGs
    • Starting with Pillow 3.0.0, zlib is required by default, but may be disabled with the--disable-zlib flag.
  • libtiff provides compressed TIFF functionality
    • Pillow has been tested with libtiff versions 3.x and 4.0
  • libfreetype provides type related services
  • littlecms provides color management
    • Pillow version 2.2.1 and below uses liblcms1, Pillow 2.3.0 and above uses liblcms2. Tested with 1.19 and 2.2.
  • libwebp provides the WebP format.
    • Pillow has been tested with version 0.1.3, which does not read transparent WebP files. Versions 0.3.0 and 0.4.0 support transparency.
  • tcl/tk provides support for tkinter bitmap and photo images.
  • openjpeg provides JPEG 2000 functionality.
    • Pillow has been tested with openjpeg 2.0.0 and 2.1.0.

 

So you would need to install these pre-requisites. Install them using

sudo apt-get install libtiff5-dev libjpeg8-dev zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev python-tk

One important thing to notice is that always use sudo if you’re on Ubuntu 13+ versions, otherwise it won’t be able to create any folders in installation directory (/usr/local/lib/python-3.4/dist-packages is where the PIL folder will need to be created).

Next, all you need to do is use the pip command to install Pillow

sudo pip3 install pillow

Look how I have used pip3 instead of pip for Python 3.0

Once you’ve run this command, you’ll be able to import PIL/Pillow library into your script. For a full installation guide, go here. Otherwise, you can also use the PyPi link for pillow, to download and use it.

 

 

Using Pillow to Crop An Image

 

To capture screenshot of an image, we would need to perform the following steps

  1. Locate Image element and and capture the screenshot of whole page ( in case of Firefox).
  2. Get element’s location using location attribute.
  3. Get element’s height and width using size attribute and location of element.
  4. Get element’s X ,Y , right , left coordinates- which would be available from height and width parameters of the image
  5. Crop original captured image from Step 1 using element’s x y coordinate position and height width parameters.
  6. Save cropped image at destination location physically.

 

__author__ = 'rahul'

import unittest
from selenium import webdriver
from PIL import Image


class ImageCrop(unittest.TestCase):

    def setUp(self):
        self.driver = webdriver.Firefox()

    def test_ImageCrop(self):

        driver = self.driver
        driver.maximize_window()
        driver.get('http://stackoverflow.com/')
        ele = driver.find_element_by_id('hlogo')

        #getting element's location
        loc1= ele.location

        #getting element's size
        size1= ele.size

        #save page's screenshot
        driver.save_screenshot('/home/rahul/Downloads/image1.png')

        #open the image using Pillow
        image2 = Image.open('image1.png')

        #setting the crop attributes using image's location and size.
        left = loc1['x']
        top = loc1['y']
        right = loc1['x'] + size1['width']
        bottom1 = loc1['y'] + size1['height']
  
        #crop the image using the attributes defined
        image2 = image2.crop((left,top,right,bottom1))

        #use the attribute to save image
        image2.save('/home/rahul/Downloads/image2.png')

    def tearDown(self):
        self.driver.quit()



if __name__ == '__main__':
    unittest.main()

We tried this code on the StackOverflow’s page and this is what we have