4

I work with Swift 3 and I use camera AVFoundation

Who know is there any way to know capacity of light?

I know that one of the approach is use ambient light sensor, but it is don't encourage and eventually apps doesn't allows in market

I found question very close to that I need

detecting if iPhone is in a dark room

And that guy explains that I can use ImageIO framework, read the metadata that's coming in with each frame of the video feed

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {
  CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL, sampleBuffer, kCMAttachmentMode_ShouldPropagate);
  NSDictionary *metadata = [[NSMutableDictionary alloc] initWithDictionary:(__bridge NSDictionary*)metadataDict];
  CFRelease(metadataDict);
  NSDictionary *exifMetadata = [[metadata objectForKey:(NSString *)kCGImagePropertyExifDictionary] mutableCopy];
  float brightnessValue = [[exifMetadata objectForKey:(NSString *)kCGImagePropertyExifBrightnessValue]  floatValue];
}

But I am a rookie in iOS and don't know how to convert this code in Swift

Thanks in advance!

haxpor
  • 2,431
  • 3
  • 27
  • 46
Sirop4ik
  • 4,543
  • 2
  • 54
  • 121

2 Answers2

18

Following code implementation is in Swift 3.x

It is possible to get an approximate luminosity value(measured in unit lux) using the EXIF data of the camera. Please refer to the following link. Using a camera as a lux meter

Here the sampleBuffer value of captureOutput method in AVFoundation is used to extract the EXIF data from camera frames.

func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, from connection: AVCaptureConnection!) {

    //Retrieving EXIF data of camara frame buffer
    let rawMetadata = CMCopyDictionaryOfAttachments(nil, sampleBuffer, CMAttachmentMode(kCMAttachmentMode_ShouldPropagate))
    let metadata = CFDictionaryCreateMutableCopy(nil, 0, rawMetadata) as NSMutableDictionary
    let exifData = metadata.value(forKey: "{Exif}") as? NSMutableDictionary

    let FNumber : Double = exifData?["FNumber"] as! Double
    let ExposureTime : Double = exifData?["ExposureTime"] as! Double
    let ISOSpeedRatingsArray = exifData!["ISOSpeedRatings"] as? NSArray
    let ISOSpeedRatings : Double = ISOSpeedRatingsArray![0] as! Double
    let CalibrationConstant : Double = 50 

    //Calculating the luminosity
    let luminosity : Double = (CalibrationConstant * FNumber * FNumber ) / ( ExposureTime * ISOSpeedRatings )  

    print(luminosity)}

Please note that the value of CalibrationConstant can be calibrated according the application as explained in the reference.

AnuradhaH
  • 512
  • 4
  • 14
  • Is it normal that I get high values with little light in the environment and low values with lots of light? Thank you – Cristina Dec 29 '17 at 16:46
  • It is not. luminance is a measure of how much luminous flux is spread over a given area. So it should be directly proportional to illumination on a surface which depends on the amount light of environment. (https://en.wikipedia.org/wiki/Lux) – AnuradhaH Jan 03 '18 at 06:45
  • 1
    It's been three years since this answer, but you've just saved me a few days of work, thank you! – Dmytro Grynets Aug 06 '21 at 12:00
0

Follow these steps to get the EXIF data from captured Image.

  • Get Image data from sample buffer.

let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)

  • use the below helper function to get the EXIF data of your need
func getEXIFFromImage(image:NSData) -> NSDictionary {
    let imageSourceRef = CGImageSourceCreateWithData(image, nil);
    let currentProperties = CGImageSourceCopyPropertiesAtIndex(imageSourceRef!, 0, nil)
    let mutableDict = NSMutableDictionary(dictionary: currentProperties!)
    return mutableDict
}
Bluewings
  • 3,438
  • 3
  • 18
  • 31
  • There is some issues : AVCaptureStillImageOutput is deprecated and another anyway this method `AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(sampleBuffer)` return `Data` , but this method `getEXIFFromImage(image:NSData)` need to get `NSData`... what do you think? – Sirop4ik Jan 30 '17 at 11:29
  • And anyway there is one more issue... if I try get value by key `kCGImagePropertyExifBrightnessValue` I get `nil` ... Do you know why? – Sirop4ik Jan 30 '17 at 14:56