"wallfix", using python to set my wallpaper

I had fun writing about my "cd" helper, so I thought I'd share another productivity helper I wrote for setting my wallpaper. It's a little silly, but I insist on my wallpaper being used for my lockscreen and my login window as well -- that way the entire time I'm on my computer the background is "seamless". Before I wrote this script it used to take me probably 3 or 4 minutes to change wallpapers!

I use the following utilities on my desktop, so I needed a way to set the background for all of them:

Due to some quirks in the way all these tools work, I found that in order for my computer to always display the exact same background I needed to resize the image to be exactly the size of my desktop. This was additionally complicated by the fact that wallpapers come in different aspect ratios, so sometimes I would have to crop things as well. Lastly, for whatever reason, SLiM wants a .jpg while i3lock only takes a .png.

I needed to write a helper that would:

  1. Resize and crop the image to fit my screen size.
  2. Generate a .png and a .jpg
  3. Tell i3lock, SLiM and my desktop (feh) to use the right image.

The first step was I established ~/.wallpaper.jpg and ~/.wallpaper.png as the canonical location of my wallpaper images. I then updated SLiM, i3lock and feh to point at those images. Doing this means that I only need to write the images to once place and everything will just work!

Resizing and cropping

I wrote this script with python and used PIL to do the image manipulation. Here is the entire script:

#!/usr/bin/env python

import os
import sys

from PIL import Image

HOME = os.environ['HOME']

WIDTH = 1440
HEIGHT = 900

def local_file(filename):
    return os.path.join(HOME, filename)

def make_wallpapers(original):
    im = Image.open(original)
    width, height = im.size
    ratio = float(width) / height

    if ratio > RATIO:
        # resize to match height, then crop horizontally from center
        new_width = int(HEIGHT * ratio)
        im.thumbnail((new_width, HEIGHT), Image.ANTIALIAS)
        offset = (new_width - WIDTH) / 2
        cropped = im.crop((offset, 0, offset + WIDTH, HEIGHT))
    elif ratio < RATIO:
        # resize to match width, then crop vertically from center
        new_height = int(WIDTH / ratio)
        im.thumbnail((WIDTH, new_height), Image.ANTIALIAS)
        offset = (new_height - HEIGHT) / 2
        cropped = im.crop((0, offset, WIDTH, offset + HEIGHT))
        im.thumbnail((WIDTH, HEIGHT), Image.ANTIALIAS)
        cropped = im

    path, ext = os.path.splitext(original)
    dest_jpg = local_file('.wallpaper.jpg')
    dest_png = local_file('.wallpaper.png')

    cropped.save(dest_jpg, 'JPEG', quality=100)
    cropped.save(dest_png, 'PNG')

if __name__ == '__main__':
    if len(sys.argv) == 1:
        filename = raw_input('New image? ')
        filename = sys.argv[-1]

    if not os.path.exists(filename):
        print 'Error: %s not found' % filename


To use this, I just run wallfix ~/pictures/Wallpapers/kittens3.jpg and everything is set up!

The moral of the story

I think I spent 30 minutes setting this all up. If the amount of time it used to take me to change my wallpaper manually was 3 minutes, after 10 changes I'll have made up the time. More than the time saved, though, I think it's useful to be mindful of tasks you do that are repetitive and figure out how to automate them.

Comments (0)

Commenting has been closed, but please feel free to contact me