Aperture Plugin: Saving The Default Folder
2007-03-31

As currently written the plugin defaults to the same folder each time I run it. This is not convenient. There is a very good chance that I will want to go back to the same folder each time, so I added the exported file path to the defaults that are written to a read from the prefs file.
As part of doing that I changed -defaultDirectory to this code:

Here I check to see if the value read from the defaults (_defaultExportPath) is a valid folder using NSFileManager. If it is, then I use it, otherwise I use the built-in default of ~/Documents. This deals with the user moving or renaming the folder between runs.
Another change I have made is to make the Generate button do something. I decided that using the current date and time would make for a good salt value:

And here is the latest interface:

Note that since I am posting this after the plugin was released, this interface design is no longer current.
The other parts of this series can be found via the Cocoa page.
|
Good Grief. What Is This?
2007-03-30

My account log showed an access from http://msdewey.ca/. So I went there to have a look. The site is Flash -- all Flash. Oh dear.
The person I found listening to music (non-white earphones, note) is, I presume, Ms. Dewey. She's bad-mannered, has a short attention span, talks on the phone, looks very bored, threatens me, stares at me a lot, and if I wait long enough does this weird super-villain laugh. It's freaky.
Oh, and it's a search engine. I type in penguins. Wait wait wait while she thinks and then talks (about nothing to do with penguins). And then some results come up:

Over two million hits! And no scroll bars. This is going to be interesting.
The URLs are not clickable. The text that falls off the right is not readable. But the titles in blue are, and sure enough I get a page about penguins. But it is in a new window, and so she is still talking. Scrolling is actually possible: putting the cursor in the fuzzy area at the bottom causes the text to scroll, but it gets stuck at times and there is no way to tell how far I have gone or have to go.
I notice a faint copyright in the bottom right: 2006 Microsoft Corp. Ah, I understand now. It's marketing. Your tax dollars at work.
Aperture: Using The Light Table
2007-03-29
There is one feature of Aperture that I rarely use: the light table. I'm usually showing pictures to people one at a time, either manually from the library or as a slide show, so I have no need to show a whole spread of pictures or to see how images look laid out next to each other. Professional photographers do have these needs, and I can see how the light table -- especially on a really big second screen -- is a big help when communicating with clients or mocking up a publication.
I find that the easiest way to create a light table is to select some images and use a control-click to get New from Selection > Light Table:

Then rename the light table by filling in the name:

At this point I try to make the light table as big as I can. I collapse the header with the small toggle button top right, and use Window > Layouts > Maximize Viewer (option command V). Using a small window so I can post the images here I get this:

There are my images at the bottom. Option W will put the thumbnails at the top, and shift W will put the thumbnails at the left or right. I like a black viewer background. This is set in the Aperture preferences:

To get images on the light table, I select and drag. They are automatically positioned if I select and drag more than one at once:

Now I can move them around and scale them with their handles. The thumbnails gain little 1 markers that tell me how many times they have been used. Since I can't use each image more than once on a light table, I never see 2 or 3 (there is a workaround for this, later).
Usually two things happen at this point that cause images to disappear. Either I lose images under other images or I drag one close to the edge of the window and it races off to one side as the light table is scaled, leaving the others far behind. To get an image out from behind others, as in this case:

there is the uncover (shift X) button top left:

Selecting a foreground image and clicking the button pulls those behind out. Clicking it again puts them back. Clicking one of the uncovered images cancels the uncover operation and leaves the clicked image on top:

The other problem, that of a dragged image leaving the others behind is fixed by using one of the controls top right:

The button second to left scales the display to fit the items. Or it should! Actually it scales to fit the light table. If the light table has been stretched, then it stays stretched and the button is not very useful. Because of this it is pretty much equivalent to dragging the scale slider on the right all the way to the left. The light table can be bigger than you think, so this can result in some small images in a big black space. I have yet to figure out how to reduce the size of the light table once it has been stretched out like this:

The leftmost control is the navigator. It can be hard to use. It scales the display and shows a very faint rectangle that represents the window. By dragging that rectangle I can select what part of the light table I want to view. I almost never use it. Unfortunately there is no working scale to selection button. That is really the only button I need for fitting content to the screen.
Having viewed the light table in this way I can drag the errant image back to the flock and then rescale it back to something sensible.
One puzzle is how to get two identical images onto the light table. Dragging an image on a second time just replaces the first image. The trick is to make new versions of the image and use those. By selecting one of my images and pressing option V twice I make two duplicates:

Then I can drag them out of the stack or use command shift K to unstack the stacked items all at once. Now each version can be dragged once to the light table:

The loupe works on the light table, as do all the other controls. T will bring up image data in a tooltip, F will make any image full-screen. Images can be adjusted in place by bringing up the adjustment HUD (H). Cropping will not work in place, but it is much easier to hit F and H and do all editing full-screen if needed, and crop works fine there.
Stacks can be viewed in-place and reordered. Most useful though is the ability to specify an album pick. By setting an album pick, a specific image from a stack can be chosen for use by this album (or light table). That lets the stack be kept in its original order while showing a particular preference just for this album:

The checkmark on the monochrome image shows the album pick. When the stack is closed, only that image will be visible. To get rid of the badges overlaying the images on the light table shown above, I can use shift G.
Two buttons lower left control how the browser and viewer are related. To use the regular viewer instead of the light table viewer to show the browser images, press the Show Viewer button on the left:

and select images as normal:

The lock button next to the Show Viewer button locks the browser to the light table viewer. With that selected, I can option click another project or album and have that display in a separate browser at the same time:

