cp2up.sh — fits the important part of Canada Post print labels two per sheet

blurred (for privacy) 2-up landscape page of Canada Post Tracked Package (to USA) shipping labels made by this script
no you will not read my 2-up shipping labels

If you need to ship things, you’re probably not too keen on queuing at the post office right now. Canada Post’s Ship Online service is pretty handy if you have a printer. The PDFs it produces are okay to print on plain paper, but if you’re using full-sheet labels like Avery 5165 you’re going to waste half a sheet of expensive labels.

If you’ve got two parcels to mail, this shell script will extract the right side of each page and create a single 2-up PDF with both your labels on the same page. You will need:

On my Ubuntu system, you can get good-enough¹ versions by doing this:

sudo apt install poppler-utils netpbm img2pdf

The code:

#!/bin/bash
# cp2up.sh - fits the important part of Canada Post print labels 2 per sheet
# scruss, 2021-05 - CC-BY-SA
# hard-coded input name (document.pdf)
# hard-coded output name (labels-2up.pdf)
# accepts exactly two labels (sorry)

dpi=600
width_in=11
height_in=8.5
# png intermediate format uses pixels per metre
dpm=$(echo "scale=3; $dpi * 1000 / 25.4" | bc)
# calculated pixel sizes, truncated to integer
half_width_px=$(echo "$width_in * $dpi / 2" | bc | sed 's/\..*$//')
height_px=$(echo "$height_in * $dpi" | bc | sed 's/\..*$//')

pdftoppm -mono -r "$dpi" -x "$half_width_px" -y 0 \
	 -W  "$half_width_px" -H "$height_px" document.pdf labels
pnmcat -lr labels-1.pbm labels-2.pbm |\
    pnmtopng -compression 9 -phys "$dpm" "$dpm" 1 > labels.png \
    && rm labels-1.pbm labels-2.pbm
# fix PDF time stamps
now=$(date --utc --iso-8601=seconds)
img2pdf -o labels-2up.pdf --creationdate "$now" --moddate "$now" \
	--pagesize "Letter^T" labels.png \
    && rm labels.png 

# saved from:
# history | tail | awk '{$1=""; print}' |\ 
#           perl -pwle 'chomp;s/^\s+//;' > cp2up.sh

It’s got a few hard-coded assumptions:

  • input name (document.pdf);
  • output name (labels-2up.pdf);
  • accepts exactly two labels (sorry).

Clever people could write code to work around these. Really clever people could modify this to feed a dedicated label printer.

Yes, I could probably have done all this with one ImageMagick command. When ImageMagick’s command line syntax begins to make sense, however, it’s probably time to retire to that remote mountain cabin and write that million-word thesis on a manual typewriter. Also, ImageMagick’s PDF generation is best described as pish.

One of the issues that this script avoids is aliasing in the bar-codes. For reasons known only to the anonymous PDF rendering library used by Canada Post, their shipping bar-codes are stored as smallish (780 × 54 px) bitmaps that are scaled up to a 59 × 19 mm print size. Most PDF viewers (and Adobe Viewer is one of these) will anti-alias scaled images, making them slightly soft. If you’re really unlucky, your printer driver will output these as fuzzy lines that no bar-code scanner could ever read. Rendering them to high resolution mono images may still render the edges a little roughly, but they’ll be crisply rough, and scanners don’t seem to mind that.

split image of simulated printed barcode: top image is five indistinct black-grey bars merging into a white background, bottom image is the same vertical lines, rendered crisply but showing some slightly rough edges
fuzzy vs crisply rough: scaled image (top) vs direct-rendered (bottom), at simulated 600 dpi laser print resolution

¹: Debian/Ubuntu’s netpbm package is roughly 20 years out of date for reasons that only a very few nerds care about, and the much better package is blocked by Debian’s baroque and gatekeepery packaging protocol. I usually build it from source for those times I need the new features.

Rockin’ it 8-bit (thanks to Maryke)

Instagram filter used: Normal

View in Instagram ⇒

Made with:

#!/bin/bash
# selfi.sh - strongly influenced by Interstellar Selfie Station
#                          http://interstellarselfiestation.com
# scruss - 2014-06-26

anytopnm "$1" |\
  pnmscale -xsize 160 |\
  pnmhisteq |\
  ppmdither -red 4 -green 4 -blue 4 |\
  pnmremap -mapfile < (echo P3 4 1 255 108 108 78 142 139 97 195 196 165 227 230 201) |\
  pnmscale -nomix 2 |\
  pnmtopng > "${1%.*}-selfi_sh.png"

Update, 2021: well, who knew that software that purportedly hasn’t changed since 2001 (netpbm on Debian) would change? This script broke between 2016–2021, and I had to remove the ppmtopgm line that was after the ppmdither call to make it work again.

Secure digital QSL cards, part 2: shell script

Following on from Creating secure digital QSL cards with your LoTW certificate, here’s a Bash script to generate encrypted signed PDF QSLs. You will need to edit the certificate file name, the QSL blank file name, your call sign, your LoTW password and the PDF encryption password. After doing so, please keep the script safe, as whoever has your LoTW password can pretend to be you.

The only checks that this script doesn’t do (and probably should) are if you have pdftk and PortableSigner executables in your path. PortableSigner is rather weird the way it runs; you need to specify full paths for all files, or it dies.

The script is called like this:

mkdqsl.sh callsign date utc mhz mode report

for example:

mkdqsl.sh VE3KPK 2011-10-02 2341 7.03581 CW 499

Code below the fold.

perhaps a slightly easier way to make SD cards bootable for CHDK under OS X

