异步加载大的BitmapImage [英] Load a large BitmapImage asynchronously
问题描述
我正在尝试将非常大的图像(大约16000x7000像素)加载到Material中,并且尝试异步加载.我的第一个尝试是创建一个加载BitmapImage的任务,然后将其用于材质:
I'm trying to load a very large image (about 16000x7000 pixel) into a Material, and I've tried to load it asynchronously. My first try was to create a task that loaded the BitmapImage and then use it into the material:
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,这是相同的.)
But what I've found is that the image it is not loaded and expanded into memory until the material is shown (it's the same if I use the ImageBrush directly).
我试图避免这种情况,因为它会冻结我的UI,但是我没有找到正确的方法来强制位图加载和解码.如果我添加一个WriteableBitmap,则图片的加载是在Task内部执行的,但是我的使用的内存量将增加一倍:
I'm trying to avoid that because it freezes my UI, but I haven't found the right way to force the bitmap loadi and decode. If I add a WriteableBitmap the load of the picture is performed inside the Task, but then I'm doubling the amount of memory being used:
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;
是否有任何方法可以在不加倍将其加载到内存的情况下强制加载.我还尝试通过解码器加载它,但是我也两次加载到内存中:
Is there any way to force the load without doubling it into memory. I also tried to load it with a decoder, but I'm also loading into memory twice:
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;
谢谢!
推荐答案
我不确定这种异步方案,但通常会设置BitmapCacheOption.OnLoad 强制立即缓存到内存:
I'm not sure about this asynchronous scenario, but you would usually set BitmapCacheOption.OnLoad to force immediate caching to memory:
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);
...
}
这篇关于异步加载大的BitmapImage的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!