Selecting items in that new browser does not take over the viewer, so I can drag them into my light table browser and manipulate them in other ways. I have more information on using multiple browsers on the page entitled Multiple Browsers For Fun And Profit.
Control-clicking brings up a small contextual menu that includes options for aligning and distributing images. And of course light tables can be printed. All the selected images will be scaled to fit on one page, with the unselected images showing up as blank areas. That can be output to a PDF or printed on a printer.
I wish for a few more features: duplication of images without new version creation, the ability to add text blocks, rotated images, images with borders, layout templates, grid lines and/or alignment markers that images snap to, distribute to grid, randomize layout, scale images to the same size, and a scale display to selection that works.
This is actually one area where 3D effects would be useful: show a perspective view of the light table so it can be seen as a tablet top would. And add the ability to stand up photos and show them rendered into frames.
I find that the easiest way to create a light table is to select some images and use a control-click to get New from Selection > Light Table:

Then rename the light table by filling in the name:

At this point I try to make the light table as big as I can. I collapse the header with the small toggle button top right, and use Window > Layouts > Maximize Viewer (option command V). Using a small window so I can post the images here I get this:

There are my images at the bottom. Option W will put the thumbnails at the top, and shift W will put the thumbnails at the left or right. I like a black viewer background. This is set in the Aperture preferences:

To get images on the light table, I select and drag. They are automatically positioned if I select and drag more than one at once:

Now I can move them around and scale them with their handles. The thumbnails gain little 1 markers that tell me how many times they have been used. Since I can't use each image more than once on a light table, I never see 2 or 3 (there is a workaround for this, later).
Usually two things happen at this point that cause images to disappear. Either I lose images under other images or I drag one close to the edge of the window and it races off to one side as the light table is scaled, leaving the others far behind. To get an image out from behind others, as in this case:

there is the uncover (shift X) button top left:

Selecting a foreground image and clicking the button pulls those behind out. Clicking it again puts them back. Clicking one of the uncovered images cancels the uncover operation and leaves the clicked image on top:

The other problem, that of a dragged image leaving the others behind is fixed by using one of the controls top right:

The button second to left scales the display to fit the items. Or it should! Actually it scales to fit the light table. If the light table has been stretched, then it stays stretched and the button is not very useful. Because of this it is pretty much equivalent to dragging the scale slider on the right all the way to the left. The light table can be bigger than you think, so this can result in some small images in a big black space. I have yet to figure out how to reduce the size of the light table once it has been stretched out like this:

The leftmost control is the navigator. It can be hard to use. It scales the display and shows a very faint rectangle that represents the window. By dragging that rectangle I can select what part of the light table I want to view. I almost never use it. Unfortunately there is no working scale to selection button. That is really the only button I need for fitting content to the screen.
Having viewed the light table in this way I can drag the errant image back to the flock and then rescale it back to something sensible.
One puzzle is how to get two identical images onto the light table. Dragging an image on a second time just replaces the first image. The trick is to make new versions of the image and use those. By selecting one of my images and pressing option V twice I make two duplicates:

Then I can drag them out of the stack or use command shift K to unstack the stacked items all at once. Now each version can be dragged once to the light table:

The loupe works on the light table, as do all the other controls. T will bring up image data in a tooltip, F will make any image full-screen. Images can be adjusted in place by bringing up the adjustment HUD (H). Cropping will not work in place, but it is much easier to hit F and H and do all editing full-screen if needed, and crop works fine there.
Stacks can be viewed in-place and reordered. Most useful though is the ability to specify an album pick. By setting an album pick, a specific image from a stack can be chosen for use by this album (or light table). That lets the stack be kept in its original order while showing a particular preference just for this album:

The checkmark on the monochrome image shows the album pick. When the stack is closed, only that image will be visible. To get rid of the badges overlaying the images on the light table shown above, I can use shift G.
Two buttons lower left control how the browser and viewer are related. To use the regular viewer instead of the light table viewer to show the browser images, press the Show Viewer button on the left:
and select images as normal:

The lock button next to the Show Viewer button locks the browser to the light table viewer. With that selected, I can option click another project or album and have that display in a separate browser at the same time:

Selecting items in that new browser does not take over the viewer, so I can drag them into my light table browser and manipulate them in other ways. I have more information on using multiple browsers on the page entitled Multiple Browsers For Fun And Profit.
Control-clicking brings up a small contextual menu that includes options for aligning and distributing images. And of course light tables can be printed. All the selected images will be scaled to fit on one page, with the unselected images showing up as blank areas. That can be output to a PDF or printed on a printer.
I wish for a few more features: duplication of images without new version creation, the ability to add text blocks, rotated images, images with borders, layout templates, grid lines and/or alignment markers that images snap to, distribute to grid, randomize layout, scale images to the same size, and a scale display to selection that works.
This is actually one area where 3D effects would be useful: show a perspective view of the light table so it can be seen as a tablet top would. And add the ability to stand up photos and show them rendered into frames.
Nail, Meet Coffin
2007-03-28
HP is exiting the Media Center business and pulling out of the Digital Entertainment Center line. This was a $2000 Windows computer in a different box sold as a media center. They had many problems: heat, noise, size, maintenance, set up. All those things that appliances shouldn't have:
And HP was the first and biggest investor in media center PCs. Have there ever been any successful Microsoft partners?
Media Center PCs designed to be used as Media Center PCs were difficult to set up and painful to support, with all the junkware pre-loaded and special settings that had to be checked for little things like avoiding system hibernation and turning off the beeps that sound at very inopportune times.
And HP was the first and biggest investor in media center PCs. Have there ever been any successful Microsoft partners?
Olympus SP-550 UZ Review At dpreview.com
2007-03-28

