【iOS】自定义相机(五)相机设置

摄像头

自定义相机需要完成闪光灯设置、摄像头切换、聚焦和曝光等关于摄像头的操作。一般涉及到摄像头操作,我们就需要使用AVCaptureDevice进行操作。

具体的相机设置代码可以参考SCCamera中的SCCameraManager.m代码,觉得有用的可以Star支持一下

基本技巧

  1. 在修改设置之前都需要判断当前设备是否支持supported
    • 比如用[device isFlashModeSupported:AVCaptureFlashModeOn]判断设备是否支持打开闪光灯
  2. 每次对设备进行修改前都需要获取设备上的一个排它锁
    • 应用程序有很多个,AVCaptureDevice对象也有很多个,但是硬件设备是有限的,因此,系统在我们设置相机的时候需要申请锁(lockForConfiguration:),并在设置完毕后释放锁(unlockForConfiguration)。

为了方便起见,我为AVCaptureDevice写了一个分类方法:

- (void)settingWithConfig:(void(^)(AVCaptureDevice* device, NSError* error))config {
    NSError *error;
    if ([self lockForConfiguration:&error]) {
        config(self, nil);
        [self unlockForConfiguration];
    }
    if (error) {
        config(nil, error);
    }
}

PS:调用此方法只需要在闭包中执行设备操作即可,默认进行锁的申请与释放。

※ 下面各种设备设置的介绍,代码部分均省略设备锁的获取与释放

聚焦模式

聚焦就是把目标对象的清晰度调至最高。

可用的聚焦的模式(AVCaptureFocusMode)有以下三种:

  • AVCaptureFocusModeLocked:锁定当前聚焦状态
  • AVCaptureFocusModeAutoFocus:自动聚焦模式
  • AVCaptureFocusModeContinuousAutoFocus:摄像头在需要的情况下持续地进行自动对焦。
    • 通过监听adjustingFocus这个属性可以找到设备当前是否在聚焦

PS:AVCaptureFocusModeAutoFocus=AVCaptureFocusModeContinuousAutoFocus+AVCaptureFocusModeLocked,即自动聚焦相当于设备持续聚焦完成后,自动设置为锁定状态

一般设备还会支持对某个兴趣点(PointOfInterest)进行聚焦。值得注意的是,该兴趣点的坐标系是设备坐标系({0,0}~{1,1}),可以使用AVCaptureVideoPreviewLayercaptureDevicePointOfInterestForPoint:方法进行获取。

if (device.isFocusPointOfInterestSupported && [device isFocusModeSupported:focusMode]) {
    device.focusPointOfInterest = point;
    // 需要设置 focusMode 才应用 focusPointOfInterest
    device.focusMode = focusMode;
}

曝光模式

曝光就是指相机的感光元件接受外界光线,再形成图像的过程,感光元件接收外界光线的多少直接影响照片的亮度。

可用曝光模式(AVCaptureExposureMode)有以下两种:

  • AVCaptureExposureModeLocked:锁定当前曝光状态
  • AVCaptureExposureModeAutoExpose:自动曝光模式
    • 实现类似于聚焦模式中的AVCaptureFocusModeAutoFocus
  • AVCaptureExposureModeContinuousAutoExposure:摄像头在需要的情况下持续自动曝光
  • AVCaptureExposureModeCustom:根据ISOexposureDuration进行曝光调整

曝光的使用于聚焦相似,它也可以在设备的支持下使用ExposurePointOfInterest

if (device.isExposurePointOfInterestSupported && [device isExposureModeSupported:exposureMode]) {
    device.exposurePointOfInterest = point;
    // 需要设置 exposureMode 才应用 exposurePointOfInterest
    device.exposureMode = exposureMode;
}

曝光的使用除了和聚焦一样都使用兴趣点设置和自动曝光,还能调整感光度ISO,做出亮度调整的操作(由于出现嵌套,这里的将会出现设备锁的代码):

if ([device lockForConfiguration:&error]) { // 第1次设置
    [device setExposureModeCustomWithDuration:device.exposureDuration ISO:val completionHandler:^(CMTime syncTime) {
        if ([device lockForConfiguration:&error]) { // 第2次设置
            [device setExposureMode:AVCaptureExposureModeCustom]; 
            [device unlockForConfiguration];
        }
    }];
    [device unlockForConfiguration];
}

ISO属性值需要根据大家的需要自行运算,在运算之前,我们可以通过device.activeFormat.minISOdevice.activeFormat.maxISO获取ISO的最大值和最小值,以免出现设备不支持导致崩溃的情况出现

