<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>system-log:tyr &#187; Holidays</title>
	<atom:link href="http://system-log.tyr.org.uk/category/holidays/feed/" rel="self" type="application/rss+xml" />
	<link>http://system-log.tyr.org.uk</link>
	<description>Skyscraper I love you</description>
	<lastBuildDate>Wed, 25 Nov 2009 15:07:01 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>A customized Aperture web gallery</title>
		<link>http://system-log.tyr.org.uk/2009/01/21/a-customized-aperture-web-gallery/</link>
		<comments>http://system-log.tyr.org.uk/2009/01/21/a-customized-aperture-web-gallery/#comments</comments>
		<pubDate>Wed, 21 Jan 2009 15:20:29 +0000</pubDate>
		<dc:creator>tyr</dc:creator>
				<category><![CDATA[Holidays]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://system-log.tyr.org.uk/?p=32</guid>
		<description><![CDATA[For many years I&#8217;ve used an install of Gallery to manage my photos online, with a customised front end written for AxKit, and I&#8217;ve also been using Aperture to manage my photo library. Managing two separate libraries became a chore and meant that photos weren&#8217;t been uploaded for friends and family to view. I tried [...]]]></description>
			<content:encoded><![CDATA[<p>For many years I&#8217;ve used an install of <a title="Gallery" href="http://gallery.menalto.com/" onclick="javascript:pageTracker._trackPageview('/outbound/article/gallery.menalto.com');">Gallery</a> to manage my photos online, with a customised front end written for <a href="http://axkit.org/" onclick="javascript:pageTracker._trackPageview('/outbound/article/axkit.org');">AxKit</a>, and I&#8217;ve also been using <a href="http://www.apple.com/aperture/" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.apple.com');">Aperture</a> to manage my photo library. Managing two separate libraries became a chore and meant that photos weren&#8217;t been uploaded for friends and family to view. I tried the built in Aperture web gallery functionality and found it to be rather inflexible and it didn&#8217;t handle hierarchies very well, the other option was to export to <a href="http://www.flickr.com/tools/aperture" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.flickr.com');">flickr</a> or something similar, which I wasn&#8217;t keen on as I&#8217;d rather host the images myself.</p>
<p>So instead I decided to write my own exporting tool, you can see the end result at <a href="http://photos.tyr.org.uk" >http://photos.tyr.org.uk</a> the default view is a match of the project/folder/album structure within my Aperture library and the &#8216;quilt&#8217; view (see top right) is just for fun.  To export photos to the website I just tag them with the &#8216;Web&#8217; keyword then run the export/sync script, it couldn&#8217;t be quicker and certainly much less hastle than maintaining two libraries.</p>
<p>Read on if you want to know more about how it was put together</p>
<p><span id="more-32"></span>The project consists of two parts. Firstly a method to get information out of Aperture and secondly some method of displaying the exported photos to the end user. I&#8217;ll cover the process I used to extract the metadata and images from Aperture in some detail in the hope it is useful to others wanting to achieve the same thing, the end user web front end is more specific to my requirements so I won&#8217;t go into it in so much depth but I&#8217;ll give some pointers to some tools used.</p>
<p>The functionaility I wanted to achieve with the export was to export all images tagged with a specific keyword and create metadata describing the folder/album structure and the image metadata. After much playing about with the inbuilt Aperture export tools I couldn&#8217;t find anything that would do this for me.</p>
<p>However all is not lost as Aperture uses a SQLite database to store it&#8217;s catalogue. Whilst it is not inteded to be accessed directly it is possible to open it up and take a look inside and figure out what is going on. However the layout of the database is not published publically not is it likelly to be stable between Aperture releases, in fact much of this code was originally written for Aperture 1.5 and had to be rewritten when 2.0 was released.</p>
<p>The first step to using the data in the database was to figure out what it all means. I used <a href="http://sourceforge.net/projects/sqlitebrowser/" onclick="javascript:pageTracker._trackPageview('/outbound/article/sourceforge.net');">SQLite Database Browser</a> to interrogate the database. The database itself is called &#8216;Library.apdb&#8217; and can be found within your Aperture library, to browse into the library option-click on it and choose &#8216;Show Package Contents&#8217;. You can then open up the Library.apdb in the database browser.</p>
<p>I wrote the data extraction script in Perl, handily OS X ships with the appropriate SQLite libraries for Perl DBI so opening up the database is easy.</p>
<pre>my $dbh = DBI-&gt;connect ( "dbi:SQLite:Library.apdb") || die "Cannot connect: $DBI::errstr";</pre>
<p>All keywords in Aperture are identified by a UUID called a ZUUID, so the first step is to extract the ZUUID associated with the Keyword, eg</p>
<pre>select ZUUID from ZRKKEYWORD where ZNAME = 'Web'</pre>
<p>Photos in Aperture consist of a &#8216;Master&#8217; image, each of which can have multiple &#8216;Versions&#8217;. We are interesting in extracting the versions that have the assocated keyword, we can find the UUID&#8217;s for these versions like this</p>
<pre>select ZVERSIONUUID from ZRKXKEYWORDVERSION where ZKEYWORDUUID = '$keyZUUID'</pre>
<p>Each of these versions will be extracted and published on the web site. We need to find out two pieces of information for each image, its location in the library and its individual metadata.</p>
<p>As part of this design we assume that all tagged images are part of an album, we&#8217;re not allowing for images that exist only in the top level of a project. We can find the albums a version is a member of like so</p>
<pre>select ZALBUMUUID from ZRKWALBUMVERSION where ZVERSIONUUID = '$versionUUID'</pre>
<p>Note that a version can belong in multiple albums. At this point we just build a list of albums and the ZVERSIONUUID&#8217;s of the versions each album.</p>
<p>The metadata for each version is stored in two places. The most significant data is stored in ZRKVERSION which contains one row per version, the less significant information such as EXIF data is stored in a huge table called  ZRKSEARCHABLEPROPERTY, this contains one row per property, as such it can contain 30 rows or so per version.</p>
<p>Firstly the information from ZRKVERSION is extracted</p>
<pre>select ZVERSIONID, ZFILENAME, ZPROCESSEDWIDTH, ZPROCESSEDHEIGHT
from ZRKVERSION
where ZUUID = '$ZVERSIONUUID'</pre>
<p>With this query we get the filename of the image and its processed width and height (so we can determine orientation) and als the ZVERSIONID, this is a different ID to the ZVERSIONUUID and we need the ZVERSIONID to extract the metadata for the image.</p>
<p>Now we can extract the bulk of the metadata for the image. This is held in ZRKSEARCHABLEPROPERTY and can be extracted like this</p>
<pre>select ZPROPERTYIDENTIFIERUUID, ZVALUETYPE, ZPROPERTYSPECIFICNUMBER, ZPROPERTYSPECIFICSTRING
from ZRKSEARCHABLEPROPERTY
where ZVERSIONID = $ZVERSIONID"</pre>
<p>Each property is either a string or a number, only one of ZPROPERTYSPECIFICSTRING and ZPROPERTYSPECIFICNUMBER contains a value, if ZVALUETYPE is &#8216;3&#8242; then it&#8217;s a string otherwise it can be assume to be a number of some sort, floating point or integer.</p>
<p>The type of property is identified by it&#8217;s ZPROPERTYIDENTIFIERUUID. The data to convert this into a human redable property description is found in ZRKPROPERTYIDENTIFIER. To enable this to work efficiently I extracted all the data from this table into a lookup hash. eg</p>
<pre>select ZPROPERTYKEY, ZUUID from ZRKPROPERTYIDENTIFIER</pre>
<p>Where the ZUUID in ZRKPROPERTYIDENTIFIER matches the ZPROPERTYIDENTIFIERUUID in ZRKSEARCHABLEPROPERTY.</p>
<p>That completes the data extraction for the individual photos. The last thing to do is to extract the folder/album structure. For each album its name and its containting folder can be found like this</p>
<pre>select ZFOLDERUUID, ZNAME from ZRKPERSISTENTALBUM where ZUUID = '$ZALBUMUUID'</pre>
<p>Then for each folder its name and containing folder can be found from ZRKFOLDER like this</p>
<pre>select Z_PK, ZNAME, ZPARENTFOLDERUUID from ZRKFOLDER where ZUUID = '$ZFOLDERUUID'</pre>
<p>This data can be merged together to give you the full tree structure.</p>
<p>Now all the data had been gathered it&#8217;s just a matter of spitting out some XML. One file called <a href="http://photos.tyr.org.uk/library.xml" >library.xml</a> contains the library structure, i.e. references  to all the folders/albums and photos. Then for each photos a &#8217;sidecar&#8217; xml file is created, this contains the exif and other metadata for the photo [<a href="http://photos.tyr.org.uk/sidecars/pc060167.jpg.jpg.xml" >example</a>]. This &#8217;sidecar&#8217; is then loaded when the user displays the photo, this increases performance and reduces the amount of data required for an initial load of the library to just a skeleton.</p>
<p>Now we can extract the photo itself from Aperture. Since Aperture can resize images on export we&#8217;ll use that functionality to create an image that&#8217;s suitable for display to the end user. Aperture can be scripted using AppleScript so we take advantage of that functionality, this can be accessed from a shell call via &#8216;osascript&#8217; for example</p>
<pre>/usr/bin/osascript -e '
   tell application "Aperture"
       set exportFolder to "MacDrive:Users:username:Documents:WebExport"
       export {image version id "$imageUUID"} using "JPEG - Web - Display" to alias exportFolder
   end tell
'</pre>
<p>It should be noted in the above that the value set for &#8216;exportFolder&#8217; is the old Classic style of directory naming with colons rather than slashes.<br />
You must create an export profile within Aperture with the name you use here, in this case &#8216;JPEG &#8211; Web &#8211; Display&#8217;.</p>
<p>Now we can rsync the images and the XML up to the server leaving just one final step and that is to create some thumbnails.</p>
<p>I wanted nice square thumbnails that didn&#8217;t change the aspect ratio of the image. Imagine the largest square you could create entirely within a full size photo then shrink that to a 50&#215;50 thumbnail. This <a href="http://www.imagemagick.org/script/index.php" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.imagemagick.org');">ImageMagick</a> magic sorted it out. I don&#8217;t have ImageMagick on my Mac so this was run on the server that serves the images.</p>
<pre>convert $sourceFile -thumbnail x200 -resize '200x&lt; ' -resize 25% -gravity center -crop 50x50+0+0 +repage -quality 90 $destFile</pre>
<p>And that completes the extraction and upload process. Finally we&#8217;ll take a quick look at the actual display side of things.</p>
<p>The idea behind the web design was to create something nice and simple that presented the photos in a non-fussy but easy to navigate way. I used the <a href="http://developer.yahoo.com/yui/" onclick="javascript:pageTracker._trackPageview('/outbound/article/developer.yahoo.com');">Yahoo User Interface Library (YUI)</a> to build the interface. The main advantage in using this library is that it hides most of the browser incompatibilities out there, for example YAHOO.util.Connect.asyncRequest provides an AJAX function.</p>
<p>Particularly usefully you can assign a single &#8216;onclick&#8217; hander to the folder browser div, then using  YAHOO.util.Event.getTarget you can find the object that was actually clicked. This makes it much more efficient than having onclick handlers all over the place.</p>
<p>The &#8216;quilt&#8217; view does some simple fadein/fadeout animation. This was achieved using the <a href="http://blog.davglass.com/files/yui/effects/" onclick="javascript:pageTracker._trackPageview('/outbound/article/blog.davglass.com');">YUI: Effects Widgets</a> from davglass.com. This creates a nice affect as the imgaes are swapped in the quilt.</p>
<p>If you&#8217;re interested you can browse the javascript on the site; [<a href="http://photos.tyr.org.uk/apgal.js" onclick="javascript:pageTracker._trackPageview('/downloadsphotos.tyr./apgal.js');">main page</a>], or [<a href="http://photos.tyr.org.uk/quilt.js" onclick="javascript:pageTracker._trackPageview('/downloadsphotos.tyr./quilt.js');">quilt</a>].</p>
<p>I hope the above info was interesting or useful, post a comment if you&#8217;ve got any queries.</p>
]]></content:encoded>
			<wfw:commentRss>http://system-log.tyr.org.uk/2009/01/21/a-customized-aperture-web-gallery/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Going the fast way down at Arcalis</title>
		<link>http://system-log.tyr.org.uk/2008/03/25/going-the-fast-way-down-at-arcalis/</link>
		<comments>http://system-log.tyr.org.uk/2008/03/25/going-the-fast-way-down-at-arcalis/#comments</comments>
		<pubDate>Tue, 25 Mar 2008 21:56:00 +0000</pubDate>
		<dc:creator>tyr</dc:creator>
				<category><![CDATA[Holidays]]></category>
		<category><![CDATA[andora]]></category>
		<category><![CDATA[arcalis]]></category>
		<category><![CDATA[skiing]]></category>

		<guid isPermaLink="false">http://system-log.tyr.org.uk/2008/03/25/going-the-fast-way-down-at-arcalis/</guid>
		<description><![CDATA[Perhaps not the most successful turn of the holiday

]]></description>
			<content:encoded><![CDATA[<p>Perhaps not the most successful turn of the holiday</p>
<p><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="373" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="wmode" value="transparent" /><param name="src" value="http://www.youtube.com/v/gao-5VjmY_g&amp;rel=0&amp;color1=0x006699&amp;color2=0x54abd6&amp;border=1&amp;hl=en" /><embed type="application/x-shockwave-flash" width="425" height="373" src="http://www.youtube.com/v/gao-5VjmY_g&amp;rel=0&amp;color1=0x006699&amp;color2=0x54abd6&amp;border=1&amp;hl=en" wmode="transparent"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://system-log.tyr.org.uk/2008/03/25/going-the-fast-way-down-at-arcalis/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