I currently have a Canon S3 that is a year old. Next year I expect to replace it with something else (no clue what yet), but if I were in the market right now, I would be looking at the Olympus SP-550 UZ. That's the ultra-zoom camera with the 18x zoom lens. Dpreview.com now has a full review of the Olympus. The only direct comparison to the S3 comes on page 17 where the resolution charts are shown.
High points for me are that the lens goes wider and longer than the S3 and it takes AA batteries. On the down side, there is no flip-out screen, and it's not all that fast a camera. You can't use sound in a movie if you want to zoom. It does RAW, but I don't believe is supported by Aperture.
Robert Scoble Is Getting Interesting
2007-03-27
Robert Scoble was blogging about Microsoft before he was part of Microsoft. Now he's no longer part of Microsoft, his blog is getting interesting. His recent posts and particularly the comments they foster and his responses are very telling. He gets it. He likes Apple TV. He doesn't believe that Microsoft is in it to win.
#127: this is the problem. Microsoft is actually something like 100 companies lashed together. The Xbox team might be doing something cool while the Internet team is totally sucking wind.
In this context we’re talking about the Internet team.
Oh, and cool?
How about Photosynth? http://scobleizer.com/2006/11/10/demo-of-the-year-photosynth/
That’s cool. But it can’t be turned into a product.
Why? Cause it takes nine hours to stitch together a few hundred photos. Unusable.
So, very cool, but not a business.
Most of what we’re talking about above is about being BOTH cool and a great business ON THE INTERNET.
Microsoft is lacking on both areas.
And the comparison to the Beattles is NOT out of place here. Demonstrates that you take a Microsoft approach here.
Comment by Robert Scoble — March 17, 2007 @ 12:03 pm
#127: this is the problem. Microsoft is actually something like 100 companies lashed together. The Xbox team might be doing something cool while the Internet team is totally sucking wind.
In this context we’re talking about the Internet team.
Oh, and cool?
How about Photosynth? http://scobleizer.com/2006/11/10/demo-of-the-year-photosynth/
That’s cool. But it can’t be turned into a product.
Why? Cause it takes nine hours to stitch together a few hundred photos. Unusable.
So, very cool, but not a business.
Most of what we’re talking about above is about being BOTH cool and a great business ON THE INTERNET.
Microsoft is lacking on both areas.
And the comparison to the Beattles is NOT out of place here. Demonstrates that you take a Microsoft approach here.
Comment by Robert Scoble — March 17, 2007 @ 12:03 pm
Aperture Plugin: Storing The Settings Between Runs
2007-03-26

[Note: my blogging this project is some way behind the development. Random Wok 1.0 has already been released.]
An inconvenience with the current version is that it always presents blank text fields to the user. I would like to store the prefix, postfix, salt, use salt, random format, random length, and alpha case selection somewhere so that their settings are retained from one run to the next.
Implementing this turned out to be harder than I thought it would be. After reading up on NSUserDefaults and looking at several examples, it all looked straight forward enough. But something very odd happened: the values I were successfully saving and restoring between runs was being stored somewhere, but not in the com.bagelturf.Aperture.Export.Random_Wok file as I had been expecting. Not only were they not in the expected file, the expected file did not exist. It was never created.
The values I was storing were actually getting put into Aperture's own preferences file in ~/Library/Preferences. While under some circumstances this would have been the desired behavior (such as writing my own plugins for my own application), in mine it was not. I could not use most of the NSUserDefaults methods because of this side-effect.
So I created two methods: -getDefaults and -setDefaults and inside them used -persistentDomainForName: and -setPersistentDomain:forName to read and write the complete plist file as a dictionary.
Setting the defaults (that is writing the file) is done like this:

It first accesses the shared instance of user defaults and then uses the bundle identifier to retrieve the settings into a mutable dictionary. That dictionary is then updated with the latest values from the ivars, suitably encoded, and written back to the file. This allows older versions of the plugin to work with newer versions of the plist file: anything not used is simply left alone.
Reading the defaults is much more involved. The extra work comes from the need to set up the file if it does not initially exist and to manage plugin version changes. The first part is much like before, with the addition of reading the version from the plugin bundle:

Then I deal with the first run. This is indicated by an empty dictionary:

This results in a file on the disk, and a mutable variable defaultsDict with the same information. Now I am ready to deal with a change of version number:

I have nothing to do: there is only one version so far. If the version has changed, then the new version number is written to the dictionary and out to the file. Finally I am ready to set up the ivars from the dictionary values:

I call -getDefaults from the -initWithAPIManager method so the ivars are ready to go when the window is created. Then in -willBeActivated I set up the various elements of the view:

Finally in -willBeDeactivated I call -setDefaults to write the current state of the interface to the plist file.
Here is what the final com.bagelturf.Aperture.Export.Random_Wok.plist file looks like:

The other parts of this series can be found via the Cocoa page.
Subversion Part 3: Checking Out And Using A Project
2007-03-24

To use my Random Wok project I have to check it out. While the files are in the database they are inaccessible to normal file operations. I will do the check out in svnX.
I'm going to check out all the files in the trunk virtual folder to a new folder called Random Wok in my Documents/Progging/Working folder. First I create that new folder. Then in svnX I select the trunk virtual folder in the browser at the bottom click on the svn checkout button and select Working/Random Wok as the folder to check out to. svnX creates the folder for me and fills it with the files:

svnX has a browser built in for looking at working copies. Opening that shows me the working version I just checked out and lets me give it a more descriptive name:

Double-clikcing on the line shows me a browser that I can use to see the file status:

Now I can get back into XCode. I double click to open the XCode project that was checked out and set it up to use subversion. From the SCM menu I select Configure SCM... and set it up like this:

I change the build location and the location for intermediate files, and enable and select the SCM. I also found it necessary to clicked on Rebuild Code Sense Index for XCode to have the data it needs about my source files. To fully set up the build destination I select the target and change the Build Products Path for all configurations to be that Random Wok Folder:

Now the SCM tab for my project looks like this, showing the initial check-in:

Now I can enable the SCM status display by selecting the Random Wok project icon at the top of the XCode project list and control-clicking on the column header:

Now if I edit a file and save it I get a status change, M, showing modified:

Also shows up in the SCM smart folder on left:

Another thing I need to do is to tell snv that the pbxuser files are binary. This will prevent svn trying to merge them. To do that I go back into the terminal:

How does svn know where the repository is? There is a hidden folder called .svn in the checked out folder. In fact there are hidden .svn folders in all the folders.
Lastly I commit my updated version to the repository. I select all the files to update and from the menu use CMS > Commit Changes, and fill in the commit message:

