【问题标题】:Load a large BitmapImage asynchronously异步加载大的 BitmapImage
【发布时间】:2012-10-01 06:31:36
【问题描述】:

我正在尝试将一个非常大的图像(大约 16000x7000 像素)加载到材质中,并且我尝试异步加载它。我的第一次尝试是创建一个加载 BitmapImage 的任务,然后将其用于材质:

var bmp = await System.Threading.Tasks.Task.Run(() =>
{
    BitmapImage img = new BitmapImage(new Uri(path));
    ImageBrush brush = new ImageBrush(img);
    var material = new System.Windows.Media.Media3D.DiffuseMaterial(brush);
    material.Freeze();
    return material;
});
BackMaterial = bmp;

但我发现,在显示材料之前,它没有加载图像并扩展到内存中(如果我直接使用 ImageBrush 也是一样的)。

我试图避免这种情况,因为它会冻结我的 UI,但我还没有找到强制位图加载和解码的正确方法。如果我添加一个 WriteableBitmap,图片的加载是在任务内部执行的,但是我正在使用的内存量增加一倍:

var bmp = await System.Threading.Tasks.Task.Run(() =>
{
    BitmapImage img = new BitmapImage(new Uri(path));
    WriteableBitmap wbmp = new WriteableBitmap(img);
    ImageBrush brush = new ImageBrush(wbmp);
    var material = new System.Windows.Media.Media3D.DiffuseMaterial(brush);
    material.Freeze();
    return material;
});
BackMaterial = bmp;

有什么方法可以强制加载而不将其加倍到内存中。我也尝试用解码器加载它,但我也加载到内存中两次:

var decoder = BitmapDecoder.Create(new Uri(path), BitmapCreateOptions.PreservePixelFormat,
     BitmapCacheOption.None);
var frame = decoder.Frames[0];
int stride = frame.PixelWidth * frame.Format.BitsPerPixel / 8;
byte[] lines = new byte[frame.PixelHeight * stride];
frame.CopyPixels(lines, stride, 0);
var img = BitmapImage.Create(
    frame.PixelWidth, frame.PixelHeight, frame.DpiX, frame.DpiY, frame.Format,
    frame.Palette, lines, stride);
frame = null;
lines = null;

谢谢!

【问题讨论】:

  • 尝试只在任务中创建img。
  • 我已经尝试过了,BitmapImage 是立即创建的,然后,在任务完成后,文件被加载和解码。我希望加载和解码发生在任务中,以便在解码大图片时显示加载动画。
  • 我不是 WPF 大师,但也许this thread 会给你一些想法?
  • 谢谢,我试过了,但在我的情况下没有用。

标签: .net wpf async-await


【解决方案1】:

我不确定这种异步方案,但您通常会设置 BitmapCacheOption.OnLoad 以强制立即缓存到内存:

var bmp = await System.Threading.Tasks.Task.Run(() => 
{ 
    BitmapImage img = new BitmapImage(); 
    img.BeginInit(); 
    img.CacheOption = BitmapCacheOption.OnLoad; 
    img.UriSource = new Uri(path); 
    img.EndInit(); 
    ImageBrush brush = new ImageBrush(img); 
    ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-11
    • 1970-01-01
    • 2010-09-10
    相关资源
    最近更新 更多