iOSDC2017「新しい画像フォーマットHEIFを 用いたiOSアプリの通信量削減」のまとめと補足

[新しい画像フォーマットHEIFを 用いたiOSアプリの通信量削減](https://speakerdeck.com/tamanyan/iosdc-heif)を発表する上で、メモったものを載せます。

# HEIFとは？

- 主にH.265/HEVCのビデオコーデックを使用した画像コンテナフォーマット
- 圧縮率がJPEGと比べて高い、約50%の圧縮率
- Burst PhotoやCinemagraphなどのシーケンス画像を効率よく保存
- 深度マップや透明度などの補助データを内包
- ExifやXMPなどのメタデータ


# HEIFに触れてみる

## High Sierra

- Previewで表示することができる
- Air DropでSierraに送信
  - 特に変換されずに、そのままの状態で送信される

## iOS11

- A10 Fusion chip搭載の端末で新しく写真を取るとheifで保存される
  - **以前からの保存していたデータはJPEGのまま**
- iPhoneから外に画像が転送される場合、基本JPEGになる
  - 写真アプリ経由で共有すると、JPEGに変換される
  - heifで保存された写真をMacでimportするとjpgに変換される
  - カメラや写真設定からHEIFを使わないオプションを設定できる
  - dropboxアプリでギャラリーからheifを保存すると、HEIFがそのまま保存されたバグがあった
- Photos.frameworkを普通に使えば問題ない
  - PHAsset
  - PHImageManager

# HEIFの作成方法

1. ffmpeg, GPAC/MP4Boxを使用可能
  - ffmpegでHEVCのビットストリームを作成
  - GPACでHEIFを作成する
2. iPhone7(A10 chip)以降に発売された端末でエンコードして作成可能

## ffmpegインストール

```
brew install ffmpeg --with-x265
```

## GPACインストール

```
brew install gpac
```

## ffmpeg, GPACの使い方

- SourceファイルからHEVCのビットストリームを作成
  - x265のオプションにSSIMを指定すると画像を生成した時にSSIMの値を出力してくれる
  - crfはQuality Controlで値は小さいほど、高画質

```
ffmpeg -i {source.png} -y -pix_fmt yuv420p -codec:v libx265 \
   -crf 13 -preset slower -x265-params ssim=1 -f hevc {output.hvc}
```

## GPACでHEIFを作成する

```
MP4Box -add-image {source.hvc} -ab heic -new {output.heic}
```

# 朝刊一週間分をエンコード

- WebPとJPEGはImageMagickで作成
- HEIFはffmpegとGPACを使用

すべてのサイズはほぼ同程度のQualityになるようなパラメータを設定。
ここでいう、同程度とはSSIMで比較して大体同じという意味。
SSIMが0.986 ~ 0.998の範囲内に収まるようなパラメータを調整しました。

## 表１ 朝刊の各フォーマットの実サイズ

|            | HEIF [MB] | WebP [MB] | JPEG [MB] |
| ---------- | --------- | --------- | --------- |
| 2017/08/21 | 40        | 57        | 85        |
| 2017/08/22 | 52        | 71        | 107       |
| 2017/08/23 | 55        | 77        | 115       |
| 2017/08/24 | 57        | 80        | 118       |
| 2017/08/25 | 54        | 77        | 113       |
| 2017/08/26 | 58        | 80        | 120       |
| 2017/08/27 | 38        | 55        | 80        |

## 表２ 朝刊の各フォーマットの割合（JPEGを100とした場合）

|            | HEIF [MB] | WebP[MB] | JPEG   |
| ---------- | --------- | -------- | ------ |
| 2017/08/21 | 47.1%     | 67.1%    | 100.0% |
| 2017/08/22 | 48.6%     | 66.4%    | 100.0% |
| 2017/08/23 | 47.8%     | 67.0%    | 100.0% |
| 2017/08/24 | 48.3%     | 67.8%    | 100.0% |
| 2017/08/25 | 47.8%     | 68.1%    | 100.0% |
| 2017/08/26 | 48.3%     | 66.7%    | 100.0% |
| 2017/08/27 | 47.5%     | 68.8%    | 100.0% |


- WebPはJPEGと比べて、約66% ~ 69%の圧縮率
  - JPEGと比べて70％と歌ってるから、妥当なラインかと
- HEIFはJPEGと比べて、約47% ~ 49%の圧縮率


# H.265/HEVC特許問題

- 4つの特許プール・企業が存在する
- H.264の様に単一のパテントプールによって取り纏められてはいない
- 特許を利用する際は、権利行使している複数の団体毎に特許使用料が必要となる
  - HEVCは複雑かつ高額なソフトウェア特許
- AppleはMPEG LAに所属
- HEIF自身はただのコンテナで、HEVCコーデックを使用している場合はHEVC特許ライセンスに属する(by wikipedia)
- Google, Amazon, NetflixなどはHEVCへの対抗のためにオープンで著作権使用料無料の次世代動画フォーマットのAlliance for Open Mediaを設立してAV1を開発
- ビデオコーデック周りの戦争はヤバイ
- 特許周りに関してはこの[資料](http://qiita.com/yohhoy/items/c2579097a507b1fbdddb)が大いに参考になりました

# 紙面ビューアの現状の仕組みは？

- 紙面画像の配信とストレージへの保存をWebPで行う
- WebPだと内部ストレージに紙面画像があっても表示までの（デコード）時間が気になる
  - ソフトウェアデコードするしかない 
  - ダウンロードしたWebPの紙面画像はJPEGに変換すると容量を圧迫してしまう
  - WebPをリアルタイムにデコードするしかない→辛い

# 紙面ビューアでHEIFを利用する場合の理想形

- 紙面画像のHEIFへの変換をAWS Lambdaだけで完結するようにしたい
- 紙面画像の配信とストレージへの保存をHEIFで行う
- 通信容量も表示までの時間の問題も解決
- しかし、特許使用の観点から難しい

# 紙面ビューアでHEIFを利用する場合の妥協案

- iPhoneでクラスタマシンを構築する
- サイレントプッシュ通知で紙面画像をダウンロード、エンコード、アップロードするアプリを立ち上げて、タスクをこなす
- 原則1ページ、1つのiPhoneだとよさそう（←おいおい本気か？）
- サイレントプッシュ通知は一度ではタスクが完了しない可能性があるので、タスクを実行し続けるためにS3に画像が反映されるまで何度も送り続ける

![iosdc-heif.040.jpeg](https://qiita-image-store.s3.amazonaws.com/0/42035/df793404-b1ee-41c6-e2e0-9f232a5373cb.jpeg)


# iOSアプリにおいてHEIFをどう利用すべきか？

- Appleは写真アプリの画像圧縮で利用している
- 画像を大量にローカルに保存するようなアプリではHEIFに変換する価値がありそう
  - 漫画ビューアアプリ、紙面ビューアアプリ、Photoアプリ
- サーバサイドの実装は絡まないので、まず試しに実装してみるには良さそう