PS:通过device.activeFormat我们可以获取很多硬件设备的信息,具体可到AVCaptureDeviceFormat的文档中查阅。

白平衡模式

白平衡指的是在任何拍摄场景的光源下,都能将白色的物体还原为白色。相机的白平衡控制,就是相机在不同的光线环境中把白色的物体拍出来的相片尽可能还原为标准的白色,其实就是为了使相片不发生偏色的过程。

可用的白平衡模式(AVCaptureWhiteBalanceMode)和聚焦模式相似,都是有三种:

  • AVCaptureWhiteBalanceModeLocked:锁定当前状态
  • AVCaptureWhiteBalanceModeAutoWhiteBalance:自动白平衡模式
  • AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance:持续自动白平衡模式
if ([device isWhiteBalanceModeSupported:mode]) {
    [device setWhiteBalanceMode:mode];
} 

缩放操作

在自定义相机中,我们需要通过捏合手势来控制镜头的远近,即缩放操作。缩放操作的使用比上面的ISO操作要更简单一点,只需要在合适的范围内进行一次设置即可。

if (device.activeFormat.videoMaxZoomFactor > factor && factor >= 1.0) {
    [device rampToVideoZoomFactor:factor withRate:4.0];
}
  • factor: 缩放因子
  • rate: 缩放速率

闪光灯操作

参照着平时使用相机,闪光灯是用三种模式AVCaptureFlashMode的:

  • AVCaptureFlashModeOff:关闭闪光灯
  • AVCaptureFlashModeOn:开启闪光灯
  • AVCaptureFlashModeAuto:设备会根据周围的光线环境来决定是否开启闪光灯
if ([device hasFlash]) { // 判断设备是否有闪光灯
    if ([device isFlashModeSupported: mode]) {
        device.flashMode = mode;
    }
}

手电筒操作

为了对场景进行持续补光,可以使用手电筒功能。一共有三种手电筒模式AVCaptureTorchMode

  • AVCaptureTorchModeOff:关闭手电筒
  • AVCaptureTorchModeOn:开启手电筒
  • AVCaptureTorchModeAuto:根据周围光线条件自动使用手电筒
if ([device hasTorch]) { // 判断设备是否有手电筒
    if ([device isTorchModeSupported: mode]) {
        device.torchMode = mode;        
    }
}

切换摄像头操作

正常手机都有两个摄像头,前置和后置,那么自定义相机就需要实现相机切换功能。切换相机其实就是切换一个输入流,那么就意味着我们需要修改当前的AVCaptureSession。还好,我们可以进行动态重新配置会话,也不用担心停止会话和重启会话带来的开销。

[session beginConfiguration];
[session removeInput:oldInput];
if ([session canAddInput:newInput]) {
    [session addInput:newInput];
} else {
    // 防止 newInput 不可用
    [session addInput:oldInput];
}
[session commitConfiguration];

注意事项:

  • 只要是涉及到会话配置,都需要将操作置于beginConfigurationcommitConfiguration之间
  • 切换会话操作也需要有放在sessionQueue中执行,以免影响主线程
  • ※ 由于有切换摄像头的操作,我们上面提到的一切摄像头的配置都应该放在sessionQueue中执行。一方面避免影响主线程,另一方面避免摄像头切换带来的Bug。

PS: sessionQueue是一个GCD的串行队列,我们通过串行队列异步执行达成在同一个子线程顺序执行的效果。

拓展

重置聚焦与曝光

自定义相机聚焦和曝光被调整后,想恢复到原来原始就需要使用以下的操作:

AVCaptureFocusMode focusMode = AVCaptureFocusModeContinuousAutoFocus;
AVCaptureExposureMode exposureMode = AVCaptureExposureModeContinuousAutoExposure;
BOOL canResetFocus = [device isFocusPointOfInterestSupported] &&
    [device isFocusModeSupported:focusMode];
BOOL canResetExposure = [device isExposurePointOfInterestSupported] &&
    [device isExposureModeSupported:exposureMode];
CGPoint centerPoint = CGPointMake(0.5f, 0.5f);
if (canResetFocus) {
    device.focusPointOfInterest = centerPoint;
    device.focusMode = focusMode;
}
if (canResetExposure) {
    device.exposurePointOfInterest = centerPoint;
    device.exposureMode = exposureMode;
}

PS:重置的方式其实就是将聚焦和曝光的兴趣点都设置为镜头中央,并且都采用一次性的自动模式。

具体的相机设置代码可以参考SCCamera中的SCCameraManager.m代码,觉得有用的可以Star支持一下

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容