Making seasonal cards with Snowglobe
You may remember Snowglobe, a screensaver alike graphical demo of generative fractal snowflakes interacting in a particle system. This week I uploaded two new versions to Hackage, snowglobe-2.0.0.2 which is compatible with the latest Haskell OpenGL libraries, and snowglobe-3 which removes an awkward dependency on hmatrix (replaced with simple small matrix maths copied from an old project of mine) and adds a new feature: saving each generated snowflake to a file (hit shift-S to activate and deactivate saving the files to the current working directory). Which makes snowglobe-2.0.0.2 obsolete already. You can get the latest (when you have ghc and cabal-install available) by:
cabal update && cabal install snowglobe
Having the flake images makes it possible to do all kinds of other fun stuff. They look like this:
I thought it would be nice to send all my neighbours a unique home made seasonal card, using these flake images. I got some card blanks from a local shop, they are 5x7 inches when folded, and from experience my printer doesn't print right to the edge (and margins are good too for aesthetic reasons), so I thought a 4x6 grid of flakes each 1 inch square would be nice.
The flake images are saved as PGM, part of the NetPBM family of formats, also known as PNM. There's a large suite of command line tools to do all kinds of image processing, here's the one's I'll be using:
- pngtopnm
- convert PNG to PNM, fairly self explanatory.
- pnmcat
- stack images next to each other, either from top to bottom (-tb) or left to right (-lr).
- pnmsplit
- takes a stream of PNM images and writes each to a separate file.
- pgmtoppm
- I use it to invert the colours, but it gives PPM (RGB) output, so...
- ppmtopgm
- ...this converts RGB back to greyscale.
- pnmgamma
- gamma adjustment, 0.25 makes it darker.
- pnmscale
- the flakes are 1024px square, so we've been working at 1024dpi - but the output should be 300dpi, with fewer pixels
- pnmtopng
- converts to PNG, -force makes the PNG greyscale instead of possibly indexed palette, -interlace makes the PNG interlaced (useful for previewing over a slow network connection, mainly), and the -phys flag sets the DPI (300dpi is 11811 pixels per metre).
- xargs
- not a NetPBM package at all, but I use it here to group same-sized batches of input lines into the pnmcat command
Here's the whole process, maybe run it one line at a time in case something explodes, you need a fair bit of free disk space too (all the NetPBM formats are uncompressed, each flake is 1MB and there are multiple copies in the temporary files):
#!/bin/bash mkdir cards cd cards gimp # make 5120x512 black bakcground greyscale image with no alpha > edge.png # make 1500x2100 white background greyscale image with no alpha > back.png snowglobe # hit shift-S to start saving images to current directory, q to quit # in another window keep track of how many files there are # you need 24 per card and a few extra because: geeqie # delete any you find ugly, there's always a few huge dense ones... pngtopnm < edge.png > edge.pgm pngtopnm < back.png > back.pgm mkdir 4x1 ls snowglobe-*.pgm | xargs -n 4 pnmcat -lr | ( cd 4x1 ; pnmsplit ) mkdir 4x6 ls 4x1/* | xargs -n 6 pnmcat -tb | ( cd 4x6 ; pnmsplit ) mkdir 5x7 cd 4x6 for i in * do pnmcat -tb -black ../edge.pgm $i ../edge.pgm | pgmtoppm white-black | ppmtopgm | pnmgamma 0.25 | pnmscale -xysize 1500 2100 | pnmcat -lr ../back.pgm - | pnmtopng -force -interlace -phys 11811 11811 1 > ../5x7/$i.png done cd ../5x7 geeqie # delete any you find ugly, often the last one is incomplete # finally, print them - load up your printer with card blanks first lp -d R220 -o landscape *.png
The final output images look something like this:
And when printed and folded, like this:
I hope my neighbours like them!