异步加载BitmapSource映像时内存泄漏

时间:2010-03-11 19:48:37

标签: c# wpf image memory-leaks bitmap

我有一些我正在加载到WPF应用程序中的ListBox中的图像。最初我使用GDI调整图像大小(原件占用的内存太多)。这很好,除了他们每张图片大约需要400毫秒。不太好。因此,在寻找另一种解决方案时,我发现了一种使用TransformedBitmap(继承自BitmapSource)的方法。那很好,我想,我可以用它。除了我现在在某处发生内存泄漏......

我正在使用BackgroundWorker异步加载图像:

BitmapSource bs = ImageUtils.ResizeBitmapSource(ImageUtils.GetImageSource(photo.FullName));
                //BitmapSource bs = ImageUtils.GetImageSource(photo.FullName);
                bs.Freeze();

                this.dispatcher.Invoke(new Action(() => { photo.Source = bs; }));

GetImageSource只从路径中获取Bitmap,然后转换为BitmapSource。

以下是ResizeBitmapSource的代码段:

const int thumbnailSize = 200;
        int width;
        int height;

        if (bs.Width > bs.Height)
        {
            width = thumbnailSize;
            height = (int)(bs.Height * thumbnailSize / bs.Width);
        }
        else
        {
            height = thumbnailSize;
            width = (int)(bs.Width * thumbnailSize / bs.Height);
        }

        BitmapSource tbBitmap = new TransformedBitmap(bs,
                                                           new ScaleTransform(width / bs.Width,
                                                                              height / bs.Height, 0, 0));

        return tbBitmap;

该代码本质上来自以下代码: http://rongchaua.net/blog/c-wpf-fast-image-resize/

任何可能导致泄漏的想法?

编辑: 这是GetImageSource的代码,按要求

using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                using (var bmp = Image.FromStream(stream, false, false))
                {
                    // Use WPF to resize
                    var bitmapSource = ConvertBitmapToBitmapSource(bmp);
                    bitmapSource = ResizeBitmapSource(bitmapSource);
                    return bitmapSource;
                }
            }

2 个答案:

答案 0 :(得分:4)

我认为您误解了TransformedBitmap的工作原理。它保留对源位图的引用,并将其转换为内存。也许你可以将转换后的位图编码成一个内存流,然后立即将其读出来。我不确定这会有多快,但你不会坚持使用全尺寸的位图。

我发现这个blog post返回了一个带有TransformedBitmap作为源的WriteableBitmap。 WriteableBitmap会将像素数据复制到初始化程序中的内存缓冲区,因此它实际上不会保留对TransformedBitmap或全尺寸图像的引用。

答案 1 :(得分:1)

猜测,从查看代码开始,您可能需要处理调用ImageUtils.GetImageSource(photo.FullName)返回的位图。

我还在博客上指出,作者已经添加了一个关于插入using语句以防止内存泄漏的更新(3月11日)。