2012-10-10 93 views
2

我試圖加載一個非常大的圖像(大約16000x7000像素)到一個材質,我試圖加載它異步。我的第一次嘗試是創建加載的BitmapImage的一個任務,然後用它進入材料:異步加載一個大的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,這是一樣的)。

我試圖避免這種情況,因爲它凍結了我的用戶界面,但我還沒有找到正確的方法來強制位圖loadi和解碼。如果我添加里面的任務進行圖片的加載一個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; 

謝謝!

+0

嘗試只在任務創建IMG。 – Paparazzi

+0

我已經試過,BitmapImage是立即創建的,然後,在任務完成後,文件被加載並解碼。我希望加載和解碼發生在任務中,以允許我在解碼大圖片時顯示加載動畫。 – jmservera

+1

我不是WPF大師,但也許[這個線程](http://stackoverflow.com/questions/36748/asynchronously-loading-a-bitmapimage-in-c-sharp-using-wpf)會給你一些想法? – Neolisk

回答

5

我不知道這個異步方案,但通常會設置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); 
    ... 
}