提高在wpf中绘制Tiled位图的性能

我正在寻找一种方法来改善我正在做的一些绘图的性能。 目前,我正在绘制一个32×32的瓷砖网格。 使用以下代码绘制到绘图上下文

for (int x = startX; x < endX; x++) { for (int y = startY; y < endY; y++) { dg.Children.Add( new ImageDrawing(_mapTiles[GameWorldObject.GameMap[x, y].GraphicsTile.TileStartPoint], new Rect(CountX * 8, CountY * 8, 8, 8) )); dg.Children.Add( new GeometryDrawing( null, new Pen( new SolidColorBrush( Color.FromRgb(255, 0, 20)), .3), new RectangleGeometry( new Rect(CountX * 8, CountY * 8, 8, 8) ) ) ); CountY++; } CountY = 0; CountX++; } dc.DrawDrawing(dg); 

我正在绘制的图像是CachedBitmap。 即使使用CachedBitmap,每次我需要重绘Canvas时仍然会有大约半秒的延迟。

不确定是否有更高效的方式来处理绘制到此网格。 最终我想扩展控制以充当迷你地图,所以我需要牢记这一点。

此外,我之前尝试过将每个位图直接绘制到绘图上下文,但这似乎有点慢。

我在绘图之前添加了DrawingGroup.Freeze(),它似乎有助于提高性能。

如果它主要是静态迷你地图将其绘制成图像,并绘制该图像。 或者你可以做一个大图像,将整个地图绘制到其中,然后绘制当前可见的部分。

编辑 :也许这个博客文章值得检查,无论你是用软件加载还是硬件加速。

这是使用WriteableBitmap的示例,其性能主要与整个地图的大小有关,而原始方法更依赖于切片的数量。 您可以将其更改为在拼贴之间具有Alpha混合边框,但在它们之间留下间隙将更容易且更高效。 你不需要随机化瓷砖的代码,但你应该有一些脏标志,所以你只需要重新绘制位图。

您可能还想查看我的答案以及其他人对此问题的看法。 那说你没有那么多项目,使用你的方法32×32对我来说并不慢。

   

 private void Button_Click(object sender, RoutedEventArgs e) { map.seed++; map.InvalidateVisual(); } 

 public class Map : FrameworkElement { private int[][] _mapTiles; public Map() { _mapTiles = Directory.GetFiles(@"C:\Users\Public\Pictures\Sample Pictures", "*.jpg").Select(x => { var b = new BitmapImage(new Uri(x)); var transform = new TransformedBitmap(b, new ScaleTransform((1.0 / b.PixelWidth)*tileSize,(1.0 / b.PixelHeight)*tileSize)); var conv = new FormatConvertedBitmap(transform, PixelFormats.Pbgra32, null, 0); int[] data = new int[tileSize * tileSize]; conv.CopyPixels(data, tileSize * 4, 0); return data; }).ToArray(); bmp = new WriteableBitmap(w * tileSize, h * tileSize, 96, 96, PixelFormats.Pbgra32, null); destData = new int[bmp.PixelWidth * bmp.PixelHeight]; } const int w = 64, h = 64, tileSize = 8; public int seed = 72141; private int oldSeed = -1; private WriteableBitmap bmp; int[] destData; protected override void OnRender(DrawingContext dc) { if(seed != oldSeed) { oldSeed = seed; int startX = 0, endX = w; int startY = 0, endY = h; Random rnd = new Random(seed); for(int x = startX; x < endX; x++) { for(int y = startY; y < endY; y++) { var tile = _mapTiles[rnd.Next(_mapTiles.Length)]; var rect = new Int32Rect(x * tileSize, y * tileSize, tileSize, tileSize); for(int sourceY = 0; sourceY < tileSize; sourceY++) { int destY = ((rect.Y + sourceY) * (w * tileSize)) + rect.X; Array.Copy(tile, sourceY * tileSize, destData, destY, tileSize); } } } bmp.WritePixels(new Int32Rect(0, 0, w * tileSize, h * tileSize), destData, w * tileSize * 4, 0); } dc.DrawImage(bmp,new Rect(0,0,w*tileSize,h*tileSize)); } }