WPFではサポートされてもFormアプリでは使えない機能があります。
Imageのheic対応もそのひとつで、次のようなコードでheicファイルを表示しようとするとメモリ不足のエラーが発生します。
pictureBox1.Image = Image.FromFile(mediaItem.FilePath);
Webでheic表示関連を検索するとMagick.NETを使う例が見つかりますが、Microsoftのライブラリだけで行う方法はまだ見つかりませんでした。Magick.NETは様々なフォーマットを扱える優れたものだと思いますが、dllをアプリに含めると、小さいなアプリでは本体よりMagick.NETの方が大きくなってしまいます。heicサポートの追加だけが目的な場合はあまり好ましくないので、Microsoftのライブラリだけで行う方法をいくつか試してみました。
なお、前提としてWindows 10, 11にHEIF画像拡張をインストールしてあるものとします。HEIF画像拡張がインストールされていない場合はMicrosoft Store から ダウンロードできます。
方法1
BitmapImageとBitmapEncoderを使用する。
今のところ、これが一番良好な結果になっています。
次のようなステップで行います。
System.Windows.Media.Imaging.BitmapImageをファイルから作る。BmpBitmapEncoderでMemoryStreamに書き出す。
MemoryStreamからSystem.Drawing.Imageを作る。
pictureBox1.Imageにセットする。
コードは次のようになります。
BitmapImage bImage = new BitmapImage();
bImage.BeginInit();
bImage.CacheOption = BitmapCacheOption.None;
bImage.DecodePixelHeight = height;
bImage.DecodePixelWidth = width;
bImage.UriSource = new Uri(FilePath, UriKind.Absolute);
bImage.EndInit();
using (MemoryStream ms = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bImage));
enc.Save(ms);
pictureBox1.Image = Image.FromStream(ms);
}
ひとつの静止画を扱うなら、これで十分でしょう。イメージのサイズを設定できるので、メモリ消費も必要最低限に抑えられ、スピードもこれ以上早くするのは難しいでしょう。
また、書き出し先をファイルにすればフォーマット変換にも使えます。
System.Windows.Media.Imagingのための参照追加 は次のとおりです。
プロジェクトの参照右クリック⇒参照の追加⇒アッセンブリ
⇒PresentationCoreをチェック⇒OK
方法2
BitmapDecoderとBitmapEncoderを使用する。
BitmapDecoderの使い方はよくわかっていませんが、複数のFrameを持ち、Animationなども扱えます。複雑な画像表示を行えるようですが、ひとつの静止画だけを扱うなら方法1で十分そうです。もしかしたら有用かもしれないので紹介しておきます。
ステップは方法1のBitmapImageがSystem.Windows.Media.Imaging.BitmapDecoderに置き換わっただけです。
コードは次のようになります。
BitmapDecoder uriBitmap = BitmapDecoder.Create(
new Uri(FilePath, UriKind.Absolute),
BitmapCreateOptions.None,
BitmapCacheOption.Default);
using (MemoryStream ms = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(uriBitmap.Frames[0]);
enc.Save(ms);
pictureBox1.Image = Image.FromStream(ms);
}
調べた限りでは、この流れでは画像サイズを指定できません。そのため、高解像度画像ではメモリ消費が多くなり、スピードも少し遅くなります。
方法3
AxWMPLib.AxWindowsMediaPlayerを使用する。
MediaPlayerは静止画も表示でき、HEIF 画像拡張がインストールされていればheicフォーマットも表示できます。ちなみにHEVCビデオも再生できます。静止画を扱う場合は uiMode="none"が良いでしょう。
メリットとしては、まずは静止画も動画も同じインタフェイスで扱えることです。また、対応していないフォーマットや壊れたファイルのエラー対応もMediaPlayerまかせにできます。
これまでのFormアプリと同じ要領で使え、次の要領でコントロールにファイルのパスを設定するだけなので、お手軽といえます。
(AxWMPLib.AxWindowsMediaPlayer)player.URL = filePath;
VisualStudioでMediaPlayerを使う方法は次のリンクを参照してください。
Microsoft Visual Studio で Windows メディア プレーヤー コントロールを使用する
https://draft.blogger.com/blog/post/edit/6538117324271148932/209217070553378409#
デメリットとしては、方法1,2に比べると遅いこと、メモリ消費量も特に高解像度のheicの場合は多くなります。
HEIFコーディックの有無チェック
Magick.NETと違い、HEIFコーディックがないとエラーになります。
以下の要領でHEIFコーディックの有無がチェックできます。
bool HeifDllExists = Registry.GetValue(@"HKEY_CLASSES_ROOT\CLSID\{E9A4A80A-44FE-4DE4-8971-7150B10A5199}\InprocServer32", null, null) != null;
参照:HEIF Format Overview
https://learn.microsoft.com/ja-jp/previous-versions/windows/desktop/legacy/mt846532(v=vs.85)