Search code examples
iosobjective-cuiimagepickercontrollercropios-camera

Custom camera on a UIView, not full screen


I'm doing an application that on a specific part of the application, the user will be able to take a picture from the camera or select from the Album and this image will be shown on the ViewController. This is kind of easy, but, what I need, that I'm not being able to do is: -I don't want that the Camera open full screen, I want it to 'open' on the ViewController that the user is, in the exactly same place as where the image will be, inside a circle. I was able to make the Camera not open full screen, but I'm not being able to put this view inside the circle view and crop the photo according to the circle.

Here is my code, it might work if you create a standard project and I think that will help to understand what's going on:

VARIABLES

@property (nonatomic, strong) UIImagePickerController * picker;
@property (nonatomic, strong) UIImageView             * photoView;
@property (nonatomic, strong) UIView                  * overlayView;
@property (nonatomic, strong) UIButton * takePhotoButton; //- function
@property (nonatomic, strong) UIButton * selectPhotoButton;
@property (nonatomic, strong) UIButton * takePicture; //- action

CODE

    @interface CameraViewController ()
{
    BOOL isFromAlbum;
}

@end

@implementation CameraViewController

@synthesize photoView;
@synthesize picker;
@synthesize takePicture;
@synthesize selectPhotoButton;
@synthesize takePhotoButton;
@synthesize overlayView;
@synthesize switchCameraButton;

#pragma mark -
#pragma mark Initialization & Life Cycle
- (void)viewDidLoad
{
    [super viewDidLoad];
    [self initInterface];
}
-(void)initInterface
{
    [super addBackButton];

    self.view.backgroundColor                   = [UIColor colorWithRed:026.0f/255.0f green:030.0f/255.0f blue:055.0f/255.0f alpha:1.0f];

    self.takePhotoButton                        = [UIButton buttonWithType:UIButtonTypeSystem];
    self.takePhotoButton.frame                  = CGRectMake(27.5f, self.view.frame.size.width/2 - 55, 110, 110);
    self.takePhotoButton.layer.cornerRadius     = self.takePhotoButton.frame.size.width / 2.0f;
    [self.takePhotoButton setImage:[UIImage imageNamed:@"take-photo-btn"] forState:UIControlStateNormal];
    [self.takePhotoButton addTarget:self action:@selector(takePhotoFunction) forControlEvents:UIControlEventTouchUpInside];
    //[self.takePhotoButton setBackgroundColor:[UIColor colorWithRed:000.0f/255.0f green:255.0f/255.0f blue:000.0f/255.0f alpha:0.25f]];
    [self.view addSubview:self.takePhotoButton];

    self.selectPhotoButton                      = [UIButton buttonWithType:UIButtonTypeSystem];
    self.selectPhotoButton.frame                = CGRectMake(self.view.frame.size.width/2 + 27.5f, self.view.frame.size.width/2 - 55, 110, 110);
    self.selectPhotoButton.layer.cornerRadius   = self.selectPhotoButton.frame.size.width / 2.0f;
    [self.selectPhotoButton setImage:[UIImage imageNamed:@"pick-photo-btn"] forState:UIControlStateNormal];
    [self.selectPhotoButton addTarget:self action:@selector(selectPhoto) forControlEvents:UIControlEventTouchUpInside];
    //[self.selectPhotoButton setBackgroundColor:[UIColor colorWithRed:0 green:255/255.0f blue:0 alpha:0.25f]];
    [self.view addSubview:self.selectPhotoButton];


    self.photoView                              = [[UIImageView alloc] init];
    self.photoView.backgroundColor              = [UIColor colorWithRed:255.0f/255.0f green:000.0f/255.0f blue:000.0f/255.0f alpha:0.25f];
    self.photoView.frame                        = CGRectMake(0, 0, 320, 320);
    self.photoView.layer.cornerRadius           = self.photoView.frame.size.width / 2;
    self.photoView.layer.masksToBounds          = YES;
    self.photoView.userInteractionEnabled       = YES;
}

