Category Archives: computers suck

LibreOffice brings the old

Twenty-two years ago, I wrote a thesis. It wasn’t a very good thesis, but it did what it needed to do. For years, its model files have been unreadable, because the spreadsheets were written in a ~1992 version of Microsoft Works. These are old files:

1993-04-21 03:19 newmodel.wks
1993-04-21 03:19 newmodel.wk1
1993-04-08 06:29 pr_fa.wks

Quite recently, LibreOffice realized that there are old files out there that (unlike my thesis models) could still be useful. As they have no commercial requirement to only support the latest and greatest, LibreOffice added the ability to read these ancient works. So my old stuff lives again:

ms works files from 1993

I found a screen dump that I used back in ’93 to illustrate the layout. The display was colour, but here it is brought back to life with a little bit of antialiasing:

'93 print stylee

LibreOffice can also read old AppleWorks files. Although Works 6 still runs on Catherine‘s Mac, it looks a bit … dated:

appleworks

Thanks, LibreOffice! It’s sometimes easy to forget (like right after updated to Ubuntu 15.04, which decided that BlueTooth support was kinda optional unless you jumped through hoops …) that people do write software just to be more useful.

Running FreeBASIC on Raspberry Pi

FreeBASIC is a pretty nifty cross-platform BASIC compiler. It uses a Microsoft-like syntax, has an active user and developer base, and is quite fast. Building the latest version on a Raspberry Pi is a bit of a challenge, though.

FreeBASIC 1.01 demo running on a Raspberry Pi
FreeBASIC 1.01 demo running on a Raspberry Pi from Geany

Part of the problem is that FreeBASIC is mostly written in FreeBASIC, so you need a working compiler to bootstrap the latest version. The following steps worked for me:

  1. Install some necessary packages:
    sudo apt-get install build-essential libncurses5-dev libffi-dev libgl1-mesa-dev libx11-dev libxext-dev libxrender-dev libxrandr-dev libxpm-dev ncurses-doc libxcb-doc libxext-doc libgpm-dev git libcunit1 libcunit1-dev libcunit1-doc

    (You don’t really have to include the cunit packages; they’re only needed if you run tests before installation.)

  2. Download a nightly binary from Sebastian’s server: http://users.freebasic-portal.de/stw/builds/linux-armv6-rpi/  and install it:
    unzip fbc_linux_armv6_rpi_version.zip
    cd fbc_linux_armv6_rpi/
    chmod +x install.sh
    sudo ./install.sh -i

    Don’t delete the installation folder just yet.

  3. Grab the latest version of the source from github:
    cd
    git clone https://github.com/freebasic/fbc.git

    Change directory to the new FreeBASIC source folder (cd fbc), and type make. (or, on a Raspberry Pi 2, make -j4 to use all the cores …). After a while (in my tests, about 52 minutes on a 512 MB Raspberry Pi, or around 6½ minutes [!] on a Raspberry Pi 2), it should finish. If there’s a bin/fbc file, the compilation worked!

  4. Before you install the new compiler, uninstall the old one: change directory to the fbc_linux_armv6_rpi folder, and type:
    sudo ./install.sh -u
  5. Once that’s done, go back to the new fbc folder, and type:
    sudo make install

And you’re done! You can delete the fbc_linux_armv6_rpi folder now. If you don’t mind it taking up space, keep the fbc folder to allow you a quick rebuild of the latest version of the compiler with:

cd fbc
git pull
make
sudo make install

Note that this will build a native armv7l compiler on a Raspberry Pi 2, and an armv6l one on a Raspberry Pi. This means you can’t run binaries you built on a Raspberry Pi 2 on a Raspberry Pi (you’ll get an Illegal Instruction error), but you should be able to run ones built on a Raspberry Pi on a Raspberry Pi 2. Binary compatibility is overrated, anyway …

∞ Noise

(Quick reminder, before it becomes obvious from the text — I have more interest in hardware random number generation than I have understanding …)

Just got Bill “WaywardGeek” Cox’s Infinite Noise USB Random Number Generator. It uses very few components, and doesn’t even have a microcontroller on board. It relies on the controlled amplification of thermal noise as its entropy source.

Not great enhanced image of the Infinite Noise board. Yes, that's all there is to it
Not great enhanced image of the Infinite Noise board. Yes, that’s all there is to it

As it’s so very simple, it uses a driver to read from the device, and then hashes the data to reduce the data stream to very close to pure noise. Building the driver is easy, once you work it that the code lives in the infnoise/software folder on the author’s github repo.

Normal operation would look like this:

sudo ./infnoise | entropy_consuming_program …

as in

sudo ./infnoise | rngtest -t 10

which I left running for a work day to get

…
rngtest: bits received from input: 10327720032
rngtest: FIPS 140-2 successes: 515955
rngtest: FIPS 140-2 failures: 431
rngtest: FIPS 140-2(2001-10-10) Monobit: 63
rngtest: FIPS 140-2(2001-10-10) Poker: 61
rngtest: FIPS 140-2(2001-10-10) Runs: 162
rngtest: FIPS 140-2(2001-10-10) Long run: 151
rngtest: FIPS 140-2(2001-10-10) Continuous run: 0
rngtest: input channel speed: (min=29.022; avg=178.828; max=19531250.000)Kibits/s
rngtest: FIPS tests speed: (min=17.403; avg=30.153; max=85.917)Mibits/s
rngtest: Program run time: 56727702860 microseconds

So from its success to failure rate, it produces pretty decent (for my casual use) results. These bytes chug out at around 22¾ Kbytes/second; not screamingly fast, but decent, considering the very simple hardware.

You can run the hardware without hashing/whitening, and the results (from a much shorter run) are less solid:

sudo ./infnoise --raw | rngtest -t 10
…
rngtest: bits received from input: 15499264
rngtest: FIPS 140-2 successes: 0
rngtest: FIPS 140-2 failures: 774
rngtest: FIPS 140-2(2001-10-10) Monobit: 0
rngtest: FIPS 140-2(2001-10-10) Poker: 774
rngtest: FIPS 140-2(2001-10-10) Runs: 774
rngtest: FIPS 140-2(2001-10-10) Long run: 0
rngtest: FIPS 140-2(2001-10-10) Continuous run: 0
rngtest: input channel speed: (min=27.201; avg=355.760; max=9765625.000)Kibits/s
rngtest: FIPS tests speed: (min=24.868; avg=30.488; max=41.554)Mibits/s
rngtest: Program run time: 49831593 microseconds

Another naïve test is seeing how images made from the data stream look:

don't stare at this too long, or richard d james's grinning mug will appear
random bytes (PNG), file size 49435 bytes
nvrandom20150121074051
raw bytes (PNG), file size 45421 bytes

Each of these 128 pixel squares should be no less than 49152 (= 128 × 128 × 3) bytes — plus the size of any PNG header/metadata — in size. The fact that the raw output is smaller shows that PNG’s compressor found some patterns it could work with.

It’s a fun little device, and Bill is adding new code and features to the driver at waywardgeek/infnoise regularly.

Home-brew Jetstream Plotter Pens

