We’re going to explore the simpler methods of dis-playing images, using UIImageView, in this section, and in section 18.2 we’ll examine the more complex means available for drawing image
Trang 1Media: images and sounds
So far, our focus on iPhone programming has mainly been on text Sure, we’ve played the occasional UIImage, such as the mountain drawing in the last chapter, but we’ve only considered the simplest means for doing so
The iPhone offers an experience that’s potentially much richer and more engaging A camera, a microphone, a complete photos library, and a speaker are just some of the utilities built into the iPhone In this chapter, we’re going to look
at these features as part of a general exploration of media We’ll provide deep erage on images, some information on the iPhone’s media player, and a basic look
cov-at playing sounds on the iPhone
More complex questions are beyond the scope of this chapter We’re saving the topic of image editing for the next chapter, when we look at the iPhone’s graphic libraries For more complex sound work, we’ll offer pointers to Apple’s extensive tutorials on the topic
This chapter covers
■ Accessing and manipulating images
■ Using the iPhone camera
■ Playing sounds and video
Trang 2An introduction to images
We’ve already touched upon using images a few times, beginning in chapter 12 where
we included an image in one of our earliest SDK examples We’ve always created
a UIImageView in Interface Builder, attached it to a filename, and not worried about the details
We’re now ready to consider the details We’ll look
at some of the options you have available when you
dive into Xcode, rather than depending upon
Inter-face Builder’s higher-level abstractions
When you look more closely, you’ll discover that
using images is a two-step process First, you load data
into a UIImage, and then you make use of that UIImage
via some other means There are two major ways to
make use of UIImages, as shown in figure 18.1
We’re going to explore the simpler methods of
dis-playing images, using UIImageView, in this section,
and in section 18.2 we’ll examine the more complex
means available for drawing images onto the back
layer of a UIView
18.1.1 Loading a UIImage
The UIImage class offers seven different ways to create an instance of an image The four factory methods are probably the easiest to use, and they’re the ones we’ve listed
in table 18.1 There are also some equivalent init methods that you can use if you prefer
The image data can be of several file types, including BMP, CUR, GIF, JPEG, PNG, and TIFF
In this book, we’ve used mostly JPEGs (because they’re small) and PNGs (because they look good and are accelerated on the iPhone hardware) You can also create a UIImagefrom a Quartz 2D object; this is the iPhone’s fundamental graphics package, which we’re going to talk about more in the next chapter There’s one suggested restriction when you’re creating UIImages: the images shouldn’t be larger than 1024x1024
Table 18.1 Factory methods for creating a UIImage
imageNamed: Creates a UIImage based on a file in the main bundle
imageWithCGImage: Creates a UIImage from a Quartz 2D object; this is
the same as initWithCGImage:
imageWithContentsOfFile: Creates a UIImage from a complete file path that you
specify, as discussed in chapter 16; this is the same
Trang 3Once you import an image into your program, you can display it If you’re going to stay entirely within the simple methods of the UIKit, you’ll want to use the UIImage-View class to display the image.
To load a normal image, you could use the image property, but there’s usually little reason to use it rather than the initWithImage: method—unless you’re dynamically changing your image If you want to create a set of images to animate, it’s useful to take advantage of the other UIImageView methods and properties
You can load an array of images into a UIImageView, declare how fast and how often they should animate, and start and stop them as you see fit A simple example of this is shown in listing 18.1
- (void)viewDidLoad {
UIImage *myImage1 =
[UIImage imageNamed:@"sproul1.jpg"];
UIImage *myImage2 =
Table 18.2 A few properties and methods of note for UIImageView
Method or property Type Summary
animationDuration Property Specifies how often an animation cycles
animationImages Property Identifies an NSArray of images to load into the
UIImageView animationRepeatCount Property Specifies how many times to run an animation cycle
image Property Identifies a single image to load into a UIImageView startAnimating Method Starts the animation
stopAnimating Method Stops the animation
Listing 18.1 UIImageView allows for animated images
Loads images
Trang 418.1.3 Modifying an image in the UIKit
Now you’ve seen how to create images and load them into image views cally Surely, the next thing to do is to start modifying them
Unfortunately, you have only limited capability to do so while working with UIImageView You can make some changes, based on simple manipulations of the view
For example, if you resize your UIImageView, it’ll automatically resize the picture it contains Likewise, you can decide where to draw your UIImageView by setting its frame to something other than the whole screen You can even layer multiple images
by using multiple UIImageViews
This all starts to get unwieldy pretty quickly, though, and you can’t do anything cier, like transforming your images or modifying how they stack through blending or alpha transparency options To do that sort of work (and to start stacking graphics, not just views) you need to learn about Core Graphics
UIImage offers some simple ways to access Core Graphics functionality that doesn’t require going out to the Core Graphics framework (or learning about contexts or the other complexities that underlie its use) We’re going to talk about those briefly here, but, for the most part, Core Graphics will wait for the next chapter, which concen-trates on the entire Quartz 2D graphics engine
Although it doesn’t give access to the entire Core Graphics library of transformations and other complexities, the UIImage class does include five simple methods that take advantage of the way Core Graphics works They’re described in table 18.3
Loads images
Creates UIView
Starts animation
Trang 5The trick is that these methods cannot be used as part of viewDidLoad: or whatever
other method you usually use to load up your objects That’s because they depend
upon a graphical context to work We’re going to talk about contexts more in the next
chapter, but a graphical context is a destination that you’re drawing to, like a window,
a PDF file, or a printer
On the iPhone, UIViews automatically create a graphical context as part of their CALayer, which is a Core Animation layer associated with each UIView You can access this layer by writing a drawRect: method for the UIView (or rather, for a new subclass that you’ve created) You’d usually have to capture a special context variable to do this type of work, but the UIView methods take care of this for you, to keep things simple Listing 18.2 shows how to collage together a few pictures using this method
- (void)drawRect:(CGRect)rect {
UIImage *myImage1 = [UIImage imageNamed:@"sproul1.jpg"];
UIImage *myImage2 = [UIImage imageNamed:@"sproul2.jpg"];
UIImage *myImage3 = [UIImage imageNamed:@"sproul3.jpg"];
[myImage1 drawAtPoint:CGPointMake(0,0) blendMode:kCGBlendModeNormal alpha:.5];
There’s still a lot that we can’t do until we delve fully into the iPhone’s Core ics framework, but for now we’ve got some control, which should be sufficient for
Graph-Table 18.3 Instance methods for drawing a UIImage
drawAsPatternInRect: Draws the image inside the rectangle,
unscaled, but tiled as necessary
drawAtPoint: Draws the complete unscaled image with
the CGPoint as the top-left corner
drawAtPoint:blendMode:alpha: A more complex form of drawAtPoint:
drawInRect: Draws the complete image inside the
CGRect, scaled appropriately
drawInRect:blendMode:alpha: A more complex form of drawInRect:
Listing 18.2 A UIView’s drawRect: allows you to use lower-level draw commands
Trang 6Accessing photos
most of your common media needs If you need more control, skip right ahead to the next chapter
We’ve talked lots about images, and we’ve
pre-sumed so far that you’re loading them from your
proj-ect’s bundle But what if you want to let a user select
photographs? That’s the topic of our next section
You can use the SDK to access pictures from an
iPhone’s photo library or its camera roll You can also
allow a user to take new photos This is all done with
the UIImage-PickerController, another modal
con-troller that manages a fairly complex graphical
inter-face without much effort on your part Figure 18.2
shows what it looks like
18.3.1 Using the image picker
The UIImagePickerController is loaded up by
creat-ing the object, settcreat-ing a few variables, and presentcreat-ing it
as a modal view controller By default, the image picker
controller will allow users to access (and optionally
edit) the pictures in their photo library:
UIImagePickerController *myImagePicker =
[[UIImagePickerController alloc] init];
myImagePicker.delegate = self;
myImagePicker.allowsImageEditing = NO;
[self presentModalViewController:myImagePicker animated:YES];
Once you’ve created your image picker controller, you need to have its delegate respond to two methods: imagePickerController:didFinishPickingImage:edit-ingInfo: and imagePickerControllerDidCancel: For the first method, you should dismiss the modal view controller and respond appropriately to the user’s picture selection, and for the second, you only need to dismiss the controller
Overall, the image picker controller is easy to use because you’re mainly reacting to
a picture that was selected We’ve got a complete example of its use in the next section
■ UIImagePickerControllerSourceTypeCamera, new picture taken by the camera
Figure 18.2 The image picker
is another preprogrammed controller for your use.
Trang 7You should always make sure that the source is available before you launch an image picker controller, although this is most important for the camera You can confirm that the source exists with the isSourceTypeAvailable: class method:
In our experience, the camera is a bit of a resource hog We had it grind to a halt a few times during testing More than anything else, this means that you need to think about saving your program’s state when using the camera, because it could cause you
to run out of memory
We’ll have an example of using the camera in our example in section 18.4
18.3.3 Saving to the photo album
You may wish to save a new photograph to the photo album, or you may wish to place
a graphic created by your program there In either case, you use the SavedPhotosAlbum function It has four variables: the first lists the image, and the other three reference an optional asynchronous notification function to call when the save has been completed Usually you’ll call the function like this:
UIImageWriteTo-UIImageWriteToSavedPhotosAlbum(yourImage,nil,nil,nil);
If you instead want to take advantage of the asynchronous notification, take a look at the UIKit function reference, which is where this function is hidden away, or look at our example in the next chapter
You can use this function (and a bit of trickery) to save the CALayer of a UIView to your photo album, which, for example, will allow you to save those draw commands that you wrote straight to the CALayer earlier This once more depends upon graphi-cal contexts, which we’ll explain in the next chapter, but here’s how to do it:
to a CALayer that can be saved
Trang 8Collage: an image example
The collage program depends on three objects The collageViewController, as usual, does most of the work It writes out to a collageView object, which exists mainly as a CALayer to be written upon Finally, you’ll have a tempImageView object that allows the user to position an image after it’s been selected but before it’s perma-nently placed
18.4.1 The collage view controller
The collage view controller is built on a few Interface Builder objects: the view troller itself; a toolbar called myTools, which will be filled over the course of the pro-gram; and the collageView UIView class, which exists as its own class file and is referred to in the program as self.view You’ll also need to add the Quartz Core framework to your project as you’ll use that save-picture trick that we just discussed Listing 18.3 shows the complete view controller, which is the most extensive file in this program
con-@implementation collageViewController
- (void)viewDidLoad {
UIBarButtonItem *picButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(choosePic:)];
UIBarButtonItem *camButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:@selector(takePic:)];
UIBarButtonItem *saveButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(savePic:)];
picButton.style = UIBarButtonItemStyleBordered;
camButton.style = UIBarButtonItemStyleBordered;
if ([UIImagePickerController
isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) { origToolbar = [[NSArray alloc] initWithObjects:
picButton,camButton,saveButton,nil];
} else if ([UIImagePickerController
isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) { origToolbar = [[NSArray alloc] initWithObjects:
C
Trang 9mySlider = [[UISlider alloc] initWithFrame:CGRectMake(90,415,210,44)]; mySlider.value = 5;
[mySlider addTarget:self action:@selector(rescalePic:)
E
Responds to picker cancellation
F
Resizes picture
G
Trang 10a camera’s available), and savePic:.
choosePic: C and takePic: D are similar methods Each calls up the image picker controller, but the first one accesses the photo library and the second one lets the user take a new picture The wonder of these modal controllers is that you don’t have to do a thing between the time when you create the picker to the point where your user either selects a picture or cancels
When the user selects a picture, Image:editingInfo will be called E, returning control to your program Here you do four things:
J
Trang 11■ Dismiss the modal view controller.
■ Look at the picture you’ve been handed and resize it to fill a quarter or less of the screen
■ Instantiate the image as a tempImageView object, which is a subclass of UIImage- View
■ Change the toolbar so that there’s a Done button available, along with a slider
At this point, the user will be able to do three things:
■ Use UITouches to move the image view (which is covered in the tempImageViewclass, because that’s where the touches go, as we saw in chapter 14)
■ Use the slider to change the size of the picture
■ Click Done to accept the image size and location
The end results of what can be produced are shown in
figure 18.3
Note that if the user instead canceled the image
pick-er, your imagePickerControllerDidCancel: method
would correctly shut down the modal controller F
The UISlider was hooked up to the rescalePic:
method G It redraws the frame of the UIImageView,
which automatically resizes the picture inside
Mean-while, the Done button activates the finishPic:
method H This sends a special addPic:at: message
to the collageView, which is where the CALayer
draw-ing is done, and which we’ll return to momentarily
finishPic: also dismisses the UISlider and the
tem-pImageView and resets the toolbar to its original setup
That original toolbar had one more button that we
haven’t covered yet: Save It activates the savePic:
method I, which saves a CALayer to the photo library
Note that this method temporarily hides toolbar in the
process Because the toolbar is a subview of the UIView,
it’d get included in the picture if you didn’t do this
The last method, scaleImage: J, is the utility that
sets each image to fill about a quarter of the screen
This code has two dangling parts: the methods in the tempImageView, which allow
a user to move the UIImageView, and the methods in the collageView, which later draw the image into a CALayer
18.4.2 The collage temporary image view
The tempImageView class only has one purpose: to intercept UITouches that indicate that the user wants to move the new image to a different part of the collage This sim-ple code is shown in listing 18.4
Figure 18.3 The collager
in use displays many photos simultaneously.