WPFで画像ファイルの寸法(幅、高さ)を高速に取得する。

コンピュータ

画像ファイルを表示するために、事前に幅や高さが知りたい場面があります。一般的な方法として画像オブジェクトのWidth(PixelWidth)Height(PixelHeight)を参照するとで知ることが出来ます。
ただ、その方法の場合、画像オブジェクトを生成する必要があり、ファイルの読み込みやデコードのコストがかかるため事前に取得する方法としては不向きです。
画像ファイルの幅と高さの部分のみスポット的に読み込んで、情報を取り出す方法があるようなので、試してみました。

プロジェクトの作成

サンプルコードを実行するためのプロジェクトを作成

cd (mkdir probeSize01)
dotnet new console -f net8.0

ソースコード

ファイル名:probeSize01.csproj


<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0-windows</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <UseWPF>true</UseWPF>
  </PropertyGroup>

</Project>

ファイル名:Program.cs


using System.Diagnostics;
using System.IO;
using System.Windows.Media.Imaging;

// 通常モード

const string imgFile1 = @"J:\images\002.png";

Stopwatch sw = Stopwatch.StartNew();

using var stream = new FileStream(imgFile1, FileMode.Open, FileAccess.Read);

BitmapImage bitmap = new();
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = stream;
bitmap.EndInit();
bitmap.Freeze();
Console.WriteLine($"width:{bitmap.PixelWidth} height:{bitmap.PixelHeight}");
// width:4532 height:6400

sw.Stop();
Console.WriteLine($"Nomal: {sw.ElapsedMilliseconds}ms");
// Nomal: 406ms


// プローブ
const string imgFile2 = @"J:\images\003.png";
const int peekBytes = 128 * 1024;

sw.Restart();
using var stream2 = new FileStream(imgFile2, FileMode.Open, FileAccess.Read);
using var ms = new MemoryStream();
stream2.CopyTo(ms, peekBytes);
ms.Position = 0;

var dec = BitmapDecoder.Create(ms,
    BitmapCreateOptions.DelayCreation | BitmapCreateOptions.PreservePixelFormat,
    BitmapCacheOption.None);

var f = dec.Frames[0];
int w = f.PixelWidth;
int h = f.PixelHeight;
Console.WriteLine($"width:{w} height:{h}");
// width:4532 height:6400

sw.Stop();
Console.WriteLine($"Probe: {sw.ElapsedMilliseconds}ms");
// Probe: 42ms

実行イメージ

image

幅:4532px、高さ:6400の2つの画像のサイズを取得してみました。

一般的な画像オブジェクトを作るタイプは
406ms

幅、高さのみ読み込むタイプは
42ms

という結果になりました。

コメント