With the files checked out I can compile and use my project just as I did before I used subversion. Each time I get to a good stopping point, I check in the files.
Eventually I will have a version that I want to release. And that means using svnX again.
The other parts of this series can be found via the Cocoa page.
Apple TV Is Very Hackable
2007-03-24

The folks over at Something Awful are hacking Apple TV. Since the ATV runs Mac OS X, this is almost trivial: pop the cover, take out the hard drive, mount it on a Mac via a Firewire case, and modify. They have it playing Xvid movies, running SSH, and more. The hard drive can be replaced with a larger one too.
I notice that it contains a ForceFeedback framework too. That means games. Only games (simulators) use force feedback.
It may seem odd that the box is as open as this. After all, the XBox and other equipment like it is locked down just as tight as the manufacturers can make it. Not that it stops anyone. But it is not odd at all when you consider that Apple is in the hardware business. An open box sells more boxes, and that is all that matters. This is really the lowest-cost Mac on the market now.
Villain Chair
2007-03-23

I want one of those. It would go well with my grey cat. Many other hard-to-find items at Suck UK. I also like the egg timer and the pen holder.
Random Wok 1.0 Released
2007-03-22

Random Wok 1.0 has now been released and is available on the Downloads page. It's a Universal binary for Aperture 1.5 or later and Mac OS X 10.4.8 or later. Random Wok exports images from Aperture and gives them random names. For more information on Random Wok see its product page.
Aperture Plugin: Dealing With Duplicate Random Names
2007-03-21

Now that I am finally exporting with random file names I feel like I am on the home straight. But there is plenty more still to do: looking for problems, for instance.
There are two things that can go wrong with the export. First there could be an existing file in the folder I am exporting to. This is actually quite likely since repeated exports will create the same names for the same files unless the salt is changed. To solve that I add some code to display an alert if the rename fails. I modify the call to movePath by adding a handler. If there is an error with the rename, the handler method will be called:

To support the handler, I added two methods:

I had to incorporate a workaround for a bug: the return value of fileManager:shouldProceedAfterError is actually ignored by movePath:toPath:. NO always comes back. So I had to create an ivar to pass that value.
Although this code handles errors just fine, there is a better way of dealing with the situation of existing files with the same name as new files. I can create all the random file names and make sure that none of them exist in the folder before I even start the export. That will ensure that errors are truly exceptional (cause by hardware or other programs maybe).
Another problem I may run into is that there may be too many files for the randomness. Exporting 1000 files with three random decimal digits in the name is guaranteed to run into trouble.
So my code needs to ensure that all of the random names are unique with respect to themselves and to the destination folder. The solution is to create dictionary of existing filenames with NSNull objects. I use a dictionary for finding duplicates because they are very efficient for large numbers of images:

To that I add the files being renamed, the difference being that the files being renamed are stored with the new random name. The case-insensitive nature of the filing system means that I need another another dictionary to track file names coerced to lower case. Collisions in that dictionary mean that I have a problem.

My renaming code ignores the existing files by looking for the NSNulls and renames the rest:

The other parts of this series can be found via the Cocoa page.
Artists Think Different
2007-03-20

Cognitive Daily shows how artists and non-artists look at images. Artists scan all over, while non-artists focus on the subject. They have been trained to look at all the details of the picture and overcome the natural tendency to fixate on salient features.
It would be interesting to do the same experiment with photographers.
Random Wok: Heading Toward Release
2007-03-19
Behind the scenes my Aperture plugin Random Wok has been undergoing development beyond the blog entries I have been posting. I plan to release on March 22nd.
The interface has transformed somewhat, and it has gained the ability to display thumbnails:

I have been learning a great deal about bindings, KVC, NSTableView, and other aspects of Cocoa programming. Over time I will post more blog articles about its development to show how this was implemented and what I learned. There will be a 1.1 release as well since there are some non-essential features and optimizations that I want to add that will not make it into the first release.
Read more about Random Wok on the Products page or see blog articles about its development on the Cocoa pages.
The interface has transformed somewhat, and it has gained the ability to display thumbnails:

I have been learning a great deal about bindings, KVC, NSTableView, and other aspects of Cocoa programming. Over time I will post more blog articles about its development to show how this was implemented and what I learned. There will be a 1.1 release as well since there are some non-essential features and optimizations that I want to add that will not make it into the first release.
Read more about Random Wok on the Products page or see blog articles about its development on the Cocoa pages.
Subversion Part 2: Setting Up A Repository And Importing A Project
2007-03-18

The repository called Random Wok Repository I set up in Documents/Progging/Repositories needs some internal structure. That's because I am going to have it contain virtual folders called trunk, releases, and branches (I prefer releases over tags).
In the original Random Wok project folder I create the new structure: trunk, branches, releases. And then copy the current contents into trunk and delete the Build folder.

Now I am ready to do the import. I need to do this from the command line. First I change my working directory to the changing to the original project folder (yellow in my diagrams) and then import using svn import. I have to give a check-in message with -m or else svn complains with an error (no editor set up). The dot in the svn import line below references the current directory. The repository is defined with a URL that starts with file:///:

Now the structure looks like this:

Everything below Random Wok/ in red is in the repository and so the folders shown are virtual folders. They can be referenced with URLs passed to svn that start with file:/// by including the path to the repository and then the path inside the repository.
Now revision 1 is in the repository I can use a utility called svnX to inspect it. I no longer need the Terminal window open. svnX will not recognise an empty repository, so up until now I could not use it. I download snvX from Apple and install it. Svnx is a GUI front end to svn.
The prefs are already set up for me:

In the Repositories panel I add a new repository pressing +, giving the repository a name, and dragging the Random Wok Repository folder onto the Path field. Now svnX knows where the repository is:

I double-click on the repository to open it in svnX and look at the contents:

The lower part is a folder browser that shows the structure of the revision select in the pane above. I can see the import message and a list of revisions with just one revision in it. The svn mkdir button is used to make more virtual folders in the repository and svn copy and svn move button copy and move virtual folder trees in the repository.
I no longer need the original project file, so I can archive it to a ZIP file to get it out of the way:

