Volume 15, Issue 10; 26 Mar 2012; last modified 10 Apr 2012

My new photo site is the product of a few evenings hacking.

For many years now, I've been relying on Flickr to host my photos publicly. I have no idea what the long term prognosis for Flickr or Yahoo! is, but it seems prudent to consider the possibility that they'll vanish under the waves someday.

If that happens, I'll need some sort of alternative. (I already have a backup, thank you.) I explored briefly, but it seemed like it might be less work to just roll my own. (No disrespect to openphoto intended, I'm just not that interested in PHP.)

Plus, MarkLogic 5 introduced an “external binaries” feature that means all the binary images no longer have to be in a database. My first thought was to use that feature to build a web view on top of my actual, local photo archive. That turned out to be tricky because mostly I archive RAW images and converting those to JPEGs on-the-fly is time consuming and non-trivial. Instead, I opted for building on top of JPEGs exported from Lighroom.

Lightroom imports camera EXIF information from the raw file and stores both that original data and additional metadata in the JPEG EXIF. Therefore, the JPEG images contain most of the important data I need for building the web view: title, subject (tag), GPS coordinates, camera, lens, exposure, and so forth.

I banged out a couple of quick Perl scripts to scale the images using ImageMagick then upload them to the server. In the course of a few evenings, I had it mostly working. As I tweeted on Saturday, the whole thing came together in about 1,000 lines of XQuery. It's about half again as large now, mostly because I added a few AJAX endpoints to allow me to edit some metadata.

At a high level, it looks like this:

  • I use ExifTool to extract an XML dump of the image metadata; that gets uploaded to the server and stored in a database. I store the image files in the same database as external binaries.

  • The EXIF metadata provides the image title, date, tags, etc. Sets are modeled as collections on the server and are provided when the image is uploaded.

  • Public users can only see files with “public” permissions (visible to the weblog-reader role, which I'm recycling from this weblog). Additional roles (would) allow an image to be marked as visible only to friends or family. The administrator can see all the images. If I really wanted to support multiple users, I'd have to work a little harder on that bit.

  • A few AJAX endpoints let the photo's owner adjust some metadata (the titles of sets, the tags associated with an image, etc.).

You can see it at work here: and I can easily generate DocBook to include in essays, like this one:

You looking at me?
You looking at me?

Some things about having my own site are straightforward (organizing images by sets, tags, and dates; counting views). Other things are clearly just SMOP (supporting comments). Some things are much, much harder. I'd like to provide some mechanism for favorites, for example, but without having viewers logged in, it's not clear how that could work. Building the infrastructure to support user logins (which no one would ever use anyway) doesn't seem worth the effort. I could probably add Google's “+1” button or even Facebook's “like” if I was so inclined, but I'm not.

It will be a while before I've migrated all my public photos to the new site. I may continue to publish them both on and on Flickr as long as Flickr exists, I don't know.

The code will find its way to eventually. In the meantime, comments, etc. are always welcome.

Oh, and the bounty for an actual, aesthetic design still stands.


Another high-profile flickr user contemplates their demise, I suspect their days are numbered, if only because everyone seems to suspect that their days are numbered.... btw. your link is 404

—Posted by Adrian on 27 Mar 2012 @ 05:51 UTC #

Though PHP isn't your thing and you do have a backup solution already... I still thought you might be interested in the "Parallel Flickr" work former Flickr engineer Aaron Straup Cope has been doing. (See also: Github Source)

—Posted by Shawn Medero on 27 Mar 2012 @ 08:01 UTC #