Displaying Thumbnails of very high resolution images Fast with Minimal Delay

雨燕双飞 提交于 2019-12-08 17:02:21

问题


I need to show the preview thumbnails of high resolution images in a control for user selection. I currently use ImageListView to load images. This works fine for low to medium resolution images.But when it comes to showing thumbnails of very high resolution images there is a noticeable delay.Sample image can be downloaded from https://drive.google.com/open?id=1Qgu_aVXBiMlbHluJFU4fBvmFC45-E81C

The image size is around 5000x3000 pixels and size is around 12 MB.The issue can be replicated by using 1000 copies of this image.

The issue screen capture is uploaded here

https://giphy.com/gifs/ZEH3T3JTfN42OL3J1A

The images are loaded using a background worker

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

1. In order to solve this issue I tried resizing large resolution images and adding the resized image to ImageListView ... but for resizing there is a heavy time consumption and thumbnail generation is slow.

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. I have also tried Image.CreateThumbnail Method but this is also quite slow.

Is there a better way to solve this issue?


回答1:


You could use 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)

You can also use WPF/WIC by code, with a code like this (adapted from this article The fastest way to resize images from ASP.NET. And it’s (more) supported-ish.. You just need to add a reference to PresentationCore and WindowsBase which shouldn't be an issue for a desktop app.

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

Otherwise there are lots of tools out there like MagicScaler, FreeImage ImageSharp, ImageMagick, Imazen, etc. Most were written for ASP.NET/Web server scenarios (for which WPF is officially not supported but works, read the article) and are also cross-platform which you don't seem to need. I'm not sure they're generally faster or use less memory than builtin Windows technology, but you should test all this in your context.

PS: otherwise there's no magic bullet, bigger images take more time.




回答2:


I would suggest using image processing library such ImageMagick.

ImageMagick has optimized this feature and you have Magick.NET a nuget package for .NET.

It is simple and straight forward:

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

example I made:

Here is some documentation and references that might be useful:

  • https://imagemagick.org/Usage/thumbnails/#creation
  • http://www.imagemagick.org/Usage/thumbnails/
  • https://github.com/dlemstra/Magick.NET
  • https://www.smashingmagazine.com/2015/06/efficient-image-resizing-with-imagemagick/

  • https://devblogs.microsoft.com/dotnet/net-core-image-processing/

  • https://weblogs.asp.net/bleroy/resizing-images-from-the-server-using-wpf-wic-instead-of-gdi
  • Alternatives to System.Drawing for use with ASP.NET?



回答3:


There's also NetVips, the C# binding for libvips.

It's quite a bit quicker than Magick.NET: between 3x and 10x faster, depending on the benchmark.

Thumbnailing is straightforward:

using NetVips;

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

There's an introduction in the documentation.



来源:https://stackoverflow.com/questions/57875015/displaying-thumbnails-of-very-high-resolution-images-fast-with-minimal-delay

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!