After a relative lack of success in making cheap plotter pens, I managed to score a trove of old pens on eBay. Some of these were dry, and I tried to resuscitate them. A few came back to life, but I ended up with a handful of very dead pen shells.

mystery_pen-alvin_maybe
A dry plotter pen, possibly Alvin

I think the pens were made or sold by Alvin, as there were several empty Alvin trays in the batch I got on eBay. In taking one apart, I thought that a pen refill might just slide inside. Lo and behold, but didn’t the pen nerd’s fave gel pen du jour refill just slide in with enough of an interference fit that it wouldn’t easily slide back out.

Taking the dry pens apart isn’t too easy:

  1. Pull the black tip straight out with pliers; it has a long fibre plug which goes into the ink reservoir. Discard the tip.
  2. While it’s really hard to see, the other end of the pen body has a push-on plug. Gently working around it with a sharp knife can open it up a bit.
  3. Once you’re inside the pen, pull the dry fibre ink reservoir out with tweezers and discard it.

Converting the pen body to use a Jetstream refill needs some tools:

  1. Drill a hole in the plug at the end of the pen body just large enough to allow the end of the refill to pass through. It helps if this is mostly centred to keep the pen point centred; this is important for accurate plots.
  2. Cut a piece of tubing just wide enough to slip over the pen refill, but not quite narrow enough to fit through the hole you just drilled. I used some unshrunk heatshrink tubing for this. It needs to be just long enough to push against the plug when the pen tip is at the right length. This should help stop the refill getting hammered back into the body by your plotter.
  3. Before you assemble the pen, I find it useful to cut a couple of flats in the sides of the plug so you can more easily change the refill. You don’t have to do this, though.
  4. Assemble the pen:
    1. Push the Jetstream refill into the pen body, and adjust it so it sticks out about 6 mm clear of the plastic collar near the nib.
    2. Put the tubing over the other end of the refill, and push the plug over the top, clicking it into place.
img_1220
Three pens in place on my DXY-1300

To get best results, you’ll have to slow your plot speed down quite a bit. At standard speeds, you get a ¼ mm interrupted line which looks like this:

Jetstream at full speed
Jetstream at full speed

Close up, the lines are really faint

A hint that I should run them slower was at the start of each line, where the line would start very thick, then taper off as the ink supply ran low:

acceleration blobs
acceleration blobs

Run at 120 mm/s, the results where a bit darker, but still blobby at the start of lines:

120 mm/s
120 mm/s

Slowing down to 60 mm/s produced slightly better results:

60 mm/s
60 mm/s

But sharpest of all was at the crawling speed 30 mm/s:

30 mm/s
30 mm/s

Some pronounced blobs at the starts of lines still. Here’s the full page at 600 dpi, squished into a very lossy PDF: jetstream_plotter-slow

The blobs could be due to this, though:

grode on pen tip
grode on pen tip

It seems that a mix of paper fibres and coagulated ink builds up on the tip. Occasional cleaning seems to be a good idea. It also seems to help to draw a quick scratch line before anything important so the ink will be flowing properly.

Just to sign off, here’s one of the pens in action:

all I wanted to do was rip a CD on my Raspberry Pi …

So, the DVD drive on my laptop’s on the fritz. It reads data fine, but ripping CDs with CDDA checks makes it go over the transport error rainbow bridge. So, partly through necessity and partly for lulz, I wondered how well a Raspberry Pi B+ would do on ripping CDs. I’ve got an old IDE DVD-R drive in an external 5¼” USB enclosure (huge!). I set about installing abcde, which is about the leanest way of ripping CDs in a terminal that I know. The standard sudo apt-get install abcde didn’t quite come up with all of the options I’d want to use, so I made the mistake of trying this:

sudo apt-get install --install-suggests abcde

