图像查看器和高内存使用率

3

我正在使用.NET的FreeImage包装器在WPF中制作一个简单的图像查看器(http://freeimage.sourceforge.net/)

这是代码:

    public static void OpenImage(string path)
    {
        _rawImage = new FreeImageBitmap(path);
        BitmapSource bs = Utils.BitmapToBitmapSource(_rawImage.ToBitmap());
        mainWindow.imageComponent.Source = bs;
        mainWindow.imageComponent.Width = _rawImage.Width;
        mainWindow.imageComponent.Height = _rawImage.Height;

    }

    [System.Runtime.InteropServices.DllImport("gdi32")]
    static extern int DeleteObject(IntPtr o);

    public static BitmapSource BitmapToBitmapSource(System.Drawing.Bitmap source)
    {
        IntPtr ip = source.GetHbitmap();
        BitmapSource bs = null;
        try
        {
            bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(ip,
               IntPtr.Zero, Int32Rect.Empty,
               System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
        }
        finally
        {
            DeleteObject(ip);
        }

        return bs;
    }

问题在于显示图片时内存峰值和总内存使用量会飙升。我用来测试的图片是一张5000x5000的jpeg图片。FreeImage报告称它在内存中占用了70MB,这是正确的。如果运行以下代码片段,我的应用程序将占用约100MB(30MB用于WPF,70MB用于图片):

_rawImage = new FreeImageBitmap(path);

运行完整代码时,内存飙升到约280MB,这太多了。在生产代码中,我可以清除所有未使用的项,但最初的峰值太高了。我使用IrfanView进行图像浏览,对于相同的图像,它只占用77MB的内存。

如果有解决方案,我想要解决加载和将图像转换为WPF Image可以显示的格式所需的峰值。如果可能,进一步减少RAM使用率。我处理大型图像,如果每次加载一个图像需要3倍的内存,那就太可怕了。我对WPF和总体上的这些东西都很陌生,所以可能会有我不知道的东西。

如果在WPF中没有可能的解决方案,还有其他的东西吗?我愿意听取建议。

我尝试过搜索,但未能找到任何解决当前问题的内容。

非常感谢。


1
我不知道freeimage是什么,但在WPF中你不需要任何它的东西。WPF拥有自己的机制来处理一切,不关心GDI或其他过时的框架。你应该移除它并使用纯WPF的东西。 - Federico Berasategui
我需要FreeImage,因为它支持许多图像格式,例如raw、hdr和psd等。 - Edgar
1
这篇文章似乎证实了我的怀疑。 - mbeckish
@mbeckish提出了一个很好的观点。以32bpp加载5000x5000并将整个图像保留在内存中,当然会使用大量内存。这是无法避免的。但是,您可以通过显示/存储用户当前可以看到的图像部分来限制您正在使用的内存量。 - Simon Whitehead
@Edgar,你最终使用了FreeImage还是其他什么东西? - Daniel
显示剩余2条评论
1个回答

1
这是我的看法:
<Window x:Class="LargeJpeg.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Image x:Name="Image" Stretch="None"/>
</Window>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var bitmap = new BitmapImage();
        bitmap.BeginInit();

        bitmap.CacheOption = BitmapCacheOption.None;
        bitmap.UriSource = new Uri(@"C:\5x5.jpg", UriKind.Absolute);
        bitmap.DecodePixelWidth = (int)Image.ActualWidth;
        bitmap.EndInit();
        bitmap.Freeze();


        Image.Source = bitmap;
    }
}

平均内存使用量:在5000 x 5000的JPEG图像上为130 MB。


如果图像未加载,ActualHeight和ActualWidth将等于0。最好取父容器的尺寸。 - Ievgen
有人知道为什么在WPF中,5000 x 5000的JPEG图片占用近100 MB内存吗?我在我的应用程序中也遇到了同样的问题。 - deathrace

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接