WPF標準のBitmapImage、Magic.NET(ImageMagic)、SkiaSharp、OpenCVSharpでPNGファイルのデコード速度を比べて見ました
プロジェクトの作成
cd (mkdir SpeedLoader01)
dotnet new wpf -f net8.0
rm *.xaml
rm MainWindow.xaml.cs
dotnet add package SkiaSharp --version 3.119.0
dotnet add package SkiaSharp.Views.WPF --version 3.119.0
dotnet add package SkiaSharp.Views.WPF
dotnet add package Magick.NET-Q8-AnyCPU --version 14.6.0
dotnet add package Magick.NET.SystemWindowsMedia --version 8.0.6
dotnet add package OpenCvSharp4
dotnet add package OpenCvSharp4.Extensions
dotnet add package OpenCvSharp4.WpfExtensions
ソースコード
ファイル名:SpeedLoader01.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
<StartupObject>SpeedLoader01.App</StartupObject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Magick.NET-Q8-AnyCPU" Version="14.6.0" />
<PackageReference Include="Magick.NET.SystemWindowsMedia" Version="8.0.6" />
<PackageReference Include="SkiaSharp" Version="3.119.0" />
<PackageReference Include="SkiaSharp.Views.WPF" Version="3.119.0" />
</ItemGroup>
</Project>
ファイル名:App.xaml.cs
using System.Diagnostics;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using SkiaSharp;
using SkiaSharp.Views.WPF;
using ImageMagick;
using OpenCvSharp;
using OpenCvSharp.WpfExtensions;
namespace SpeedLoader01;
public class App : Application
{
[STAThread]
public static void Main()
{
var imagePath = "X:\\testdata\\00001un.png"; // 実際のパスに置き換えてください
byte[] buffer = File.ReadAllBytes(imagePath); // ファイルはUIスレッドで一括読み込み
var imageControl = new Image
{
Stretch = Stretch.Uniform
};
var window = new System.Windows.Window
{
Title = "画像を表示",
Width = 400,
Height = 300,
Content = new Grid { Children = { imageControl } }
};
window.Loaded += async (_, _) =>
{
var bitmap = await LoadBitmapAsync(buffer);
//var bitmap = await LoadWithSkiaSharpAsync(buffer);
//var bitmap = await LoadWithMagickAsync(buffer);
//var bitmap = await LoadWithOpenCVSharpAsync(buffer);
imageControl.Source = bitmap;
};
var app = new App();
app.Run(window);
}
// デコード処理(BitmapImage)
private static Task<BitmapSource> LoadBitmapAsync(byte[] buffer)
{
return Task.Run(() =>
{
using var memStream = new MemoryStream(buffer);
var sw = Stopwatch.StartNew();
var bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = memStream;
bitmap.EndInit();
bitmap.Freeze();
sw.Stop();
Console.WriteLine($"BitmapImage Decode time: {sw.ElapsedMilliseconds} ms");
return (BitmapSource)bitmap;
});
}
// デコード処理(SkiaSharp)
private static Task<BitmapSource> LoadWithSkiaSharpAsync(byte[] buffer)
{
return Task.Run(() =>
{
var sw = Stopwatch.StartNew();
using var skStream = new SKManagedStream(new MemoryStream(buffer));
using var skBitmap = SKBitmap.Decode(skStream);
var source = skBitmap.ToWriteableBitmap();
source.Freeze();
sw.Stop();
Console.WriteLine($"SkiaSharp decode time: {sw.ElapsedMilliseconds} ms");
return (BitmapSource)source;
});
}
// デコード処理(ImageMagick)
private static Task<BitmapSource> LoadWithMagickAsync(byte[] buffer)
{
return Task.Run(() =>
{
var sw = Stopwatch.StartNew();
using var memStream = new MemoryStream(buffer);
using var image = new MagickImage(memStream);
var source = image.ToBitmapSource(); // WPF で表示可能
source.Freeze();
sw.Stop();
Console.WriteLine($"Magick.NET decode time: {sw.ElapsedMilliseconds} ms");
return source;
});
}
// デコード処理(OpenCV)
private static Task<BitmapSource> LoadWithOpenCVSharpAsync(byte[] buffer)
{
return Task.Run(() =>
{
var sw = Stopwatch.StartNew();
using var memStream = new MemoryStream(buffer);
using var mat = Cv2.ImDecode(memStream.ToArray(), ImreadModes.Unchanged); // Unchanged: 透過も保持
var bitmapSource = mat.ToBitmapSource();
bitmapSource.Freeze();
sw.Stop();
Console.WriteLine($"OpenCVSharp decode time: {sw.ElapsedMilliseconds} ms");
return bitmapSource;
});
}
}
PNG
BitmapImage Decode time: 376 ms
SkiaSharp decode time: 412 ms
Magick.NET decode time: 669 ms
OpenCVSharp decode time: 512 ms
JPG
BitmapImage Decode time: 26 ms
SkiaSharp decode time: 83 ms
Magick.NET decode time: 108 ms
OpenCVSharp decode time: 45 ms
コメント