Nooooooooooooooooooooooooooo! This horror suggested I install the following:

  abcde acl akonadi-backend-mysql akonadi-backend-postgresql
  akonadi-backend-sqlite akonadi-server alien antiword apache2 apache2-doc
  apache2-mpm-worker apache2-suexec apache2-utils apache2.2-bin
  apache2.2-common apmd aptdaemon aptdaemon-data at atomicparsley auctex
  autoconf autoconf-archive autoconf-doc autoconf2.13 automake automake1.4
  autopoint autotools-dev autotrace avahi-autoipd avahi-daemon bc bind9-host
  binfmt-support binutils-multiarch bsd-mailx bsh bsh-doc bsh-gcj
  ca-certificates-java catdvi cd-discid cdparanoia cdtool chktex chromium
  chromium-browser chromium-inspector chromium-l10n cjet cl-asdf cl-swank
  clisp clisp-dev clisp-doc cm-super cm-super-minimal colord comerr-dev
  common-lisp-controller cpufrequtils cup cups cups-filters cups-pdf
  cups-pk-helper cups-ppdc darcs db5.1-util dbtoepub dc debhelper
  debiandoc-sgml debiandoc-sgml-doc default-jdk default-jdk-doc default-jre
  default-jre-headless devhelp devhelp-common dh-make dhelp diffstat distmp3
  djtools djview-plugin djview4 djvulibre-bin djvulibre-desktop doc-base
  docbook docbook-defguide docbook-dsssl docbook-dsssl-doc docbook-mathml
  docbook-xml docbook-xsl docbook-xsl-doc-html docbook-xsl-saxon dot2tex
  dvidvi dvipng eject elfutils enscript ethtool exim4 exim4-base exim4-config
  exim4-daemon-light exim4-doc-html eximon4 exiv2 eyed3 fam fancontrol feynmf
  ffmpeg finger firebird-dev firebird2.5-common firebird2.5-common-doc
  firebird2.5-examples firebird2.5-server-common flac fontforge fontforge-doc
  fontforge-extras fonts-arphic-bkai00mp fonts-arphic-bsmi00lp
  fonts-arphic-gbsn00lp fonts-arphic-gkai00mp fonts-beng fonts-beng-extra
  fonts-comfortaa fonts-deva fonts-deva-extra fonts-dustin fonts-freefont-otf
  fonts-gfs-artemisia fonts-gfs-baskerville fonts-gfs-complutum
  fonts-gfs-didot fonts-gfs-neohellenic fonts-gfs-olga fonts-gfs-porson
  fonts-gfs-solomos fonts-gubbi fonts-gujr fonts-gujr-extra fonts-guru
  fonts-guru-extra fonts-hosny-amiri fonts-inconsolata fonts-indic
  fonts-ipaexfont-gothic fonts-ipaexfont-mincho fonts-ipafont-gothic
  fonts-ipafont-mincho fonts-junicode fonts-knda fonts-knda-extra
  fonts-liberation fonts-linuxlibertine fonts-lohit-beng-assamese
  fonts-lohit-beng-bengali fonts-lohit-deva fonts-lohit-gujr fonts-lohit-guru
  fonts-lohit-knda fonts-lohit-mlym fonts-lohit-orya fonts-lohit-taml
  fonts-lohit-telu fonts-mlym fonts-nakula fonts-navilu fonts-oflb-asana-math
  fonts-orya fonts-orya-extra fonts-pagul fonts-sahadeva fonts-samyak-gujr
  fonts-samyak-taml fonts-sil-gentium fonts-sil-gentium-basic fonts-smc
  fonts-stix fonts-taml fonts-telu fonts-telu-extra
  foomatic-db-compressed-ppds foomatic-db-engine foomatic-db-gutenprint
  foomatic-filters fop fop-doc fragmaster freeglut3 freetds-common
  frei0r-plugins gawk gawk-doc gcc-4.6-doc gcc-doc-base gcj-4.7-base
  gcj-4.7-jre-lib gcr gdal-bin geoip-bin geoip-database geotiff-bin gettext
  gettext-doc gfortran gfortran-4.6 gfortran-4.6-doc ghostscript-cups
  ghostscript-x gimp gimp-data gimp-data-extras gimp-gutenprint
  gimp-help-common gimp-help-en gimp-ufraw gir1.2-atk-1.0 gir1.2-freedesktop
  gir1.2-gdkpixbuf-2.0 gir1.2-gst-plugins-base-0.10 gir1.2-gstreamer-0.10
  gir1.2-gtk-3.0 gir1.2-pango-1.0 gir1.2-vte-2.90 gnome-keyring
  gnome-mime-data gnu-standards gnuplot gnuplot-doc gnuplot-nox gnutls26-doc
  gocr grads graphicsmagick graphicsmagick-dbg graphviz graphviz-doc groff
  gstreamer0.10-alsa gstreamer0.10-doc gstreamer0.10-ffmpeg
  gstreamer0.10-gconf gstreamer0.10-plugins-bad gstreamer0.10-plugins-base
  gstreamer0.10-plugins-good gstreamer0.10-plugins-ugly
  gstreamer0.10-pulseaudio gstreamer0.10-x gutenprint-doc gutenprint-locales
  gv hardening-includes hdf4-tools hdparm heirloom-mailx hp2xx hpijs
  hpijs-ppds hplip hplip-cups hplip-data hplip-doc hplip-gui hspell html2ps
  html2text hylafax-client i2c-tools iamerican icedtea-6-jre-cacao
  icedtea-6-jre-jamvm icedtea-6-plugin icedtea-netx icedtea-netx-common
  icedtea-plugin icoutils id3 id3v2 ienglish-common ijsgutenprint imagemagick
  imagemagick-common imagemagick-doc info2www intltool-debian ir-keytable
  ispell jadetex java-wrappers javascript-common jlex kate-data katepart
  kde-runtime kde-runtime-data kdelibs-bin kdelibs5-data kdelibs5-plugins
  kdepim-runtime kdepimlibs-kio-plugins kdoctools ko.tex-extra-hlfont
  krb5-config krb5-doc krb5-multidev krb5-user lacheck latex-beamer
  latex-cjk-all latex-cjk-chinese latex-cjk-chinese-arphic-bkai00mp
  latex-cjk-chinese-arphic-bsmi00lp latex-cjk-chinese-arphic-gbsn00lp
  latex-cjk-chinese-arphic-gkai00mp latex-cjk-common latex-cjk-japanese
  latex-cjk-japanese-wadalab latex-cjk-korean latex-cjk-thai
  latex-fonts-sipa-arundina latex-fonts-thai-tlwg latex-sanskrit latex-xcolor
  latexdiff latexmk liba52-0.7.4 libaio1 libakonadi-kabc4 libakonadi-kcal4
  libakonadi-kde4 libakonadi-kmime4 libakonadiprotocolinternals1 libamd2.2.0
  libao-common libao4 libapache-pom-java libapm1 libappconfig-perl libapr1
  libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libapt-pkg-perl
  libarchive-zip-perl libarmadillo3 libart-2.0-2 libasm1 libasound2-plugins
  libatk-wrapper-java libatk-wrapper-java-jni libatk1.0-doc libatkmm-1.6-1
  libattica0 libaudio-scrobbler-perl libauthen-ntlm-perl libauthen-sasl-perl
  libautotrace3 libav-tools libavahi-core7 libavalon-framework-java
  libavalon-framework-java-doc libavdevice53 libavfilter2 libavfilter3
  libavformat53 libavresample1 libbabl-0.1-0 libbackport-util-concurrent-java
  libbackport-util-concurrent-java-doc libbatik-java libbcel-java
  libbcel-java-doc libbind9-80 libbonobo2-0 libbonobo2-bin libbonobo2-common
  libbonoboui2-0 libbonoboui2-common libboost-program-options1.49.0
  libbsf-java libc6-dbg libcairomm-1.0-1 libcanberra-gtk-module
  libcanberra-gtk0 libcanberra-gtk3-0 libcanberra-gtk3-module
  libcanberra-pulse libcanberra0 libcap-dev libcap-ng0 libcap2-bin libcdaudio1
  libcddb2 libcdt4 libcf0 libcgraph5 libclass-accessor-chained-perl
  libclass-accessor-perl libclass-load-perl libclass-singleton-perl
  libclone-perl libclucene0ldbl libcommandline-ruby1.8 libcommons-codec-java
  libcommons-io-java libcommons-io-java-doc libcommons-logging-java
  libcommons-logging-java-doc libcommons-parent-java libconfig-inifiles-perl
  libconvert-binhex-perl libcpufreq0 libcrypt-openssl-bignum-perl
  libcrypt-openssl-rsa-perl libcrypt-ssleay-perl libcupscgi1 libcupsdriver1
  libcupsfilters1 libcupsmime1 libcupsppdc1 libcurl3-dbg libcurl4-gnutls-dev
  libcxxtools-dev libcxxtools8 libdap11 libdapclient3 libdapserver7
  libdata-dump-perl libdata-float-perl libdata-integer-perl
  libdata-optlist-perl libdata-page-perl libdatetime-format-mail-perl
  libdatetime-format-w3cdtf-perl libdatetime-locale-perl libdatetime-perl
  libdatetime-timezone-perl libdb-ruby1.8 libdbd-mysql-perl libdbi-perl
  libdbi1 libdbusmenu-qt2 libdevhelp-3-0 libdigest-hmac-perl libdirac-decoder0
  libdiscid0 libdjvulibre-text libdjvulibre21 libdlrestrictions1 libdns88
  libdom4j-java libdom4j-java-doc libdvbpsi7 libdw1 libebml3 libelf1 libelfg0
  libemail-valid-perl libencode-locale-perl libepsilon0 libescpr1
  libexcalibur-logkit-java libexiv2-12 libexpat1-dev libfam0 libfbclient2
  libfbembed2.5 libffcall1 libffi-dev libfile-listing-perl libfile-remove-perl
  libfile-which-perl libfont-afm-perl libfontforge1 libfop-java libfreexl1
  libftdi1 libgail18 libgavl1 libgcc1-dbg libgcj-bc libgcj-common libgcj13
  libgcj13-awt libgcj13-dbg libgck-1-0 libgconfmm-2.6-1c2 libgcr-3-1
  libgcr-3-common libgcrypt11-dev libgcrypt11-doc libgd-gd2-perl
  libgd-graph-perl libgd-graph3d-perl libgd-text-perl libgdal1 libgdraw4
  libgegl-0.2-0 libgeoip1 libgeos-3.3.3 libgeos-c1 libgeotiff-epsg libgeotiff2
  libgettext-ruby1.8 libgettextpo0 libgfortran3-dbg libgimp2.0 libgl1-mesa-dev
  libglademm-2.4-1c2a libglib2.0-bin libglib2.0-dev libglib2.0-doc
  libglibmm-2.4-1c2a libglu1-mesa-dev libgnome2-0 libgnome2-common
  libgnomecanvas2-0 libgnomecanvas2-common libgnomeui-0 libgnomeui-common
  libgnomevfs2-0 libgnomevfs2-bin libgnomevfs2-common libgnomevfs2-extra
  libgnuinet-java libgnujaf-java libgnujaf-java-doc libgnumail-java
  libgnumail-java-doc libgnutls-dev libgnutls-openssl27 libgnutlsxx27
  libgpg-error-dev libgraph4 libgraphics-magick-perl libgraphicsmagick++3
  libgraphicsmagick3 libgraphite3 libgrib2c0d libgssapi-perl libgssrpc4
  libgstreamer-plugins-bad0.10-0 libgstreamer-plugins-base0.10-dev
  libgstreamer0.10-dev libgtk-3-doc libgtk2.0-doc libgtkimageview0
  libgtkmm-2.4-1c2a libgtkmm-3.0-1 libgusb2 libgutenprint2 libgutenprintui2-1
  libgvc5 libgvpr1 libhdf4-0 libhdf4-0-alt libhdf4-alt-dev libhdf4-doc
  libhdf5-7 libhpmud0 libhtml-form-perl libhtml-format-perl libhtml-lint-perl
  libhtml-parser-perl libhtml-tagset-perl libhtml-template-perl
  libhtml-tree-perl libhttp-cookies-perl libhttp-daemon-perl libhttp-date-perl
  libhttp-message-perl libhttp-negotiate-perl libi2c-dev libib-util libical0
  libice-dev libice-doc libid3-3.8.3c2a libid3-tools libidl0 libidn11-dev
  libieee1284-3 libio-pty-perl libio-socket-inet6-perl libio-socket-ip-perl
  libio-socket-ssl-perl libio-string-perl libio-stringy-perl libiodbc2
  libipc-run-perl libipc-sharedcache-perl libipc-sharelite-perl libisc84
  libisccc80 libisccfg82 libiso9660-8 libjavascriptcoregtk-1.0-0 libjaxen-java
  libjaxme-java libjaxme-java-doc libjaxp1.3-java libjaxp1.3-java-gcj
  libjboss-jmx-java libjdom1-java libjdom1-java-doc libjline-java
  libjline-java-doc libjpeg-progs libjpeg62 libjpeg8-dev libjs-jquery
  libjs-underscore libkabc4 libkadm5clnt-mit8 libkadm5srv-mit8
  libkatepartinterfaces4 libkcal4 libkcalcore4 libkcalutils4 libkcmutils4
  libkdb5-6 libkde3support4 libkdeclarative5 libkdecore5 libkdesu5 libkdeui5
  libkdewebkit5 libkdnssd4 libkemoticons4 libkfile4 libkhtml5 libkidletime4
  libkimap4 libkio5 libkjsapi4 libkjsembed4 libkldap4 libkmediaplayer4
  libkmime4 libkml0 libknewstuff2-4 libknewstuff3-4 libknotifyconfig4
  libkntlm4 libkparts4 libkpathsea6 libkpimutils4 libkprintutils4 libkpty4
  libkrb5-dev libkresources4 libkrosscore4 libktexteditor4 libldap2-dev
  liblensfun-data liblensfun0 liblircclient0 liblist-moreutils-perl
  liblog4j1.2-java liblog4j1.2-java-doc liblqr-1-0 libltdl-dev liblua5.1-0
  liblwp-mediatypes-perl liblwp-protocol-https-perl liblwres80 liblzo2-2
  libmagickcore5 libmagickcore5-extra libmagickwand5 libmail-box-perl
  libmail-dkim-perl libmail-imapclient-perl libmail-sendmail-perl
  libmail-spf-perl libmailtools-perl libmailtransport4 libmath-round-perl
  libmatroska5 libmhash2 libmicroblog4 libmime-tools-perl libmime-types-perl
  libmodule-implementation-perl libmodule-runtime-perl libmpcdec6 libmpeg2-4
  libmtp-common libmtp-runtime libmtp9 libmusicbrainz-discid-perl libmyodbc
  libmysqlclient-dev libmysqlclient16 libmysqlclient18 libneon27-gnutls
  libnepomuk4 libnepomukquery4a libnepomukutils4 libnet-dns-perl
  libnet-domain-tld-perl libnet-http-perl libnet-ident-perl libnet-ip-perl
  libnet-ssleay-perl libnetaddr-ip-perl libnetcdf-dev libnetcdfc++4
  libnetcdfc7 libnetcdff5 libnetpbm10 libnl-route-3-200 libnspr4-0d
  libnss-mdns libnss3-1d libntrack-qt4-1 libntrack0
  libobject-realize-later-perl libodbc1 libodbcinstq4-1 libogdi3.2
  libopencv-core2.3 libopencv-imgproc2.3 libopenraw1 liborbit2 libosp5
  libostyle1c2 libp11-kit-dev libpackage-deprecationmanager-perl
  libpackage-stash-perl libpackage-stash-xs-perl libpam-cap
  libpam-gnome-keyring libpango1.0-doc libpangomm-1.4-1
  libparams-classify-perl libparams-util-perl libparams-validate-perl
  libparse-debianchangelog-perl libparse-recdescent-perl libpathplan4
  libpcre3-dev libpcrecpp0 libperl5.14 libperlio-gzip-perl libphonon4
  libplasma3 libplot2c2 libpod-plainer-perl libpolkit-qt-1-1 libpoppler-glib8
  libpostproc52 libpotrace0 libpq-dev libpq5 libproj0 libpstoedit0c2a
  libptexenc1 libpthread-stubs0 libpthread-stubs0-dev libpulse-mainloop-glib0
  libpython2.6 libqca2 libqca2-plugin-cyrus-sasl libqca2-plugin-gnupg
  libqca2-plugin-ossl libqt3-mt libqt3-mt-mysql libqt3-mt-odbc libqt3-mt-psql
  libqt4-declarative libqt4-declarative-folderlistmodel
  libqt4-declarative-gestures libqt4-declarative-particles
  libqt4-declarative-shaders libqt4-designer libqt4-dev libqt4-dev-bin
  libqt4-help libqt4-opengl libqt4-opengl-dev libqt4-qt3support libqt4-script
  libqt4-scripttools libqt4-sql libqt4-sql-mysql libqt4-sql-psql
  libqt4-sql-sqlite libqt4-test libqt4-xmlpatterns libqtassistantclient4
  libqtwebkit-dev libraptor2-0 librarian0 librasqal3 librdf-storage-mysql
  librdf-storage-postgresql librdf-storage-sqlite librdf0 librecode0
  libregexp-java libresid-builder0c2a librhino-java librhino-java-doc
  libroman-perl librpm3 librpmbuild3 librpmio3 librpmsign1 librrd4
  librrds-perl librtmp-dev libruby1.8 libsane libsane-common libsane-extras
  libsane-extras-common libsane-hpaio libsaxon-java libsaxon-java-doc
  libsaxonb-java libsaxonb-java-doc libscalar-number-perl libsensors4 libserf1
  libservlet2.5-java libsgmls-perl libshp1 libsidplay1 libsidplay2 libsigsegv2
  libslp1 libslv2-9 libsm-dev libsm-doc libsnmp-base libsnmp15 libsocket-perl
  libsocket6-perl libsolid4 libsoprano4 libsp1c2 libspatialite3 libspeexdsp1
  libspiro0 libsqlite0 libsqlite0-dev libsqlite3-dev libssh-4 libssh2-1-dev
  libssl-dev libssl-doc libstreamanalyzer0 libstreams0 libsub-install-perl
  libsub-name-perl libsvn-perl libsvn-ruby1.8 libsvn1
  libsys-hostname-long-perl libsystemd-daemon0 libtar0 libtasn1-3-dev
  libtemplate-perl libtemplate-perl-doc libtemplate-plugin-gd-perl
  libtemplate-plugin-xml-perl libterm-readkey-perl libterm-readline-gnu-perl
  libtext-format-perl libtext-template-perl libthreadweaver4 libtiff-opengl
  libtiff-tools libtiff5 libtntnet-dev libtntnet10 libtool libtool-doc
  libtry-tiny-perl libtwolame0 libudunits2-0 libumfpack5.4.0 libuninameslist0
  libunistring0 libupnp6 libupower-glib1 liburi-perl liburiparser1
  libuser-identity-perl libutempter0 libuuid-perl libva-x11-1 libvcdinfo0
  libvirtodbc0 libvlc5 libvlccore5 libvte-2.90-9 libvte-2.90-common
  libwebkitgtk-1.0-0 libwebkitgtk-1.0-common libwebrtc-audio-processing-0
  libwebservice-musicbrainz-perl libwmf-bin libwmf0.2-7 libwww-perl
  libwww-robotrules-perl libx11-dev libx11-doc libxalan110 libxalan2-java
  libxalan2-java-doc libxau-dev libxcb-composite0 libxcb-doc libxcb-keysyms1
  libxcb-randr0 libxcb-xv0 libxcb1-dev libxdmcp-dev libxdot4 libxerces-c28
  libxerces2-java libxerces2-java-doc libxerces2-java-gcj libxext-dev
  libxext-doc libxml-commons-external-java libxml-commons-resolver1.1-java
  libxml-commons-resolver1.1-java-doc libxml-dom-perl libxml-libxml-perl
  libxml-namespacesupport-perl libxml-parser-perl libxml-perl
  libxml-regexp-perl libxml-rss-perl libxml-sax-base-perl
  libxml-sax-expat-perl libxml-sax-perl libxml-simple-perl libxml2-dev
  libxml2-doc libxml2-utils libxmlgraphics-commons-java libxom-java
  libxom-java-doc libxpp2-java libxpp3-java libxsltc-java libxslthl-java
  libxt-dev libxt-doc libxvmc1 libyajl2 libyaml-tiny-perl libzvbi-common
  libzvbi0 lintian linuxdoc-tools linuxdoc-tools-info linuxdoc-tools-latex
  linuxdoc-tools-text lirc lirc-x lm-sensors lmodern locales-all lsb lsb-core
  lsb-cxx lsb-desktop lsb-graphics lsb-languages lsb-multimedia lsb-printing
  lsb-release lsb-security luatex m4 magicfilter man2html man2html-base
  media-player-info mesa-common-dev mgetty-viewfax mkcue mp3gain mpg321
  mplayer mplayer-doc mscompress mysql-client mysql-client-5.5 mysql-common
  mysql-server-core-5.5 netcdf-bin netcdf-doc netpbm netselect netselect-apt
  normalize-audio ntrack-module-libnl-0 odbc-postgresql odbcinst
  odbcinst1debian2 ogdi-bin oidentd openjade openjdk-6-demo openjdk-6-doc
  openjdk-6-jdk openjdk-6-jre openjdk-6-jre-headless openjdk-6-jre-lib
  openjdk-6-source openprinting-ppds openslp-doc opensp openssl-blacklist
  otf-freefont oxygen-icon-theme paman paprefs patchutils pavucontrol
  pavumeter pax pdf2djvu perl-doc perl-tk perlmagick pfb2t1c2pfb pgf phonon
  phonon-backend-gstreamer phonon-backend-vlc plasma-scriptengine-javascript
  pm-utils po-debconf postgresql postgresql-9.1 postgresql-client
  postgresql-client-9.1 postgresql-client-common postgresql-common
  postgresql-doc-9.1 potrace powermgmt-base preview-latex-style
  printer-driver-all printer-driver-c2050 printer-driver-c2esp
  printer-driver-cjet printer-driver-escpr printer-driver-foo2zjs
  printer-driver-gutenprint printer-driver-hpcups printer-driver-hpijs
  printer-driver-m2300w printer-driver-min12xxw printer-driver-pnm2ppa
  printer-driver-postscript-hp printer-driver-ptouch printer-driver-pxljr
  printer-driver-sag-gdi printer-driver-splix proj-bin proj-data proj-ps-doc
  prosper ps2eps psgml pstoedit pstotext psutils pulseaudio
  pulseaudio-module-gconf pulseaudio-module-x11 pulseaudio-module-zeroconf
  pulseaudio-utils purifyeps python-apt python-apt-common python-apt-dbg
  python-apt-doc python-aptdaemon python-aptdaemon-gtk
  python-aptdaemon.gtk3widgets python-aptdaemon.gtkwidgets python-cairo
  python-chardet python-cups python-cupshelpers python-dbg python-debian
  python-defer python-dev python-distribute-doc python-doc
  python-egenix-mx-base-dbg python-egenix-mx-base-dev python-egenix-mxbeebase
  python-egenix-mxbeebase-doc python-egenix-mxdatetime
  python-egenix-mxdatetime-doc python-egenix-mxproxy python-egenix-mxproxy-doc
  python-egenix-mxqueue python-egenix-mxqueue-doc python-egenix-mxstack
  python-egenix-mxstack-doc python-egenix-mxtexttools
  python-egenix-mxtexttools-doc python-egenix-mxtools
  python-egenix-mxtools-doc python-egenix-mxuid python-egenix-mxuid-doc
  python-egenix-mxurl python-egenix-mxurl-doc python-examples python-eyed3
  python-fontforge python-gconf python-gdal python-gdbm python-gdbm-dbg
  python-gi-dbg python-gi-dev python-glade2 python-gnome2 python-gnome2-doc
  python-gnomekeyring python-gnupginterface python-gobject python-gobject-2
  python-gobject-2-dbg python-gobject-2-dev python-gobject-dbg
  python-gobject-dev python-gst0.10 python-gst0.10-dbg python-gst0.10-dev
  python-gtk2 python-gtk2-doc python-imaging python-imaging-dbg
  python-imaging-doc python-imaging-doc-html python-imaging-doc-pdf
  python-imaging-tk python-imaging-tk-dbg python-kde4 python-libxml2
  python-notify python-pexpect python-pkg-resources python-pycurl
  python-pycurl-dbg python-pyorbit python-pyparsing python-qt4 python-qt4-dbg
  python-qt4-dbus python-renderpm python-renderpm-dbg python-reportlab
  python-reportlab-accel python-reportlab-doc python-setuptools python-sip
  python-sip-dbg python-smbc python-smbus python-software-properties
  python-subversion python-vte python2.6 python2.6-doc python2.6-minimal
  python2.7-dbg python2.7-dev python2.7-doc python2.7-examples python3-gi
  pyzor qt-assistant-compat qt4-designer qt4-dev-tools qt4-doc qt4-doc-html
  qt4-linguist-tools qt4-qmake qt4-qmlviewer radeontool radiance radiance-doc
  radiance-materials raptor2-utils rarian-compat rasqal-utils razor re2c
  read-edid realpath recode redland-utils rhino ri ri1.8 ri1.9.1 rpm
  rpm-common rpm-i18n rpm2cpio rrdtool rtkit ruby ruby-bdb ruby-commandline
  ruby-dev ruby-gettext ruby-locale ruby-open4 ruby-svn ruby-switch
  ruby-text-format ruby1.8 ruby1.8-examples ruby1.9.1-dev sane-utils sensord
  sessioninstaller setcd setserial sgml-data sgmls-doc sgmlspl
  shared-desktop-ontologies sidplay-base slime slpd slv2-jack smistrip
  snmp-mibs-downloader soprano-daemon sp spamassassin spamc spell
  spf-tools-perl sqlite sqlite-doc sqlite3 sqlite3-doc ssl-cert subversion
  subversion-tools svn2cl swaks swath swish++ system-config-printer
  system-config-printer-kde system-config-printer-udev t1utils tcl-tclreadline
  tcl8.4 tcsh tdsodbc tex-common tex-gyre texinfo texinfo-doc-nonfree texlive
  texlive-base texlive-binaries texlive-common texlive-doc-base texlive-doc-en
  texlive-doc-zh texlive-extra-utils texlive-font-utils texlive-fonts-extra
  texlive-fonts-extra-doc texlive-fonts-recommended
  texlive-fonts-recommended-doc texlive-generic-recommended
  texlive-lang-african texlive-lang-all texlive-lang-arabic
  texlive-lang-armenian texlive-lang-cjk texlive-lang-croatian
  texlive-lang-cyrillic texlive-lang-czechslovak texlive-lang-danish
  texlive-lang-dutch texlive-lang-english texlive-lang-finnish
  texlive-lang-french texlive-lang-german texlive-lang-greek
  texlive-lang-hebrew texlive-lang-hungarian texlive-lang-indic
  texlive-lang-italian texlive-lang-latin texlive-lang-latvian
  texlive-lang-lithuanian texlive-lang-mongolian texlive-lang-norwegian
  texlive-lang-other texlive-lang-polish texlive-lang-portuguese
  texlive-lang-spanish texlive-lang-swedish texlive-lang-tibetan
  texlive-lang-vietnamese texlive-latex-base texlive-latex-base-doc
  texlive-latex-extra texlive-latex-extra-doc texlive-latex-recommended
  texlive-latex-recommended-doc texlive-luatex texlive-metapost
  texlive-metapost-doc texlive-pictures texlive-pictures-doc texlive-pstricks
  texlive-pstricks-doc texlive-xetex thailatex time tipa tix tk8.4 tntnet
  tntnet-demos tntnet-doc tntnet-runtime transfig ttf-dejavu ttf-dejavu-extra
  ttf-dustin ttf-indic-fonts ttf-liberation ttf-marvosym ttf-wqy-microhei
  tzdata-java ufraw ufraw-batch unattended-upgrades unixodbc unixodbc-bin
  unixodbc-dev unpaper upower videolan-doc virtuoso-minimal
  virtuoso-opensource-6.1-bin virtuoso-opensource-6.1-common vlc vlc-data
  vlc-nox vlc-plugin-notify vlc-plugin-pulse vorbis-tools vorbisgain
  w3-dtd-mathml w3-recs w3c-dtd-xhtml wamerican weblint-perl wwwconfig-common
  x11proto-core-dev x11proto-input-dev x11proto-kb-dev x11proto-xext-dev xalan
  xapm xaw3dg xfig xfig-doc xfig-libs xfonts-75dpi xhtml2ps xindy xindy-rules
  xorg-sgml-doctools xsane xsane-common xsidplay xsltproc xtrans-dev zip

