检测 iOS 图像数据是 HEIF 还是 HEIC

Posted

技术标签:

【中文标题】检测 iOS 图像数据是 HEIF 还是 HEIC【英文标题】:Detecting that iOS image data is HEIF or HEIC 【发布时间】:2017-10-19 12:36:54 【问题描述】:

我的服务器不支持 HEIF 格式。所以我需要在从我的应用上传之前将其转换为 JPEG。

我这样做:

UIImage *image = [UIImage imageWithData:imageData];                                 
NSData *data=UIImageJPEGRepresentation(image, 1.0);

但是我怎么知道数据是 HEIF(或 HEIC)?我可以看一个文件:

([filePath hasSuffix:@".HEIC"] || [filePath hasSuffix:@".heic"])

但我认为这不是一个好的答案。有没有其他解决办法?

【问题讨论】:

【参考方案1】:

现有的两个答案都有很好的建议,但试图讲述整个故事......

UIImage 不代表图像文件,甚至图像文件格式的二进制数据UIImage 最好被认为是编码该数据的可显示图像的抽象表示——也就是说,UIImage 是解码过程的结果。当你有一个 UIImage 对象时,它并不关心它来自什么文件格式。

因此,正如@Ladislav's answer 所指出的,如果您已经拥有UIImage,并且您只想获取特定图像文件格式的数据,请调用其中一个便捷函数以将UIImage 转换为文件格式数据。顾名思义,UIImageJPEGRepresentation 返回适合写入 JPEG 文件的数据。

如果您已经有UIImageUIImageJPEGRepresentation 可能是您最好的选择,因为无论原始图像格式如何,您都可以使用它。


作为@ScottCorscadden implies,如果您还没有UIImage,因为您在较低级别工作,因此您可以访问原始文件数据,那么您需要检查该数据推测它的格式,或者询问你从哪个来源获得数据的元数据来描述它的格式。

如果您想检查数据本身,最好阅读 HIEF 格式标准。请参阅nokiatech、MPEG group 或wikipedia。

HEIF 容器格式和可存储在其中的可能媒体类型有很多内容,因此请确定您是否不仅拥有 HEIF 文件,还拥有与这种或那种查看器兼容的 HEIF/HEVC 文件可能很棘手。由于您在谈论排除您的服务器支持的东西,因此从仅包含这些东西的角度编写代码可能会更容易您的服务器确实支持。也就是说,如果您有没有元数据的数据,请查找类似 JPEG 幻数 0xffd8ff 的内容,并使用它来排除任何不是 JPEG 的内容。

不过,更好的方法可能是查找元数据。如果您使用PHImageManager.requestImageData(for:options:resultHandler:) 从照片库中挑选图像,则结果处理程序的第二个参数是图像数据的Uniform Type Identifier:对于 HEIF 和 HEIC 文件,public.heifpublic.heif-standardpublic.heic 在野外被发现。

(同样,如果您正在寻找“我的服务器不支持的图像”,您最好检查您的服务器支持的格式并拒绝任何不支持的格式列表,而不是试图找出所有可能不受支持的格式。)

【讨论】:

【参考方案2】:

当您发送到您的服务器时,您很可能会解码UIImage 并将其发送为Data,所以就这样做

let data = UIImageJPEGRepresentation(image, 0.9)

只需确定最适合您的质量,这里是 0.9

【讨论】:

谢谢。但是我怎么知道数据是 HEIF(或 HEIC)?只判断file的后缀是什么?【参考方案3】:

聚会有点晚了,但除了检查扩展名(在最后一个点之后)之外,您还可以检查“幻数”又名文件签名。字节 5 到 8 应该给你常量“ftyp”。以下 4 个字节将是主要品牌,我相信它是“mif1”、“heic”和“heix”之一。 例如,.heic 图像的前 12 个字节是:

00 00 00 18 66 74 79 70 6d 69 66 31

其中,在删除 0 并修剪结果后,逐字解码为 ftypmif1

【讨论】:

其实前四个字节是:00 00 00 28作为第四个字节,ftyp之前的那个是左括号。【参考方案4】:

好吧,您可以查看魔术字节 - JPEG 和 PNG 肯定是已知的,而且我似乎看到一些 HEIF (.heic) 以 NUL 字节开头的引用。如果您使用任何PHImageManager 方法,例如requestImageDataForAsset:options:resultHandler,则该resultHandler 将被传递NSString * _Nullable dataUTI 引用。有一个不错的 WWDC 视频/幻灯片(可能是 here),如果 UTI 不是 kUTTypeJPEG,则建议您转换它(并且幻灯片有一些较低级别的示例代码可以快速执行它,以保持方向)。

我还应该提到,如果您在应用层拥有控制权并且所有上传都来自那里,那么所有这些都来自那里。

【讨论】:

【参考方案5】:

如果您正在使用Photos 框架并从照片库中导入图像,则在 WWDC17 期间简要提到了一个解决方案。一、导入核心服务:

import MobileCoreServices

然后,当您请求图像时,检查作为第二个参数返回给您的块的UTType

// asset: PHAsset
PHImageManager.default().requestImageData(for: asset, options: nil)  imageData, dataUTI, orientation, info in
  guard let dataUTI = dataUTI else  return 
  if !(UTTypeConformsTo(dataUTI as CFString, kUTTypeJPEG) || UTTypeConformsTo(dataUTI as CFString, kUTTypePNG)) 
    // imageData is neither JPG not PNG, possibly subject for transcoding
  

其他UTTypes可以找到here

【讨论】:

以上是关于检测 iOS 图像数据是 HEIF 还是 HEIC的主要内容,如果未能解决你的问题,请参考以下文章

如何让Android 支持HEIF 图片解码和加载(免费的方法)

在网络中显示苹果 heif 图像

heif-convert 错误:JPEG 支持尚未编译

OpenCV 是不是支持 .HEIC 图像格式?

Ubuntu (Linux) 上查看 HEIC 格式的图片 / 显示缩略图

hebzbx是啥格式的文件