Now that CHDK has a working beta in the source tree for my Canon PowerShot SD790is, I actually have to prepare SD cards for it. The Bootable SD card – OS X instructions seem a bit contrived, so I took a look at the linux instructions, and modified them accordingly. These instructions should work for FAT16-formatted SD cards of 2GB capacity and under. It will not work for SDHC cards, which are generally formatted to FAT32.

This is all command-line only for here on in. It seems to work. Please note that you will be modifying raw file systems with root permissions here; there is no safety net. If you b0rk your main hard drive, don’t say I didn’t warn you.

Firstly, you’re going to have to find out where the SD card in mounted. Do this with:
df
I got:

Filesystem    512-blocks      Used Available Capacity  Mounted on
/dev/disk0s2   487463200 318749896 168201304    66%    /
devfs                222       222         0   100%    /dev
map -hosts             0         0         0   100%    /net
map auto_home          0         0         0   100%    /home
/dev/disk2s1     3969280      3328   3965952     1%    /Volumes/CANON_DC

There are three important concepts to note when looking at the mounted card:

  1. The mount point (or volume) – in this case /Volumes/CANON_DC. This is the location that you see in Finder when moving files around.
  2. The filesystem – here /dev/disk2s1. This is the partition on the disk, arranged according to a certain formatting scheme like MS-DOS FAT16.
  3. The disk device – which for me is /dev/disk2. This is the disk device itself, and it may contain several filesystems.

Your locations for these three could well be different, so please substitute your values.

You’ll need to unmount the device, as writing to a raw filesystem while the OS thinks it has control often results in hilariously unexpected results. I used the OS X-specific command

diskutil unmount /Volumes/CANON_DC

You should get a message like Volume CANON_DC on disk2s1 unmounted. Now you need to write the boot instruction:

echo -n BOOTDISK | sudo dd bs=1 count=8 seek=64 of=/dev/disk2s1

This will prompt you for your password.

If you need to, you can remount the filesystems on the card with

diskutil mountDisk /dev/disk2

(Note that we used the disk name here, not the filesystem. If there were several partitions on the disk, this command would mount all of them that it could. It’s also kinda handy for remounting USB devices that you’ve accidentally ejected from Finder.)

Update: Knowing a difficulty getting the firmware update method of getting CHDK to work on a Mac? Running a Leopard or newer machine? Then you need to learn all about Apple’s quarantine attribute and how to remove it with xattr: FAQ/Mac – Still having trouble?.

ffms2m3u.sh – create playlist for all files on a Firefly Media Server

ffms2m3u – create playlist for all files on a Firefly Media Server.

If you run Firefly Media Server, you can run this script to create an M3U of all the tracks on your server. You can play this in most audio players; VLC likes it, as does iTunes (though big playlists take an age to load). Rhythmbox and the default Ubuntu Movie Player won’t touch my playlist of over 17,000 tracks.

To configure the script you need to edit three lines:


# where the Firefly database lives
DATABASE="/usr/var/cache/mt-daapd/songs3.db"
# server domain name or IP address
SERVER="server.example.com"
# Port to talk to server - don't leave blank
PORT="3689"

If you’re running Ubuntu, you’ll probably only need to change the SERVER line. It spits the M3U playlist, ordered by album, to stdout. Note that in the default Ubuntu install, regular users can’t read the database file.

If you’re running this from a cron job, it’s probably a good idea to fill in the real paths for sqlite3 and awk.

batch renaming iTunes directories

In partial response to the Ask Metafilter question “How can I rename my music folders on my Mac based on ID3 tags?“:

#!/bin/bash
# itunes_sanity.sh - fix dir names created by iTunes
# only works for mp3s, and not actually tested on a Mac
# created by scruss on Sun Sep 4 22:05:00 EDT 2005

find "$@" -type d -mindepth 1 | while read directory
do
  artistdir=$(dirname "$directory")
  firstfile=$( find "$directory" -type f -iname '*.mp3' | head -n1 )
  year=$( id3info "$firstfile" | egrep ' TYE ' | sed 's/=== TYE (Year): //; s/[^0-9]*//;' )
  album=$( id3info "$firstfile" | egrep ' TAL ' | sed 's,=== TAL (Album/Movie/Show title): ,,;' )
  echo mv \'$directory\' \'$artistdir/\[$year\] $album\'
done

So if you were in the terminal, in your music library (one up from the individual artist directories), and you did:

itunes_sanity.sh Dan\ Jones Tripping\ Daisy

you’d get:

mv 'Dan Jones/Get Sounds Now' 'Dan Jones/[2005] Get Sounds Now'
mv 'Dan Jones/One Man Submarine' 'Dan Jones/[2003] One Man Submarine'
mv 'Tripping Daisy/Jesus Hits Like the Atom Bomb' 'Tripping Daisy/[1998] Jesus Hits Like the Atom Bomb'

If that looks okay, run the output through the shell:

itunes_sanity.sh Dan\ Jones Tripping\ Daisy | sh

and all should be well.

You’ll need id3lib, which is probably most easily installed from Fink. Also, this only works for mp3 files; I can’t grok the tag info for AAC files. And finally, this might go seriously screwy on weird characters in filenames. You know my feelings on that …

Geeky PostScript Stuff

These scripts can be ignored if you’re not likely to be working with PostScript files. I wrote/modified these ages ago, and hope someone can use them.

Download epstotiff – convert an Encapsulated PostScript figure to just about any raster format.

Download bbox – calculate the BoundingBox of a page. Should probably be combined with epstotiff.

Download joinps – concatenate a number of PostScript documents.

You’ll pretty much need a Unix box with ghostscript to make these work.