最新有拍照的需求是这样的 ~
手动点击屏幕聚焦,聚焦完成之后就自动拍照
于是开始各种脑补,在别人的基本拍照框架上进行改造 ~
据说IOS 6开放了相机的自动对焦API,看到这里我就觉得稳了
//更改设备属性前一定要锁上
-(void)changeDevicePropertySafety:(void (^)(AVCaptureDevice *captureDevice))propertyChange{
//也可以直接用_videoDevice,但是下面这种更好
AVCaptureDevice *captureDevice= [_input device];
//AVCaptureDevice *captureDevice= self.device;
NSError *error;
//注意改变设备属性前一定要首先调用lockForConfiguration:调用完之后使用unlockForConfiguration方法解锁,意义是---进行修改期间,先锁定,防止多处同时修改
BOOL lockAcquired = [captureDevice lockForConfiguration:&error];
if (!lockAcquired) {
NSLog(@"锁定设备过程error,错误信息:%@",error.localizedDescription);
}else{
[_session beginConfiguration];
propertyChange(captureDevice);
[captureDevice unlockForConfiguration];
[_session commitConfiguration];
}
}
// 点击屏幕,触发聚焦
- (void)cameraDidSelected:(ZLCameraView *)camera{
// 当设置完成之后,需要回调到上面那个方法⬆️
[self changeDevicePropertySafety:^(AVCaptureDevice *captureDevice) {
// 触摸屏幕的坐标点需要转换成0-1,设置聚焦点
CGPoint cameraPoint= [self.preview captureDevicePointOfInterestForPoint:camera.point];
/*****必须先设定聚焦位置,在设定聚焦方式******/
//聚焦点的位置
if ([self.device isFocusPointOfInterestSupported]) {
[self.device setFocusPointOfInterest:cameraPoint];
}
// 聚焦模式
if ([self.device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
[self.device setFocusMode:AVCaptureFocusModeAutoFocus];
}else{
NSLog(@"聚焦模式修改失败");
}
//曝光点的位置
if ([self.device isExposurePointOfInterestSupported]) {
[self.device setExposurePointOfInterest:cameraPoint];
}
//曝光模式
if ([self.device isExposureModeSupported:AVCaptureExposureModeAutoExpose]) {
[self.device setExposureMode:AVCaptureExposureModeAutoExpose];
}else{
NSLog(@"曝光模式修改失败");
}
// 防止点击一次,多次聚焦,会连续拍多张照片
self.canTakePicture = YES;
}];
}
聚焦完成了,那么就是拍照了
于是又是各种问,各种 🔍,发现苹果没有提供对焦成功的事件,但是提供了对焦发生改变的属性那么,是可以监听这个属性 adjustingFocus
// 监听焦距发生改变
-(void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context {
if([keyPath isEqualToString:@"adjustingFocus"]){
BOOL adjustingFocus =[[change objectForKey:NSKeyValueChangeNewKey] isEqualToNumber:[NSNumber numberWithInt:1]];
NSLog(@"adjustingFocus~~%d change~~%@", adjustingFocus, change);
// 0代表焦距不发生改变 1代表焦距改变
if (adjustingFocus == 0) {
}
}
}
// 增加监听
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
AVCaptureDevice *camDevice =[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
int flags =NSKeyValueObservingOptionNew;
[camDevice addObserver:self forKeyPath:@"adjustingFocus" options:flags context:nil];
}
// 移除监听
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
AVCaptureDevice*camDevice =[AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
[camDevice removeObserver:self forKeyPath:@"adjustingFocus"];
}
问题来了,焦距发生改变,不一定最清楚的
后来发现adjustingFocus
的值为0的时候(聚焦没有改变)
聚焦基本是完成。并且还有时候,聚焦一次(adjustingFocus会有两次打印 1:聚焦发生改变 0:聚焦没有改变),有的时候会聚焦两次(adjustingFocus会有四次打印 1 0 1 0)。这两种方式都是最后的0处有较清楚的图片
于是我增加了延时,让每次拍照,都能保证在最后的adjustingFocus = 0的地方,我测试都可以得到较清楚的照片,现在只能先这样了 ~ 有更好的方式记得@me
// 监听焦距发生改变
-(void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary*)change context:(void*)context {
if([keyPath isEqualToString:@"adjustingFocus"]){
BOOL adjustingFocus =[[change objectForKey:NSKeyValueChangeNewKey] isEqualToNumber:[NSNumber numberWithInt:1]];
NSLog(@"adjustingFocus~~%d change~~%@", adjustingFocus, change);
// 0代表焦距不发生改变 1代表焦距改变
if (adjustingFocus == 0) {
// 判断图片的限制个数
if ((self.images.count == 1 && self.cameraType == ZLCameraSingle) || !self.GraphRecognition || !self.canTakePicture) {
return;
}
// 点击一次可能会聚一次焦,也有可能会聚两次焦。一次聚焦,图像清晰。如果聚两次焦,照片会在第二次没有聚焦完成拍照,应为第一次聚焦完成会触发拍照,而拍照时间在第二次未聚焦完成,图像不清晰。增加延时可以让每次都是聚焦完成的时间点
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[NSThread sleepForTimeInterval:0.2];
dispatch_sync(dispatch_get_main_queue(), ^{
// 拍照
[self stillImage:nil];
});
});
}
}
}
最后附上代码 ~ demo下了好久了,来不及找到在哪里下的 ~ 如有知道,@我,我会第一时间注明出处 下载