HEIF & HEVC 你知道多少

HEIF & HEVC 研究

来自我的 blog – 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 格式和与其他图片格式相比的优劣。
发展史如下:
screenshot

什么是 HEIF?

screenshot

这张图是 WWDC Session 511 的形容 Heif 的一句英文诗,JPEG 很大,但是 HEIF 和小。

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

  • 压缩比高,在相同的图片质量情况下,平比 JPEG 高两倍。
  • 能增加如图片深度信息,透明通道等辅助图片。(苹果正是通过这个就能实现动态的调整图片的景深)。
    depth
  • 支持存放多张图片,类似相册和集合。(实现多重曝光的效果)
    screenshot

  • 支持多张图片实现 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 编码后的图片:
screenshot

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

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

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

HEIF 所采用的熵编码也和 JPEG 不一样,JPEG 是用的霍夫曼编码(Huffman),而 HEIF 使用的是基于上下文的自适应二进制算术编码(CABAC),编码的是数据量更小且更快。

兼容性

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

对一般用户

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

screenshot

支持的设备

  • 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 ,供开发者检测设备是否支持新的格式。提供了两种推荐的工作场景事例。

  • 社交网络
    在社交软件中,涉及到图片分享之类的内容,是无法确定接受者是否能支持新的格式的, Apple 的策略是建议都进行转换到 JPEG 的操作,比如发送邮件,或者通过 extension 分享的时候,传入其他 app 中的时候,都已经进行了转换了。

  • 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 487 KB 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 的处境一样,只是成为了苹果的标准而已,终究还是要看市场的反应了。

参考

Posted in iOS

发表评论

电子邮件地址不会被公开。