WPF で APNG を表示する
.NET Framework WPF で APNG (Animated PNG) を表示しようとしたところ、ドンピシャなライブラリー等が見つからなかったので、C# 製 ライブラリーを fork して用意しました。
細かな仕様の部分で間違いやバグがあるかもしれませんが、自分用にはとりあえず使えるものができました。control ではないので Image control に表示するには、今のところコードビハインドでコード記述が必要です。
APNG の仕様について少し
APNG は、ファイル内に複数の PNG 画像があるようなフォーマットです。ただ、差分データによるアニメーションを実現できる仕様のため、単にファイル内の PNG 画像を取り出すだけはなく、画像の合成が必要です。デコードするだけでなく、この点も実装する上で手間ですね。
既存の APNG のライブラリー等について少し
C#, WPF で使えそうなライブラリーを検索すると次のようなものが見つかりました。
- GitHub - xupefei/XamlAnimatedPng: A simple library to display animated PNG (i.e., APNG) images in WPF and UWP
- Animated GIF を WPF 等でサポートするライブラリー作者による APNG 用ライブラリーのようですが、fork しただけで実装がないようです。
- ttp://apngwpf.codeplex.com/ ※ Google Chrome ではブロックされるため URL 表記のみ
- サービスが終了した CodePlex で公開されていた WPF 向けの APNG ライブラリー。C++/CLI 製で libpng を利用している模様。LGPL ライセンス。環境が古く、作者名等も不明なため使いませんでした。libpng を利用しているので、フレーム画像の合成などもきちんと動いているのかも。
- APNG Viewer - CodeProject
- C# 製。フレーム画像が差分データの場合が、考慮されていませんでした。
そして、上記ひとつ目の作者 xupefei 氏が、公開しているライブラリー APNG.NET。これを fork しました。
- GitHub - xupefei/APNG.NET: A fully-managed APNG parser, written in C#
- C# 製。XNA 向け。フレーム画像の合成は XNA 向けのコードで行っているので、合成部分を WPF 向けに用意しました。
APNG.NET for WPF
C# 製のライブラリー APNG.NET を使い、WPF 用の拡張メソッドを作っています。
APNG を BitmapSource に変換
合成済みのフレーム画像を BitmapSource オブジェクトとして取得します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var apng = new APNG("a.png"); | |
var bitmaps = apng.ToBitmapSources(); | |
// Save to PNG files | |
foreach (var (bitmap, index) in bitmaps.Select((item, index) => (item, index))) | |
{ | |
using (var fileStream = new FileStream($"{index}.png", FileMode.Create)) | |
{ | |
var encoder = new PngBitmapEncoder(); | |
encoder.Frames.Add(BitmapFrame.Create(bitmap)); | |
encoder.Save(fileStream); | |
} | |
} |
APNG を Image control に表示
APNG からキーフレームアニメーションを生成し Storyboard を使ってアニメーションを表示します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Image Name="PngImage" /> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var apng = new APNG("a.png"); | |
if (apng.IsSimplePNG) | |
PngImage.Source = BitmapFrame.Create( | |
apng.DefaultImage.GetStream(), BitmapCreateOptions.None, BitmapCacheOption.OnLoad); | |
else | |
apng.ToAnimation().CreateStoryboardFor(PngImage).Begin(PngImage); |