web-dev-qa-db-ja.com

非常に高解像度の画像のサムネイルを最小限の遅延で高速に表示

ユーザーが選択できるように、コントロールに高解像度画像のプレビューサムネイルを表示する必要があります。現在、イメージのロードに ImageListView を使用しています。これは低解像度から中解像度の画像では問題なく機能しますが、非常に高解像度の画像のサムネイルを表示する場合、顕著な遅延が生じます。サンプル画像は https://drive.google.com/open? id = 1Qgu_aVXBiMlbHluJFU4fBvmFC45-E81C

画像のサイズは約5000x3000ピクセルで、サイズは約12 MBです。この画像のコピーを1000枚使用すると、問題を再現できます。

問題の画面キャプチャはこちらにアップロードされています

https://giphy.com/gifs/ZEH3T3JTfN42OL3J1A

画像はバックグラウンドワーカーを使用して読み込まれます

foreach (var f in filepaths)
{
    imageListView1.Items.Add(f);              
}

1。この問題を解決するために、大きな解像度の画像のサイズを変更して、ImageListViewにサイズ変更した画像を追加しようとしましたが、サイズ変更には時間がかかります消費とサムネイルの生成が遅い。

Bitmap x = UpdatedResizeImage2(new Bitmap(f), new Size(1000, 1000));
string q = Path.GetTempPath() + Path.GetFileName(f);
x.Save(Path.GetTempPath() + Path.GetFileName(f));
x.Dispose();
imageListView1.Items.Add(Path.GetTempPath() + Path.GetFileName(f));

2。私も試しましたImage.CreateThumbnailメソッドですが、これもかなり遅いです。

この問題を解決するより良い方法はありますか?

8
techno

WPF interop を使用し、 DecodePixelWidth/Heightプロパティ を使用できます。基盤となるWindowsイメージングレイヤーテクノロジー( " Windows Imaging Component ")を使用して最適化されたサムネイルを作成し、大量のメモリ(および場合によってはCPU)を節約します。 方法:BitmapImage(XAML)を使用する)

次のようなコードを使用して、コードでWPF/WICを使用することもできます(この記事から適応 ASP.NETから画像のサイズを変更する最速の方法。そして(もっと)サポートされているようです。 。デスクトップアプリの問題ではないはずのPresentationCoreおよびWindowsBaseへの参照を追加する必要があります。

    // needs System.Windows.Media & System.Windows.Media.Imaging (PresentationCore & WindowsBase)
    public static void SaveThumbnail(string absoluteFilePath, int thumbnailSize)
    {
        if (absoluteFilePath == null)
            throw new ArgumentNullException(absoluteFilePath);

        var bitmap = BitmapDecoder.Create(new Uri(absoluteFilePath), BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.None).Frames[0];
        int width;
        int height;
        if (bitmap.Width > bitmap.Height)
        {
            width = thumbnailSize;
            height = (int)(bitmap.Height * thumbnailSize / bitmap.Width);
        }
        else
        {
            width = (int)(bitmap.Width * thumbnailSize / bitmap.Height);
            height = thumbnailSize;
        }

        var resized = BitmapFrame.Create(new TransformedBitmap(bitmap, new ScaleTransform(width / bitmap.Width * 96 / bitmap.DpiX, height / bitmap.Height * 96 / bitmap.DpiY, 0, 0)));
        var encoder = new PngBitmapEncoder();
        encoder.Frames.Add(resized);
        var thumbnailFilePath = Path.ChangeExtension(absoluteFilePath, thumbnailSize + Path.GetExtension(absoluteFilePath));
        using (var stream = File.OpenWrite(thumbnailFilePath))
        {
            encoder.Save(stream);
        }
    }

それ以外の場合は、MagicScaler、ImageImageImagerp、ImageMagick、Imazenなどのツールがたくさんあります。ほとんどはASP.NET/Webサーバーシナリオ(WPFは公式にはサポートされていませんが、動作するため、記事を読んでください)用に書かれており、クロスツールでもあります。 -あなたが必要と思わないプラットフォーム。組み込みのWindowsテクノロジよりも一般的に高速であるか、メモリ使用量が少ないかはわかりませんが、すべての状況でテストする必要があります。

PS:それ以外の場合、特効薬はありません。大きな画像ほど時間がかかります。

4
Simon Mourier

ImageMagickなどの画像処理ライブラリを使用することをお勧めします。

ImageMagickはこの機能を最適化しており、Magick.NETには.NET用の nuget パッケージがあります。

シンプルで簡単です。

var file = new FileInfo(@"c:\temp\input.jpg");

using (MagickImage image = new MagickImage(file))
{
    {
        image.Thumbnail(new MagickGeometry(100, 100));
        image.Write(@"C:\temp\thumbnail.jpg");
    }
}

私が作った例:

enter image description here

役立つと思われるいくつかのドキュメントとリファレンスを次に示します。

LibvipsのC#バインディングである NetVips もあります。

Magick.NETよりもかなり高速です: 倍から10倍高速 、ベンチマークによって異なります。

サムネイルは簡単です。

using NetVips;

var image = Image.Thumbnail("some-image.jpg", 128);
image.WriteToFile("x.jpg");

ドキュメントには 概要 があります。

0
jcupitt