2

非常に大きな画像(約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を追加すると、画像の読み込みはタスク内で実行されますが、使用されているメモリの量が2倍になります。

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;

メモリに2倍にすることなくロードを強制する方法はありますか?また、デコーダーを使用してロードしようとしましたが、メモリにも2回ロードしています。

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;

ありがとう!

4

1 に答える 1

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); 
    ...
}
于 2012-10-10T19:10:27.477 に答える