Trim whitespace using PIL

Is there a simple solution to trim whitespace on the image in PIL?

ImageMagick has easy support for it in the following way:

convert test.jpeg -fuzz 7% -trim test_trimmed.jpeg

I found a solution for PIL:

from PIL import Image, ImageChops

def trim(im, border):
    bg = Image.new(im.mode, im.size, border)
    diff = ImageChops.difference(im, bg)
    bbox = diff.getbbox()
    if bbox:
        return im.crop(bbox)

But this solution has disadvantages:

  1. I need to define border color, it is not a big deal for me, my images has a white background
  2. And the most disadvantage, This PIL solution doesn’t support ImageMagick’s -fuzz key. To add some fuzzy cropping. as I can have some jpeg compression artifacts and unneeded huge shadows.

Maybe PIL has some built-in functions for it?
Or there is some fast solution?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

I don’t think there is anything built in to PIL that can do this. But I’ve modified your code so it will do it.

  • It gets the border colour from the top left pixel, using getpixel, so you don’t need to pass the colour.
  • Subtracts a scalar from the differenced image, this is a quick way of saturating all values under 100, 100, 100 (in my example) to zero. So is a neat way to remove any ‘wobble’ resulting from compression.

Code:

from PIL import Image, ImageChops

def trim(im):
    bg = Image.new(im.mode, im.size, im.getpixel((0,0)))
    diff = ImageChops.difference(im, bg)
    diff = ImageChops.add(diff, diff, 2.0, -100)
    bbox = diff.getbbox()
    if bbox:
        return im.crop(bbox)

im = Image.open("bord3.jpg")
im = trim(im)
im.show()

Heavily compressed jpeg:

enter image description here Cropped: enter image description here

Noisy jpeg:

enter image description here Cropped: enter image description here

Method 2

Use wand http://docs.wand-py.org/en/0.3-maintenance/wand/image.html

trim(color=None, fuzz=0)
Remove solid border from image. Uses top left pixel as a guide by default, or you can also specify the color to remove.

Method 3

using trim function at ufp.image module.

import ufp.image
import PIL
im = PIL.Image.open('test.jpg', 'r')
trimed = ufp.image.trim(im, fuzz=13.3)
trimed.save('trimed.jpg')


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x