以最小的延迟快速显示非常高分辨率图像的缩略图

Displaying Thumbnails of very high resolution images Fast with Minimal Delay

我需要在控件中显示高分辨率图像的预览缩略图以供用户选择。我目前使用 ImageListView 加载图像。 这适用于中低分辨率 images.But 当显示非常高分辨率图像的缩略图时,有一个明显的 delay.Sample 图像可以从 https://drive.google.com/open?id=1Qgu_aVXBiMlbHluJFU4fBvmFC45-E81C

下载

图像大小约为 5000x3000 像素,大小约为 12 MB.The 使用此图像的 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方法,但是这个也很慢。

有没有更好的方法来解决这个问题?

我建议使用 ImageMagick 等图像处理库。

ImageMagick 优化了此功能,您有 Magick.NET 一个 nuget .NET 包。

简单明了:

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");
    }
}

我做的例子:

以下是一些可能有用的文档和参考资料:

您可以使用 WPF interop and use the DecodePixelWidth/Height properties. They use underlying Windows imaging layer technology ("Windows Imaging Component") to create an optimized thumbnail, saving lots of memory (and possibly CPU): How to: Use a BitmapImage (XAML)

您也可以通过代码使用 WPF/WIC,代码如下(改编自这篇文章 The fastest way to resize images from ASP.NET. And it’s (more) supported-ish.。您只需要添加对 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、FreeImage ImageSharp、ImageMagick、Imazen 等。大多数是为 ASP.NET/Web 服务器场景编写的(官方不支持 WPF)但有效,请阅读文章)并且也是您似乎不需要的跨平台。我不确定它们通常比内置 Windows 技术更快或使用更少的内存,但您应该在您的上下文中测试所有这些。

PS:否则没有灵丹妙药,更大的图像需要更多时间。

还有 NetVips,libvips 的 C# 绑定。

它比 Magick.NET 快很多:between 3x and 10x faster,具体取决于基准。

缩略图很简单:

using NetVips;

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

文档中有 an introduction