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

rt4zxlrg  于 2022-11-16  发布在  其他
关注(0)|答案(4)|浏览(226)

我需要在一个控件中显示高分辨率图像的预览缩略图供用户选择。我目前使用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方法,但速度也很慢。

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

vmjh9lq9

vmjh9lq91#

我建议使用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");
    }
}

我做例子:

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

hi3rlvi2

hi3rlvi22#

您可以使用WPF interopDecodePixelWidth/Height properties。它们使用底层Windows图像层技术(“Windows Imaging Component“)来创建优化的缩略图,从而节省大量内存(可能还节省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:否则就没有灵丹妙药了,大图像需要更多时间。

disho6za

disho6za3#

还有NetVips,它是libvips的C#绑定。
它比Magick.NET快很多:速度提高3倍到10倍,具体取决于性能指标评测。
缩略图是简单明了的:

using NetVips;

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

文档中有an introduction

r9f1avp5

r9f1avp54#

大多数的解决方法是调整位图的大小,然后保存它。这当然有点慢,特别是如果你说very high resolution
为什么不使用windows资源管理器创建的现有缩略图呢?这是最快的方法(特别是如果你使用较小的缩略图)。

//https://stackoverflow.com/a/1751610
using Microsoft.WindowsAPICodePack.Shell;

var shellFile = ShellFile.FromFilePath(pathToYourFile); Bitmap
Image image = shellFile.Thumbnail.LargeBitmap;

Nuget:https://www.nuget.org/packages/WindowsAPICodePack-Shell(大约600KB)

相关问题