Eep! That looks like the full TeXLive system, most of QT4, almost every TrueType font ever (plus a font editor), printer drivers, the full Apache webserver setup, MySQL, a couple of web browsers, scanner drivers and OCR programs, a mail server … 2.4 GB of downloads, or over 6 GB installed. And all this for a command line script for ripping CDs.

Eventually, I got by by installing just this:

sudo apt-get install abcde lame eject id3 id3v2 eyed3 normalize-audio vorbisgain mkcue mp3gain libdata-dump-perl flac

Much better. Installed in a couple of minutes. Worked quite well, if not fast — ripped and encoded a 45 minute CD in just under 26 minutes (using lame -V2, which is good enough for me). For setup hints for abcde, abcde: Command Line Music CD Ripping for Linux is a good resource. On a Raspberry Pi, with its single core processor, you probably want to set MAXPROCS=1 in the abcde.conf file, or the encoders will fight for resources and get really slow.

Everybody needs a Level 43 Tickle-Mimic

ProgressQuest!The display gets a bit mixed up under Linux, but Progress Quest is still delightful.

It also has some of the best Release Notes ever:

  Changes for version 6.1:

     * I really just don't remember.
     * I also don't see how it could matter much.

Fetch me a teratoma!

Log your electricity consumption with Powermon433

NB: this is in the  early stages of development, but does work. It’s by no means a plug-and-play solution. You’re going to have to do some coding, and perhaps some soldering. Undaunted? Read on …

I really like the Blue Line Innovations PowerCost Monitor™ (aka the Black & Decker Power Monitor EM100B). I bought one long before the OPA started to give them away free to Ontario households as part of their peaksaver PLUS program. It’s a little device that clamps to your hydro meter and sends instantaneous power readings to a display.

PowerMonitor-displays
Power Monitor displays — Black & Decker on the left, Blueline on the right

Wouldn’t it be so much better if you could log and analyze these data? So a day’s power consumption might graph to something like this:

PowerMonitor-20140929Yup, this is my real electricity consumption, as logged from the PowerCost Monitor. You can see the fridge cycling on and off, and I think the big mid-day spike was either the AC or the dryer; someone was home on that Monday. The rather blocky green line is Toronto Hydro’s hourly smart meter data. It really hasn’t got the resolution to show really detailed power use.

That spike at 06:30; what’s that? Let’s take a look:

PowerMonitor-20140929-kettleThat’s me boiling the kettle. You can see that the time resolution is better than a minute, and the power is to the watt. Mmm, coffee …

All of this is recorded using a simple Arduino-based solution, originally cooked up by Bryan Mayland. I’ve forked his code and added some instructions: scruss/Powermon433. Here’s the rig I’ve been using to log data over a USB serial link:

