I am cloning Apple's camera app using AVCaptureSession based on Apple's AppCam app sample. The problem is I cannot see focus rectangle in the video preview screen. I used following code for setting focus, but still focus rectangle is not shown.
AVCaptureDevice *device = [[self videoInput] device];
if ([device isFocusModeSupported:focusMode] && [device focusMode] != focusMode) {
NSError *error;
printf(" setFocusMode \n");
if ([device lockForConfiguration:&error]) {
[device setFocusMode:focusMode];
[device unlockForConfiguration];
} else {
id delegate = [self delegate];
if ([delegate respondsToSelector:@selector(acquiringDeviceLockFailedWithError:)]) {
[delegate acquiringDeviceLockFailedWithError:error];
}
}
}
When I use UIImagePickerController, auto focus, tap focus are supported by default, and can see focus rectangle. Is there no way to show focus rectangle in the video preview layer using AVCaptureSession?
The focus animation is a complete custom animation which you have to create by your own. I am currently having exact the same problem like you: I want to show a rectangle as a feedback for the user after he tapped the preview layer.
The first thing you want to do is implementing the tap-to-focus, probably where you initiate the preview layer:
UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapToFocus:)];
[tapGR setNumberOfTapsRequired:1];
[tapGR setNumberOfTouchesRequired:1];
[self.captureVideoPreviewView addGestureRecognizer:tapGR];
Now implement the tap-to-focus method itself:
-(void)tapToFocus:(UITapGestureRecognizer *)singleTap{
CGPoint touchPoint = [singleTap locationInView:self.captureVideoPreviewView];
CGPoint convertedPoint = [self.captureVideoPreviewLayer captureDevicePointOfInterestForPoint:touchPoint];
AVCaptureDevice *currentDevice = currentInput.device;
if([currentDevice isFocusPointOfInterestSupported] && [currentDevice isFocusModeSupported:AVCaptureFocusModeAutoFocus]){
NSError *error = nil;
[currentDevice lockForConfiguration:&error];
if(!error){
[currentDevice setFocusPointOfInterest:convertedPoint];
[currentDevice setFocusMode:AVCaptureFocusModeAutoFocus];
[currentDevice unlockForConfiguration];
}
}
}
The last thing, which i haven't implemented by myself yet, is to add the focusing animation to the preview layer or rather the view controller which is holding the preview layer. I believe that could be done in tapToFocus:. There you already have the touch point. Simply add a animated image view or some other view which has the touch position as its center. After the animation has finished, remove the image view.
Swift implementation
Gesture:
private func focusGesture() -> UITapGestureRecognizer {
let tapRec: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(kTapToFocus))
tapRec.cancelsTouchesInView = false
tapRec.numberOfTapsRequired = 1
tapRec.numberOfTouchesRequired = 1
return tapRec
}
Action:
private func tapToFocus(gesture : UITapGestureRecognizer) {
let touchPoint:CGPoint = gesture.locationInView(self.previewView)
let convertedPoint:CGPoint = previewLayer!.captureDevicePointOfInterestForPoint(touchPoint)
let currentDevice:AVCaptureDevice = videoDeviceInput!.device
if currentDevice.focusPointOfInterestSupported && currentDevice.isFocusModeSupported(AVCaptureFocusMode.AutoFocus){
do {
try currentDevice.lockForConfiguration()
currentDevice.focusPointOfInterest = convertedPoint
currentDevice.focusMode = AVCaptureFocusMode.AutoFocus
currentDevice.unlockForConfiguration()
} catch {
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With