Explain Codes LogoExplain Codes Logo

Removing white space around a saved image

python
matplotlib
image-processing
plotting
Anton ShumikhinbyAnton Shumikhin·Sep 16, 2024
TLDR

Delete that pesky whitespace in an image using Pillow's getbbox() function for automatic trim. getbbox() computes the bounding box of the non-empty spots and crop() function trims away what doesn't belong. Here's the crux:

from PIL import Image def trim_whitespace(image_path): with Image.open(image_path) as img: bbox = img.getbbox() # Find the party spots... the non-empty areas img = img.crop(bbox) if bbox else img # Crop the boring parts img.save('trimmed_image.png') # Save the fun... trim_whitespace('your_image.png') # Input the pizazz... your image path here

Invoke trim_whitespace() with your image file path to get a whitespace-free image.

Trimming alternates and optimizations

Sometimes, the image might be a matplotlib plot. Worry not! There's a treasure trove of options to bid farewell to the unwanted white border, without even touching an image editor.

Tightening the image in matplotlib

To make your image fit snug, like skinny jeans, use bbox_inches='tight' and pad_inches=0 in plt.savefig(). An example, tailored for you:

import matplotlib.pyplot as plt # Plotting marathon begins here... plt.plot(...) # Save with 0% baggage... White space, be gone! plt.savefig('tight_figure.png', bbox_inches='tight', pad_inches=0)

Exile padding and axis

If axis extras are taking up space, send them to oblivion with plt.gca().set_axis_off(). Set the matplotlib plot margins to zero using plt.margins(0,0):

plt.gca().set_axis_off() # Axis Off... Just like Boss Off plt.margins(0,0) # No more Mr. Nice Margin

plt.subplots_adjust() lets you say no to subplot parameters causing unwanted space:

plt.subplots_adjust(left=0, right=1, top=1, bottom=0) # The ultimate space manager... in one line!

Sweet transparency: invisible backgrounds

White backgrounds can be misleading. But no more! Use transparent=True for that seamless integration wherever this image goes:

plt.savefig('transparent_figure.png', transparent=True) # Your image is now a chameleon!

All in one function: plot and trim

Combine both, matplotlib and Pillow, to create an all-in-one function for plot and trim:

def create_and_trim_plot(x, y): plt.figure() plt.plot(x, y) plt.savefig('temporary_figure.png', bbox_inches='tight', pad_inches=0) # Pre-trim trim trim_whitespace('temporary_figure.png') # Post-trim trim

Why settle for one? Do both generations of trim.

Beyond static images: the method to the madness

It's not always about static images. The plot thickens as we venture into the realms of web and GUIs.

Web rendering perils

On the web, CSS can reintroduce whitespace. Fight this by setting the style attribute in your image tag:

<img src="trimmed_image.png" style="display:block;" />

Look ma, no extra space!

Gui framework nuances

Working with GUI frameworks? Ensure you're using compatible classes. Like PhotoImage for Tkinter. And watch out for excessive margins handed by the GUI elements:

# Tkinter allows for Christmas without the snow (white space, of course). from tkinter import PhotoImage trimmed_image = PhotoImage(file="trimmed_image.png")

Slim fit images, for the win.

Potential pitfalls: edge cases

There might be cases, like shadows or anti-aliasing, where whitespace clings on like a stubborn sticker. What do we do? We adapt:

  • Adjustment in Pillow trim: Use ImageOps.expand before getbbox() to handle anti-aliasing.
  • Threshold finetuning in matplotlib: Get granular with the extent parameter or custom clipping paths.
  • Testing: Iteratively test through visual inspection or image comparison tests.