iOS Custom UIImagePickerController Camera Crop to Square
Solution 1
Here's the easiest way to do it (without reimplementing UIImagePickerController
). First, use an overlay to make the camera field look square. Here's an example for 3.5" screens (you'd need to update it to work for iPhone 5):
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.sourceType = source;
if (source == UIImagePickerControllerSourceTypeCamera) {
//Create camera overlay
CGRect f = imagePickerController.view.bounds;
f.size.height -= imagePickerController.navigationBar.bounds.size.height;
CGFloat barHeight = (f.size.height - f.size.width) / 2;
UIGraphicsBeginImageContext(f.size);
[[UIColor colorWithWhite:0 alpha:.5] set];
UIRectFillUsingBlendMode(CGRectMake(0, 0, f.size.width, barHeight), kCGBlendModeNormal);
UIRectFillUsingBlendMode(CGRectMake(0, f.size.height - barHeight, f.size.width, barHeight), kCGBlendModeNormal);
UIImage *overlayImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *overlayIV = [[UIImageView alloc] initWithFrame:f];
overlayIV.image = overlayImage;
[imagePickerController.cameraOverlayView addSubview:overlayIV];
}
imagePickerController.delegate = self;
[self presentViewController:imagePickerController animated:YES completion:nil];
Then, after you get a picture back from the UIImagePickerController
, crop it to a square with something like this:
//Crop the image to a square
CGSize imageSize = image.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
if (width != height) {
CGFloat newDimension = MIN(width, height);
CGFloat widthOffset = (width - newDimension) / 2;
CGFloat heightOffset = (height - newDimension) / 2;
UIGraphicsBeginImageContextWithOptions(CGSizeMake(newDimension, newDimension), NO, 0.);
[image drawAtPoint:CGPointMake(-widthOffset, -heightOffset)
blendMode:kCGBlendModeCopy
alpha:1.];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
And you're done.
Solution 2
@Anders answer was very close to correct for me on iPhone 5. I made the following modification to add an overlay hardcoded for iPhone 5:
CGRect f = imagePickerController.view.bounds;
f.size.height -= imagePickerController.navigationBar.bounds.size.height;
UIGraphicsBeginImageContext(f.size);
[[UIColor colorWithWhite:0 alpha:.5] set];
UIRectFillUsingBlendMode(CGRectMake(0, 0, f.size.width, 124.0), kCGBlendModeNormal);
UIRectFillUsingBlendMode(CGRectMake(0, 444, f.size.width, 52), kCGBlendModeNormal);
UIImage *overlayImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageView *overlayIV = [[UIImageView alloc] initWithFrame:f];
overlayIV.image = overlayImage;
overlayIV.alpha = 0.7f;
[imagePickerController setCameraOverlayView:overlayIV];`
I hope this helps someone.
NSDavidObject
Updated on October 19, 2020Comments
-
NSDavidObject over 3 years
I'm trying to create a camera like Instagram where the user can see a box and the image would crop to that box. For Some reason the camera doesn't go all the way to the bottom of the screen and cuts off near the end. I'm also wondering how would I go about cropping the image to be 320x320 exactly inside that square?
-
NSDavidObject almost 11 yearsThanks works great! I was wondering if there's anyway I can make the camera opening animation go on top of the overlay?
-
Ander almost 11 yearsNo, unfortunately there is no way of doing this using publicly documented APIs (i.e. without doing something that would cause Apple to reject the App). If you wanted to do this you properly you would need to reimplement
UIImagePickerController
. -
Bastien Beurier over 10 yearsWhat should we change to make it work on both iphone 5 and previous iphones?
-
Mark Lummus about 10 yearsMy experience with this on IOS7 on an iPhone 5 was not great. specifically, I could see the overlay, but I could not use the native zoom controls. finally, when I took the photo and the "Retake" and "Use Photo" buttons, appeared, I was not able to click either button. YMMV
-
Boosa Ramesh almost 10 yearshere may i know source is which type of variable and in which image picker delegate method we need to write above code
-
PaperThick over 9 yearsworked great at first but now I am getting memory issues when running this code. Anyone experiencing the same issue?
-
Martin Berger about 8 yearsThis solution uses
imagePickerController.cameraOverlayView
but that only works if source type isUIImagePickerControllerSourceTypeCamera
. docs -
frank almost 8 yearsThe square frame and the crop frame are slightly, but very noticeably, offset.