iphone - AVFoundation - 如何控制曝光

标签 iphone objective-c avfoundation

AFTER 点击拍照后,我想锁定曝光并在曝光不再调整后立即关闭手电筒。所以,我添加了一个观察者来处理调整曝光:

- (IBAction)configureImageCapture:(id)sender
{
    [self.session beginConfiguration];

    [self.cameraController device:self.inputDevice exposureMode:AVCaptureExposureModeAutoExpose];
    [self.cameraController device:self.inputDevice torchMode:AVCaptureTorchModeOn torchLevel:0.8f];

    [self.session commitConfiguration];

    [(AVCaptureDevice *)self.inputDevice addObserver:self forKeyPath:@"adjustingExposure" options:NSKeyValueObservingOptionNew context:MyAdjustingExposureObservationContext];        
}

这是 observeValueForKeyPath 方法:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (context == MyAdjustingExposureObservationContext) {
        if( [keyPath isEqualToString:@"adjustingExposure"] )
        {
            BOOL adjustingExposure = [ [change objectForKey:NSKeyValueChangeNewKey] isEqualToNumber:[NSNumber numberWithInt:1] ];

            if (!adjustingExposure)
            {
                [(AVCaptureDevice *)self.cameraController.inputDevice removeObserver:self forKeyPath:@"adjustingExposure"];

                if ([self.inputDevice isExposureModeSupported:AVCaptureExposureModeLocked]) {
                    dispatch_async(dispatch_get_main_queue(),
                                   ^{
                                       NSError *error = nil;
                                       if ([self.inputDevice lockForConfiguration:&error]) {
                                           // 5) lock the exposure
                                           [self.cameraController device:self.inputDevice exposureMode:AVCaptureExposureModeLocked];

                                           // 6) turn off the Torch
                                           [self.cameraController device:self.inputDevice torchMode:AVCaptureTorchModeOn torchLevel:0.0001f];

                                           [self.inputDevice unlockForConfiguration];
                                       }
                                   });
                }                    
            }
        }
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

@user3115647 发布了这个 information ,这正是我想要做的。

但我的照片是在手电筒关闭之前拍摄的。

这是我的 captureStillImageAsynchronouslyFromConnection:self.captureConnection completionHandler。此 block 发生在拍摄图像之后。 observeValueForKeyPath 应该在相机拍摄图像之前调整曝光时发生。但是在拍摄图像之前,我的手电筒并没有走低。这是一个时间问题,或者我没有正确设置相机配置。

- (void)captureImage
{
    // configureImageCapture has already been done
    [self.stillImageOutput captureStillImageAsynchronouslyFromConnection:self.captureConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error)
     {
         if (imageSampleBuffer != NULL)
         {
             // Log the image properties
             CFDictionaryRef attachmentsRef = CMGetAttachment(imageSampleBuffer, kCGImagePropertyExifDictionary, NULL);
             NSDictionary *properties = (__bridge NSDictionary *)(attachmentsRef);
             NSLog(@"Image Properties => %@", (properties.count) ? properties : @"none");

最佳答案

通过使用闪光灯而不是手电筒,我得到了类似的结果。我也有一个 @"videoDevice.flashActive" 的观察者。我确实首先尝试使用 exposureModeLocked,但它对我也不起作用。

  1. 打开闪光灯拍照
  2. 然后在曝光有时间调整之前立即关闭闪光灯并拍摄另一张照片

下面的代码可能不能独立运行,而是根据我所做的进行了简化。

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context
{
    if (context == AdjustingExposureContext)
    {
        self.isAdjustingExposure = [change[NSKeyValueChangeNewKey] boolValue];
    }
    else if (context == FlashModeChangedContext)
    {
        self.isFlashActive = [change[NSKeyValueChangeNewKey] boolValue];
        if (!self.flashActive)
        {
            [self captureImage];  // QUICKLY! capture 2nd image without
        }                         // flash before exposure adjusts
    }
    if (!self.isAdjustingExposure && self.flashActive)
    {
        [self removeObserver:self forKeyPath:@"videoDevice.adjustingExposure" context:AdjustingExposureContext];
        [self captureImage];  // capture 1st image with the flash on
    }
}

现在在 captureStillImageAsynchronouslyFromConnection: 的回调中,

if (self.isFlashActive)
    [self.videoDeviceInput.device setFlashMode:NO];

但是,如果您需要在不使用闪光灯的情况下以较低的曝光度拍摄多张照片,则此策略可能不起作用。

关于iphone - AVFoundation - 如何控制曝光,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22029381/

相关文章:

iphone - applicationWillResignActive x 屏幕保护程序

iphone - UIScrollView 和 setContentOffset

ios - 想要固定方向,但 UIImage 自动旋转

ios - 如何查找为什么 iOS 应用程序的主线程在 "semaphore_timedwait_trap"上被阻止?

ios - 为什么 audioRecorderDidFinishRecording 没有被调用?能够成功录制和播放音频

swift - 从 AVFoundation 捕获与 Swift 中 AVCaptureVideoPreviewLayer 上的取景器边框匹配的静止图像

iphone - 将 CGPoint 沿某个方向移动一定距离...iphone

ios - FIRInstanceID 在 FIRInstanceIDAPNSTokenType.Sandbox 中为零

iphone - Objective-c iPhone 百分比编码一个字符串?

objective-c - AVAudioPlayer 只播放部分声音