9

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

我这样做:

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

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

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

但我认为这不是一个好的答案。还有其他解决方案吗?

4

5 回答 5

9

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

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

因此,正如@Ladislav 的回答所指出的那样,如果您已经有了 aUIImage并且只想获取特定图像文件格式的数据,请调用其中一个方便的函数来获取UIImage文件格式的数据。顾名思义,UIImageJPEGRepresentation返回适合写入 JPEG 文件的数据。

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


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

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

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

不过,更好的方法可能是寻找元数据。如果您从带有 的照片库中挑选图像,PHImageManager.requestImageData(for:options:resultHandler:)则结果处理程序的第二个参数是图像数据的统一类型标识符:对于 HEIF 和 HEIC 文件,public.heifpublic.heif-standardpublic.heic已在野外被发现。

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

于 2017-10-27T19:09:00.047 回答
3

当您发送到您的服务器时,您很可能会解码UIImage并发送它,Data就像这样

let data = UIImageJPEGRepresentation(image, 0.9)

只需决定哪种质量最适合您,这里是 0.9

于 2017-10-19T13:40:02.413 回答
2

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

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

其中,在删除 0 并修剪结果后,从字面上解码为ftypmif1.

于 2020-06-19T03:00:28.407 回答
1

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

我还应该提一下,如果您可以控制应用层并且所有上传都来自那里,那么就在那里进行所有这些操作。

于 2017-10-27T14:46:15.170 回答
1

如果您正在使用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 可以在这里找到

于 2018-06-22T19:28:29.267 回答