【问题标题】:Displaying Thumbnails of very high resolution images Fast with Minimal Delay以最小的延迟快速显示高分辨率图像的缩略图
【发布时间】:2020-01-12 11:03:04
【问题描述】:

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

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

【问题讨论】:

  • 首先,1000x1000 不是缩略图大小。我会选择更小的,例如 64x64 甚至 128x128 像素。接下来,您需要在用户开始滚动之前预加载缩略图。此外,您可以预期列表视图中的这么多图像会有一些滞后,当您滚动浏览一个装满照片的文件夹时,甚至可以在 Google Drive 上看到相同的行为,它们加载速度很慢并且有一些延迟
  • @Jon 我也尝试过使用较小的尺寸...有些延迟是可以接受的...但是如果您看到屏幕截图,您会发现延迟太多并且缩略图没有生成线性时尚。
  • 您的缩略图每个为 1MB (1000 x 1000)。您需要将它们做得更小,而 Bitmap 可能不会尝试使用 JPG 或 PNG 来使它们更小。
  • @Jon 调整大小的过程是需要时间的。不是图像填充。
  • 您是否考虑过提前生成和存储缩略图?

标签: c# .net winforms system.drawing


【解决方案1】:

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

我做的例子:

这里有一些可能有用的文档和参考资料:

【讨论】:

  • 感谢您的回答。WIC 似乎运作良好..您看到@simon-mourier 的评论了吗。ImageMagick 是否更优化?
  • 具体比WIC好吗?
  • 您能否在答案中提及这一点。
  • 我会试试这个并回复你。谢谢
【解决方案2】:

您可以使用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:否则没有灵丹妙药,更大的图像需要更多时间。

【讨论】:

  • 对于赏金,我很抱歉,它是自动授予的..没有选择更改和奖励您的选项。我已接受并赞成您的回答。
  • @techno - 谢谢。不用担心,我认为(一半的)赏金是投票最多的答案。
  • 谢谢...你能看看这个相关的问题stackoverflow.com/questions/58061904/…
  • 我认为您的答案需要稍作修改,以解决创建流时“文件正在其他地方使用”的问题。您如何看待Stream stream = new FileStream(fileToRead, FileMode.Creat, FileAccess.ReadWrite, FileShare.ReadWrite);
  • @techno - 调整 FileStream 是一个好的开始,但我可以在这里向您推荐我的答案:stackoverflow.com/a/5441631/403671 :-)
【解决方案3】:

还有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

【讨论】:

    猜你喜欢
    • 2014-05-26
    • 2013-08-04
    • 1970-01-01
    • 2017-11-25
    • 1970-01-01
    • 1970-01-01
    • 2012-10-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多