简体   繁体   English

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

[英]Detecting that iOS image data is HEIF or HEIC

My server doesn't support the HEIF format.我的服务器不支持 HEIF 格式。 So I need to transform it to JPEG before uploading from my app.所以我需要在从我的应用程序上传之前将其转换为 JPEG。

I do this:我这样做:

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

But how can I know that the data is HEIF (or HEIC) ?但是我怎么知道数据是 HEIF(或 HEIC)? I can look at a file:我可以查看一个文件:

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

But I don't think it's a good answer.但我认为这不是一个好的答案。 Is there any other solution?还有其他解决方案吗?

Both existing answers have good recommendations, but to attempt to tell the whole story...现有的两个答案都有很好的建议,但试图讲述整个故事......

UIImage doesn't represent an image file or even binary data in an image-file format . UIImage不代表图像文件,甚至不代表图像文件格式的二进制数据 A UIImage is best thought of as an abstract representation of the displayable image encoded in that data — that is, a UIImage is the result of the decoding process.最好将UIImage视为该数据中编码的可显示图像的抽象表示——也就是说, UIImage是解码过程的结果。 By the time you have a UIImage object, it doesn't care what file format it came from.当您拥有UIImage对象时,它并不关心它来自什么文件格式。

So, as @Ladislav's answer notes, if you have a UIImage already and you just want to get data in a particular image file format, call one of the convenience functions for getting a UIImage into a file-formatted data.因此,正如@Ladislav 的回答所指出的那样,如果您已经有一个UIImage并且您只想以特定的图像文件格式获取数据,请调用其中一个方便的函数以将UIImage转换为文件格式的数据。 As its name might suggest, UIImageJPEGRepresentation returns data appropriate for writing to a JPEG file.顾名思义, UIImageJPEGRepresentation返回适合写入 JPEG 文件的数据。

If you already have a UIImage , UIImageJPEGRepresentation is probably your best bet, since you can use it regardless of the original image format.如果您已经拥有UIImageUIImageJPEGRepresentation可能是您最好的选择,因为无论原始图像格式如何,您都可以使用它。


As @ScottCorscadden implies , if you don't have a UIImage (yet) because you're working at a lower level such that you have access to the original file data, then you'll need to inspect that data to divine its format, or ask whatever source you got the data from for metadata describing its format.正如@ScottCorscadden 暗示的那样,如果您(还)没有UIImage因为您在较低级别工作,以便您可以访问原始文件数据,那么您需要检查该数据以判断其格式,或者询问您从哪个来源获取数据以获取描述其格式的元数据。

If you want to inspect the data itself, you're best off reading up on the HIEF format standards.如果您想检查数据本身,最好阅读 HIEF 格式标准。 See nokiatech , MPEG group , orwikipedia .请参阅nokiatechMPEG groupwikipedia

There's a lot going on in the HEIF container format and the possible kinds of media that can be stored within, so deciding if you have not just a HEIF file, but an HEIF/HEVC file compatible with this-or-that viewer could be tricky. HEIF 容器格式和可以存储在其中的可能类型的媒体有很多事情发生,因此决定您是否不仅拥有 HEIF 文件,还有与此或那个查看器兼容的 HEIF/HEVC 文件可能会很棘手. Since you're talking about excluding things your server doesn't support, it might be easier to code from the perspective of including only the things that your server does support.既然你在谈论的东西除外您的服务器支持,它可能是更容易代码仅包括您的服务器支持的事情的角度。 That is, if you have data with no metadata, look for something like the JPEG magic number 0xffd8ff , and use that to exclude anything that isn't JPEG.也就是说,如果您有没有元数据的数据,请查找类似 JPEG 幻数0xffd8ff ,并使用它来排除任何不是 JPEG 的内容。

Better, though, might be to look for metadata.不过,更好的方法可能是查找元数据。 If you're picking images from the Photos library with PHImageManager.如果您使用PHImageManager.从照片库中挑选图像PHImageManager. requestImageData(for:options:resultHandler:) , the second parameter to your result handler is the Uniform Type Identifier for the image data: for HEIF and HEIC files, public.heif , public.heif-standard , and public.heic have been spotted in the wild. requestImageData(for:options:resultHandler:) ,你的结果处理的第二个参数是统一类型标识符的图像数据:对于HEIF和HEIC文件, public.heifpublic.heif-standard ,并public.heic已被发现在野外。

(Again, though, if you're looking for "images my sever doesn't support", you're better off checking for the formats your server does support and rejecting anything not on that list, rather than trying to identify all the possible unsupported formats.) (同样,不过,如果你要寻找的“我的服务器不支持图像”,你最好检查格式服务器支持,并拒绝任何不在名单上,而不是试图找出所有可能的不支持的格式。)

When you are sending to your server you are most likely decoding the UIImage and sending it as Data so just do当您发送到您的服务器时,您很可能会解码UIImage并将其作为Data发送,所以就这样做

let data = UIImageJPEGRepresentation(image, 0.9)

Just decide what quality works best for you, here it is 0.9只需决定哪种质量最适合您,这里是 0.9

Well, you could look at magic bytes - JPEG and PNG certainly are known, and I seem to see some references that HEIF (.heic) starts with a NUL byte.好吧,您可以查看魔术字节 - JPEG 和 PNG 肯定是已知的,而且我似乎看到一些参考资料表明 HEIF (.heic) 以 NUL 字节开头。 If you're using any of the PHImageManager methods like requestImageDataForAsset:options:resultHandler , that resultHandler will be passed a NSString * _Nullable dataUTI reference.如果您正在使用任何PHImageManager方法,例如requestImageDataForAsset:options:resultHandler ,则该 resultHandler 将被传递一个NSString * _Nullable dataUTI引用。 There's a decent WWDC video/slides on this (possibly here ) that suggest if the UTI is not kUTTypeJPEG you convert it (and the slides have some lower-level sample code in swift to do it that preserve orientation too).有一个不错的 WWDC 视频/幻灯片(可能在这里)表明如果 UTI 不是kUTTypeJPEG您可以转换它(并且幻灯片有一些较低级别的示例代码可以快速执行以保持方向)。

I should also mention, if you have control at your app layer and all uploads come from there, do all this there.我还应该提到,如果您在应用层拥有控制权并且所有上传都来自那里,请在那里执行所有操作。

If you're using Photos framework and are importing images from photo library, there's a solution that was mentioned briefly during WWDC17.如果您正在使用Photos框架并从照片库导入图像,那么在 WWDC17 期间简要提到了一个解决方案。 First, import core services:一、导入核心服务:

import MobileCoreServices

Then, when you request the image, check the UTType that is returned as a second parameter to your block:然后,当您请求图像时,检查作为第二个参数返回到您的块的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
  }
}

Other UTTypes can be found here其他 UTType 可以在这里找到

A bit late to the party, but other than checking the extension (after the last dot), you can also check for the "magic number" aka file signature.聚会有点晚了,但除了检查扩展名(在最后一个点之后)之外,您还可以检查“幻数”,即文件签​​名。 Byte 5 to 8 should give you the constant "ftyp".字节 5 到 8 应该为您提供常量“ftyp”。 The following 4 bytes would be the major brand, which I believe is one of "mif1", "heic" and "heix".以下 4 个字节将是主要品牌,我认为它是“mif1”、“heic”和“heix”之一。 For example, the first 12 bytes of a .heic image would be:例如,.heic 图像的前 12 个字节将是:

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

which, after removing 0s and trim the result, literally decoded to ftypmif1 .在删除 0 并修剪结果后,从字面上解码为ftypmif1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM