Graphics and Imaging • 51:42
Aperture provides a revolutionary RAW-focused workflow to import, manage, edit, adjust, export, and archive your images more effectively and efficiently than ever before. Learn how to access Aperture's images and extensive metadata using export plug-ins. Extend the Aperture workflow to integrate images with your application or web service. See how Aperture provides access to all its metadata and allows you to send metadata back into its database, completing the workflow loop.
Speaker: Blake Seely
Unlisted on Apple Developer site
Transcript
This transcript has potential transcription errors. We are working on an improved version.
Welcome to Extending the Aperture Workflow. My name is Blake Seely. I'm one of the engineers on the Aperture team. And today we're going to talk about how to build export plug-ins for Aperture. So here are some of the high level things we're going to talk about. We'll talk about Aperture and how its work flow works, how it gets images from camera out to print and how your plug-ins can fit into that workflow. And we'll also obviously talk about what the specific features of the export API are and what you can build into your plug-in.
Here are some of the specifics. We're going to talk about the Aperture SDK. We'll actually build a small plug-in during the session so you can see what some of the features are, you can see how it works. We'll talk about how to provide your own custom UI in an export plug-in. And obviously, and most importantly, how to access Aperture's image data, how to get metadata out of Aperture, how to get thumbnails so you can show them to your user, and how to send metadata back into Aperture again so your plug-ins can be part of that workflow.
So how many of you are familiar with Aperture or Aperture users? Good. It's hard to demo an app like Aperture in one slide, so, you know, it's geared towards getting project management, raw images from camera, organizing them, editing them, sorting them, adjusting them and getting them out to print. It's heavy on project management, being able to search, sort, filter based on really extensive metadata.
Obviously it works with other formats, but raw is traditionally difficult to work with. So that's really where Aperture shines. I'm going to do a brief demo of Aperture and point out a few of the things that are going to be important to use plug-in developers. So let's switch to the demo machine.
So as you all probably know, this is the Aperture main window. Aperture is a non destructive editor, which means it always keeps the original master file on disk, never touches it, everything you see here is done in real time, if we bring up the adjustments,you know, we use core image and image IO and other OS features to do all the image manipulations in realtime as the user wants to see them.
If I put away the adjustment panel and bring up metadata, and it's grouped, but you can see some of the extensive metadata that Aperture provides on this right side. All of this information is searchable, sortable, filterable, you can build smart albums around it. And through the export API, your plug-ins have access to all of this, all the IPTC, all the exit information, everything Aperture can store.
And Aperture also provides something else that's really flexible for users, which is custom metadata, which is basically any key value pair you want. The user can type in anything they want. I mean, it could be, you know, something about the color and the image and then search for red, and there you go, you get that image.
And so what's great about this is not only is it incredibly flexible for users to be able to attach any key value pairs they want to images, but through the export API, you can read and write this information. So your plug-in can record really flexibly what it did to an image and actually store that back in Aperture's database.
So something else is key words, which, you know, key words, usually just a list of key words, just a list of strings that you can attach to images, but in Aperture, these are also hierarchical, which, again, provides incredible flexibility for users, so, you know, I can attach, you know, backyard to this image and search on backyard. But because it's hierarchical, I can also search on personal, and, you know, basically still get the same image.
Again, that's something that's really flexible, and not only can you read that information out of Aperture to see what the user's done and get all their information, but you can also write that information back into photos when your plug-in has done its thing, including the full hierarchy. And then the last thing we want to point out is, you know, versions and masters.
Again, a master file is everything that the user imported that's sitting on disk. Aperture never touches it. And everything you see on screen is a version. And that means I can change, I can change, I can duplicate versions, so let's say I wanted to do something, oops, not delete, I want to duplicate.
Now I can do something totally different with this image than I did with any other image. But there's still only one master file on disk. And that's really important during export because exporting a version, Aperture actually has to render that image data. And the export API is geared around that rendering process. There's no file on disk that you can just read and upload. Aperture actually has to build it for you.
So in normal export for Aperture, there's export version, and you can see there's, you know, different presets, different formats for how Aperture should actually render that data for the user. And you can change these presets, specify different sizes, different formats, everything. And the export API takes advantage of these presets to let you, as a developer, specify how users are allowed to export their versions.
And then there's also master export, which allows the user to take the original master file, again, with no changes, nothing done to it, exactly as it came out of the camera or exactly how it was imported and export it out of the application. That can be sometimes of limited use, but, you know, archiving, back-up, or if the user wants that original copy so that someone can compare against the version to see how much manipulation was done, they may want to do that. And again, the export API, you have access to export versions or masters and control what the user is allowed to do. So if we look at the export menu, everything below this divider, all of the installed plug-ins, if they're not installed, it will say no plug-ins installed.
Let's take a look at the FTP plug-in. So this is a plug-in that should slit the SDK. You can build it. It does standard FTP. You can put in your server path and it will upload versions along with whatever format or however you want to export those. You can also export masters. And obviously that menu goes away if you're going to export a master because there's no format to choose from. You're getting that original file and users can name the exported images however they wish.
Here is another plug-in that allows a user to export any number of images they want and build a Final Cut Pro movie out of them, including the format of the movie and the transitions that they want. And then they can go into Final Cut to do, you know, the really flexible editing there. And here's a plug-in we're actually going to build today. It's very simple. You put in different sizes of images you want. So let's say I want a 400 pixel image and I want a 500 pixel image, and let's say I want a 200.
And I also want the full size image. So let's put these on my desktop, and then the plug-in goes and actually generates each of the thumbnails you specified. So if I go out to the desktop, you'll see I got a full size image plus each of the ones I specified including the file name I specified. And if I open these in preview, you'll see we've got several different sizes. So very simple. All right, so that's the brief run through of Aperture and a little bit about what plug-ins can do. And let's go ahead and switch back to the slides.
So the key things from that are you have a lot of flexibility with custom metadata and key words because you can write them back into the Aperture database. Besides that, Aperture stores a ton of metadata. You have access to all of that through the export API. And there's a difference between versions and masters. And again, you have full control of that through the export API.
So specifically for the API, it's available in Aperture 1.5 and later. The SDK is available on Apple developer connection. We're actually going to build a plug-in, like I said, during this session. So if you want to download it now, you can. If you just go to developer.apple.com, click on Apple applications, click on Apple application downloads, and it should be in the list there. As far as how plug-ins are actually structured, there's standard Cocoa bundles. If you're not familiar with OS X or Cocoa bundles, they're just folders with a very specific code and folder hierarchy underneath them.
So as far as the user developer is concerned, they're just folders. But the finder will treat them as files and they'll have the Aperture plug-in icon. But Aperture plug-ins are also something just a little bit more called a pro plug. And that is an architecture that a lot of the proaps use to build plug-ins. For example, if you're familiar with FX plug that Final Cut Pro and Motion use, that's also a type of pro plug.
And there's only three things that are a little bit different about a pro plug And none of them will really affect you for Aperture plug-ins. So the first is an info.plist file. There are a few pro plug keys that are specific to Aperture and specific to pro plug. The documentation and the SDK describe them. The project template that comes at the SDK has almost everything you need in there, including documentation. So it shouldn't get in your way too much.
Then there's two protocols that are part of pro plug. The first allows you to put multiple plug-ins inside one bundle. So let's say you're going to ship a suite of export plug-ins. You can put them all in one bundle and they'll show up as several in the Aperture menu.
It's fully documented in the SDK. It's totally optional that you use it, so we're not going to cover it today. And then the last one, the last protocol is something that your plug-in will use at initialzation time. But the Xcode template includes all the codes you need for that.
And again, it's fully covered in the documentation, so we're not going to discuss it a whole lot today here either. But the last two things, the last two protocols you will care about, and those are the two most important, which are ApertureExportManager and ApertureExportPlugin And those are the ones we're going to really cover today because those are the ones you're going to use the most when you're building a plug-in. So let's switch to the demo machine.
I'll actually go into Xcode, and I'll show you what the basics of-- let me make sure we're logged off here. All right, so let's go into Xcode. And once you install the SDK, when you create a new project, you scroll down towards the bottom, there should be a section called standard Apple plug-ins, and you'll see Aperture Export Plug-in. So let's go ahead and create a new one.
So here's what the basic project that you get from the template looks like. You see we already have the required Aperture headers. It's created the base class for you. And we've got a basic nib and an info.plist file. So let's look at some of the things. The top of the info.plist file is more or less a standard Cocoa bundle info.plist file.
If you scroll down a little bit, you'll start to see some of the pro plugs specific keys, and again, some documentation telling you not to change certain ones because Aperture needs to use them. And there's really only two things in this file that when you're building a plug-in, you'll probably change.
The first is right here, the helpURL. If you put a URL there, Aperture will put a help button on your export window for you. And when the user clicks it, Aperture will launch that URL. This can be on your website, this can be a file URL, any valid URL will work. We don't have one for this session, so I'm just going to go ahead and delete that. And then Aperture will hide that help button for us.
And the next thing is where it says put a UUID here, including the comments also saying you need to put a universal unique ID here. And that's so Aperture can identify your plug-ins specifically. And building one of these is very easy. If you haven't done it before, we'll just go to terminal. And you're just going to type UUIDgen. And there's a unique ID for you. So all you have to do is copy that and paste it into your file. Those are really the only two things you'll want to change in your info.plist file. So I'll save that.
After you create a project, if you haven't done plug-in development before, there's two other things you'd probably want to do to make plug-in development very easy. The first is you'll notice the build and go button is disabled in Xcode. And that's because there is no executable. There's nothing to run in this project. There's no application. But we can actually fix that.
If you go to executables and right click, you can say add new custom executable, and what do we want to run? Well, we want to run Aperture. When we run our plug-in or when we click run in Xcode, we run around Aperture. So we can actually do that. Just say choose and just select Aperture.
Click finish. We don't need to change any specifics about how Aperture runs. Xcode will take care of most of it. So now if we click build and go, Aperture is what will run, which is exactly what we want. Aperture will-- when Aperture loads our plug-in code, we can separate points in there. We can debug write-in our plug-in running inside Aperture.
But that begs the question how does Aperture know to run the plug-in? How does Xcode tell it? And, you know, Aperture only looks in a couple specific places for your plug-in. It's in the library folders, application support Aperture. Obviously it's not going to look in our build folder.
So there's one more thing you can do, and that's when you build, you want to get Xcode, you want to get your project to put your plug-in in the correct spot. And there's a couple ways to do that. You can configure your build settings to do it for you.
I like to use a shell script that does the copying for me. So I actually have some of that code that I can just copy in. And if you want this code, it's actually included in the project attached to the session. But I just want to add new build phase, new run script build phase, and I'll paste in that code and tell you briefly what it's going to do here. So first of all, it's just a shell script that makes sure your Aperture plug-ins folder exists.
Then if we run this previously, it just cleans up any old versions of our plug-in. And then the last thing is if you're debugging, it puts a symbolic link from your build directory to the plug-ins folder. And if you are in release mode, it will just copy it over there for you.
And that's it. Now whenever we click build, Xcode will automatically copy or link our plug-in into the correct spot. And whenever we run, Xcode will run Aperture for us. So now we're pretty much ready to, you know, build and debug our plug-in, really easy, we don't have to worry about copying, we don't have to worry about running Aperture ourselves.
So let's go ahead and switch back to the slides. So that was the basics of getting started on a plug-in development. Make sure you install the SDK. It comes with an Xcode template, which is the best way to get started. One thing I didn't mention, but all the places in the code where you have to return something just to compile, they're marked with Xcode markers, which means when you hit control slash, those will be highlighted for you and you can just control slash through the file and add the return values just to get going. We'll actually show that in a bit.
And then the two things, the one thing you have to do just to get your Aperture to recognize your plug-in is make sure you add a UUID. If you get built, you put in the right spot, everything you can tell is great, but Aperture is just not seeing it, double check the UUID. Make sure that's there. And then just two tricks to make sure you can build and run directly from Xcode.
So as I mentioned, there's two protocols that you're going to care about in the API. The first is ApertureExportManager. As far as you're concerned as a plug-in developer, this is Aperture. When you're talking to this object, you're asking Aperture for information about the export. You want to know how many images are being exported. I want to get metadata for a certain image. I want to get thumbnails for a certain image. And whenever you want to add metadata back to the database, you talk to this object.
And then obviously the most important one is the ApertureExportPlugIn This is the class that you're going to implement, and this is important because this is where all your custom code is going to go. All the things that you do that make your plug-in unique are going to happen in this protocol that you're going to implement. It has methods for updating Aperture's progress panel so you can show the user where you're at and what you're doing. And it has all the methods that you need to provide the custom UI and make your plug-in look unique.
So speaking of which, what does a plug-in look like? So we saw this when we did the brief Aperture demo. This is the resizer. And you see there's some controls there that are obviously unique to this plug-in. And then there's a few controls that we saw in several plug-ins. Aperture provides this whole window for you, it provides the window object. But you can provide a custom view. And Aperture will put it in the window for you so you can provide all your own controls, they'll go in the top of the window.
And then there's a series of controls that Aperture provides, but your plug-in can turn them on and off depending on what it needs. There's a lot of functionality built into these, and we thought we can either provide some detailed API into specifically asking your plug-in for certain aspects. But you know what? It's just easier, all these controls are here, it will be easier for you as developers if we can just provide all of this for you and you tell us whether you want them or not.
So to get your custom UI in, there's one method to do it. It's called settingsView. You can return any NSView you want in this method. It can be an NSView that you create in code on the fly. It can be something you create in interface builder. It doesn't matter, any NSView, Aperture will go ahead and put it in the window for you, make sure the window is sized correctly.
There is one constraint, and there is a maximum size to that window, which is 1,100 pixels by 750. So keep that in mind when you're building your UI. It can't be just gigantic. If it is, Aperture will actually size it down for you. And that's where you just need to make sure that your sizing constraints are all set. That guarantees that if this changes or as Aperture does its thing behind the scenes, your plug-in will always look good. So just make sure it resizes well, pass it to custom view, and you're good to go with your custom UI.
Now, the controls that Aperture provides are a little different. So again, Aperture is going to give you all of these basics. And there's three main areas up here. The first is whether you will add export of masters or versions. These are very simple. There's two methods that control it.
And you just return yes or no and Aperture will do the right thing. So if you don't want to allow master export, return no to the top method there, allowsMasterExport. If you say no, Aperture will hide the radio buttons and consume the extra space for you. If you return no to both, Aperture will default to version, so you can't try and outsmart it.
Next is a version preset menu. Now, that one is a little more complicated of whether Aperture is going to show that or not. So obviously the master version methods will have a say in that. If you're going to export masters, that menu has no use, so Aperture will hide it for you.
But you actually, as a plug-in developer, like I said, have control over what shows up in this menu. So you can provide your own plug-in presets that will show up at the bottom of this menu. Aperture does that for you automatically if you include them in your plug-in.
Now, the bottom method here, if you say allowsOnlyPlugInPresets, and you return yes, then Aperture shows only your presets in that menu. And if you include only one preset in your plug-in, then the menu goes away all together. So to hide this, you either need to only export masters, which may not be what you want to do, or you need to do three things, which is include your own preset, include only one, and return yes to allowsOnlyPlugInPresets.
And we'll show that in case it isn't clear. And then the file name and controls is these last three fields. They all go together. And again, it's very simple. Aperture will ask you if you want the final naming controls. If you reply yes, it will show the controls to the user. If you reply no, it will hide all three fields, consume the extra space. So let's actually go in and implement the UI. Let's switch to the demo.
So still in the same project here. We'll build the UI. There's a couple ivars I know I'll need just to build what we saw earlier, so I'm just going to go ahead and add them now before we switch to interface builder. First is an array controller just to store the different sizes the user inputs. And then the second is that check box that allows the user to say yeah, I want a full size version of this as well or not.
And there's one other I'll need that's not for the UI, but I'm going to go ahead and put it in there now, which is where the user is actually going to save the files to. So let's open our nib. I'll drag in my header so we get all the extra outlets. So this is the default nib that comes with the project template. You can see we already have a custom view built in.
Very basic. You don't have to use this. You can use it. You can throw it all away. It doesn't matter, again, as long as you just provide a custom view. I'm going to go ahead and keep this for now. We already have an NS box in here as well. So let's open my library and put in the controls I need. Let's put in the array controller. I'll put in the table where the user is going to store all of their choices.
We have a size column, a suffix column. And the size column is going to be a number. And I'll just set the properties in that number now. We probably don't want them to have zero sized images, so we'll say 10 pixels is the minimum. We want buttons for them to be able to add and remove the values.
And we also wanted a check box that tells whether they want to include the full size version or not. So let me just size everything up now. So remember, one of the keys is making sure everything resizes correctly. So one of the first things I always do is just go in and set our resize controls so that as Aperture is shuffling window sizes and things behind the scenes, our view will always resize correctly.
We want the buttons to stay on the bottom right, the check box to stay on the bottom left, and that view and that view are already set correctly. So those are the basics of our UI. Let's go ahead and set up our outlets. So array controller, our button.
And then your class is already set up with outlets to provide the settings view. So we'll just hook that up. And then so that your view hooks into the tab order correctly, we also have first view, so let's hook that up to our table, assuming that will be the first one the user can tab to.
And then our last view, we'll make this button. And then I'll hook up these. So now the user can totally tab through our interface as well. And there's your UI. That's basically all we need to do to build a UI. I'm actually just going to save this in Interface Builder 3 format.
And now let's hook up our bindings, just so we don't have to write a whole lot of data storage codes. So there's our table view. Just hook it to arranged objects. We'll make this a thumbnail size, thumbnail suffix, hook this to the add of our array controller, hit the remove button to remove, and I think that's it. Let me make sure I set the selection so we can add and remove the correct ones. Save. And there's our UI.
So if I want to build a run this just to see how it looks, like I said, there's a few values, a few methods that require a return value. So just to build, there's a few things I'll have to fill out. And let's fill those out real quick. You can see there's a lot of code that's already here for you, all the basic initialization code releasing and retaining your nib objects, getting your settings view out of the nib, that's all there already for you.
WillBeActivated and willBeDeactivated, there's nothing special our plug-in needs to do at those times. But they be we get to some of the ones with the Xcode markers, again, so if I hit control slash, the next one will be highlighted for me. For now, we don't have any of our own presets, so we'll say no. Control slash. We don't allow master export. We do allow version export.
We do want file naming controls. These next three methods have to do with how Aperture will determine where to save the files, where shall we export them to. We just want the user to choose. So we'll say yes to wantsDestinationPathPromp. That means will Aperture give the user an open save dialogue.
If we didn't do that, then we would need to tell Aperture where those files go. And that's what the destinationPath method is for. Since we're going to ask the user, we don't need to return anything here. And when the user gets the open save dialogue, what's the default directory, we may want to save in between runs here so we leave them-- we start them where they left off.
But I'm just going to take the easy way out and just leave them in their home directory for now. So all the methods below here have to do with the actual export process, which we'll discuss in just a little bit, but I'm going to go ahead and fill in a few methods. The first just tells Aperture to begin the export process.
The next is Aperture asking us to confirm whether we should export certain images. Say yes. Whether it should write image data to disk for us. We'll say yes. And then the last two calls are for finishing the export process. Again, we'll just fill those in for now. And exportManagerShouldCancel in case the user clicks the cancel button. And then there's some progress methods, which we'll discuss in a bit as well. So we should have filled everything in. So we should be able to build and run Xcodable-- well, actually, I want to put this in debug mode, save.
So we've set up our project so our plug-in should end up in the right spot. Xcode knows to run Aperture for us. And there we go. And if we go to the export plug-ins area, you'll see there's the plug-in we just built. And there's our UI. And as we specified, we get the version presets and we get the file naming controls, but we don't get the master version radio buttons. All right, so let's switch back to the slides for just a moment.
So that was the basics of building the UI. It's very simple. You're just going to create your own custom view. Aperture will put that view in a window for you. Aperture provides several custom controls, but you can turn those on and off as you need. And you can optionally provide your own export presets.
So now let's actually go in and finish the rest of the export process, if we switch to the demo again, please. So let's get Aperture. Now let's talk about those actual export methods that I just ran through really quick. So the first one, you need to tell Aperture when it should actually start generating image data for you. Now, this isn't just a return value, because your plug-in may want to do initialization. It may need to do some network activity. So Aperture will tell your plug-in when it's ready to start.
You can go off and run callbacks, run something on another thread, do anything you want. You just have to call this shouldBeginExport method when you're ready to go. And that's when Aperture will start. We don't have any initialization, any checks we need to do here. So I'm just going to call shouldBeginExport directly. The next method is Aperture will confirm. Here's the path the user chose or here's the path that you gave me. Just so you can save it if you need to, which we will do.
The next two methods allow you to confirm whether you really want to export certain images or not. And why would this be useful? Because generating the image data can take time. And maybe your plug-in like iStockphoto or Geddy Images that require a lot of extra metadata for your images, maybe the images aren't appropriate size that the user selected. So you may indicate that to them, to the user, and say well, you filled out the correct information for five images out of the ten.
Do you want me to go ahead and export the rest? And this method allows your plug-in to say don't generate data for this image, do generate data for this image. If you're going to do that, make sure it's clear to the user what's going on. For this plug-in, we just reply yes to each one. We don't have any criteria where we wouldn't export an image for the user. And the next method just confirms your previous reply.
This next method, export manager should write image data to relative path for image at index. This is the heart of the API. So this is where Aperture has rendered an image for you, has put it in the NS data object and is giving it to do with as you wish.
And it's telling you here's the path that I will store this at. Now, you'll notice it says relativePath. In Aperture 15, this is just going to be a file name. But creating folders is part of Aperture's export process. So this may contain a relative path in the future. It may contain something that has directory names in it. So you should just be ready for that.
Now, if I return yes here, I'm basically telling Aperture go ahead and write this to disk at that path. If I return no, Aperture's assumption is it's done with that image data. It will not write it to disk. It's going to release it. So you're going to do all the handling you need to do, whether that's uploading it, writing it to your own location on disk, anything like that. For our plug-in, this is where we want to do most of our work. We have the image data. We want to call the CG methods and do all the resizing here. So I actually have code for that that I will paste in and just go through briefly.
So this is some fairly basic CG and CF code. We basically create an image source on that data and then walk through each of the entries the user made, get the thumbnail size, create a thumbnail, figure out what suffix they wanted to add and build the new file name and then write that new thumbnail to disk and then release all our objects. We also update the progress here. For progress Aperture, the code template builds a structure.
And you can update that structure whenever you want. Make sure, because of threading, in that some of these methods are going to run on separate threads, make sure you call lock progress and unlock progress every time you use the structure. But there's several fields. The first is just a message. And that's the text that Aperture will put in the window for you.
There is the value of a progress bar. You can set the total and the current value however you want or you can set it to indeterminant. And then the last thing is do we want Aperture to write this data to disk? Well, if the user clicked the check box, we do. If they didn't click the check box, we don't.
And that's it. If Aperture writes the data, there's nothing we need to do in the next method, which is Aperture just telling us that it did that. ExportManagerDidFinishExport. It means Aperture is done with all of the images. It's rendered data for every single image, and now it's time for your plug-in to do any other work it needs to do. For a lot of plug-ins, this is where the export code is going to be. This is where you're going to upload from, do any further image processing. For us, we can go ahead and tell Aperture that we're also done.
And then should cancel. Aperture will call this when the users click the cancel button or if there's been some sort of other error on Aperture's side, and it's similar. You can clean up, do whatever you want here, Aperture will leave the progress bar up until you tell it that you are also ready to cancel. And the unique thing about these two methods is as soon as you confirm that you're ready to finish or that you're ready to cancel.
Aperture will clean up on its side and release your plug-in. So especially for cancel, if you have anything running on any other run loops, if you have anything running on other threads, make sure those are cleaned up and totally finished here because Aperture is going to release you right away. And if those run loops or those threads are still calling back, they're going to call back to a released object. Your plug-in will crash. Aperture will crash.
So make sure you clean up before you call these, and then your plug-in goes away. So that's basically all of the logic needed for resizer. We should be able to build and go again. Let's select a few images here Let's just say we want 100 pixel small image. And let's export that.
Put it in a new folder. So we should just get three images. I will then initialize the progress so it's not going to change. But you saw some of the text pop up. So now if I switch-- so I included a full size, and then I got three small versions of each image. There's my 100 pixel version along with the full size version.
All right, so let's switch back to the slides. So that was just a real brief look at how do you actually import-- how do you actually implement the export process. A couple quick things to note. You're going to get a path from Aperture saying where it wants to store the disk, where it wants to store the image.
That may contain directories, so don't just assume it's going to be a file name all the time. When you tell Aperture that you're done or when you tell it that you're ready to cancel, make sure your callbacks are done. Make sure anything that you've got running in other threads is totally finished because you're going to be released as soon as you call those methods.
And one thing I didn't mention, but as you get image data back from Aperture, that could be many, many megabites of image data. Do not try and retain each of those as they come back. Keep them in memory and then do uploads from memory or anything like that. Try and work on image-- with image data one at a time. If you-- a good strategy is usually to write all the images to a temporary disk or temporary directory and then work with them one at a time after Aperture is done.
So the last thing that we haven't covered is how do you get metadata back into Aperture? I mean, that's really what makes this export API unique is its ability to not only be the end point, you know, I'm getting images out of Aperture, but to record what your plug-in did, to save information later both for the user or for the next run of your plug-in.
Maybe you get a unique ID or something from a service that you uploaded to and you want to save that so you can actually use that next time. Or maybe you're the FTP plug-in, you want to actually record the URL that the user uploaded to. So this is how you're going to become kind of part of the ongoing workflow, part of Aperture.
There's two things to note about putting metadata back in Aperture. First is as soon as you call the method to add the data, it will get applied to the image. It cannot be undone. Even if the user cancels halfway through an export, if you've applied metadata, it's already been applied. It doesn't get taken back off images.
So just make sure you're applying it after something has happened in your plug-in. When the plug-in comes up, don't settle their metadata and then assume that all your exports are going to go through successfully. Wait until something happens and then apply it. So real quick, let's just show how that works. Let's switch to the demo.
So I'll go back into our export. And this is an excellent example. This is fairly simple. But, you know, maybe we want to attach key words back to our images that say, you know, what sizes the user resized their images to using our plug-in. So I'll have some very brief code that does it. Again, three lines to add those key words. And right after we actually write the image, let's do that.
So as I mentioned earlier, not only can you just add a key word like resized to an image, but you can actually add the whole hierarchy. So you specify a hierarchy by putting the hierarchy in an array. So let's put the suffix that the user asked for, whatever it was, under apparent of resized. So that way, if they ever want to know what are all the images I resized, they can type in resized.
Or what are all the images that I attached small to? They can search for that as well. We'll put all those key words in an array, and then we just tell the export manager, we tell Aperture add these hierarchical key words to an image. So let's save that and build and run.
So if I'm looking for small images now, there's nothing in the database that has small in any key words, any metadata, any custom metadata, anything. But let's do another export. And we'll do a couple sizes. We'll do a 150. That's small. 300. That's medium. And then a full size. So let's export this. We'll put it in a new folder.
And you can see the key words tags just popped up on those images, which tells me that it's working. First let's go look. So we've got six images, which was what we expected, a small and a medium for each one. Now let's go back to Aperture. Now, if I look at our key words head, I'll see there's now a resized key word that has some children in it.
And these are from a previous run. So now we have these key words have been attached to some images. So if I search now for small, I get all three of those. If I search for resized, I also get all three. So again, this can be a really flexible way to attach what your plug-in did to certain images and allow the user to find those later. And let's go back to the slides, please.
So that was a very basic life cycle of building a plug-in and running it in Aperture. These are some of the tips and tricks. These are some things to watch out for as you're building your plug-ins. Some methods are going to be called on your plug-in in a secondary thread. They're all noted in the documentation. And I mentioned some things like locking the progress or surrounding those things with locks and making sure any threads or callbacks you start finish. Here are some other things to note. Don't try and create or modify UI in those methods.
Don't try and do KVO or bindings to any UI items while those methods are running on a separate thread. And again, finish your callbacks. Your plug-in is going to be released as soon as you tell Aperture you're done. The ApertureExportManager object is not bindings-enabled. So things like metadata, don't try and bind directly to that object. It builds those things on the fly for you. They're not necessarily cached there. So if you need to use bindings, cache them on your side, cache them in your plug-in and then use bindings to your UI, as long as you're running on the main thread.
Again, key words Custom Metadata, extremely useful and a great way to, you know, integrate your plug-in back into Aperture. They're going to be applied immediately and the user can't undo them. Your plug-in can't undo them. So apply them when something has happened. Don't retain a lot of thumbnails in metadata, especially if your plug-in needs to run through every single image that's being exported and look for something in the metadata.
Make sure you set up your own auto release pool and release those as you use them. Otherwise, you'll run out of memory pretty quick if the user decides to export 700 images. And then the last thing for plug-in development, if you haven't done it before, set up a Custom Executable, set up a shell script or change the build rule so that the plug-in gets put in the correct place.
So that was it, that was the basics of creating an Aperture export API. It's available in Aperture 15 and later. Plug-ins are basic Cocoa bundles, written Objective C, the API is an objective C. You have to install the software development kit. It comes with all the documentation you need. It comes with sample code. It comes with an Xcode plug-in.
Aperture has to render versions. There's a difference between versions and masters. That kind of shows in the API. So make sure you have an idea of what you want users to do. And you have full control over what formats and how users are allowed to export. And you can send data back to Aperture.
So if you want more information, here's some great resources. Again, I've got the URL to where you can get the SDK. You have to install it in order to build any of this stuff. If the graphics in media lab, me and several other Aperture team members will be there tomorrow from 2:00 to 6:00, if you have any specific questions, if you want to ask us or show us anything, or, you know, even if you just want to see some of the stuff again, drop by, grab one of us, we'll be happy to discuss it with you.
And a great resource is the Aperture dev mailing list. You can sign up at list.apple.com. Not only is there all kinds of people that have built plug-ins and done a lot of this stuff before, but, you know, engineers are also on that list, so we see what's going on.
It's a great place to ask questions, great place to get help. So if you're interested in plug-ins, sign up there. And then there's also a whole website dedicated to Aperture plug-ins. So if you're looking for a plug-in, if you want to see what's out there, if you want to see what other people are doing or if you want to ask questions on those forums, go to aperturepluggedin.com.