AVFoundation - 如何控制曝光

时间:2014-02-26 00:45:34

标签: iphone objective-c avfoundation

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

- (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。拍摄图像后会出现此块。当摄像机在拍摄图像之前调整曝光时,应该发生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");

2 个答案:

答案 0 :(得分:1)

通过使用闪光而不是火炬,我得到了类似的东西。我也有@"videoDevice.flashActive"的观察员。我确实首先尝试使用exposureModeLocked,但它对我也不起作用。

  1. 使用闪光灯拍摄照片
  2. 然后立即关闭闪光灯并拍摄另一张照片,然后再进行曝光调整
  3. 下面的代码可能不仅仅是单独工作,而是简化了我的工作。

    - (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];
    

    但是,如果您需要在降低曝光时拍摄多张没有闪光灯的照片,则此策略可能无效。

答案 1 :(得分:1)

这几乎肯定是一个时间问题。在captureStillImageAsynchronouslyFromConnection:completionHandler:区块内拨打if。然后在锁定曝光后始终执行捕获。

if ([self.inputDevice isExposureModeSupported:AVCaptureExposureModeLocked]) {
    dispatch_async(dispatch_get_main_queue(), 
        ^{
            NSError *error = nil;
            if ([self.inputDevice lockForConfiguration:&error]) {
                //code to lock exposure here
                //take photo here
            }
        });
}