In its current state I cannot use my project. It is inside the repository and inaccessible to XCode and other tools. So the next step is to check out a copy.
The other parts of this series can be found via the Cocoa page.
Aperture Plugin: Generating The Random Name and Renaming Images
2007-03-16

Now I am able to generate the random string I can rename the images after they have been exported. So for each image file I do this:

To get the image UUID, depending on the API version I call either a method that gets the image properties with or without the thumbnail. I don't need the thumbnail, so I prefer to use the one that uses least memory. To determine which API to use, I add this code to the -initiWithAPIManager method:

To generate the random string I either use the salt string or not, depending on whether the checkbox is set. Then the random string is combined with the other parts of the name and used for the rename (achieved with the movePath:toPath:handler method). I add hyphens to the name in the code above for debug purposes. In real life the format string will drop the hyphens.
This code is not very memory-friendly. Each time around the loop will allocate more memory, so I need to refactor it with better memory use.
There. Finally making random file names!
The other parts of this series can be found via the Cocoa page.
Aperture: Backing Up With Aperture
2007-03-15

I have a sizable article published in MacZealots today entitled Backing Up With Aperture. It looks in detail at the various ways of backing up your Aperture library.
Mac OS X 10.4.9 Update Improves Aperture
2007-03-14
Apple's Knowledgebase article 305121 lists the benefits that Aperture gets from the Mac OS X 10.4.9 update:
The full list of supported cameras is listed on Apple's site. I expect we will see an update to Aperture before very long. Joe Schorr has already posted such on Apple's Aperture forums recently.
• Adds support for the RAW image formats of these third-party cameras: Leaf Aptus 17, Leaf Aptus 22, Leaf Aptus 65, Leaf Aptus 75, Leaf Valeo 11, Leaf Valeo 17, Leaf Valeo 22, Leica Digilux 3, Nikon D40, Pentax K10D, Pentax K110D, Pentax K100D, Panasonic Lumix DMC-L1, Samsung GX-1L.
• Improved Spot & Patch results: The update contains changes to Core Image that improve the visual correctness of images using Spot & Patch adjustment.
• Reduces issues of temporary "black" Viewer: Mac OS X 10.4.9 addresses several issues that could cause the Viewer to temporarily turn black when displaying adjusted images.
• GPS metadata is preserved when image versions are exported.
• Incorporates all RAW file format compatibility and other imaging issues originally addressed in Digital Camera RAW Support Update 1.0.1. This update improved RAW file format compatibility for the Canon Digital Rebel XTi / 400D / Kiss X Digital, Nikon D80, and Pentax *ist DS. It also addressed the following issues: Handling of large Canon RAW files (.CRW); DNG compatibility on Intel-based Macs; Lines sometimes appearing in images exported from Aperture.
• Improved Spot & Patch results: The update contains changes to Core Image that improve the visual correctness of images using Spot & Patch adjustment.
• Reduces issues of temporary "black" Viewer: Mac OS X 10.4.9 addresses several issues that could cause the Viewer to temporarily turn black when displaying adjusted images.
• GPS metadata is preserved when image versions are exported.
• Incorporates all RAW file format compatibility and other imaging issues originally addressed in Digital Camera RAW Support Update 1.0.1. This update improved RAW file format compatibility for the Canon Digital Rebel XTi / 400D / Kiss X Digital, Nikon D80, and Pentax *ist DS. It also addressed the following issues: Handling of large Canon RAW files (.CRW); DNG compatibility on Intel-based Macs; Lines sometimes appearing in images exported from Aperture.
The full list of supported cameras is listed on Apple's site. I expect we will see an update to Aperture before very long. Joe Schorr has already posted such on Apple's Aperture forums recently.
Subversion Part 1: Downloading and Set Up
2007-03-14

For a long time I have wanted to implement a version control system. The attraction is being able to gain control over my code without simply making duplicates of the project folders. In particular I want to be able to fork and merge different code bases and roll back to working versions. As soon as I involve anyone else in the development process (even testers), it is no longer just me and all this becomes a necessity.
So I am going to install subversion and move my active projects over to it. I have been reading up on subversion for a while on and off, and think that I understand it well enough to implement it and blog it. For the record I'm using XCode 2.4.1, subversion 1.4.3, Mac OS X 10.4.8. Since the interaction among these changes, bugs get fixed, and features get added, not all of this article will stand the test of time.
I'm going to concern myself with just a local repository. I don't need remote access yet, so that will do. This decision means that I don't have to deal with Apache, WebDAV, and a host of other issues that make the set up complex.
A significant cause of confusion is the number of folder hierarchies that have to be understood and managed in the setting up and running of subversion. So to make what I am doing crystal clear, I have some diagrams to illustrate and am using color to differentiate the parts.
I have to work with three different folder hierarchies, so I better get organized.
The first hierarchy is my current project, Random Wok. Its project folder is called Random Wok and its path is Documents/Progging/Cocoa/Aperture/. Inside Random Wok is the XCode project file, the Build folder, and all the source files and resources. Once I have put the project into my repository I will mothball the Random Wok folder. Currently I create new versions by duplicating the Random Wok folder and numbering them. These files and folders are yellow:

The second hierarchy is a new one. To use subversion I will put my code into a folder called trunk that lives inside a virtual folder hierarchy inside subversion repository. That repository (implemented inside a folder) will itself be one of a number, all organized into a real folder hierarchy on my hard drive. As per the subversion documentation, I will also have a branches folder and a releases folder at the same level as the trunk folder. So my first step is to create a folder Documents/Progging/Repositories on my hard drive. That is the real folder that will hold all my repositories. The first one will be called Random Wok Repository and will hold one project. These files and folders will be red.
The third hierarchy I have to concern myself with is that of the checked-out code. I will be checking my code out of the repository to this new location, building and debugging it, and finally checking it back in again when I am happy with the result. If I want I can then delete the code, because it's all in the repository. I create a folder called Working in Documents/Progging and another called Builds. Working is where I will check the source out to and will be green. Builds is where I will have all the Build folders live. I want to be able to keep the builds separate from the code. Inside Builds I create a folder called Random Wok. Inside that is where the builds and temporary files will be kept. The Build files and folders will be blue.
Now I need a copy of subversion. Subversion is actually a collection of utilities, svn and svnadmin being the two I will use the most. I download a prebuilt binary from Coding Monkeys and run the installer. That puts the binaries into /usr/local/bin:

