iOS如何无需加载DNG图像、不使用CIFilter读取其分辨率?
嘿,我之前也踩过DNG分辨率读取的坑!你说的这两个API其实都有门道,尤其是CGImageSourceCopyPropertiesAtIndex,你没拿到正确的分辨率大概率是选项没设置对。
先给你说最靠谱的系统方法——不用加载整个DNG,也不用CIFilter:
你需要给CGImageSourceCopyPropertiesAtIndex传一个包含kCGImageSourceShouldCache: kCFBooleanFalse的选项字典。这个选项会告诉系统不要缓存整个图像数据,只读取必要的元数据和属性,这样就不会默认返回预览图的信息,而是直接拿到主图像(索引0)的真实分辨率。
代码示例
Objective-C版本
NSURL *dngURL = [NSURL fileURLWithPath:@"/path/to/your.dng"]; CGImageSourceRef source = CGImageSourceCreateWithURL((__bridge CFURLRef)dngURL, NULL); if (source) { CFDictionaryRef options = (__bridge CFDictionaryRef)@{ (NSString *)kCGImageSourceShouldCache: @NO }; CFDictionaryRef properties = CGImageSourceCopyPropertiesAtIndex(source, 0, options); if (properties) { NSNumber *width = (__bridge NSNumber *)CFDictionaryGetValue(properties, kCGImagePropertyPixelWidth); NSNumber *height = (__bridge NSNumber *)CFDictionaryGetValue(properties, kCGImagePropertyPixelHeight); NSLog(@"DNG真实分辨率: %@x%@", width, height); CFRelease(properties); } CFRelease(source); }
Swift版本
guard let dngURL = URL(fileURLWithPath: "/path/to/your.dng") else { return } guard let source = CGImageSourceCreateWithURL(dngURL as CFURL, nil) else { return } let options: CFDictionary = [kCGImageSourceShouldCache: false] as CFDictionary guard let properties = CGImageSourceCopyPropertiesAtIndex(source, 0, options) as? [CFString: Any] else { return } if let width = properties[kCGImagePropertyPixelWidth] as? Int, let height = properties[kCGImagePropertyPixelHeight] as? Int { print("DNG真实分辨率: \(width)x\(height)") }
为什么之前没成功?
你之前用CGImageSourceCopyPropertiesAtIndex只拿到预览图分辨率,大概率是没加kCGImageSourceShouldCache: NO这个选项。默认情况下,系统为了加载速度,会优先返回嵌入的预览图属性,而不是主图像的核心属性。加上这个选项后,系统会直接解析主图像的元数据,不会“偷懒”用预览图。
至于CGImageSourceCopyMetadataAtIndex,它返回的是EXIF、IPTC这类标准元数据,很多DNG文件不会把分辨率存在这些标准元数据里,而是直接存在图像的核心属性中,所以这个API拿不到很正常。
如果上面的方法还是不行,那可能你的DNG文件是专业相机导出的特殊格式,这时候确实可能需要第三方库(比如libraw或者libexif),但我个人觉得系统API应该能覆盖绝大多数情况,先试试上面的代码再说。
内容的提问来源于stack exchange,提问作者igor

