Cropping AVCaptureVideoPreviewLayer output to a square Cropping AVCaptureVideoPreviewLayer output to a square ios ios

Cropping AVCaptureVideoPreviewLayer output to a square


Have you tried to set videoGravity?

previewLayer = AVCaptureVideoPreviewLayer(session: captureSession)previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill


Even if the preview layer is square, keep in mind that the generated still image keeps its original size.

From what I see, the problem is here:

UIGraphicsBeginImageContext(CGSizeMake(width, width));[image drawInRect: CGRectMake(0, 0, width, width)];

You already made your context square with the first line. You still need to draw your image in its original format, it will be clipped by that context. On the second line, you are forcing the drawing of the original image in a square, thus making it look "squeezed".

You should find the right image height that keeps the original ratio while fitting your "width". Next, you will want to draw that image with the correct size (keeping the original ratio) in your square context. If you want to clip the center, change your Y position of the drawing.

Something similar to this:

- (void) processImage:(UIImage *)image {    UIGraphicsBeginImageContext(CGSizeMake(width, width));    CGFloat imageHeight = floorf(width / image.width * image.height);    CGFloat offsetY = floorf((imageHeight - width) / 2.0f);    [image drawInRect: CGRectMake(0, -offsetY, width, imageHeight)];    UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();    [captureImageGrab setImage:smallImage];}

That should do it.


Looking at the code it appears to me that you are drawing the image into a square. This is the part that shrinks the image without regard to the aspect ratio.

Instead, do something like this:

- (void) processImage:(UIImage *)image { //process captured image, crop, resize and rotate    haveImage = YES;    CGRect deviceScreen = _previewLayer.bounds;    CGFloat width = deviceScreen.size.width;    CGFloat height = deviceScreen.size.height;    NSLog(@"WIDTH %f", width); // Outputing 320    NSLog(@"HEIGHT %f", height); // Outputting 320    CGRect cropRect = CGRectZero;    if (image.size.width > image.size.height) {        cropRect.origin.x = (image.size.width-image.size.height)/2;        cropRect.size = CGSizeMake(image.size.height, image.size.height);    } else {        cropRect.origin.y = (image.size.height-image.size.width)/2;        cropRect.size = CGSizeMake(image.size.width, image.size.width);    }    CGImageRef croppedImage = CGImageCreateWithImageInRect(image.CGImage, cropRect);    UIGraphicsBeginImageContext(CGSizeMake(width, width));    [[UIImage imageWithCGImage:croppedImage] drawInRect:CGRectMake(0, 0, width, width)];    UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();    CGImageRelease(croppedImage);    [captureImageGrab setImage:[UIImage imageWithCGImage:smallImage.CGImage scale:image.scale orientation:image.imageOrientation]];}