The iPhone 4 (and 4S) (as well as the iPad 2) has a camera (in fact two - one front facing and one rear facing) that enables users to both take pictures and record videos. These pictures and videos are saved in the Photos application. As a developer, you have two options to manipulate the camera and to access the pictures and videos stored in the Photos application:
Every iOS device includes the Photos application, in which pictures are stored. Using the iOS SDK, you can use the UIImagePickerController class to programmatically display a UI that enables users to select pictures from the Photos application. The following Try It Out demonstrates how you can do that in your application.
TRY IT OUT: Accessing the Photos in the Photo Library
#import <UIKit/UIKit.h>
@interface PhotoLibraryViewController : UIViewController
<UINavigationControllerDelegate,
UIImagePickerControllerDelegate> { IBOutlet UIImageView *imageView; UIImagePickerController *imagePicker; } @property (nonatomic, retain) UIImageView *imageView; -(IBAction) btnClicked: (id) sender; @end
#import “PhotoLibraryViewController.h” @implementation PhotoLibraryViewController @synthesize imageView; - (void)viewDidLoad { imagePicker = [[UIImagePickerController alloc] init]; [super viewDidLoad]; } - (IBAction) btnClicked: (id) sender{ imagePicker.delegate = self; imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; //---show the Image Picker--- [self presentModalViewController:imagePicker animated:YES]; } - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *image; NSURL *mediaUrl; mediaUrl = (NSURL *)[info valueForKey: UIImagePickerControllerMediaURL]; if (mediaUrl == nil) { image = (UIImage *) [info valueForKey: UIImagePickerControllerEditedImage]; if (image == nil) { //---original image selected--- image = (UIImage *) [info valueForKey:UIImagePickerControllerOriginalImage]; //---display the image--- imageView.image = image;
} else { //---edited image picked--- //---get the cropping rectangle applied to the image--- CGRect rect = [[info valueForKey:UIImagePickerControllerCropRect] CGRectValue]; //--display the image--- imageView.image = image; } } //---hide the Image Picker--- [picker dismissModalViewControllerAnimated:YES]; } - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { //---user did not select image; hide the Image Picker--- [picker dismissModalViewControllerAnimated:YES]; } - (void)dealloc { [imageView release]; [imagePicker release]; [super dealloc]; }
NOTE Because the iPhone Simulator does not contain any built-in photo albums, you might not be able to test this application on the simulator. Thus, I suggest you test this on a real device. Appendix A discusses how to test your application on real devices.
How It Works
Access to the Photo Library is provided by the UIImagePickerController class, which provides the UI for choosing and taking pictures and videos on your iPhone. All you need to do is create an instance of this class and provide a delegate that conforms to the UIImagePickerControllerDelegate protocol. In addition, your delegate must conform to the UINavigationControllerDelegate protocol because the UIImagePickerController class uses the Navigation Controller to enable users to select photos from the Photo Library. Therefore, you first needed to specify the protocols in PhotoLibraryViewController.h:
@interface PhotoLibraryViewController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate> {
When the Load Library button is clicked, you set the type of picker interface displayed by the UIImagePickerController class and then display it modally:
- (IBAction) btnClicked: (id) sender{ imagePicker.delegate = self; imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; //---show the Image Picker--- [self presentModalViewController:imagePicker animated:YES]; }
Note that if you want the picture to be editable when the user chooses it, you can add the following statement:
imagePicker.allowsEditing = YES;
By default, the source type is always UIImagePickerControllerSourceTypePhotoLibrary, but you can change it to one of the following:
When a picture has been selected by the user, the imagePickerController:didFinishPickingMediaWithInfo: event fires, which you handle by checking the type of media selected by the user:
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *image;
NSURL *mediaUrl; mediaUrl = (NSURL *)[info valueForKey: UIImagePickerControllerMediaURL]; if (mediaUrl == nil) { image = (UIImage *) [info valueForKey: UIImagePickerControllerEditedImage]; if (image == nil) { //---original image selected--- image = (UIImage *) [info valueForKey:UIImagePickerControllerOriginalImage]; //---display the image--- imageView.image = image; } else { //---edited image picked--- //---get the cropping rectangle applied to the image--- CGRect rect = [[info valueForKey:UIImagePickerControllerCropRect] CGRectValue]; //---display the image--- imageView.image = image; } } //---hide the Image Picker--- [picker dismissModalViewControllerAnimated:YES]; }
The type of media selected by the user is encapsulated in the info: parameter. You use the valueForKey: method to extract the appropriate media type and then typecast it to the respective type:
mediaUrl = (NSURL *) [info valueForKey:UIImagePickerControllerMediaURL];
If the user cancels the selection, the imagePickerControllerDidCancel: event fires. In this case, you simply dismiss the Image Picker:
- (void)imagePickerControllerDidCancel:(UIImagePickerController *) picker { //---user did not select image; hide the Image Picker--- [picker dismissModalViewControllerAnimated:YES]; }
Besides accessing the Photo Library, you can also access the camera on your iPhone. Although accessing the hardware is the focus of the next chapter, this section takes a look at how to access the camera because it is also accomplished using the UIImagePickerController class.
In the following Try It Out, you modify the existing project created in the previous section. There isn't much to modify because most of the code you have written still applies.
TRY IT OUT: Activating the Camera
- (IBAction) btnClicked: (id) sender{ imagePicker.delegate = self; //---comment this out--- /* imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; */ //---invoke the camera--- imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera; NSArray *mediaTypes = [NSArray arrayWithObjects:kUTTypeImage, nil]; imagePicker.mediaTypes = mediaTypes; imagePicker.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto; imagePicker.allowsEditing = YES; //---show the Image Picker--- [self presentModalViewController:imagePicker animated:YES]; }
-(NSString *) filePath: (NSString *) fileName { NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDir = [paths objectAtIndex:0]; return [documentsDir stringByAppendingPathComponent:fileName]; } - (void) saveImage{ //---get the data from the ImageView--- NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(imageView.image)]; //---write the data to file--- [imageData writeToFile:[self filePath:@“MyPicture.png”] atomically:YES]; }
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { UIImage *image; NSURL *mediaUrl; mediaUrl = (NSURL *)[info valueForKey:UIImagePickerControllerMediaURL]; if (mediaUrl == nil) { image = (UIImage *) [info valueForKey:UIImagePickerControllerEditedImage];
if (image == nil) { //---original image selected--- image = (UIImage *) [info valueForKey:UIImagePickerControllerOriginalImage]; //---display the image--- imageView.image = image; } else { //---edited image picked--- //---get the cropping rectangle applied to the image--- CGRect rect = [[info valueForKey:UIImagePickerControllerCropRect] CGRectValue]; //---display the image--- imageView.image = image; } //---save the image captured--- [self saveImage]; } //---hide the Image Picker--- [picker dismissModalViewControllerAnimated:YES]; }
In this exercise you modified the source type of the Image Picker to camera:
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
When the camera takes a picture, the picture is passed back in the imagePickerController:didFinishPickingMediaWithInfo: method and displayed in the ImageView view. However, it is your responsibility to manually save the image to a location on the phone. In this case, you defined the filePath: method to save the picture to the Documents folder of your application:
- (NSString *) filePath: (NSString *) fileName { NSArray *paths = NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDir = [paths objectAtIndex:0]; return [documentsDir stringByAppendingPathComponent:fileName]; }
The saveImage: method extracts the image data on the ImageView view and then calls the filePath: method to save the data into a file named MyPicture.png:
- (void) saveImage{ //---get the date from the ImageView--- NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(imageView.image)]; //---write the date to file--- [imageData writeToFile:[self filePath:@“MyPicture.png”] atomically:YES]; }
NOTE By default on the iPhone 4 and iPhone 4S, the rear camera is always activated when you use the UIImagePickerController class. If you want to activate the front camera instead, you can set the cameraDevice property of the UIImagePickerController class, which can be either of the following values: UIImagePickerControllerCameraDeviceRear (default) or UIImagePickerControllerCameraDeviceFront.
Appendix A discusses how to prepare your iPhone for testing.
3.139.59.5