Posts about photography, contract bridge, astrophotography, astronomy, Java development, internet systems.

Perfect wallpaper from digital photos using Linux and Netpbm

The world is full of wallpaper managers for every operating system out there. I enjoy wallpapers taken from some of my digital photography, such as this trip to Yosemite last year.

On nice modern monitors, you can really enjoy the full resolution of your pictures. Jane and I just replaced our old Viewsonic CRT monitors with some nice Dell 23-inch LCD models.

Immediately I saw that I needed to regenerate our collection of wallpaper photos to match the aspect ratio and higher resolution of our new monitors. I admit to being a stickler for my wallpaper photo albums. I have these requirements:

  • I want to scale and crop the photos to fill the screen exactly, no tiling or stretching.
  • I want no black bars, letterboxing, or distorted aspect ratios
  • I want to dim the maximum brightness of the photos so my desktop icons are still discernable

My Canon 20D full-resolution pictures have more than enough pixels to fill the biggest screen, so I cobbled together a shell script some time ago using the PBM (Portable Bitmap) tools that have been around since probably the 80’s for manipulating images. I don’t think many of the Linux distros install the toolset by default, but they’re easily available. On Ubuntu or Debian you can install them with “apt-get install netpbm”.

I start by making a work directory (“wallpaper” in this instance) and a subdirectory to hold the full-resolution original images, named “full”. I collect copies of my full-resolution pictures there in ~/wallpaper/full.

Next I need to work out the transform. My original resolution images are 3504 pixels wide by 2336 pixels vertically. My monitor is 2048 pixels by 1152 pixels.

Rather than work out the math, I just scaled an original picture to the monitor width to see how tall it would be. This command pipeline would scale a picture to 2048 pixels wide:

jpegtopnm full/IMG_1234.jpg | pnmscale -width 2048 | pnmtojpeg >IMG_1234.jpg

Opening that scaled image in Gimp told me that it was 2048 x 1365. That tells me that I need to crop some lines from the top and bottom of the image to fit them exactly to my monitor field. 1365 – 1152 leaves 213 lines to cut from the image. With the pbmtool “pamcut” I plan to cut 107 lines from the top of the image and give it a total height of 1152.

So I made this shell script to process all of the photos. The plan is to read all of the files from the “full” directory, and write perfectly scaled images to a subdirectory named “2048”. I’m also going to use the “ppmdim” utility to reduce the overall brightness of the images just a little. Here is the final script, called “mkwall2048”:

for i in `ls -1 full`
echo $i
jpegtopnm full/$i \
 | pnmscale -width 2048 \
 | pamcut -top=107 -height=1152 \
 | ppmdim 0.8 \
 | pnmtojpeg >2048/$i

This loops through every file in the “full” directory, putting the filename in variable $i. The rest of the script is a pipeline that feeds the image through five different tools from the Portable Bitmap collection, as follows:

  1. jpegtopnm converts the input file to a portable “any” map, then feeds it to stdout
  2. pnmscale scales the image to a width of 2048 pixels, preserving the aspect ratio
  3. pamcut slices off the top 107 lines, and preserves the next 1152 lines of the image
  4. ppmdim reduces the brightness of the image by 20% (80% of the existing brightness)
  5. pnmtojpeg converts the portable bitmap image back to a JPEG file

I’ve adjusted this script using the same process to make perfect wallpapers for my laptop monitors and desktops at work. It’s a real treat having a slideshow of my favorite photography available behind my work.

Leave a Reply




You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>