iOS 用前置摄像头闪光灯的新值覆盖 EXIF 闪光灯属性
Posted
技术标签:
【中文标题】iOS 用前置摄像头闪光灯的新值覆盖 EXIF 闪光灯属性【英文标题】:iOS overwrite EXIF flash property with new value for front camera flash 【发布时间】:2015-06-20 23:51:23 【问题描述】:我正在尝试更改 Exif 字典的 kCGImagePropertyExifFlash
属性。我的应用程序提供前置闪光灯模式,因此我正在尝试更改此 Exif 值。当我使用ALAssetsLibrary
的writeImageDataToSavedPhotosAlbum
方法保存newImageData
时,无论我做什么,它都会删除我设置的值。
如果能提供任何帮助,我将不胜感激。
[self.stillImageOutput captureStillImageAsynchronouslyFromConnection:
[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo]
completionHandler:^(CMSampleBufferRef imageSampleBuffer, NSError *error)
if (imageSampleBuffer && !error)
CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL, imageSampleBuffer, kCMAttachmentMode_ShouldPropagate);
NSDictionary *metadata = [NSDictionary dictionaryWithDictionary:(__bridge NSDictionary *)metadataDict];
CFRelease(metadataDict);
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
if (metadata && imageData)
NSMutableDictionary *newMetaData = [NSMutableDictionary dictionaryWithDictionary:metadata];
NSMutableDictionary *exifMetadata = [NSMutableDictionary dictionaryWithDictionary:
[metadata objectForKey:(NSString *)kCGImagePropertyExifDictionary]];
if (self.isUsingFrontCamera && exifMetadata)
if (self.flashButton.flashMode == On)
[exifMetadata setObject:@"On, Fired" forKey:(NSString *)kCGImagePropertyExifFlash];
else if (self.flashButton.flashMode == Off)
[exifMetadata setObject:@"Off, did not fire" forKey:(NSString *)kCGImagePropertyExifFlash];
else if (self.frontFlashAutoDidFire)
[exifMetadata setObject:@"Auto, Fired" forKey:(NSString *)kCGImagePropertyExifFlash];
[newMetaData setObject:exifMetadata forKey:(NSString *)kCGImagePropertyExifDictionary];
NSData *newImageData = [self writeMetadataIntoImageData:imageData metadata:newMetaData];
[ALAssetsLibrary.new writeImageDataToSavedPhotosAlbum:newImageData metadata:nil completionBlock:nil];
- (NSData *)writeMetadataIntoImageData:(NSData *)imageData metadata:(NSDictionary *)metadata
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef) imageData, NULL);
CFStringRef UTI = CGImageSourceGetType(source);
NSMutableData *data = [NSMutableData data];
CGImageDestinationRef destination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)data, UTI, 1, NULL);
CGImageDestinationAddImageFromSource(destination, source, 0, (__bridge CFDictionaryRef) metadata);
CGImageDestinationFinalize(destination);
CFRelease(destination);
CFRelease(source);
return data;
【问题讨论】:
【参考方案1】:当我在使用相机开发 ios 应用程序时遇到相同类型的问题时,我查找了一些典型的 EXIF 键,以及它们的标准翻译。
这是 EXIF flash 属性说明:
IFD Exif
代码 37385(十六进制 0x9209) 名字闪光说明
Indicates the status of flash when the image was shot.
Bit 0 indicates the flash firing status, bits 1 and 2 indicate the flash return status, bits 3 and 4 indicate the flash mode, bit 5 indicates whether the flash function is present, and bit 6 indicates "red eye" mode.
Values for bit 0 indicating whether the flash fired.
0 = Flash did not fire
1 = Flash fired
Values for bits 1 and 2 indicating the status of returned light.
00 = No strobe return detection function
01 = reserved
10 = Strobe return light not detected
11 = Strobe return light detected
Values for bits 3 and 4 indicating the camera's flash mode.
00 = unknown
01 = Compulsory flash firing
10 = Compulsory flash suppression
11 = Auto mode
Values for bit 5 indicating the presence of a flash function.
0 = Flash function present
1 = No flash function
Values for bit 6 indicating the camera's red-eye mode.
0 = No red-eye reduction mode or unknown
1 = Red-eye reduction supported
Not all combinations make sense though. The specification defines these combined values:
hex 0000 = Flash did not fire
hex 0001 = Flash fired
hex 0005 = Strobe return light not detected
hex 0007 = Strobe return light detected
hex 0009 = Flash fired, compulsory flash mode
hex 000D = Flash fired, compulsory flash mode, return light not detected
hex 000F = Flash fired, compulsory flash mode, return light detected
hex 0010 = Flash did not fire, compulsory flash mode
hex 0018 = Flash did not fire, auto mode
hex 0019 = Flash fired, auto mode
hex 001D = Flash fired, auto mode, return light not detected
hex 001F = Flash fired, auto mode, return light detected
hex 0020 = No flash function
hex 0041 = Flash fired, red-eye reduction mode
hex 0045 = Flash fired, red-eye reduction mode, return light not detected
hex 0047 = Flash fired, red-eye reduction mode, return light detected
hex 0049 = Flash fired, compulsory flash mode, red-eye reduction mode
hex 004D = Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected
hex 004F = Flash fired, compulsory flash mode, red-eye reduction mode, return light detected
hex 0059 = Flash fired, auto mode, red-eye reduction mode
hex 005D = Flash fired, auto mode, return light not detected, red-eye reduction mode
hex 005F = Flash fired, auto mode, return light detected, red-eye reduction mode
使用十六进制到十进制的转换和objective-C,这里有一个方法来翻译通过调用给出的枚举:
[[exifDictionary objectForKey : @"Flash"] integerValue]
变成一个 NSString 描述
-(NSString *) translateFlashEnumToNSString: (long) flash
switch (flash)
case 0:
return @"Flash did not fire";
case 1:
return @"Flash did fire";
case 5:
return @"Strobe return light not detected";
case 7:
return @"Strobe return light detected";
case 9:
return @"Flash fired, compulsory flash mode";
case 13:
return @"Flash fired, compulsory flash mode, return light not detected";
case 15:
return @"Flash fired, compulsory flash mode, return light detected";
case 16:
return @"Flash did not fire, compulsory flash mode";
case 24:
return @"Flash did not fire, auto mode";
case 25:
return @"Flash fired, auto mode";
case 29:
return @"Flash fired, auto mode, return light not detected";
case 31:
return @"Flash fired, auto mode, return light detected";
case 32:
return @"No flash function";
case 65:
return @"Flash fired, red-eye reduction mode";
case 69:
return @"Flash fired, red-eye reduction mode, return light not detected";
case 71:
return @"Flash fired, red-eye reduction mode, return light detected";
case 73:
return @"Flash fired, compulsory flash mode, red-eye reduction mode";
case 77:
return @"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected";
case 79:
return @"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected";
case 89:
return @"Flash fired, auto mode, red-eye reduction mode";
case 93:
return @"Flash fired, auto mode, return light not detected, red-eye reduction mode";
case 95:
return @"Flash fired, auto mode, return light detected, red-eye reduction mode";
default:
return @"Flash mode unsupported";
调用方法:
NSLog(@"Flash EXIF : %@", [self translateFlashEnumToNSString: [[exifDictionary objectForKey:@"Flash"] integerValue]];
希望它会有所帮助。 对于其他 EXIF 密钥及其描述:http://www.awaresystems.be/imaging/tiff/tifftags/privateifd/exif/flash.html
【讨论】:
【参考方案2】:我想通了;原来kCGImagePropertyExifFlash
是NSCFNumber
,而不是NSCFString
,这是我的问题。我能够记录 Flash 模式的默认整数值:
代码:
[self.stillImageOutput captureStillImageAsynchronouslyFromConnection:
[self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo]
completionHandler:^(CMSampleBufferRef imageSampleBuffer, NSError *error)
if (imageSampleBuffer && !error)
CFDictionaryRef metadataDict = CMCopyDictionaryOfAttachments(NULL, imageSampleBuffer, kCMAttachmentMode_ShouldPropagate);
NSDictionary *metadata = [NSDictionary dictionaryWithDictionary:(__bridge NSDictionary *)metadataDict];
CFRelease(metadataDict);
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
if (metadata && imageData)
NSMutableDictionary *newMetaData = [NSMutableDictionary dictionaryWithDictionary:metadata];
NSMutableDictionary *exifMetadata = [NSMutableDictionary dictionaryWithDictionary:
[metadata objectForKey:(NSString *)kCGImagePropertyExifDictionary]];
if (self.isUsingFrontCamera && exifMetadata)
if (self.flashButton.flashMode == On)
[exifMetadata setObject:@(9) forKey:(NSString *)kCGImagePropertyExifFlash];
else if (self.flashButton.flashMode == Off)
[exifMetadata setObject:@(16) forKey:(NSString *)kCGImagePropertyExifFlash];
else if (self.flashButton.flashMode == Auto)
[exifMetadata setObject:@(24) forKey:(NSString *)kCGImagePropertyExifFlash];
if (self.frontFlashAutoDidFire)
[exifMetadata setObject:@(25) forKey:(NSString *)kCGImagePropertyExifFlash];
[newMetaData setObject:exifMetadata forKey:(NSString *)kCGImagePropertyExifDictionary];
[ALAssetsLibrary.new writeImageDataToSavedPhotosAlbum:imageData metadata:newMetaData completionBlock:nil];
【讨论】:
以上是关于iOS 用前置摄像头闪光灯的新值覆盖 EXIF 闪光灯属性的主要内容,如果未能解决你的问题,请参考以下文章
Flutter小记3Android打开前置或广角摄像头的同时打开闪光灯方案