Media • 1:08:03
Image Kit provides Cocoa developers with a straightforward interface for common image handling tasks. Discover how easily you can equip your application with image capture, browsing, viewing, import, adjustment and presentation, all within a crisp and consistent user experience. Learn how to apply image processing filters for lightweight image editing, how to capture images from the camera and how to assemble an enhanced image browser. An important technology for Cocoa developers who want to handle photos and other media in their Mac OS X applications.
Speakers: Werner Neubrand, Thomas Goossens, Baskaran Subramaniam
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.
Hello and welcome to this year's Image Kit session. This session is called actually Image Capture, Manipulation, and Display with Image Kit. And in a bit you'll see why. I'm Werner Neubrand and I'm part of the Graphics and Imaging group. Image Kit. Image Kit was a new framework that we introduced with Mac OS X Leopard.
It's actually dealing with images. So it's a framework, part of Quartz frameworks of the umbrella. Frameworks lives at the same place where PDFKit lives and deals with images. It has several components and the most adopted, most used is really the image browser view. The image browser view is a highly optimized view that deals with a large number of images and displays those in a grid view. It's optimized because it's very fast. It's optimized because it takes very little memory. So, internal caching, nice rendering, fast display. brings up your thumbnails, your images on the screen, and you can have subtitles and more.
The next component of Image Kit is the picture taker. You all see the picture taker if you have a laptop, a MacBook, MacBook Pro, and you install it in your system. Because then the setup assistant at the end will allow you to take a picture, If you use Address Book, you will see it. iChat is adopting that. So it's a common UI that works with the built-in iSight or attached iSight, as you will see in a bit. And yeah, nice way to get images from your iSight into your application.
The next component is the image view. Again, you could use like an NS image view, but we try to do a few things in the IK image view that NS image view does not handle directly or not handle the same way. For example, we do take care automatically of embedded EXIF information to correctly rotate an image when you load that.
We do take care of like non-square pixels, so if you have a resolution, different DPIs for width and height. And we also try to work with very large images by using a sub-sampling algorithm to initially bring up the images very quickly and then load the image in higher resolution after the initial display is up.
Next component is the Image Edit Panel. The Image Edit Panel allows you, for example, to work directly with an IK image view, to display a set of CI filters and manipulate those and you will see the result in the image view. It also has a tab where you basically bring up separate previews of thumbnails where a filter is already applied and you can just choose the one that you want to apply to your main image. And lastly, it has an information pane, an information tab where you get some metadata, including very nice representation of GPS metadata directly from the image that you may have in the main display.
The next component is the slideshow. Again, a kind of easy way to display images full screen with nice transitions, index mode. And, for example, if you have iPhoto installed, it allows you to export individual images directly to your iPhoto application. So last year, for the Image Kit session, we were facing an iPhoto coding challenge.
Which means, in that session, we tried to create an application in several steps that would kind of cover the functionality of an iPhoto application. Which means, you would be able to browse images. Obviously, this is the IK image browser view. We would be able to import, through the image picker, import images from an eyesight. We want to view a selected image in a large image view.
We want to edit it. We want to save it. By the way, that's another component of the Image Kit framework, an attach or like an add-on to the save panel to have a kind of common UI to select various options for different file formats. And at the end we want to present the result in the slideshow. So the idea was to have an iPhoto application in six easy steps. And actually I want to show you that application because we will continue with that application and enhance that during this session.
So this is the application up and running. You see we have the image browser view. And very nicely I can resize and you see it's really fast. "Resize and when I let loose on the mouse button then it fetches the full resolution of the image. So I can select an image here, zoom in and it's very fast." So the image browser view allows you also to reorder, and it does that with very nice animations.
So I can select three, move them here, see very nicely, reorder. Or for example, I could select multiple ones and get rid of those. So now we have only images up. Then, in this application, we want to make use of the eyesight. So we bring up the image picker view.
We will see that. Go in and add an effect to it. And set it and we'll see it's important. Now, when a selection changes in the image browser view, we want to display it in the main image view. Well, let's do that. Let's see. We can do that very easily.
And if we select one image, double click on it, then we get the image edit panel. Where we can adjust, for example, convert it to a sepia or a white image. We can select different effects. And we can get some details, so for example, the X and Y dimension, we get the orientation, whether it's rotated, what software created and so on.
and you see the title of that image is Golden Palace JPEG. So it's a JPEG image, but we want to save it as, for example, as a TIFF file. It's very easy to do because we bring up our kind of common UI, select TIFF, and then we could specify, for example, for the compression. We could save it as GIF, while no options there. JPEG, we can specify the quality. So let's go ahead and actually save it as a TIFF file.
And it already exists, so let's replace it. And what should happen is, well, we just got a new TIP file. So the next step, very quickly going through that application, is presenting it. So we have the slideshow mode where we would just go I'm on play mode. Oh, I'm on the last image, so let's pick-- "I can go to the next one or in play I can transition to the next image and go through all the images." So that's the application. And let's quickly look at the code for this. So we don't want to go through everything, but just look at the main classes.
We do have a controller, and the controller has a reference to an image browser view and an image view. And all our images are kept in a mutable array. The images. Now the controller acts as an image browser data source. So the concept is very simple. It's very similar actually to NS table view. So you have a data source and as data source you have to tell the object, the image browser view, how many items do I have and give me item at index.
So in our case, it's very simple. Our image array is just an array of items. And the number of items that we want to display on that image browser view was just the count of that array. And if we want to get it to an item at a given index, it's very simple because it's in a mutable array. It's just objected index.
What's different from like a regular table view data source is we are not returning the item, the object to display directly. We return an item that has to implement a couple of methods. And the couple of methods are those that are in the item data source protocol. So we need a representation and that could be one of many. It could be a path, it could be URL, it could be an NS image, it could be a Yeah, a lot of things. And we need a unique ID.
Because internally, the image browser view tries to optimize the reloading, refetching. If you return an ID and you modify the image, then you have to somehow update that ID. Otherwise, the browser view would not try to refetch the data. And then, optionally, we would have a title, because we want to display the title there.
So to set up the browser, all we do is we create initially our image array. And we add images from a given directory. Whenever you install Mac OS X system, then you will get a couple of images as desktop pictures, and that's basically what we are pointing to. So it's very simple.
In the add images from directory, so we get in, get passed in a path to a directory. And we get the content at this path. That gives us an array with file names that are within that directory. And all we have to do is take the given path, append that individual file name to it, and add the image to our array.
Look at that, very quickly. It's very simple. All we do is basically we filter out everything that starts with a dot. So .ds store or something like that is treated as a hidden file, and we don't want to add that. Other than that, all we do is we create an image object.
Set the path, add that image object to the images and We have that wrapped in "will change" and "did change" value for key to be binding friendly. Actually, you can download the code for these six steps and you will be surprised how little code it actually is because a lot of things are done through bindings. So it's actually very easy to use.
So that was this step. And now if you can get back to the presentation. So we had the iPhoto in six easy steps. We got a couple of requests after last year's WWDC. And a lot of people were asking, well, it's great to have this image browser view, but I want to have on the images, I want to have something custom. I would have a label. Or I don't like the background, because the background in my application is completely different. So how can I customize that? So that was really number one request.
And the other request was like, I have another device. I don't have an eyesight. I want to get images from a camera, from a scanner. So what we're doing this year, we're beefing up our application, add two more steps. And the first one would be the customization of the image browser. And for that, I'm asking Thomas to come up on stage. He will tell you everything about the image problem.
So the image browser was introduced on Leopard. So for this presentation, I will just start with a quick overview to just describe what the image browser is. And then I will spend more time on the new APIs related to Snow Leopard, and especially on the new customization APIs. So let's start with a quick overview. So here is the image browser. So this is a view. And its class name is IK Image Browser View. And you can use this view to display and to browse large amount of images.
So typically this view lays out images in a grid and users can scroll or zoom in, zoom out to browse the content. Also this view comes with a set of features that you will have for free like the graphical selection, type select, reordering, drag and drop, animations, all those kind of things. You can find some examples of use of this view on several applications on the system, like in the Finder, Image Capture, Preview, the iLife Media Browser, etc. and in some third-party applications as well.
And you can use this view to browse images, so typically any kind of image format supported by Image I/O. You can also browse movies, and for movies you can even play the movies directly in the image browser view, which is very practical. You can browse PDFs and in fact you can browse any kind of document thanks to Quick Look.
So you can browse any kind of document natively supported by Quick Look, like HTML pages, contacts, notes or whatever. But also, if you write your own Quick Look plugin for your own document, then you can use the IK Image Browser View to browse your own document in your application.
And then how it works. So here, just to give you the basis, as Werner said, the image browser uses the same data source mechanism as the NS TableView or NS OutlineView. So concretely, you implement a data source, and its role is to provide the images to the image browser when the image browser requests them.
Your data source can provide the images using file paths, URL, NS images, CG image ref, bitmaps, NSData as icon refs. So there's a lot of different ways to provide the images. And then the image browser takes care of calculating the thumbnails from your images and draws them at the correct location in the view.
The image browser was designed to support very large datasets. It supports hundreds of thousands of images. It is entirely rendered using the GPU to offer a very smooth scrolling and zooming experience. And another important aspect of Image Kit is that the image browser manages its own cache by keeping the last presently used images on the GPU and automatically discard the others to never exceed a given memory limit. So you don't have to write any code to keep the memory allocation constant. The only thing you have to do is to not cache any image on your side. Just compute if needed and return the images you want to display when the image browser requests them.
So that's for the quick overview. Now we'll have to talk about what's new on Snow Leopard. And the first request of developers was to be able to customize the appearance of the view so that it looks more consistent with the application. So we added new APIs in Snow Leopard that allows you to control the rendering, the layout and the rendering. And I will talk about this in a little bit.
Also, some other miscellaneous stuffs like drop-on items. On Leopard, it was possible to drop something between two cells or on the whole view. Now it's also possible to drop something on a given cell. Like in the Finder, for instance, when you drop a file in a folder or on an application, now you can do the same thing with the IK Image Brother view.
Also, Image Kit now provides an additional image representation, that is, a PDF page representation. And this lets you feed the image browser with PDF pages you get from PDF Kit or CG/PDF Document Ref. So now let's focus on the customization. And usually you customize the appearance in two steps. First, you customize the appearance of the view itself. And then you customize the appearance of the cells. So let's see the first step.
So on Snow Leopard you can now use the methods of IK Image Browser View to change the appearance of the background, add some overlays, change the margins between cells, And you can still, of course, change the size of the cells, the decoration of the cells, like if you want to toggle on/off the shadows, the outline, the title or subtitles. And you can change the common font that is shared by all the cells to draw the title or subtitles.
So let's go more into details for the three first ones. So here are three new accessories on Snow Leopard. The first one allows you to change the margin between cells. The second one and third one allows you to change the appearance of the background and to add some overlays.
And here in set foreground layer, the first segment of set foreground layer and set background layer is a layer. So that means you can set any kind of layer here to change the appearance of the background or the overlays. So it can be a movie layer or a cross composition layer. It can be even a custom layer that you render using the AppKit or Core Graphics.
It can be an image embedded into a layer or whatever. And also it's not only limited to one layer, but it can be a complete layer tree. So layers with sub layers. And to finish, you can also add animations to your layers if you want your background to animate, for instance.
So the next slide shows an example of over-customized image browser view. So in this example, there is a quad composition in the background. And so it's a quad composition embedded into an layer. And in the foreground, there is another layer that embeds another course composition that draws the curtains.
So this example is probably unusable, but it illustrates quite well the fact you can do really what you want for the background and the foreground, including animations, transparency, and media like course compositions. So now we can really customize the background and the overlays of the view. And then we may want to change the appearance of the cells. So that's the second step of the customization. And here we introduce in Image Kit the concept of cell.
A cell for the image browser is represented by the IK ImageBrowserCell class. An IK ImageBrowserCell is quite similar to an NSCell in the way it handles all drawing operations for your cell. However, the way it renders things is very different than NSCell. The ImageBrowser renders everything using the GPU, so it's not possible for you to add some drawing code based on Core Graphics or the AppKit to draw the things you want. So instead of overriding your draw method where you will draw everything using the AppKit, instead of that, your custom cell provides layers.
Layers have several advantages in comparison to the traditional NSL approach. First, layers are rendered using the GPU, which is much better on a performance point of view. Then you can associate animations to layers, which is more practical if you want to animate something. It is really easy to embed medias like movies or cross compositions in your layers. And to finish, you can still use the App Kit or Core Graphics to do everything you want in your custom layer. So you still have the convenience and flexibility of high-level APIs like the App Kit, but you also take benefit of the GPU.
Now let's see how to implement a custom cell. So here, our API is quite close to the NS Collection View API. So the first thing you have to do is to override-- is to a subclass, sorry, the IK ImageBrowserView and implement the method newCellForRepresentedEtem. And this is where you return a new instance of your custom cell. And your custom cell must be a subclass of IK ImageBrowserCell, of the IK ImageBrowserCell class. And so by doing this, the image browser will use the instance of your custom class to represent graphically the data source item and item.
So now we have our custom cell in place, let's see how we can impact the appearance. So here is the default appearance of a cell in the IK Metros overview. And the cell is in fact made of several components. There is the thumbnail, a cell of course has a thumbnail. A cell can have a selection, a title, and a subtitle.
And the first thing we can do to modify the appearance of a cell is to modify the layout of those components. So here is a schematic view of the same cell that shows each frame of each component. So the image frame is the frame where the image will be drawn, the selection frame is the frame of the selection, the title frame is the frame of the title, and so on.
And if we look at the header of IK ImageBrowserCell, all those frames are defined by the method here. And Accept Frame, which defines the whole frame of the cell that includes all the other frames. You can override any of these methods here. So Image Container Frame is the frame that will contain the thumbnail. Image Alignment is how the thumbnail is aligned in the container. Image Frame is the frame calculated from the Image Container Frame that takes into account the aspect ratio of the thumbnail plus the image alignment. the selection from the from the selection, et cetera.
And so by just overriding some of these methods, we can easily turn this to look into this. And so having our cell to finally looks like this in the image browser view. So that's how to modify the layout. Now you may want to change how the cells render itself. So again, here is the appearance of a cell. And you can imagine the fact that a cell is made of several layers that can be decomposed like this.
So a cell has a background layer that is empty by default, so it just draws nothing. It has a selection layer that is drawn only when the cell is selected. It has a placeholder layer which is drawn only when the thumbnail is not calculated yet. There is a thumbnail, of course, a title and a subtitle, and the foreground layer that is empty by default.
And so now on Snow Leopard, you can replace any of these layers. You can change the appearance of the background, the selection, the placeholder, and the foreground layer. And to do this, You have to implement in your custom cell the method LayerForType. And this is where you return the layer or layer tree you want for a given type. So for instance, if you want to change the appearance of the placeholder, implement LayerForType in your custom cell. And when the type is IK ImageBrowserCellPlaceholderLayer, return the layer you want.
So for instance, if I do this, if I return a white wounded square when the type is a background layer, this will change the appearance of my background layer to look like this. Same thing if I return a slightly transparent pink and wounded layer for the selection, it will change the appearance of my selection like this.
Then I can also embed an image in a layer. If I want to add a kind of glossy overlay to my cell, I can return a layer that embeds a kind of glossy image. This will modify the foreground layer to look like this. And to finish, we can still use the methods of the IK Image Browser view to change the font size and the font color of the title and the subtitle. And so by doing all of these changes, our cell finally looks like this.
and when it's not selected to look like this. So in Snow Leopard, now you have methods to change the appearance of the background and the foreground of the view, to re-change the layout and the rendering of the cells. And so you can, as an example, change the appearance of the default appearance here to look into something like this. And this is what I'm going to illustrate now with the demo application. Can we switch to the demo machine, please? OK.
So first, I start with the end of the step six we made last year. So last year, the last step of our applications was that. And now we want to change the appearance of the image browser a little bit. And the first step, the first thing I will do, is change the appearance of the background. And let's say I want to draw an image in the background instead of a flat white color. And so what I have to do is to first fix the typo here.
And then I have to use the method setBackgroundLayer of the IK image browser view. And this is where I set a layer. And my layer is allocated here. - So it's a custom layer. It's class is ImageBrowserBackgroundLayer. So I locate an instance here and I set the background layer here. And if we look at the interface of ImageBrowserBackgroundLayer, An image browser background layer here is just a subclass of a CA layer because it's a custom layer.
And its implementation is very easy. So I just override drawing context. This is the usual way to implement a custom layer. And this is where I will draw an image, typically an image that looks like this. So there is an image in my project. I load that image and I draw it several times using the, here I use Core Graphics, but you could use the AppKit. So I get the width of my image, the height of my image, and I draw it several times in my layer so that it fills my layer.
So now if I run the same application again, now the background of my view looks like this. The view of course is still functional. Can still zoom in, zoom out. But as you can see, now the titles are not really readable anymore, so I want to change the appearance of the cells.
So this is what I call the second step of the customization. And as I said, the first thing you have to do is to subclass the IK image browser view. Here my subclass is image browser view. And you have to implement the method new cell for represented item.
And this is where you return a new instance of your custom cell. In here, my custom cell is an image browser cell. So if we look at the interface of image browser cell, An image browser cell is simply a subclass of IK image browser cell. And if we look at the implementation, I implement layer for type. And in this example, I return custom layers for any type because I customize a placeholder layer here, the foreground layer here, the selection layer.
and the background layer. So let's see just one, which is the foreground layer, for instance. In my project, I also have two other images, which is a kind of-- it's not visible, but it's a kind of glossy overlay. So there is also a pin image here. And then what I want to do is to add a glossy overlay plus a pin image as another overlay to my cell.
So what I have to do here is to allocate a first layer and then allocate two other layers that I, and I add those two other layers as the sub layers of my first layer. So here is my first layer. I create a glossy layer here where I set an image as a content of my glossy layer. And I add my glossy layer as a sub layer of the main layer. And same thing for the pin image.
I allocate a new layer, set the content, set a pin image as the content of the pin layer. And finally, add the pin layer as a sub layer of my main layer. So my main layer here has two sub layers, which are a glossy image and a pin image.
And if I run it again now, My custom cell looks like this, so it's really completely different. The selection is different as well because it's another custom layer. And the view is of course still functional. You can still reorder things or search for images, etc. Everything is still functional.
Okay, so that's for demo. Can we switch back to the slides? And I directly pass back to Werner to the rest of the presentation. Thank you. Now that we saw it's very simple to customize the image browser view, let's go back to our request number two, and that was really importing the images.
As we saw, we can do that with the eyesight, but actually there are more devices out there, like cameras or iPhones and scanners. What about these devices? How do we get images from there into our image browser view into our application? Well, we have and had that for a long time, the Image Capture Framework. Image Capture Framework is part of the Carbon Framework. It has a C API.
And it was redesigned to do synchronous and asynchronous calls. It's kind of bad that you have to know about this synchronous/asynchronous behavior, because ideally you would just use it and have a simple way to go to the images from a scanner or camera. So a lot of people were struggling with the API. And so we said for Snow Leopard, we actually want to do something new. We want to have a new framework, Image Capture Core. And we pass over to Baskaran to introduce this new framework.
Image Capture Core is a new framework for Snow Leopard and It's the foundation for applications that use cameras and scanners. And it is buzzword compliant. It's 100% pure Cocoa, 64-bit, garbage collected. And it is Cocoa bindings friendly. makes it easy to create UI using Interface Builder and bind directly to the objects from this framework.
And it uses delegation to manage asynchronous communication with devices. I want to emphasize this aspect of communicating with devices. Cameras and scanners can be slow to respond and maybe busy, maybe in a state that you need to recover from before it can respond to your request. So trying to communicate with them in a synchronous way is not a good way of doing it because it can block your application until the device responds.
And, um, For example, let's say that you want to download a large file from the camera. And if you call it synchronously, the download call will return only after the entire download completes, which you may not want to do. You may want to issue a request to download and then be notified later when the download is complete.
The other situation is that devices may have some state information that it may want to report to that application that you have. For example, when you try to scan from a scanner, it may want to report to you that there is no document to scan in the feeder.
And to handle that, you need some kind of a delegation mechanism, and that's what we have in this framework. All requests to the devices are handled asynchronously, and you handle the responses back using delegate methods. The main components in the Image Capture Core framework There are two main components.
One is the device browser that allows you to browse for image capture devices. And you can browse for cameras and scanners. And in this case, when you browse for cameras, it will deliver you a camera if it finds one. Or you can just browse for scanners and then you'll find only the scanners.
Or you can browse for both. And the browser is represented by the IC device browser class. Since you need delegation, you need to have a delegate assigned to each of the classes in the image capture core. And we use properties, Objective-C2 properties, throughout our framework so it is easy to write your code.
You assign a delegate, and then-- You actually first create it and then assign it to Legit. And then you can use one of these three methods to start browsing. You can browse for all of them or just for cameras or for scanners. Then when you have found what you want, you can stop browsing.
And the delegate methods that you need to implement in your delegate in order to receive the devices reported by the browser or if the devices are removed, they are here. So did add device will tell you when there is a device and did remove device will report to you if the device has been turned off.
Okay, let's look at the device. The IC device is an abstract base class representation of a device, a camera or a scanner. And the camera device and scanner device both share several properties that are represented in the base class. For example, the type tells you whether it's a camera or a scanner, the name of the device, an icon representation for the device, and whether there is a session open on the device or not. And also you can request to open a session on the device or to close a session. The camera device has some additional properties. For example, the contents of the camera. That contents property will give you a hierarchical representation of the folders and files.
[Transcript missing]
The device and the camera device both have some delegate methods that you need to implement if you are going to use them. For example, you may want to know when the device is removed. So you definitely want to implement that did remove device. And also when you open a session, when the session open is complete, you will be called back with a did open session. And when the device is ready, you will be called with that device to become ready.
And that call will come to you for camera device when the framework has completely cataloged the contents of the camera. For the scanner, when it has identified all the functional units on the scanner. And in addition for a camera device, if you are taking a picture in a tethered mode, you'll be called with the add item any time a picture arrives. And if you delete, you'll be notified about that as well. Let's look at the demo.
This demo is available download for you to look at. There is very little code written in this. Most of what you see is done using Cocoa bindings. And I'm going to show you the little piece of code that I have here. When the application launches, I'm creating an instance of the device browser. I started out as a developer, signing myself as a delegate, and started browsing for cameras.
The browser finds a device. It's going to call-- With this did add device delegate method, and at that point what I'm doing is checking to see if it's a camera device and then assigning to my instance variable, which is an array. I'm adding the device. And if the device is removed, I'm doing the reverse of that. That's about all the code I have here. And let me just show... I just turned on the other camera. So I have two devices. One is a card reader, another is a camera. And let me select that.
So I open the session and then when it finds the contents and the camera contents are available, the bindings automatically populate the content in that table view. So all the columns in the table view are bound to properties of the camera device and it's automatically populated. There is no line of code written in the application itself to do that. And for example, if I now take a picture, get added.
and I believe you can delete them as well. So let me just quickly look at-- Let's quickly look at the binding here. So I have a camera array, which is an instance variable of my project here, the class in the controller class. And I am getting the camera's controller for that array and getting the icon property, which is the property of the device, IC device.
And of course, it is a CG image ref, so I have a little transformer that transforms CG image ref into NS image so that it can be directly rendered here. And then I'm getting the name directly from the device. And then this is another array, which is a media files array controller. And I'm getting the name of the, the thumbnail of the object, name, name.
And width, height, and so on. So these are all directly bound. There's no line of code in the sources. And in fact, even-- These are directly bound. So I'm sending, not that one, this one is directly bound. I'm sending a request take picture, which is part of the method in the camera device. Okay. Let's go back to the slides.
I'll just quickly go over the scanner side of it. We have a scanner device, which is a subclass of an IC device. The scanners have different functional units like a flatbed or a document feeder or a transparency unit. So the scanner device class has properties that tells you about available functional units.
And the selected functional unit. By default, one of the units is selected by the device module, which is actually communicating the device, and that's the one that is going to be shown here as a selected one. And then you can transfer your scans using either files or in memory that you can set in the transfer mode. And if you're transferring to your file system, then you would set your downloads directory using that property. Then you can switch between different functional units using the request select functional unit.
And to do the overview scan, you can do request overview scan, and you can do the scan using the request scan. If you notice, all the methods have a request prefix. It is just to make clear that none of them are going to be acting synchronously. Everything requires a delegate method when it is done. You need to have a delegate method in your class to be notified when the request is completed.
Let's look at the functional units here. That's the main part of the scanner. The functional unit has several properties that are common, whether it is a flatbed transparency or a document feeder. The first one is a type and supported bit depths and the current bit depth, supported resolutions, the current resolution, the area which will be scanned, and then an overview image that when you do an overview scan, that image will be updated. As the scanner sends the overview data.
And the flatbed unit has, in addition, a physical size that tells you the platen size. And the same is true for the transparency unit. In addition, transparency unit also tells you what film types it supports and also the current film type that it is set to use. And for the document feeder, it can, document feeder may be able to scan different sizes of documents. That is reported to you on the supported site. and size tells us the current size.
And the scanner device delegate protocol, this is the device delegate, if you, your device delegate for the scanner need to implement these methods in order to successfully interact with the scanner. And when you select a functional unit, you would get called back and select functional unit when it is done. And when you scan to a file, then you will be reported about the location of the file using the DIT scan to URL, or if you scan to memory, then it will be returned in the data as an NSData. Let's quickly look at the demo of this.
When the application launches, I do exactly what I did in the camera. I create a browser, set a delegate for it, and then here I start browsing for scanners. And I'm going to show you the rest of the thing. The code here is almost the same as in the camera, but I'm going to show you something in the nib file where The overview scan is directly bound to the overview image property. I mean, the NSImage view is directly bound to the overview image property of the functional unit. And this progress indicator is bound to the scan progress percent done property of the functional unit.
And you'll see that without writing a single line of code, you can do an overview scan and get the progress indicator at the same time. So here's a scanner. I'm going to open a session. This scanner only has a flatbed. This area is blank, left as an exercise for you to fill in. And now I'm going to do an overview.
I think the scanner needs to warm up. Okay. This you get for free by using Cocoa Binding. And when I do a scan, let me just show you where the code that's called when I click on the scan button. When I do a start scan, I get the scanner from my controller. I'm getting the functional unit of the scanner. And then I am checking to see for what type of scanner it is because I want to do something different depending upon the type of, I mean, what type of functional unit it is.
If it is not a document feeder, I want to scan a specific area. So I'm setting its measurement unit to inches. And if it is a flatbed, I want to scan the whole Physical size. I'm taking the size and then setting the scan area to be the full platen size.
And then I'm setting the resolution to be picking up from the supported resolutions, a resolution that is greater than or equal to 100, 100 dpi, and setting that as a current resolution. And setting the bit depth, pixel data type as RGB. It's file based. I want to transfer to my pictures folder. And the document name, scan, as the name of the document. I want it as a JPEG data. So when I do the scan, it will scan and save it in my pictures folder as scan.jpg.
It actually automatically renamed it as Scan 1 because there was a name conflict. So that's the scan. It just completed. I guess that completes the introduction to the Image Capture Core. Werner will take over from me and show some work. Well, thanks a lot for that. And I guess everyone who had to use the old image capture framework will really appreciate the new Objective-C based one.
It's very, very easy to use. So now the question is, what can we do in Image Kit to use the image capture core framework? Well, what you want to do is introduce a couple of classes, new classes, that make it even easier for you to use scanner support and camera support.
If we look at the main classes of the image capture core framework, we have the device browser and the main devices, the scanner and camera. And what we want to do inside Image Kit is we want to have view classes for those. If we look at the first one for the device browsing, We have an IK device browser view that goes nicely with an IC device browser.
and it's used for browsing devices. Well, it allows for customization. For example, you could specify very easily, I want to display, look only for cameras, only for scanners, do it only for local devices or network shared devices. And it comes in a couple of UI flavors. For example, you could say I want to have a table view, an icon view, which is of course an IK image browser view. And the nice thing overall is we do have an interface builder plug-in. So all you do is an interface builder, drag it over and you can directly use it.
The class itself has a delegate and the delegate gets called whenever a selection changes or when a device reports an error. You can have a couple of booleans as properties that you can specify what to look for. If you want to do it in code, you could do that, or as I said before, you could directly do it in interface building.
Then the display mode you can specify and you can always query for the current selected device. For the camera, we have the iK Camera Device View that works together with an iC Camera Device. And again, we have a couple of UI flavors. Now, we have a list view and we do a couple of things that you do not get immediately free by just using the bindings. For example, we do auto rotate the icon.
So depending on the EXIF information that you will have on the image, you will rotate it correctly. And we also try to interpret a couple of the metadata. For example, internally, a flash property in EXIF would be one of the values 1 up to 15, indicating the flash fired, it did not fire, it did fire in automatic mode, it did fire so and so. So we put that into like a human readable string and display that. And in the icon view, we again use an IK Image browser view where you can select the images to download and all these things.
You can customize it by specifying a couple of properties. For example, you could have a download folder pop up. and the Post Processing App, Popup. Another thing that could be useful to customize is, for example, if you're writing an application like Preview. Preview has currently an import image menu item and it brings up the old common UI. And there, if you do not want to have the download on the button label, but maybe import or import all. And again, the nice thing, all this can be done by just using an interface builder palette.
If you want to do it in code, yes, you can do it. It's very simple. You need, again, a delegate and the camera device. The camera device could also be set directly from the device browser view. We have the different display modes, the label for downloading, and a couple of downloads related, like whether to display or hide different pop-ups.
And a couple of can-dos that would allow you to, for example, have a toolbar that would rotate left, rotate right. And because these are some of the actions that we do have for the device view. We can delete the selected items, you can download all or just the selected ones.
Then you get notified by just querying or binding to the selected indexes. And you have a couple of delegate methods. For example, when you did download an image, From the camera, then you get notified, oh, this one is downloaded to this URL. Or if you specify as transfer mode, do it in memory, then you will get past the NSData.
Usually, getting the images in memory is not always a good idea because the images are getting larger and larger, SD cards larger. So if the user on an 18 gigabyte or 64 gigabyte flash card or an iPod, you would download all the images. You don't want to do that in memory.
Let me do a quick demo. And actually, this demo is a demo without writing any code. Because all we want to do-- is just fire up Interface Builder, create an empty window, And if we display the library, then you will notice we have a device browser view. I can just drag over.
I use a camera view, just right next to it. Then all I have to do is make the delegate of the device browser view, make that the camera view. Then hit run. Then I should be able to just-- Select this and without writing any code, you get full functionality. So you can switch between the two.
You see, for example, we have the shutter speed in a kind of human readable form, not in whatever, 0.025 or whatever. We get the maker model ISO, as I mentioned before, the flash information and all that. To that, it does a lot of things through bindings, like the number of selected items, all that is done internally through bindings and automatically. And I could download all or download the selected ones. So this is without writing any line of code. We can go back to the slides.
Now, what do we have for scanners? Well, obviously an IK scanner device view that works with an IC scanner device. Here again, we do have a couple of UI flavors. Well, we do have a simple mode. This is pretty new because in the past, image capture as application did not have a simple way to do a scan. Because there you always have an advanced mode where you have to have a lot of pop-ups, a lot of edit fields, you have to specify a lot and the download for the post-processing application, the resolution and all that.
And here again we want to do some customization, so give you the option, for example, to show or hide the download destination or the post-processing application. So they may go away or show up. Overall, that view is really highly dynamic, so depending on the scanner that you connect, you may get a slightly different UI.
For example, if a scanner supports multiple resolution in a range, let's say from 50 dpi through 4800 dpi, then we would very likely display that in a combo box. There are scanners out there that have only a fixed resolution or only a fixed set of resolutions. That could be a very small number, like 50, 70, 100, 150, and 300, so a couple of values only. In that case, you would have a pop-up. There are scanners that do not support scaling, so then the scaling and the new size thing, they would just not show up.
And for customization, the next thing would be really we could have, again, relabeling the scan, the overview and scan things. And here again we have an interface builder plugin to do that. If you want to do it in code, what you need for the device view is again a delegate and scanner device.
You specify the display mode, the label. You have to implement a couple of callbacks, delegate methods. And you have a couple of properties where you can query or set basically some default behavior. For example, you could specify always download to the My Picture directory in my user home folder.
And that's about it. So let's go back to the demo machine. And-- I'm actually going to quit Interface Builder and go to our application, our iPhoto application. And I want to show you, let's quickly run it and then I'll show you what... I have to do in code. Well, first of all, all we did was adding an extra item in the toolbar that would bring up an image capture UI. This image capture UI has on its side a device browser view.
On the right side, it does not have a single view because if we would have just the camera view, then it wouldn't do any good if I select a scanner. And if I had a scanner view, it wouldn't do any good for a camera. So we do have a view that switches between-- so it's a tap view, basically, switching between camera and scanner views.
And here you see like the old behavior, very similar to image capture application. So you could very easily do an overview scan, then select an area and do a scan. I think that's not that interesting. More interesting is this one because it's, again, the simple case. And if I do a scan, then what happens is we should do an overview scan.
So very nicely you get that. And it detects the areas and moves it over. And scans the image. So it scans the image and actually does the right rotation. So the result of this should be in our picture folder. So it's adding up. And you see I'm scanning as TIFF in this case. So it's now doing the last scan.
and so this one is straightened and they're all straightened so that's the area detection and all that. So just to show you. Very quickly, how it behaves if the objects that you throw up are not rectangular and May look a little bit different. Let me quickly show you how we would handle that.