#pragma  mark -
#pragma mark Button's Actions
- (void)takePhotoFunction
{
    self.picker                     = [[UIImagePickerController alloc] init];
    self.picker.delegate            = self;
    self.picker.allowsEditing       = YES;
    self.picker.sourceType          = UIImagePickerControllerSourceTypeCamera;
    self.picker.showsCameraControls = NO;
    self.picker.view.frame          = self.photoView.bounds;
    [self.photoView addSubview:self.picker.view];

    self.takePicture                    = [UIButton buttonWithType:UIButtonTypeSystem];
    self.takePicture.frame              = CGRectMake(self.photoView.frame.size.width/2 - 35, self.photoView.frame.size.height - 70, 70, 70);
    [self.takePicture addTarget:self action:@selector(takePhotoAction:) forControlEvents:UIControlEventTouchUpInside];
    [self.takePicture setBackgroundImage:[UIImage imageNamed:@"take-photo-action"] forState:UIControlStateNormal];
    [self.photoView addSubview:self.takePicture];

    self.switchCameraButton = [[UIButton alloc] init];
    self.switchCameraButton.frame              = CGRectMake(self.photoView.frame.size.width/2 - 35, self.photoView.frame.origin.y, 70, 70);
    [self.switchCameraButton addTarget:self action:@selector(switchCamera:) forControlEvents:UIControlEventTouchUpInside];
    [self.switchCameraButton setBackgroundImage:[UIImage imageNamed:@"reverse-camera-btn"] forState:UIControlStateNormal];
    [self.photoView addSubview:self.switchCameraButton];


    [self.view addSubview:self.photoView];
    isFromAlbum = NO;
}

- (void)selectPhoto
{
    self.picker = [[UIImagePickerController alloc] init];
    self.picker.delegate = self;
    self.picker.allowsEditing = YES;
    self.picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

    isFromAlbum = YES;

    [self presentViewController:self.picker animated:YES completion:NULL];
}

-(IBAction)takePhotoAction:(id)sender
{
    [self.picker takePicture];
}

-(IBAction)switchCamera:(id)sender
{
    if (picker.cameraDevice == UIImagePickerControllerCameraDeviceFront)
    {
        picker.cameraDevice = UIImagePickerControllerCameraDeviceRear;
    }
    else if (picker.cameraDevice == UIImagePickerControllerCameraDeviceRear)
    {
        picker.cameraDevice = UIImagePickerControllerCameraDeviceFront;
    }
}

#pragma mark -
#pragma mark PickerController Delegate Methods
- (void)imagePickerController:(UIImagePickerController *)myPicker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    //NSString *mediaType = [info objectForKey: UIImagePickerControllerMediaType];
    UIImage *originalImage, *editedImage, *imageToSave;

    // Handle a still image capture
    //if (CFStringCompare ((CFStringRef) mediaType, kUTTypeImage, 0) == kCFCompareEqualTo)
    if (isFromAlbum == NO)
    {
        editedImage = (UIImage *) [info objectForKey:
                                   UIImagePickerControllerEditedImage];
        originalImage = (UIImage *) [info objectForKey:
                                     UIImagePickerControllerOriginalImage];

        if (editedImage)
        {
            imageToSave = editedImage;
        }
        else
        {
            imageToSave = originalImage;
        }

        // Save the new image (original or edited) to the Camera Roll
        //UIImageWriteToSavedPhotosAlbum (imageToSave, nil, nil , nil);
        [self.takePhotoButton removeFromSuperview];
        [self.switchCameraButton removeFromSuperview];
        [self.selectPhotoButton removeFromSuperview];
        [self.picker.view removeFromSuperview];
        [self.takePicture removeFromSuperview];


        CGFloat minimumSide = fminf(imageToSave.size.width, imageToSave.size.height);
        CGFloat finalSquareSize = 640.;

        //create new drawing context for right size
        CGRect rect = CGRectMake(0, 0, finalSquareSize, finalSquareSize);
        CGFloat scalingRatio = 640.0/minimumSide;
        UIGraphicsBeginImageContext(rect.size);

        //draw
        [imageToSave drawInRect:CGRectMake((minimumSide - originalImage.size.width)*scalingRatio/2., (minimumSide - originalImage.size.height)*scalingRatio/2., originalImage.size.width*scalingRatio, originalImage.size.height*scalingRatio)];

        UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();

        UIGraphicsEndImageContext();



        //[self.photoView setImage:imageToSave];
        [self.photoView setImage:croppedImage];
    }
    else
    {
        [self.takePhotoButton removeFromSuperview];
        [self.selectPhotoButton removeFromSuperview];
        UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
        [self.photoView setImage:chosenImage];
        [self.view addSubview:self.photoView];
        [myPicker dismissViewControllerAnimated:YES completion:NULL];
    }
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)myPicker
{
    //[picker.view removeFromSuperview];
    [myPicker dismissViewControllerAnimated:YES completion:NULL];
}

