LoginSignup
100
63

More than 5 years have passed since last update.

WWDC17で新しく発表された画像フォーマットHEIFを使ってみた

Last updated at Posted at 2017-06-16

HEIFとは

HEIFとはHigh Efficiency Image File Formatの略でMPEGよって開発された画像フォーマットの標準規格です。ちなみにヒーフと呼ぶ場合が多いようです。iOS11から公式にサポートされ、JPEG以上の圧縮率深度情報透過処理タイル化アニメーションなどJPEGにはなかった機能や改善点がある新しい画像フォーマットです。JPEGなどとの詳しい差分はwikiに載っています。

H.265/HEVCとは

まずHEIFを語る上で避けて通れない事として、H.265/HEVC(High Efficiency Video Coding)があります。ISO/IECのMPEGとITU-TのVCEGによる研究開発チームJCT-VC によって提案され、ITU-Tは2013年に承認されました。

HEIFはHEVCのコーデックが選択可能(というかこれ以外ありえない?)でHEIFとHEVCの違いはなんとなくでも理解しておきましょう。

Working with HEIF and HEVCによると
HEVCのエンコードは以下の環境でエンコード可能で

iOS
Hardware Encode A10 Fusion chip(iPhone7iPhone7 Plus
Software Encode 無理

逆にデコードに関しては

iOS
Hardware Decode A9 chip(iPhone6siPhone6s Plus)以上
Software Decode All iOS Devices

の端末で読み込む事が可能です。
なんか動かねーぞという場合には以上の内容を参考にしてください。
あっあともちろんiOS11以上でAPIは使用可能です

実際にHEIFを作成するには

HEIFを作成するには大まかに2つの方法があって、

  1. iPhone7, iPhone7 Plus, macOSのAPIを用いてエンコードする
  2. FFmpegNokiaのHEIFの実装を利用する

正直1.は研究段階ならともかく現実的ではないので2.を選択するのが無難だと思います。

FFmpegはHomebrewからインストールできます。

1. H.265/HEVCのエンコーダーが必要なのでまず以下のコマンドを入力します

brew install x265

2. FFmpegをオプションをつけてインストールします

brew uninstall ffmpeg
brew install ffmpeg --with-x265

3. NokiaのHEIFの実装をビルドします

git clone https://github.com/nokiatech/heif.git
cd heif
cmake .
make

4. FFmpegを用いてJPEGやPNGをHVECのbytestreamに変換します

crfは画像のQualityなのでスケールの範囲は0から51で、0ではLossless、23がデフォルト、51は最低です。 より小さい値でよりよい画質となります。
(追記)どうやらH.264ドキュメントを見ていたようです、@yohhoy さんの通りなので、間違えのないように

ffmpeg -i ./your-image.png -crf 12 -preset slower -pix_fmt yuv420p -f hevc bitstream.265

5. configファイルを作成します

詳しい内容はwikiのリンクで説明してありますので、こちらをどうぞ。HEIFは画像の中にサムネイルの情報を入れることができるのですが、今回は必要ないので除外してます(あってるのかな?)。

{
	"general": {
		"output": {
			"file_path": "output.heic"
		},
		"brands": {
			"major": "mif1",
			"other": ["mif1", "heic", "hevc"]
		}
	},
	"content": [{
		"master": {
			"file_path": "./path-to/bitstream.265",
			"hdlr_type": "pict",
			"code_type": "hvc1",
			"encp_type": "meta"
		}
	}]
}

6. 3でビルドした実行ファイルに5で作成したconfig.jsonを指定して実行します。

./Bins/writerapp ./path/to/config.json

作成したHEIFファイルの中身はHEIFのブランチ gh-pagesで確認することができます。

iOSでHEIFを読み込むには

iOSでローカルのHEIFファイルを読み込むには以下のコードを書きます。

// Read a jpeg image from file

let inputURL = URL(fileURLWithPath: "/tmp/image.heic")

if let source = CGImageSourceCreateWithURL(inputURL as CFURL, nil) {
    let image = CGImageSourceCreateImageAtIndex(source, 0, nil)
    // set image
}

ちなみにHEIFファイルがWEB上にある場合には

let inputURL = URL(string: "https://../image.heic")

// 何かのダウンローダー
downloader.download(url: inputURL) { (data: Data?, error: Error) in
    if let data = data, let source = CGImageSourceCreateWithData(data as CFData, nil) {
        let image = CGImageSourceCreateImageAtIndex(source, 0, nil)
        // set image
    }
}

でっ実際どれくらい圧縮されんのよ

記事の一覧を表示するための192x192のサムネイル画像を30個ほど圧縮してみましたが、JPEGと比べると**15~20%**近く合計で圧縮されていました。
画像サイズはffmpegのQualityのオプションによって上下すると思うので、一概には言えませんがWebPとも遜色ない圧縮率です。

HEIF最高や!!WebPなんて最初っからいらんかったんや!!

実験はiPhone 7Plusで行いましたが、デコード時間もハードウェアアクセラレーションを使っているおかげもあるのか、違和感なく表示されていました。

最後に

今回調べる上で技術的なドキュメントやWebの資料が少ないので、多少苦労しました。とくにHEVCなどのコーデック周りは専門家がいたほうがやりやすいと思います。何か情報クレ...クレメンス...。

自分たちが作っているアプリの要件やサポートOSや運用なども含めて、今後導入するかどうかを検討するといいと思います。

(追記)HEVC及びHEIFのエンコーダには特許の問題がありffmpegなどを使用した実用化は難しいです。現状iPhoneでしかHEIFのエンコードが不可能なので、サーバサイドでの作成は将来に期待しましょう。

100
63
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
100
63