Capturing zoomed preview view in AVFoundation

2019-01-31 10:14发布

I am working with zoom functionality in AVFoundation camera, i have implemented zoom by scaling the view that has AVCaptureVideoPreviewLayer. Now i want to capture the zoomed image.

here is my code for adding AVFoundationVideoPreviewLayer to view:

 // create a uiview subclass for showing the camera feed
 UIView *previewView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 430)];
 [[self view] addSubview:previewView];

 CGRect layerRect = CGRectMake(0, 0, 320, 430);
 [[self avCaptureVideoPreviewLayer] setBounds:layerRect];

 [[self  previewLayer] setPosition:CGPointMake(CGRectGetMidX(layerRect), CGRectGetMidY(layerRect))];

 // add the video previewview layer to the preview view
 [[previewView layer] addSublayer:[self avCaptureVideoPreviewLayer]];

code for zooming preview view

  // zoom the preview view using core graphics
 [previewView setTransform:CGAffineTransformMakeScale(2.0, 2.0 )];

Now i want to capture this zoomed image from previewView

Thanks in advance.

4条回答
放荡不羁爱自由
2楼-- · 2019-01-31 10:45

Finally i have managed to add capturing zoomed photo in my app. Its a bit ugly but it works. I used UIImage+resize code from the net and then scaled the image to zoom scale, and the calculated the offset position for the zoomed region [that is visible in the camera view] and then i cropped it.

Now my app crashes sometimes when the zoom scale is at max i.e. at 6x. I am receiving memory problem as the zoomed image is too big, i will ask this as a another question.

Hoping this code might be usefull for someone.

 if (cameraZoom > 1.0) 
 {
        // save the images original size
        CGSize orgSize = [image size];  

        // resize the image to the zoom scale  
        image = [image resizedImage:CGSizeMake(image.size.width * cameraZoom, image.size.height *cameraZoom) interpolationQuality:kCGInterpolationNone];           

        // now calculate the offset x and offset y
        CGFloat offsetX = ( image.size.width / 2 ) - (orgSize.width /2) ;
        CGFloat offsetY =  ( image.size.height / 2 ) - (orgSize.height /2);

         // crop the image from the offset position to the original width and height
         image = [image croppedImage:CGRectMake(offsetX, offsetY, orgSize.width, orgSize.height)];
    }


    UIButton *imgBtn = (UIButton *)[self.view viewWithTag:500];
    [imgBtn setImage:image forState:UIControlStateNormal];
查看更多
等我变得足够好
3楼-- · 2019-01-31 10:55

I was able to accomplish cropping first and then zooming using core graphics image transforms. Notice that we keep the original image size and scale in the image buffer and do the zoom feature completely with transform operations on the individual pixels. Note that this code does not take into account the device orientation (in my case I only use portrait upright currently), but could easily be accomplished with an additional rotation transform:

UIGraphicsBeginImageContextWithOptions(imageSize,NO,1.0); // this will crop

CGContextRef context = UIGraphicsGetCurrentContext();


CGRect newRect = CGRectMake(0, 0, width, height);

// apply a scaling transform to zoom
// rotate about the center
// First we scale, then rotate, then translate
// actual matrix multiplication steps are applied in reverse when using
// right-handed coordinate system
// M' = M * translatation * rotation * scale
CGContextTranslateCTM(context, (width - scaledWidth)*0.5f,
                               (height-scaledHeight)*0.5f);
CGContextScaleCTM(context,scaleFactor,scaleFactor);

[sourceImage drawInRect:newRect];

newImage = UIGraphicsGetImageFromCurrentImageContext();
if (newImage == nil) {
    NSLog(@"could not scale image");
}

// pop the context to get back to the default
UIGraphicsEndImageContext();
查看更多
小情绪 Triste *
4楼-- · 2019-01-31 11:02

I'm setting image scale and crop directly with:

AVCaptureConnection *stillImageConnection = [_stillImageOutput.connections objectAtIndex:0];
[stillImageConnection setVideoScaleAndCropFactor:imagePreviewScale];

It supposed to work only with video connections but for still image works also like a charm.

查看更多
在下西门庆
5楼-- · 2019-01-31 11:06

You should try crop first and then resize, that way you will not memory problem.

What you are doing now is like: 600X600 image will become 3600X3600 when 6x, then you crop it, that will give 600X600 again. But, why dont you try 600X600 with crop of 6x gives 100X100, then resize it to 600X600 again.

It may possible that if original resolution is low then output image of both process differ a bit, but if original resolution is 8MP/5MP/3MP (highest in 5/4s/4/3G) then output will be nearly similar.

So, to get better result, use you process when low resolution and for high resolution use reverse one that I suggested above.

查看更多
登录 后发表回答