检测到iOS图像数据是HEIF或HEIC

时间:2017-10-19 12:36:54

标签: ios cocoa-touch uiimage heif

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

我这样做:

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

但我怎么知道数据是HEIF(或HEIC)?我可以查看一个文件: ([filePath hasSuffix:@".HEIC"] || [filePath hasSuffix:@".heic"] 但我认为这不是一个好的答案。还有其他解决方案吗?

5 个答案:

答案 0 :(得分:6)

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

UIImage不代表图像文件,甚至不代表图像文件格式的二进制数据UIImage最好被认为是在中编码的可显示图像的抽象表示,即数据 - 即UIImage是解码过程的结果。当你有一个UIImage对象时,它并不关心它来自哪种文件格式。

因此,正如@Ladislav's answer所述,如果您已经有UIImage并且您只想获取特定图像文件格式的数据,请调用其中一个便捷函数来获取UIImage进入文件格式的数据。正如其名称所暗示的那样,UIImageJPEGRepresentation返回适合写入JPEG文件的数据。

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

作为@ScottCorscadden implies,如果您还没有UIImage,因为您在较低级别工作,以便您可以访问原始文件数据,那么您需要检查数据以确定其格式,或者询问您获取数据的任何来源,以获取描述其格式的元数据。

如果您想检查数据本身,最好阅读HIEF格式标准。请参阅nokiatechMPEG groupwikipedia

HEIF容器格式和可能存储的媒体类型有很多,所以决定你是不是只有一个HEIF文件,而是一个与这个或那个观众兼容的HEIF / HEVC文件可能很棘手。既然你在谈论排除你的服务器不支持的东西,那么从的角度编写代码可能更容易,包括只有东西您的服务器支持。也就是说,如果您的数据没有元数据,请查找类似JPEG幻数0xffd8ff的内容,并使用它来排除任何非JPEG内容。

但更好的方法是寻找元数据。如果您使用PHImageManager. requestImageData(for:options:resultHandler:)从照片库中选择图像,则结果处理程序的第二个参数是图像数据的Uniform Type Identifier:对于HEIF和HEIC文件,{{1在野外发现了},public.heifpublic.heif-standard

(但是,如果您正在寻找“我的服务器不支持的图像”,那么您最好检查服务器支持的格式支持并拒绝任何不在其上的内容列表,而不是尝试识别所有可能不支持的格式。)

答案 1 :(得分:3)

当您发送到服务器时,您很可能正在解码UIImage并将其作为Data发送,所以只需执行

let data = UIImageJPEGRepresentation(image, 0.9)

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

答案 2 :(得分:1)

好吧,你可以看看魔术字节 - JPEG和PNG肯定是已知的,我似乎看到一些HEIF(.heic)以NUL字节开头的引用。如果您使用PHImageManager之类的任何requestImageDataForAsset:options:resultHandler方法,那么resultHandler将会传递NSString * _Nullable dataUTI引用。有一个像样的WWDC视频/幻灯片(可能here)表明,如果UTI不是kUTTypeJPEG你转换它(并且幻灯片中有一些较低级别的示例代码,以保存它方向也是。)

我还应该提一下,如果您在应用层控制并且所有上传都来自那里,请在那里完成所有这些。

答案 3 :(得分:0)

如果您使用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
  }
}

可以找到其他UTType here

答案 4 :(得分:0)

聚会晚了一点,但是除了检查扩展名(在最后一个点之后)之外,您还可以检查“魔术号码”,也就是文件签名。字节5到8应该为您提供常数“ ftyp”。接下来的4个字节将是主要品牌,我认为这是“ mif1”,“ heic”和“ heix”之一。 例如,.heic图像的前12个字节为:

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

将其除去0并修剪结果后,立即将其解码为ftypmif1