Arduino FIO compatible + RFM69W board + FTDI serial
Arduino FIO compatible + RFM69W board + FTDI serial

That’s a particularly ugly rig, due to the limitations of the 3.3 V receiver board I was using. There are other options that work with more normal Arduino boards up on github.

Here’s a sample of the data I’m logging, including the kettle incident:

Datetime Elapsed_s Energy_Wh Power_W Temp_C
2014-09-29T06:27:44 23241.7 25876 289 15
2014-09-29T06:28:16 23273.6 25876 290 15
2014-09-29T06:28:48 23305.5 25876 291 15
2014-09-29T06:29:20 23337.4 25892 294 15
2014-09-29T06:29:52 23369.2 25892 286 15
2014-09-29T06:30:24 23401.1 25892 277 15
2014-09-29T06:30:56 23433.0 25892 357 15
2014-09-29T06:31:28 23464.9 25892 1844 15
2014-09-29T06:32:00 23496.8 25892 1836 15
2014-09-29T06:32:31 23528.5 25952 1829 15
2014-09-29T06:33:03 23560.2 25952 1818 15
2014-09-29T06:33:35 23592.1 25952 1836 15
2014-09-29T06:34:07 23624.0 25952 1836 15
2014-09-29T06:34:39 23655.8 25952 1836 15
2014-09-29T06:35:11 23687.7 25952 1848 15
2014-09-29T06:35:43 23719.6 26048 1832 15
2014-09-29T06:36:15 23751.5 26048 2000 15
2014-09-29T06:36:46 23783.4 26048 2000 15
2014-09-29T06:37:18 23815.2 26048 2000 15
2014-09-29T06:37:50 23846.9 26048 368 15

