はじめに
今回は有名なGIFサポートライブラリを比較してみたいと思います。
対象ライブラリは以下の3つ。
UniGifmgGifUnity-GifDecoder
GitHub - WestHillApps/UniGif: GIF image decoder for Unity.
GitHub - gwaredd/mgGif: A unity library to parse GIF files and extract the images as textures
GitHub - 3DI70R/Unity-GifDecoder: Gif decoding utility for Unity engine
評価
複数の観点から見た時評価は以下の通り。
| ライブラリ名 | パフォーマンス | 利用しやすさ | コードの柔軟性 | オススメ度 |
|---|---|---|---|---|
UniGif |
× | ◎ | △ | △ |
mgGif |
◎ | ○ | △ | ◎ |
Unity-GifDecoder |
○ | △ | ◎ | ◎ |
コードを利用せず出回っているサンプルコードを利用する場合はmgGif,コードを書く場合はUnity-GifDecoderがオススメかなと思います。
パフォーマンス
パフォーマンスに関してはmgGif > Unity-GifDecoder >>>>>> UniGifのようなイメージになっています。
| Library | Editor | Mono | IL2CPP |
|---|---|---|---|
| UniGif | 7321 ms | 3790 ms | 3178 ms |
| Unity-GifDecoder | 365 ms | 123 ms | 88 ms |
| mgGif | 247 ms | 112 ms | 80 ms |
| mgGif (Unsafe Mode) | 280 ms | 106 ms | 70 ms |
GitHub - gwaredd/mgGif: A unity library to parse GIF files and extract the images as textures
こちらはmgGifのGitHubのReadmeに記載されているベンチマークです。
補足ではありますがmgGifにはunsafeを利用することでパフォーマンス向上できる機能が実装されています。
これをみるとUniGifのパフォーマンスの悪さが顕著になっていますね。
またUnity-GifDecoderのGC.Allocを含めた計測結果でも、Unity-GifDecoder >>>>>>> UniGifとなっています。
| 名前 | 処理時間 | GC.Alloc |
|---|---|---|
| Unity-GifDecoder | ~0.96ms | 385.1kb |
| UniGif | ~19.27ms | 0.81gb |
GitHub - 3DI70R/Unity-GifDecoder: Gif decoding utility for Unity engine
またmgGifとUnity-GifDecoderのGC.Allocの比較もしてみたいということで自身でコードを書いて実験してみました。(Editor上)
| 名前 | 処理速度 | GC.Alloc |
|---|---|---|
| mgGif(unsafe) | 11.63ms | 79.0kb |
| mgGif | 6.53ms | 339.5kb |
| Unity-GifDecoder(Memory) | 13.29ms | 111.0kb |
| Unity-GifDecoder(File) | 14.60ms | 107.7kb |
処理速度ではmgGif > mgGif(unsafe) > Unity-GifDecoder(Memory) > Unity-GifDecoder(File)、GC.AllocではmgGif(unsafe) > Unity-GifDecoder(File) > Unity-GifDecoder(Memory) > mgGifという結果になりました。
ただしこれはEditor上で動作させており、メモリからGifを読み取る場合はFile.ReadAllBytesも含めた結果になっています。
思ったよりもUnity-GifDecoder頑張っていますね。またEditor上だとmgGif > mgGif(unsafe)になるのも公式ベンチマーク通りで少し関心しました。
利用しやすさ
利用しやすさというなんとも曖昧な評価基準ですが、あまり知識がなくても導入しやすいかどうかの指標として載せました。
UniGif
UniGifは以下の点から評価できると考えています。
RawImageに対してGif適応するサンプルが同梱- コードが直感的に書ける
サンプルがあるので、自身でコードを書かなくて導入できることが魅力的ですね。
またコードもGifのバイト列を渡せば、Texture2Dと画像の間隔(s)が返ってくると直感的です。
yield return StartCoroutine(UniGif.GetTextureListCoroutine(www.bytes, (gifTexList, loopCount, width, height) => { /* Do something */ }));
mgGif
mgGifに関しては以下の点を評価しました。
Rendererに対してGif適応するサンプルが同梱- コードがやや直感的
Rendererに対してのサンプルがあるのは嬉しいですが、正直Imageのサンプルの方が嬉しいかなと思い少し減点しました。
またコードの書き方としては、直感的ではありますがUniGifに比べるとC#の知識が必要かなと言った感じがします。
byte[] data = File.ReadAllBytes( "some.gif" ); using( var decoder = new MG.GIF.Decoder( data ) ) { var img = decoder.NextImage(); while( img != null ) { Texture2D tex = img.CreateTexture(); int delay = img.Delay; img = decoder.NextImage(); } }
GitHub - gwaredd/mgGif: A unity library to parse GIF files and extract the images as textures
Unity-GifDecoder
最後にUnity-GifDecoderに関してです。
- サンプルコードがない
- コードを書くには知識が必要
コードを書く場合はGifの構造に関する知識が少し必要になってしまいます。
var frames = new List<Texture>(); var frameDelays = new List<float>(); using (var gifStream = new GifStream(yourFile)) { while (gifStream.HasMoreData) { switch (gifStream.CurrentToken) { case GifStream.Token.Image: var image = gifStream.ReadImage(); var frame = new Texture2D( gifStream.Header.width, gifStream.Header.height, TextureFormat.ARGB32, false); frame.SetPixels32(image.colors); frame.Apply(); frames.Add(frame); frameDelays.Add(image.SafeDelaySeconds); // More about SafeDelay below break; case GifStream.Token.Comment: var commentText = gifStream.ReadComment(); Debug.Log(commentText); break; default: gifStream.SkipToken(); // Other tokens break; } } }
GitHub - 3DI70R/Unity-GifDecoder: Gif decoding utility for Unity engine
Gifの構造を知らない方はGifStream.Token.Imageってなんやってなってしまいますよね。
GIFフォーマットの詳細 - とほほのWWW入門
利用するための障壁は少し高そうな印象です。
コードの柔軟性
コードの柔軟性についてですが、Unity-GifDecoder >>>>> UniGif = mgGifといった感じでしょうか。
Unity-GifDecoderがUniGif・mgGifに最も優っている点はStreamを扱えることです。
// Unity-GifDecoderではStreamを扱える var path = Path.Combine(Application.streamingAssetsPath, "sample.gif"); var file = File.ReadAllBytes(path); // ファイルから直接読み取り using var gifStream1 = new GifStream(path); // メモリから読み取り using var gifStream2 = new GifStream(file); using var gifStream3 = new GifStream(new MemoryStream(file));
UniGifとmgGifはバイト配列(メモリ上に確保されている)を受け取ってデコードを行うのですが、Unity-GifDecoderならメモリだけでなくファイルやネットワークなどから読み取りデコードをすることができます。
またUnity-GifDecoderはメインスレッド以外でも動作することがReadmeに記載されている点もありがたいですね。
結論
UniGifがあまりにパフォーマンスが悪いので私的には除外ですかね。
mgGifとUnity-GifDecoderではそこまでのパフォーマンス差がありませんし、コードがある程度描ける人ならUnity-GifDecoderが良いのではないのかなと個人的には思います。
ただ誤解してほしくないのはUniGifを利用するなといった訳ではないことに注意してください。
サンプルコードもしっかりと書かれていますし、それぞれの環境・状況に応じて適切に選択してもらえれば幸いです。
それぞれのライブラリの使い方
www.hanachiru-blog.com
www.hanachiru-blog.com
www.hanachiru-blog.com