Tim Hatch

Weblog | Photos | Projects | Panoramas | About

JPEGThumbnail Exif Extraction 31 Jan, 2006

In working on my photo gallery (called photoz for lack of a better name, right now), I discovered a very interesting fact.

My camera, a Canon S410, saves a jpeg thumbnail inside the large jpeg. Helloooo instantaneous thumbnails. Here's some code to extract that image (using EXIF.py):

from EXIF import process_file
f = file("/path/to/fullsize.jpg", "rb")
p = process_file(f)
fo = file("thumb.jpg", "wb")
fo.write(p['JPEGThumbnail'])
fo.close()

That's deceptively easy, but really all it takes. Note, for my Canon model, a small patch was required if you want repr() to work on the result of process_file().

Making Perl "Less Bad," Part 2 31 Jan, 2006

In my next installment of perl trickery, I've found out how to actually print a traceback! My previous reference for Python to Perl conventions said there was no equivalent to Python's traceback functionality, and Google searches for perl traceback brought up references to try/catch modules or perl6 syntax suggestions, but no working code.

After much mucking around, the caller function was located, which effectively gives info on one frame of the stack (although certain parameters are offset one frame). Armed with this and a little more Googling, I found that someone has indeed implemented rudimentary tracebacks for Perl already, in PGLanguage.

My minimal implementation to hijack handling of die() to print a traceback instead follows (with demo):

use strict;

sub b() {
    die("Couldn't contact database");
}

sub a(){
    b();
}


sub dotb {
    print STDERR "Traceback (most recent call last):\n";
    my $err = shift;
    my @trace; #FIXME: empty list?
    
    # Skip the first frame [0], because it's the call to dotb.
    # Skip the second frame [1], because it's the call to die, with redirection
    my $frame = 2;
    while (my ($package, $filename, $line, $sub) = caller($frame++)) {
        if ($package eq 'main') {
            $sub =~ s/main:://;
            push(@trace, "  $sub() called from $filename on line $line")
        } else {
            push(@trace, "  $package::$sub() called from $filename on line $line\n");
        }
    }
    print STDERR join("\n", reverse @trace)."\n";
    print STDERR "Error: $err"; #already has \n at end
    exit(1);
}

a(); #somewhere later, this is going to fail.

# Yes, this is _trying_ to overwrite the global one
BEGIN {
    $SIG{'__DIE__'} = sub { dotb($_[0]); };
}

"Syntactic Sugar" considered harmful 31 Jan, 2006

If I read that phrase one more time, I'm going to scream.

Making Perl "Less Bad" 27 Jan, 2006

I've got a little project I'm doing in Perl right now at the office. As a requirement I was setting for myself, I was going to do it in OOP Perl as opposed to "code soup flat namespace perl" and use some sort of tests.

While I have yet to find anything as universal/easy as Python's doctest mechanism, Test::More does provide a nice little set of functions. To utilize them, make sure you have it (one of our versions of Perl didn't come with it), then use syntax something like the following (check the perldoc for it, it's an easy read):

use Test::More tests => 3; # change this number
ok(1, "One is a valid answer");
is("blah", "bl"."ah", "Test blah concatenation");
ok(0, "Zero is a valid answer");

I noticed that the perl makefiles seemed to perform a slightly different output that was more concise, so after some digging, located this command (here for future reference, because I'm going to forget).

perl -MExtUtils::Command::MM -e 'test_harness(0);' t/*.t

I also came up with this colorizer for when using just Test::More, not the harness (I haven't tried them together).

#!/bin/bash

perl testit.pl 2>&1 | \
  perl -pe 's/^(ok )/\033[0;32m$1\033[0m/' | \
  perl -pe 's/^(not ok)/\033[01;41m$1\033[0m/' | \
  perl -pe 's/^(# Looks like you )(failed \d+)/$1\033[01;41m$2\033[0m/g'

I also spent way too long fighting the use of Error.pm (which is not well documented — that link is the best I can find), which kept giving me the following:

Can't use string ("1") as a HASH ref while "strict refs" in use at /usr/local/share/perl/5.8.4/Error.pm line 183.

The cause was forgetting the semicolon after the end of the try/catch block.

Game Class, Spring 2006 24 Jan, 2006

Will and I are in the game class again this semester, and our team of artists has come up with a great set of concept art. We’re going to see how this one turns out, but I’ll make sure to post the demo once it’s done.

Game Class Results From Fall 2005 24 Jan, 2006

We did okay, we didn’t get last place, and it was possible to win our game. It was gnome-themed, and a basic sidescroller where you kill stuff. If you have a recent video card (GF4MX+/Radeon 7200+), DirectX 9.0c, and wish to try it out, feel free to download the code and executable. Sadly it does not run under Wine/Cedega any more, though the early demos did. It’s compiled in debug mode because it has so many memory leaks, the exceptions in release mode were just too much. Executable is under dist/ and source is under code/. The code under code/fromneds/ is under some weird textbook-inspired license, but our additions to it can be considered released under a nonrestrictive license such as the BSD license.

Random Tidbits 24 Jan, 2006

The last time I posted something here was, I must admit, in the year 2005. It’s been 2006 for almost a month now, and I’m finally getting around to posting something for the first time.

In the meantime, there has been another World Wide Panorama event. My entry is windmills from Lubbock, TX, where I was over the Christmas break.

Intel Macs have been released, along with new versions of lots of Apple programs that we’re told still run perfectly fine on what we’ve taken to calling the “SlowBook Pro” around the office. In one swift motion, all my Mac friends are now “old-school.” Still waiting to see how this one plays out.

I lost another hard drive, this one making a nice clickit-click noise. Not the usual tick-tick-tick, but a dual tone “death noise.” I thought that was interesting.

I’ve read Joel Spolsky’s book “Joel on Software” (a good read!) and subsequently found this quote which fits perfectly with the tone of the book and my personal experience trying to find reusable php code: “php has a very low barrier to entry… consequently, a lot of very bad code is written in it” (paraphrased)

I tried to get Unicode working under OS-X and eventually had help to find out a simple export LANG=en_US.utf8 will solve it for both the built-in and Fink Python, however iTerm doesn’t grok unicode, period. You need to use the built-in Terminal.app. In the process I found this great quote: “…if it’s not, the definition of ‘will work’ changes.