# HEIF 和 HEVC 研究

在升级 iOS 11 之后，iPhone 7 及更新的设备内的照片存储将不再用 JPEG 了，而采用了一种新的图片格式 HEIF（发音同 heef），在 iOS 中对应的文件后缀为 .heic ，其编码用的是 HEVC（这个发不了音，哈哈哈）格式，又称 H.265 （这个就很熟悉了 H.264 的下一代），同时视频也用 HEVC 作为编码器，对应的文件后缀还是 .mov 。

这里要注意他们俩的关系， HEIF 是图片格式，而 HEVC 是编码格式(类似 H.264,VP8)，HEIF 是图片容器（类似于视频的 mkv，mp4 后缀），而用 HEVC 进行编码的 HEIF 图片就是后缀为 .heic 的图片，也是苹果主要使用的格式。

这两个都是很新的标准，分别在 2015 和 2013 年才被 ISO 批准。这篇文章主要介绍一下 HEIF 格式和与其他图片格式相比的优劣。\
发展史如下：

![](https://1795314173-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LAdZ7gFz4IllRQpWbzu%2F-LAdZ8MxWrHaExfP4jSI%2F-LAdZWOs52JkMRqzItG7%2FHEIF1.png?generation=1524337111362018\&alt=media)

图1

## 什么是 HEIF？

HEIF 全称 High Efficiency Image Format (HEIF)。是由 Moving Picture Experts Group 制定的，存储图片和图片序列的格式。\
相关的介绍位置这边可以看到 <https://nokiatech.github.io/heif/> ，对的，你没有看错，是 Nokia 的技术人员们制定的。相比 JPEG ，PNG 等传统的图片格式来说， HEIF 可算是相当年轻了，但是这种格式相比 JPEG 等有很多的优点。

* 压缩比高，在相同的图片质量情况下，平比 JPEG 高两倍。
* 能增加如图片深度信息，透明通道等辅助图片。(苹果正是通过这个就能实现动态的调整图片的景深)。

![](https://1795314173-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LAdZ7gFz4IllRQpWbzu%2F-LAdZ8MxWrHaExfP4jSI%2F-LAdZWQo7pCsF_ezgLax%2FHEIF2.jpg?generation=1524337111418704\&alt=media)

图2

* 支持存放多张图片，类似相册和集合。（实现多重曝光的效果）
* 支持多张图片实现 GIF 和 livePhoto 的动画效果。
* 无类似 JPEG 的最大像素限制。
* 支持透明像素。
* 分块加载机制。
* 支持缩略图。

在这个 Nokia 网站上可以看到相关的例子。

## 文件组成

在视频文件中，容器和编码是独立开的，比如 mp4,mkv 等格式是容器，而 H.264,VP8 等是编码。但是图像文件中，像 JPEG 就是混合在一起的（所以它不好用啊，哈哈哈哈），HEIF 就把容器和编码分开了，有用来存放单个或者多个图像的容器。

所以基于不同的编码器，会有不同的文件后缀。

| 编码器       | 单文件后缀 | 连续图片后缀 |
| --------- | ----- | ------ |
| HEVC      | .HEIC | .HEICS |
| H.264     | .AVCI | .AVCS  |
| Any codec | .HEIF | .HEIFS |

Apple 设备中默认使用的都是 HEVC 的编码的 HEIF 格式。

在 Apple 所编码的 HEIF 的文件组成大致如下图，其 mdat – Media Data 中存放的是 exif 信息，缩略图（320\*240），和 HEVC 编码后的图片：

![](https://1795314173-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LAdZ7gFz4IllRQpWbzu%2F-LAdZ8MxWrHaExfP4jSI%2F-LAdZWUIVftT-xiOZXUI%2FHEIF3.png?generation=1524337111482873\&alt=media)

图3

HEIF 底层是默认 tiled，就是片状的有 512×512 个，由一个个小的图块，组成一张大图，这一特性有如下的优点：

* 加速解码
* 缩放加快(不用加载整张图片)
* 裁剪加快

HeifTile 和 SystemTile (CATiledLayer 等系统所提供的分块加载)是不一样的，但是两者结合会有很大的提升，所以在加载和处理特大图片时，性能有大幅度的提升。

## 兼容性

每当一个新的技术推进至工业化，兼容性无疑是最重要的考量点。像 HEIF 这样的图片格式，并不像 JPEG / PNG 等已经被广泛应用和适配了，估计在 Apple 推出之前，大部分开发者和我一样应该都是不知道的。目前工业化的体系内，对 HEIF 几乎是不兼容，Windows 上无法打开 HEIF 文件，10.13 前的 macOS 也无法打开。苹果在推行这一技术的时候，在内部也是做了很多兼容工作的。

## 对一般用户

一般情况下，用户是对这个格式无感知的，因为只有在新款支持硬解码的 iOS 手机内部是以 heif & hevc 格式来存储照片和视频的，而在用户通过 Airdrop 或者数据线传送到电脑上的时候，对不兼容的设备会自动转换到 JPEG 的格式。所以也不会影响你使用微信，微博等软件。\
不过在苹果内部的 app 中，基本都已经用上了这一技术，如照片，FaceTime 等应用。意味着以后同等储存空间能存放更多的照片和视频，同时 FaceTime 也能节省更多了流量，相同网络情况下，FaceTime 也会更加清晰。\
通过在 设置 -> 照片 选项中可以设置传到 MAC 或者 PC 上时保持 HEIF 格式。

![](https://1795314173-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LAdZ7gFz4IllRQpWbzu%2F-LAdZ8MxWrHaExfP4jSI%2F-LAdZWZGs6it08JDI-yR%2FHEIF4.png?generation=1524337110729872\&alt=media)

图4

## 支持的设备

* HEIF 图片：

  编码：
* 硬件：A10 及以上芯片 iOS 设备。即只有 iPhone7 及以上是支持 HEIF 的(有双摄像头，才有深度信息)。
* 软件：iOS11，运行 macOS 系统的 Mac 设备。\
  解码：
* 硬件：A9 及以上芯片 iOS 设备（iPhone6s），配备 6 代及以上 Inter Core 处理（Skylake）。
* 软件：iOS11 和 macOS 支持软解码，但是 iOS11 锁版本代表最低只支持到 5s 。
* HECV 视频：\
  视频分为 8 位 / 10 位 两种模式。\
  基本和图片编解码保持一致，唯一有区别的是 10 位硬解码要求是 7 代 Intel 处理器。

总结一下，就是升到iOS 11之后，你的设备就能解析新格式的图片和视频，软硬解码的区别就是，硬解码会更快并更省电。

## 对开发者

### 上层框架 PhotoKit

对用户的几乎无感知切换的前提，肯定是上层 API 没有变化，调整的是最底层的 API，所以一般开发者使用上层的框架时，如 PhotoKIt 是不受影响的，不同格式的图片都抽象为了同一个对象。而且对图片增加滤镜和视频的调整修改，最后都会渲染为 JPEG 和 H.264。在这一级别的 API 是接触不到图片文件格式转换所带来的变化的。

### 下层框架 Image I/O

Image I/O 中可以直接读写 .heic 文件。\
iOS 11 中 Image I/O 能够直接读取 heif 的文件，包括读取 exif，xmp 等信息。

```
let inputURL = URL(fileURLWithPath:Bundle.main.resourcePath! + "/IMG_0513.HEIC")
let source = CGImageSourceCreateWithURL(inputURL as CFURL, nil)
let image = CGImageSourceCreateImageAtIndex(source!, 0, nil)

let options = [kCGImageSourceCreateThumbnailFromImageIfAbsent as String: true, kCGImageSourceThumbnailMaxPixelSize as String: 320] as [String: Any]
let thumb = CGImageSourceCreateThumbnailAtIndex(source!, 0, options as CFDictionary)

guard let cImage = image else {
print("not support heic")
return;
}
```

当然也可以选择把 CGImage 写入到 HEIC 格式，虽然这样可以节约更多的存储空间，实际使用的时候还是要注意转换操作。

```
let url = URL(fileURLWithPath: "/tmp/output.heic")
guard let destination = CGImageDestinationCreateWithURL(url as CFURL,AVFileType.heic as CFString, 1, nil) 
else{
fatalError("unable to create CGImageDestination")
}
CGImageDestinationAddImage(imageDestination, image, nil) 
CGImageDestinationFinalize(imageDestination)
```

Apple 提供的很多 API ，供开发者检测设备是否支持新的格式。提供了两种推荐的工作场景事例。

1. 社交网络\
   在社交软件中，涉及到图片分享之类的内容，是无法确定接受者是否能支持新的格式的， Apple 的策略是建议都进行转换到 JPEG 的操作，比如发送邮件，或者通过 extension 分享的时候，传入其他 app 中的时候，都已经进行了转换了。
2. p2p 场景\
   在该场景中，设备和设备间的直接连接，首先把接受者的支持格式告知发送者，然后发送者根据兼容的情况，选择 HEIF 或者 JPEG。比如 AirDrop 。

同时诸如 SDWebImage 目前也正在做对 heif 的兼容。

## 跨平台

大部分的播放器已经支持了 HEVC 即 H.265 的编码器，但是针对 HEIF 的图片兼容性还是相对较差的。\
目前有的是 Nokia 提供了一个 C++ 的读写库，通过该库，支持把 HEIF 的图片的解码到 HEVC 的编码数据。

* Android 兼容性：

  依赖 Nokia 的库，目前只能通过 CPU 软解。

据说 LG 正在研发支持硬解的手机。（raddit)

* 网页兼容性：\
  Nokia 提供 JS 库。
* Windows 兼容性：

目前也没有能直接打开 HEIF 文件的应用

## 对比

常常拿来与 HEVC 来做对比的是 VP9。两者的性能相近，但是 VP9 是开源的，而 HEVC 是需要专利费的（ $2 每设备）。\
目前暂时没有通过 VP9 进行编码的图片，所以这里主要对比的是 webp 就是通过 VP8 进行编码的图片。\
webp\
WebP目前支持桌面上的Chrome和Opera浏览器，手机支持仅限于原生的Android浏览器、Android系统上的Chrome浏览器、Opera Mini浏览器。

* WebP 有损支持

  Google Chrome (desktop) 17+

  Google Chrome for Android version 25+

  Opera 11.10+

  Native web browser, Android 4.0+ (ICS)
* WebP 有损 / 无损 / 透明支持

  Google Chrome (desktop) 23+

  Google Chrome for Android version 25+

  Opera 12.10+

  Native web browser, Android 4.2+ (JB-MR1)

  Pale Moon 26+
* WebP 动画支持

  Google Chrome (desktop and Android) 32+

  Opera 19+

下面是几个关键技术点的对比，可见 HEIF 功能是最强大的。

|          | .heic | WebP        | JPEG        |
| -------- | ----- | ----------- | ----------- |
| 最大尺寸     | 无上限   | 16383×16383 | 65535×65535 |
| 编码       | HEVC  | VP8         | JPEG        |
| 是否支持其他编码 | YES   | NO          | NO          |
| 支持音频/文字  | YES   | NO          | NO          |
| 支持多图片    | YES   | YES         | NO          |
| 支持裁剪     | YES   | NO          | NO          |
| 支持透明     | YES   | YES         | NO          |
| 支持缩略图    | YES   | NO          | YES         |
| 分块加载     | YES   | NO          | NO          |

## 压缩效率

下面的数据均是官方提出：\
Webp 同等质量下，比 JPEG 图像小 25-34%。\
JPEG 平均需要比 HEVC 多 139% 的比特率，意味着同等质量下，JPEG 的大小是 HEVC 的 2.39 倍！\
把两个的参考标准统一一下：\
Webp 比 JPEG 小 25-34%\
HEVC 比 JPEG 小 58%

实际测试:webp 以 80 的质量进行压缩，hevc 以 crf 18 （视觉无损）压缩，同时增加一个 320×240 的缩略图。

进行 HEIF 转码的流程是，将图片通过 ffmpeg 编码到 H.265，再通过 Nokia 的库转成 HEIC 文件(Heif)。

```
//生成主图像编码
ffmpeg -i $1 -crf 18 -preset slower -pix_fmt yuv420p -f hevc bitstream.265 
//生成缩略图编码
ffmpeg -i $1 -vf scale=320:240 -crf 28 -preset slower -pix_fmt yuv420p -f hevc bitstream.thumb.265
//调用 Nokia 的工具
./writerapp config.json
```

实际测试数据:

| 格式             | 原图大小    | heic   | webp   |
| -------------- | ------- | ------ | ------ |
| JPEG 4352×3264 | 5.7 MB  | 487KB  | 538 KB |
| JPEG 8688×5792 | 34.7 MB | 3.5 MB | 2.7 MB |
| tiff 3840×2160 | 1.8 MB  | 238 KB | 264 KB |
| PNG  1243×2208 | 1.5 MB  | 175 KB | 209 KB |
| PNG  512×512   | 243 KB  | 13 KB  | 14 KB  |

除了一组特大图的表现不一样外，其他几组图片相比， heif 确实比 webp 压缩效率高 10-20%。

毕竟和 HEVC 对标的技术应该是 VP9，所以 heif 能够领先也是情理之中。

## 解码的消耗测试

主要测试设备是 iPhone 6s Plus 系统 iOS 11，用的解码方法 webp 为 Google 提供的库，hevc 和 jpeg 用的是 CGImageSource 来解码。\
测试用图片还是之前的五组图片，同时对 JPEG 进行了一些压缩，测试了 5 组平均值(去一个最高，去一个最低)，估计加载的时候存在缓存，所以第一次读图片数据的时候耗时较大。

第一组用第一张 7.7 mb 的 jpeg 压缩后大小 1.1mb\
jpeg 7.43 2.77 1.46 1.9 2.14 2.00 【占用率 6 %】\
hevc 41.0 3.45 3.35 2.62 2.92 2.66 【占用率 6 %】\
webp 216.6 216.8 217.5 261.9 195.2 【占用率 21 %】

| 格式   | 平均时间    | 占用率 |
| ---- | ------- | --- |
| jpeg | 2.20ms  | 5 % |
| hevc | 3.01ms  | 6 % |
| webp | 220.1ms | 20% |

第二组用第三张 1.8 mb 的 tff，转换成 jpeg 之后大小为 815 KB。

hevc 58.4 3.1 2.8 1.13 2.65 2.82 2.02 【 2% 】\
jpeg 65.3 2.67 2.76 2.73 2.69 2.87 1.34 【 2% 】\
webp 130.2 110.9 117.5 114.8 120.9 112.8 124.84 【 12% 】

| 格式   | 平均时间     | 占用率 |
| ---- | -------- | --- |
| jpeg | 2.73ms   | 2 % |
| hevc | 2.68ms   | 2 % |
| webp | 115.58ms | 12% |

第三组用的最后一张 243KB PNG ，转换成 JPEG 之后大小为 43 KB。\
hevc 47 3.24 2.7 3.21 2.63 1.74 【 1 %】\
jpeg 16 6.70 6.97 4.46 7.2 6.76 7.08 【 1% 】\
webp 20.7 20.2 12.5 22.0 19.3 19.4 【 2 % 】

| 格式   | 平均时间   | 占用率 |
| ---- | ------ | --- |
| jpeg | 6.90ms | 1 % |
| hevc | 2.95ms | 1 % |
| webp | 20.1ms | 2 % |

测试结果由于硬解码的支持，jpeg 和 hevc 解码速度和 CPU 占用率都比 webp 快和小很多，jpeg 和 hevc 不相伯仲，可见苹果内部对齐优化也相当到位，才把它放到 iOS 11 中。

## 总结

相比 JPEG 来比很强大，毕竟是下一代技术，但是兼容性可想而知，在“最大效率”和“最大兼容”两者中间还是要根据使用场景进行权衡，目前的优势也只有最新的 iPhone 能体验到，但不久的将来可能所有的手机都去支持照片深度，动态照片，更广的色域等。HEVC 也许和推行 H.264 一样，逐渐成为了工业界的标准，但又可能和推行 acc 的处境一样，只是成为了苹果的标准而已，终究还是要看市场的反应了.
