Creating a Fun iPhone App Called “Bearded” – Part 2

post2-featured

In Part 1 we created the interface and added gesture recognizers for the beard image view. We still have three main features to complete: capturing a photo, blending or merging images and sharing the final image. So let’s get started.

Camera Controls

We want to provide the user with two options either to take a photo or pick one from the camera roll. For this we will display a UIActionSheet to present the user with choices. Finally, we will use the simple UIImagePickerController to facilitate camera or library functions.

Firstly, we will connect the camera button within the toolbar to an IBAction called cameraBtnAction.

Connecting toolbar button to IBAction

The implementation of the cameraBtnAction involves creating the action sheet:


- (void) cameraBtnAction:(UIButton *)sender {

    UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:nil
                                                             delegate:self
                                                    cancelButtonTitle:@"Cancel"
                                               destructiveButtonTitle:nil
                                                    otherButtonTitles:@"Take a Picture",@"Choose from Library", nil];
    [actionSheet showInView:self.view];

}

Do not forget to add UIActionSheetDelegate in the interface declaration of ViewController.h.

@interface THViewController : UIViewController <UIGestureRecognizerDelegate,UIActionSheetDelegate>

We can intercept the user selection of the action sheet with the following delegate method.

- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
    // Create a new image picker instance:
    UIImagePickerController *picker = [[UIImagePickerController alloc] init];

    // Set the image picker source:
    switch (buttonIndex) {
        case 0:
            picker.sourceType = UIImagePickerControllerSourceTypeCamera;
            break;
        case 1:
            picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
            break;
        default:
            break;
    }

    picker.delegate = self;

    // Show picker if Take a picture or Choose from Library is selected
    if ( buttonIndex == 0 || buttonIndex == 1)
        [self presentViewController:picker animated:YES completion:nil];

}

The method above receives the buttonIndex as a parameter which contains the index of the selected button. We create an instance of UIImagePickerController and then based on the selection we set the sourceType, which determines whether the user will take a picture or be allowed to pick one from the camera roll. Finally, the picker objects delegate is set to self which means we need to add two more delegates to our interface defintion.

@interface THViewController : UIViewController <UIImagePickerControllerDelegate, UINavigationControllerDelegate,UIGestureRecognizerDelegate,UIActionSheetDelegate>

After the photo is taken or picked, we need to set that image to our photoView using the delegate method from the UIImagePickerControllerDelegate.

- (void) imagePickerController: (UIImagePickerController *) picker
            didFinishPickingMediaWithInfo: (NSDictionary *) info {

   self.photoView.image = [info valueForKey:UIImagePickerControllerOriginalImage];

    [self dismissViewControllerAnimated:YES completion:nil];    
}

Blending or Merging Images

Now that you know how to implement the camera functionality and set the photoView to an image taken or selected by the user, it is time to figure out how to merge the photo and beard into a single image.

UIKit contains some useful functions for image manipulation and one those is UIGraphicsBeginImageContext which helps create a bitmap-based graphics context for a specified rectangular area. You can then draw anything to this context and capture the resulting image.

Here is what the code for the blendImage method looks like:


- (UIImage *) blendImages {
    UIImage *photoImage = self.photoView.image ;
    UIImage *beardImage = self.beardView.image;
    
    // Get the size of the photo
    CGSize photoSize = CGSizeMake(photoImage.size.width, photoImage.size.height);
    
    // Create a bitmap graphics context of the photoSize
    UIGraphicsBeginImageContext( photoSize );
    
    // Draw the photo in the specified rectangle area
    [photoImage drawInRect:CGRectMake(0,0,photoSize.width,photoSize.height)];
    
    CGPoint origin = self.beardView.frame.origin;
    CGSize size = self.beardView.frame.size;
    
    CGFloat xScale = photoImage.size.width / self.view.bounds.size.width;
    CGFloat yScale = photoImage.size.height / (self.view.bounds.size.height-44);
    
    // Draw the beard in the specified rectangle area
    [beardImage drawInRect:CGRectMake((origin.x * xScale), (origin.y * yScale),
                                       size.width * xScale, size.height * yScale)
                  blendMode:kCGBlendModeNormal alpha:1.0];

    
    // Save the generated image to an image object
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();
    
    return newImage;
} 

You are probably wondering about the two variables xScale and yScale. The photoView is set to “Aspect Fit”, which means that the original photo is proportionately fitted to be displayed on the screen. The size of photo is much larger than what is displayed on the screen, therefore if we simply applied the screen size and position of the beard to be drawn then the resulting image would be of a tiny misplaced beard. After applying scaling the beard is increased in size and positioned relative to its screen position.

Scaling Images

Social Framework

A new feature in iOS 6 is social framework which allows you to share content using various methods from within your app. All you have to do is specify which social functions you want to make available to the user and an action sheet is displayed to the user. Of course you have to provide it with the content that needs to be shared.

iOS Social Framework

Just as we had connected the camera button to an IBAction called cameraBtnAction, similarly we are going to connect the share button to an IBAction called shareBtnAction.

Implementation of the shareBtnAction.

- (void) shareBtnAction:(UIButton *)sender {


    // An array of content that needs to posted
    NSArray *activityItems = @[@"You have been Bearded!", UIImageJPEGRepresentation([self blendImages],0.75)];


    // Create a new UIActivityViewController with the activityItems array 
    UIActivityViewController *activityController = [[UIActivityViewController alloc]
                                                    initWithActivityItems:activityItems applicationActivities:nil];
    // Exclude activities that are irrelevant
    activityController.excludedActivityTypes = @[UIActivityTypePostToWeibo,UIActivityTypePrint,UIActivityTypeCopyToPasteboard,UIActivityTypeAssignToContact];

    // Present the activityController
    [self presentViewController:activityController
                       animated:YES completion:nil];

}

iPhone 5 Compatibility

So far we have been creating the app without worrying about whether it will scale for the 4″ screen on the iPhone 5. You must be wondering since we disabled autolayout if it is at all possible. It is simpler than you think because we have a very basic application. All you need to do is add this line to your viewDidLoad method.

self.photoView.autoresizingMask = UIViewAutoresizingFlexibleHeight;

Now the photoImageView will scale vertically for the iPhone 5. The taller screen also requires a taller default image. For that we need to check if the device is an iPhone 5 and for using a macro:

#define IS_IPHONE_5 ( fabs( ( double )[ [ UIScreen mainScreen ] bounds ].size.height - ( double )568 ) < DBL_EPSILON )

The macro uses the screen sizes to determine the height. Once again within the viewDidLoad method we set the image “photo-tall.png” to the photoView

    if ( IS_IPHONE_5 )
        self.photoView.image = [UIImage imageNamed:@"photo-tall.png"];

Conclusion

There you have it, a fun and easy app that teaches you a whole lot and requires little time and effort to build. Happy Holidays and Get Bearded!

You can download the complete source code from my github:
https://github.com/abijlani/bearded

Coming soon you will be able to download the app directly from the app store.

Free Workshops

Watch one of our expert, full-length teaching videos. Choose from either HTML, CSS or Wordpress.

Start learning

Amit Bijlani

Amit is an iOS Developer who loves teaching and speaking about iOS. When not in front of a computer, he's exploring the outdoors or meditating. Follow him on Twitter: @paradoxed

Comments

One comment on “Creating a Fun iPhone App Called “Bearded” – Part 2