#pragma mark -
#pragma mark NavigationController Methods
-(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [[UIApplication sharedApplication] setStatusBarHidden:NO];
}

Solution

  • With the code below, I get the following results:

    1. A single view with a dark blue background.
    2. 2 green circles (the buttons)
    3. Tapping on the left circle puts the camera's "sight" inside of it.
    4. Tapping on the "take" button (at the bottom of the circle on the left) fires off the "takePhotoAction" method.

    [Code]

       //  ViewController.m
        #import "ViewController.h"
        @interface ViewController () <UIImagePickerControllerDelegate, UINavigationControllerDelegate> {
            BOOL isFromAlbum;
        }
        @property (nonatomic, strong) UIImagePickerController * picker;
        @property (nonatomic, strong) UIImageView             * photoView;
        @property (nonatomic, strong) UIView                  * overlayView;
        @property (nonatomic, strong) UIButton * takePhotoButton; //- function
        @property (nonatomic, strong) UIButton * selectPhotoButton;
        @property (nonatomic, strong) UIButton * takePicture; //- action
    
        @end
    
    @implementation ViewController
    
    #pragma mark -
    #pragma mark Initialization & Life Cycle
    - (void)viewDidLoad {
        [super viewDidLoad];
        [self initInterface];
    }
    -(void)initInterface {
        self.view.backgroundColor                   = [UIColor colorWithRed:026.0f/255.0f green:030.0f/255.0f blue:055.0f/255.0f alpha:1.0f];
    
        self.takePhotoButton                        = [UIButton buttonWithType:UIButtonTypeSystem];
        self.takePhotoButton.frame                  = CGRectMake(27.5f, self.view.frame.size.width/2 - 55, 110, 110);
        self.takePhotoButton.layer.cornerRadius     = self.takePhotoButton.frame.size.width / 2.0f;
        [self.takePhotoButton setImage:[UIImage imageNamed:@"take-photo-btn"] forState:UIControlStateNormal];
        [self.takePhotoButton addTarget:self action:@selector(takePhotoFunction) forControlEvents:UIControlEventTouchUpInside];
        [self.takePhotoButton setBackgroundColor:[UIColor colorWithRed:000.0f/255.0f green:255.0f/255.0f blue:000.0f/255.0f alpha:0.25f]];
        [self.view addSubview:self.takePhotoButton];
    
        self.selectPhotoButton                      = [UIButton buttonWithType:UIButtonTypeSystem];
        self.selectPhotoButton.frame                = CGRectMake(self.view.frame.size.width/2 + 27.5f, self.view.frame.size.width/2 - 55, 110, 110);
        self.selectPhotoButton.layer.cornerRadius   = self.selectPhotoButton.frame.size.width / 2.0f;
        [self.selectPhotoButton setImage:[UIImage imageNamed:@"pick-photo-btn"] forState:UIControlStateNormal];
        [self.selectPhotoButton addTarget:self action:@selector(selectPhoto) forControlEvents:UIControlEventTouchUpInside];
        [self.selectPhotoButton setBackgroundColor:[UIColor colorWithRed:0 green:255/255.0f blue:0 alpha:0.25f]];
        [self.view addSubview:self.selectPhotoButton];
    
    
        self.photoView                              = [[UIImageView alloc] init];
        self.photoView.backgroundColor              = [UIColor colorWithRed:255.0f/255.0f green:000.0f/255.0f blue:000.0f/255.0f alpha:0.25f];
        self.photoView.frame                        = self.takePhotoButton.frame;
        self.photoView.layer.cornerRadius           = self.photoView.frame.size.width / 2;
        self.photoView.layer.masksToBounds          = YES;
        [self.photoView setUserInteractionEnabled:YES];
    }
    #pragma  mark -
    #pragma mark Actions
    - (void)takePhotoFunction {
        self.picker                     = [[UIImagePickerController alloc] init];
        self.picker.delegate            = self;
        self.picker.allowsEditing       = YES;
        self.picker.sourceType          = UIImagePickerControllerSourceTypeCamera;
        self.picker.showsCameraControls = NO;
        self.picker.view.frame          = self.photoView.bounds;
        [self.photoView addSubview:self.picker.view];
    
        self.takePicture                    = [UIButton buttonWithType:UIButtonTypeSystem];
        self.takePicture.frame              = CGRectMake(self.photoView.frame.size.width/2 - 35, self.photoView.frame.size.height - 40, 70, 70);
        [self.takePicture addTarget:self action:@selector(takePhotoAction:) forControlEvents:UIControlEventTouchUpInside];
        [self.takePicture setBackgroundImage:[UIImage imageNamed:@"take-photo-action"] forState:UIControlStateNormal];
        [self.photoView addSubview:self.takePicture];
    
        [self.view addSubview:self.photoView];
        isFromAlbum = NO;
    }
    - (void)selectPhoto {
        self.picker = [[UIImagePickerController alloc] init];
        self.picker.delegate = self;
        self.picker.allowsEditing = YES;
        self.picker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
    
        isFromAlbum = YES;
    
        [self presentViewController:self.picker animated:YES completion:NULL];
    }
    
    -(IBAction)takePhotoAction:(id)sender {
        [self.picker takePicture];
    }
    #pragma mark -
    #pragma mark PickerController Delegate Methods
    - (void)imagePickerController:(UIImagePickerController *)myPicker didFinishPickingMediaWithInfo:(NSDictionary *)info {
        //NSString *mediaType = [info objectForKey: UIImagePickerControllerMediaType];
        UIImage *originalImage, *editedImage, *imageToSave;
    
        // Handle a still image capture
        //if (CFStringCompare ((CFStringRef) mediaType, kUTTypeImage, 0) == kCFCompareEqualTo)
        if (isFromAlbum == NO) {
            editedImage = (UIImage *) [info objectForKey:
                                       UIImagePickerControllerEditedImage];
            originalImage = (UIImage *) [info objectForKey:
                                         UIImagePickerControllerOriginalImage];
    
            if (editedImage) {
                imageToSave = editedImage;
            } else {
                imageToSave = originalImage;
            }
    
            // Save the new image (original or edited) to the Camera Roll
            //UIImageWriteToSavedPhotosAlbum (imageToSave, nil, nil , nil);
            [self.takePhotoButton removeFromSuperview];
            [self.selectPhotoButton removeFromSuperview];
            [self.picker.view removeFromSuperview];
            [self.takePicture removeFromSuperview];
            [self.photoView setImage:imageToSave];
    
        } else {
            [self.takePhotoButton removeFromSuperview];
            [self.selectPhotoButton removeFromSuperview];
            UIImage *chosenImage = info[UIImagePickerControllerEditedImage];
            [self.photoView setImage:chosenImage];
            [self.view addSubview:self.photoView];
            [myPicker dismissViewControllerAnimated:YES completion:NULL];
        }
    }
    - (void)imagePickerControllerDidCancel:(UIImagePickerController *)myPicker {
        //[picker.view removeFromSuperview];
        [myPicker dismissViewControllerAnimated:YES completion:NULL];
    }
    #pragma mark -
    #pragma mark NavigationController Methods
    -(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
        [[UIApplication sharedApplication] setStatusBarHidden:NO];
    }
    @end