You’ll see that I’m recording:

  • a system timestamp
  • the elapsed logging time, from the Arduino’s clock
  • instantaneous meter readings in watt-hours. Note that not every row has an update
  • the average power since the last record. The product of this and the time between records adds up to the energy consumption
  • the outside temperature in °C. This is not very accurate (in full sun it over-reads vastly) but better than nothing.

Compare that to the smart meter data:

DateTime Hour KwhUsage Cost Rate
2014-09-29 05:00:00 5 0.29 $0.02 $0.075
2014-09-29 06:00:00 6 0.31 $0.02 $0.075
2014-09-29 07:00:00 7 0.59 $0.04 $0.075

Not much data there, is there? Certainly not enough resolution to tell if a kettle has been running.

Even though this interface is homebrew and cheap, it is accurate. Here’s how four days of continuous readings stack up against Toronto Hydro’s meter:

  Power Monitor ndToronto Hydro Smart Meter
Day First Reading / Wh Last Reading / Wh Total Consumption / kWh No of readings Daily Total / kWh No of readings
2014-09-29 23896 43668 19.772 2711 19.77 24
2014-09-30 43668 52500 8.832 2710 8.82 24
2014-10-01 52500 68004 15.504 2711 15.51 24
2014-10-02 68004 81996 13.992 2712 13.99 24

The difference looks to me like aliasing; THES’s reporting is much more granular.

I’m going to develop this further to turn it into an easy (or at least, easier) to use logging platform. It’s taken us a few years to get here, but there’s nothing quite like a project finally working!

fun with darktable

LiquidI’m really impressed with darktable, a raw photo workflow for Linux.  Unlike Gimp, it uses floating point for all image processes, so it doesn’t get caught up in quantization error. It’s a non-destructive editor, too: it assumes your source images are like negatives, and any changes you make are only applied to the exported images. Darktable also has a very intuitive black and white filtering mode (where you apply a virtual colour filter to the front of the lens, and see the results in real time) and some very powerful geotagging features. I’m sold.

darktable-uiIt’s not immediately obvious how some of the features work, and it took me a few hours (and some reading of the manual — eek!) to get files to export as I wanted them. It’s not quite perfect yet — the map feature can become unresponsive if you click too much on image icons — but it’s definitely solid enough for my purposes.

More of my initial darktable attempts on flickr: A Day by the Lake.

Notes on mini-printers and Linux

miniprinter galleryOver the last few weeks, I’ve been playing with a few small thermal printers. Meant as POS or information booth printers, they make a diverting project for the lo-fi printing enthusiast. While they all have common features — 58 mm/2¼” paper width, 8 pixel/mm resolution, 48 mm print width, serial connection — they all have their quirks. You may have seen these sold as the Adafruit Mini Thermal Receipt Printer or Sparkfun’s Thermal Printer, but there are many others. I’m going to write more on interfacing these directly to Raspberry Pi, Arduino, and (if I can navigate the documentation) a CUPs driver.

For now, I’m just leaving you a list of things I’ve found helpful for the DP-EH600 and 701 printers. Note that the similar-looking BTHT-v6 printer uses a completely different command set.

  • Replacement paper is sold as 2¼” × 30′. Staples have a box of 30 rolls for under $25 (item 279096, not on their website). Longer rolls don’t fit.
  • You’ll need a USB→TTL Serial adaptor, preferably one with DTR control. I use one from JY-MCU. In a pinch, you can use a simpler  Debug / Console Cable for Raspberry Pi, but you risk serial overruns and dodgy results. Remember that RX on the adaptor goes to TX on the printer, and vice versa.
  • A good solid power supply is needed; these printers draw ~8 W when printing. Some printers only support 5 V (for which a 3 amp adaptor would be ideal), others 5-9 V. The higher voltage makes text printing faster. You can’t drive these directly from your Raspberry Pi/Arduino power supply.
  • Linux serial ports are set to some defaults which may have been historically useful, but now corrupt 8-bit data. A trick I picked up here is to first issue the command
    stty -F /dev/ttyUSB1 0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0:0
    which clears all settings, then set the device up as you need it:
    stty -F /dev/ttyUSB1 speed 9600 raw cs8
    (Most of these printers default to 9600 baud. Your device may be called something different to ttyUSB1.)
  • I’ve written a couple of Python driver stubs which take an image and produce the relevant binary output:
    • scruss / esc-pos-image.py – prints an image as a single command. May not work on the SparkFun printer. Does not work on the BTHT-v6.
    • scruss / esc-pos-image-star.py – prints the image in 24 pixel deep bands. Can sometimes cause visible gaps in the printout, but will work on almost all printers, except the BTHT-v6.
  • These Python libraries also work, as long as you address the printer properly (right device, right speed):

Notes/Credits

  1. Reed Zhao (of Tangram Software) lent me a couple of different printers for testing after I bought a different one from him. He’s put a lot of work into sourcing these printers direct from the manufacturers. Thanks, Reed!
  2. Image credits for print samples:

JPEG 2000 on Ubuntu — without anyone getting stabbed