To make using these simpler I set the PATH variable in the current tcsh shell invocation to /usr/local/bin with setenv by typing setenv PATH /usr/local/bin.
Next I need to run svnadmin to create my first repository:

And there it is:

Now I run svn once so it will create a folder called .subversion in my home directory:

Much more information follows that. In the .subversion folder is a config file. I edit this using TextWrangler with File > Open Hidden... and selecting Enable: All Files. In the [miscellany] section I modify the list of global-ignores so that it looks like this (it's actually all on one line):

The modifications make subversion ignore some extra XCode files that I don't care about. I don't include the *.pbxuser files as some people do. That is because those per-user values include the custom executable settings that I need to launch Aperture. Here is the hierarchy so far:

Next I need to set up the repository and import a project.
The other parts of this series can be found via the Cocoa page.
China Wheelie: 25,000km On Three Wheels
2007-03-13

Rob Luxton is cycling that machine 25,000km around China in support of two charities. The web site has some great photos and movies of life in China.
Aperture Plugin: Generating A Random String From A UUID
2007-03-12

The final part to implementing the randomness is actually making the real file names. To do that I write a method for generating a string from an NSData object using a character set and a length:

This first uses eight bytes to create a long long (64 bit) value and then uses repeated division to extract character via an index into the character set string.
Then I use that to help create the random string from the UUID and the salt:

First it makes a single string from the UUIDF and salt, then converts that to an NSData object and creates the MD5 digest of that. That is then used to generate the final string that will be used in the file name.
The other parts of this series can be found via the Cocoa page.
Late Night Cocoa
2007-03-11

Late Night Cocoa is a podcast dedicated to Cocoa programming . It's very good. The hour-long podcasts are in the form of interviews with Cocoa programmers: XCode Projects, Scriptable Applications, Custom Views, Leopard, Core Data, and more. There is also an RSS feed.
One Reason I Have Never Written Any Windows Code
2007-03-10
Verity Stob writes about the quality of documentation on the Microsoft Developer Network in an article entitled Unhelpful Microsoft help denies helpless millions help. It's all about one function: LockWindowUpdate and how effectively its real purpose is omitted from the information available from Microsoft:
I have actively avoided writing anything for Windows. The documentation for Mac OS X is really very good and very available, and that is one of the reasons I have gotten into programming again.
How about this: because LockWindowUpdate is entirely typical of MSDN. The whole, bloated thing is jam-packed with function descriptions that tell you everything about the function except what you need to know, huge, dull, explaining-by-not-explaining articles extracted like rotten teeth from MSDN Magazine and its predecessor MSJ, and filled with bogus enthusiasm for, say, this month's approved way of interfacing to databases.
I have actively avoided writing anything for Windows. The documentation for Mac OS X is really very good and very available, and that is one of the reasons I have gotten into programming again.
Aperture Plugin: Creating The Example File Name
2007-03-09

There are several parameters that depend on the settings for the random string format, the alpha case, and the length. I concentrate all the decisions for these into one big ugly switch statement that starts off like this:

This sets a character set for generating the random string, and also an example string that I will use on the display. Displaying the example random string now consists of this:

I truncate the example random part by the selected string length. Anywhere that the random string parameters change, I add a call to recalculate the parameters, such as in the action code for selecting the length:

Now the dialog looks like this:

The example file name now follows the settings.
The other parts of this series can be found via the Cocoa page.
Cocoa: I Will Be At Silicon Valley CocoaHeads Tonight
2007-03-09

The second Thursday of each month sees a meeting of Silicon Valley CocoaHeads, usually on Apple's campus at 1 Infinite Loop. This month the topics are Core Animation and Related Leopard APIs (starter), and Cocoa Binding Tips And Tricks (main course). I will be there, trying to get my head around bindings one more time.
Aperture: Using TextWrangler To Browse And Modify Aperture Libraries
2007-03-08

TextWrangler is a freeware text editor and general-purpose text-processing tool published by Bare Bones Software. One of the things it is good at is processing a whole folder hierarchy of files at once, making the same edits to each with just a few mouse clicks. Since Aperture libraries and vaults are just large file hierarchies, I can use this tool to browse and modify them.
TextWrangler can be set to automatically process hundreds or thousands of files, so it is a really fast way to destroy an Aperture library too. Conversely, if I really know what I am doing, it is a fast way to find things and make changes that Aperture cannot, such as recovering from corruption, removing problem data, or globally changing parameters.
The simplest way to use TextWrangler is to open a new blank document and drag an Aperture library onto it. TextWrangler reads the file hierarchy and displays it as tab-indented text:

Now I can browse and search this text document. If there are lines that I don't want to see I can use the Text > Process Lines Containing... function to delete or modify all lines that matches criteria I define, such as file name endings or character patterns.
I can also do the same thing with two libraries and two windows and then go to the menu and compare their contents with Search > Compare Two Front Documents. In this way I can compare the contents of two Aperture libraries side by side:

Another way to use TextWrangler is to look inside the files in the library. In the example that follows I browse all my library image file information files (only the XML .apfile files) and examine the information they store about the disk that hosts the image.
I launch TextWrangler and hit command F to bring up the find panel. To get TextWrangler to open the library, I locate it on my hard drive and drag it onto the drawer on the left (the Open dialog will not allow it to be selected):

Pressing the Options... button bottom right allows me to set up a filter so that TextWrangler will only open certain files in the library. I set up the dialog as below:

I click on Edit Filter to set up a new filter called apfiles that will make TextWrangler only open the XML files that describe images in the Aperture library:

Closing that and clicking OK takes me back to the Find window. By typing diskUuid into the top search box and clicking Find All I get a window that shows all the matches:

I can scroll up and down by clicking on the top pane and using the up and down arrow keys. This allows me to view each file in turn in the lower panel and look at the disk and other data that the apfile contains. It's so fast that I can easily flick back and forth across several files and see the differences.
This technique can be used to make global edits on the Aperture library. By filling the Replace With box and clicking Replace All, TextWrangler will go through all the matching files and match and replace the values. Of course this is very dangerous, so I recommend only working on a copy of the library, and even then going very carefully. Since exported projects are almost identical to a library, they make a good practice area.
Many changes to the files that make up the library also have to be made to the database if they are to have any effect. But since the database is out of bounds to applications like TextWrangler, the only way to accomplish this is to quit Aperture, delete the database and then open the library, so causing Aperture to rebuild it. Another way to achieve the same effect is to launch Aperture with option and command held down.
I've only scratched the surface of what TextWrangler can do. It's a very powerful tool and can be put to good use to explore and solve Aperture library problems. But be careful with it!
Black Sheep
2007-03-08

The movie Black Sheep looks like a cross between Tremors, Alien, Shaun Of The Dead, and A Close Shave. And since it's set in New Zealand, I'd expect Hobbits as well.
Aperture Plugin: Adding Randomness
2007-03-07

To get my randomness I will use the MD5 message digest. That delivers a 128 bit number based on an input of any number of bytes. Since Mac OS X ships with MD5 functions in a dynamic library, all I have to do is to call that appropriately.
Appropriately in this case means using code that has already been written. Andreas Mayer submitted some code to the Cocoa mailing list that creates a category on NSData for MD5 and SHA1 digests. A Cocoa category is a collection of methods that extend those of an existing class. They cannot add ivars. The interface to the category AMDigest looks like this:

It declares two methods, each returning an NSData object with the digest inside. Since it is a category on NSData, the methods are used just as any other NSData methods are. The implementation code wraps some C function calls and returns a new autoreleased NSData object:

To add the methods, I create a new Objective C class called AMDigest in my XCode project and paste in the code. Left as is, this does not work, because I have not told XCode to link to the library and the function calls go unresolved. It took some work to figure out that the libcrypto.dylib file that is provided with OS X is a stub and should not be added to the project in the Frameworks and Libraries folder. All that is actually needed is to select the Random_Wok target and add this item to the build configuration:

To use the new method I also have to #import the header file that contains the interface in my Random_Wok.m file.
The plan is to concatenate the salt and the UUID of the Aperture image together and create an MD5 digest of that. I can then use 64 bits of the digest to create a random string based on the settings of the length, format, and alpha case that the user has selected.
The other parts of this series can be found via the Cocoa page.
Canon S3: Easy Flash Control
2007-03-06
In low light conditions I want to know what shutter speed I can achieve without flash, but also want the flash ready in case I need it. And I want to be able to control whether or not the flash is used without having to press any buttons allowing me to make my choice at the last second. It turns out that with a simple trick I can do all of this.
With the shutter button held down and focussed, the Canon S3 shows the shutter speed in the display. If the flash is raised, then a different shutter speed is shown, typically 1/60. With the shutter still held down, if I depress the pop-up flash just a little with my left hand, two things happen: the flash is turned off, and the shutter speed changes in the display.
So I can be ready on a subject, focussed and about to take a picture, but still easily see the difference in shutter speed between flash and no flash, and remain able to turn the flash on or off for that single image by just poking the flash unit a little.
With the shutter button held down and focussed, the Canon S3 shows the shutter speed in the display. If the flash is raised, then a different shutter speed is shown, typically 1/60. With the shutter still held down, if I depress the pop-up flash just a little with my left hand, two things happen: the flash is turned off, and the shutter speed changes in the display.
So I can be ready on a subject, focussed and about to take a picture, but still easily see the difference in shutter speed between flash and no flash, and remain able to turn the flash on or off for that single image by just poking the flash unit a little.
Aperture Plugin: Ending Editing
2007-03-05

I discovered a problem with the Use Salt checkbox. If the checkbox is clicked then it disables the salt string text field. When it is clicked again, the field is re-enabled, but the string it contained is gone. Looking into this further I found that if I clicked away from the text field before disabling the field, the string would stick.
What is happening is that the field editor attached to the text field is not being told to end editing. Normally that is done when focus moves to another field or control, but not in the case of disabling the control. The cure was to change the -useSalt: method like this:

That call to -endEditingFor: tells the window manager to end editing for the field and all is well.
I also fixed the name "Random_Wok" in the menu and the window title. I edited the info.plist file by changing the display name string:

The other parts of this series can be found via the Cocoa page.
Probably The Hardest Obstacle Course You Will Ever See
2007-03-05

Makoto Nagano completes what must be the hardest obstacle course in the world. It's Japanese. About the only thing missing is sharks with frickin laser beams attached to their heads.
Aperture: Speed Up Aperture By Rebuilding The Database Index
2007-03-04

Everyone is excited about the discovery of using the sqlite vacuum command to rebuild the index for Mail.app. Well the same trick works for Aperture. Rebuilding the library database indexes is much faster than rebuilding the entire database. While probably not as effective, it does improve the speed of Aperture, especially for heavily-used libraries with a lot of deleted images. [Update: Aperture 2.0 has two databases: the Aperture.apdb database and a new one called BigBlogs.apdb. As currently written, this script does not touch the BigBlobs database.]
Here is the script. You can download a ZIPped version from the download page or paste the text below into Script Editor. Be careful of the single- and double-quotes getting modified in the process. They are all straight quotes. [Update: I added an improvement sent to me by Adam Tow. The script now only opens bundles and defaults to the Pictures folder.]
tell application "Aperture" to quit
set new_file to choose file with prompt "Select Aperture Libary to compact its database" default location (path to pictures folder) of type {"BNDL"}
set libname to (POSIX path of new_file) & "Aperture.aplib/"
set dbname to libname & "Library.apdb"
set sizeBefore to do shell script "ls -lah " & (quoted form of libname) & " | grep -E 'Library.apdb$' | awk {'print $5'}"
do shell script "/usr/bin/sqlite3 " & (quoted form of dbname) & " vacuum"
set sizeAfter to do shell script "ls -lah " & (quoted form of libname) & " | grep -E 'Library.apdb$' | awk {'print $5'}"
display dialog ("Database before: " & sizeBefore & return & "Database after: " & sizeAfter & return & return & "Now try it out!")
After prompting to select an Aperture library, it runs for a while (up to a minute on large libraries) and then shows a dialog box comparing the size of the library database before and after processing:

Let me know how much it helps.
Cocoa: Resources For Programmers
2007-03-03

Writing Random Wok and other code is always a very punctuated experience. I decide what to implement next, then read and take notes, then figure out what I think I need to do, then write the code, then debug, then blog. Sometimes a lot of time is spent during the reading and figuring out stages as I try to understand either how something is done, or, knowing how it is done, trying to understand how to do it that way in my code.
I go to several offline and online resources to get my curiosity satisfied, my brain overloaded, and my questions answered. Here is a short list of where I go, in order of attack:
1. XCode's Built-in Help and Documentation
My first stop is XCode, Apple's IDE for Cocoa development. XCode has a great deal of information built in: more than a gigabyte of Reference Library, in fact. Access to it all is via XCode's Help menu:

The documentation for XCode itself is found via the XCode Help item. The full developer reference library opens in a viewing window via Documentation:

The documentation window has two modes of searching. If you don't know how these work you will not find things and be very confused. Access the modes by clicking on the magnifying glass:

API search is immediate and needs no carriage return. The window below the search box shows the matches in order of fit. Click on one and I have the document in the lower pane. Double click and it opens in a separate window.
Full-Text Search is not immediate. I must press carriage return for anything to happen. And then the scope of the search is controlled by the selection in the library browser on the left:

My search for NSNull will only be carried out for documentation on Carbon in this case. I have to leave the Reference Library line at the top selected if I want to see all the documents (as I normally do).
The help menu also has two search items that work on selected text. Find selected text in documentation and Find selected text in API reference. An option double click on a word also takes me to Find selected text in API reference. I use this all the time.
Another very handy shortcut is to command double click on a word. That takes me to the definition in the code. This can be very useful because the context and comments in the code can often tell more than the documentation:

I set the languages that are searched via the Configure Options button on the toolbar:

I don't do C++ or Java and this prevents anything about them from showing up. Updates come out periodically. I have auto-checking enabled in the preferences:

So that I get update notifications:

And when a new set of documentation is available, 250 MB or so later, I have it.
Finally, I have access to the Man pages at the bottom of XCode's Help menu. I don't type "man" into a terminal: it is all there in the XCode documentation package.
2. Spotlight
The next place I go is Spotlight. I have all of the developer material indexed so spotlight will locate example code, saved web pages, and all kinds of other documents on my hard drive.
3. Cocoadev

Then I go to the web. Cocoadev is a WikiWikiWeb site containing a huge amount of user-contributed advice, code, explanations, links, and other material. It is easy to search, and you can contribute your own comments.
4. Cocoabuilder

Cocoabuilder is an archive of all of the postings to the Apple XCode, Cocoa, and Macosxdev mailing lists. There is a lot of Apple input on there. You can't post here. To post questions, sign up for the appropriate mailing lists at http://lists.apple.com/.
5. Borkware Quickies

Borkware and its associated Quickies page is a great place to find some of more useful and less documented ways of doing things. It's the creation of Mark Dalrymple, author of several Unix and Mac programming books and teacher at the Big Nerd Ranch.
6. Google

Finally, I Google what I am looking for. That will catch all kinds of things, including hits on the core foundation code, and open source efforts to duplicate parts of the Mac OS.
Apple's Aperture Download Page
2007-03-02
Aperture Plugin: Adding a Progress Bar
2007-03-02

So far the progress bar supplied by Aperture as my images export does nothing. I'd like it to progress according to the fraction of images that have been exported out of the total number. Since progress for Random Wok includes a final renaming step that is very fast, I can display a progress bar that goes up to 90% for the actual export and then label the last 10% "Randomizing".
To implement the progress bar I have to set up the export progress structure and then update the current values that it contains as the situation progresses. The progress structure looks like this:

To protect it against simultaneous update by multiple threads an NSLock is used. That lock has to be claimed and relinquished by any thread that wants access, so protecting against partial changes caused by context switching. The SDK comes with two methods already included: -lockProgress and -unlockProgress that lock using an NSLock ivar called _progressLock.
I set up the progress bar just before I tell Aperture to start the export. The code I add to -exportManagerShouldBeginExport looks like this:

It does some math to make the progress bar go to about 90% of its full travel when all the images have been exported, then loads up the structure before starting the export. As the export proceeds, -exportmanagerShouldWriteImageData:toRelativePath:forImageAtIndex: will be called for each image. So it is that method that hosts the following code:

In -exportManagerDidFinishExport I have an opportunity to change the progress message and handle the randomizing rename. So I add this code to the beginning of that method to switch the message and use an indeterminate style of bar:

Notice that I do some memory management here with autorelease and retain. The example code does this, and I believe that I need to do it with the way I have handled the strings too. If not, using it in my code is harmless.
And here is the resulting progress bar:

The other parts of this series can be found via the Cocoa page.
Aperture: Custom Keyboards Marked With Shortcuts
2007-03-01

LogicKeyboard is selling keyboards with keycaps designed specially for Aperture. They also have versions for many other pro applications. You can buy complete keyboards or key cap sets.
The Bagelturf site welcomes Donations of any size