(NB: JPEG 2000 images still maybe crash Ubuntu’s file browser in 14.10. My old installation didn’t like them, but my reinstall seems quite happy. Go figure.)

JPEG 2000 is a great image file format: well-defined, and able to store high quality photographic data in a very small space. It truly is the JPEG of the 2000s — except for its dismal support under Ubuntu.

The problem is the patents. An open library has been a long time coming, and lots of Linux software is built without JP2 support. This helped keep it away from my desktop.

Under Ubuntu 14.04, here’s what does and doesn’t support JP2 files:

  • Gimp — not supported. It appears to have a non-functioning plugin that tries to read the file, then gives up. This is annoying, as Gimp is defined as the system default viewer for JPEG 2000.
  • Image Viewer — does support JP2, but occasionally mis-renders pages. To make this the default, right-click on a JP2 file, and select Open with → Other Application …, then choose Image Viewer. It should work from then onwards.
  • Document Viewer — a bit rough when looking at JPEG 2000-encoded PDFs. Very slow, too.
  • GraphicsMagick — seems to be the most painless way of converting graphics files to JPEG 2000. My preferred method of invoking it is:
    gm convert -define 'jp2:rate=0.008' in.png out.jp2
    The rate option should be a small number; the smaller, the greater the compression, and the worse the image quality.
  • OpenJPEG — provides the image_to_j2k and j2k_to_image tools. Far more picky about input formats than it should be, and often fails on seemingly perfect input.
  • img2pdf — (built from source)  is a tiny gem of a package. All it does is wrap various image formats into a PDF file. It doesn’t modify the image data in any way, so with a bit of ingenuity (and pdftk) you can use PDF as a true metafile archive. You can view the content on any platform, but get the source images out bit-for-bit perfect. We used to call files which could contain files metafiles, but that stopped being popular when TIFF started to be a baroque travesty of an image container back in the mid-1990s.
  • poppler — (for full features, build from source) has a tool, pdfimages, which can extract embedded image files from PDFs. Some of the metadata might get lost, but all of the image bits come through.

Since JPEG 2000 isn’t included in web browsers (grar), I’ve embedded a sample scanned JPEG into a PDF, and added a series of progressively more compressed JPEG 2000 versions: JPEG-2000Booklet [PDF].  The booklet has notes showing the byte size of each page. The image still looks pretty good at 8% of the original file size!

The cuddliest microfiche reader of 1968

wooster-cuddly_microfiche_reader

Remind you of anything?

(from Wooster, Harold. Towards a Uniform Federal Report Numbering System and a Cuddly Microfiche Reader, Two Modest Proposals, 1968, cited in Stevens, Mary Elizabeth. “Research and Development in the Computer and Information Sciences. Volume 2, Processing, Storage, and Output Requirements in Information Processing Systems: A Selective Literature Review.” (1970).)

Ⓗⓞⓦ ⓣⓞ ⓑⓔ ⓐⓝⓝⓞⓨⓘⓝⓖ ⓦⓘⓣⓗ Ⓟⓔⓡⓛ ⓐⓝⓓ Ⓤⓝⓘⓒⓞⓓⓔ

It’s been so long since I’ve programmed in Perl. Twelve years ago, it was my life, but what with the Raspberry Pi intervening, I hadn’t used it in a while. It’s been so long, in fact, that I wasn’t aware of the new language structures available since version 5.14. Perl’s Unicode support has got a lot more robust, and I’m sick of Python’s whining about codecs when processing anything other than ASCII anyway. So I thought I’d combine re-learning some modern Perl with some childish amusement.

What I came up with was a routine to convert ASCII alphanumerics ([0-9A-Za-z]) to Unicode Enclosed Alphanumerics ([⓪-⑨Ⓐ-Ⓩⓐ-ⓩ]) for advanced lulz purposes. Ⓘ ⓣⓗⓘⓝⓚ ⓘⓣ ⓦⓞⓡⓚⓢ ⓡⓐⓣⓗⓔⓡ ⓦⓔⓛⓛ:

#!/usr/bin/perl
# annoying.pl - ⓑⓔ ⓐⓝⓝⓞⓨⓘⓝⓖ ⓦⓘⓣⓗ ⓤⓝⓘⓒⓞⓓⓔ
# created by scruss on 2014-05-18

use v5.14;
# fun UTF8 tricks from http://stackoverflow.com/questions/6162484/
use strict;
use utf8;
use warnings;
use charnames qw( :full :short );
sub annoyify;

die "usage: $0 ", annoyify('string to print like this'), "\n" if ( $#ARGV < 0 );
say annoyify( join( ' ', @ARGV ) );
exit;

# 💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩

sub annoyify() {
    # convert ascii to chars in circles
    my $str = shift;
    my @out;
    foreach ( split( '', $str ) ) {
        my $c = ord($_);             # remember, can be > 127 for UTF8
        if ( $c == charnames::vianame("DIGIT ZERO") )
	{
            # 💩💩💩 sigh; this one's real special ... 💩💩💩
            $c = charnames::vianame("CIRCLED DIGIT ZERO");
        }
        elsif ($c >= charnames::vianame("DIGIT ONE")
            && $c <= charnames::vianame("DIGIT NINE") )
        {
            # numerals, 1-9 only (grr)
            $c =
              charnames::vianame("CIRCLED DIGIT ONE") +
              $c -
              charnames::vianame("DIGIT ONE");
        }
        elsif ($c >= charnames::vianame("LATIN CAPITAL LETTER A")
            && $c <= charnames::vianame("LATIN CAPITAL LETTER Z") )
        {
            # upper case
            $c =
              charnames::vianame("CIRCLED LATIN CAPITAL LETTER A") +
              $c -
              charnames::vianame("LATIN CAPITAL LETTER A");
        }
        elsif ($c >= charnames::vianame("LATIN SMALL LETTER A")
            && $c <= charnames::vianame("LATIN SMALL LETTER Z") )
        {
            # lower case
            $c =
              charnames::vianame("CIRCLED LATIN SMALL LETTER A") +
              $c -
              charnames::vianame("LATIN SMALL LETTER A");
        }
        else {
            # pass thru non-ascii chars
        }
        push @out, chr($c);
    }
    return join( '', @out );
}

Yes, I really did have to do that special case for ⓪; ⓪…⑨ are not contiguous like ASCII 0…9. ⓑⓞⓞ!

Precisely what nobody wanted — the Hershey fonts as a huge great PDF

HersheyNumberedOccidentalGrid-section

It’s impractically huge, but under the image link lives a table of all of the Hershey fonts (well, the Western ones, at least). It’s interesting to note Dr Hershey’s preferences in this pre-ASCII table: almost every variant has degree, minute and second symbols, but none of them have ‘\’. Many of them don’t have ‘@’, either, so no e-mail addresses in Hershey Fraktur for you …

Forgive me, A V Hershey …

I’ve been playing with the Hershey Fonts, vector data digitised by the US government in 1967. It’s in a bit of a bear of a format.

I hope to do more fun stuff with the data. For now, here’s an 120 page sample book showing all the characters:

hershey_sample_page