在WPF画布中书写数千笔画的最佳方法 [英] Best way to write thousands of strokes in WPF canvas

查看:53
本文介绍了在WPF画布中书写数千笔画的最佳方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须在Wacom平板电脑上(例如在纸上)通过触摸来实现书写,并且需要在WPF画布中每秒渲染高达200笔画.问题是,在大约20s的持续写入后,它会有点滞后,并且滞后会增长.我将所有笔画存储在 HashSet 中.当HashSet包含600多个元素并将其设置为背景图像并清除HashSet时,我曾考虑过进行屏幕截图,但是在大约30次屏幕截图之后,它会变得有点模糊.您有任何想法如何使其变得更好吗?

I have to implement writing by touch on Wacom tablet ( like on paper) and I need to render up to 200 strokes per second in WPF Canvas. The problem is that after about 20s of constant writing it gets a bit laggs and the laggs grows. I store all strokes in HashSet. I thought about taking screen shoot when HashSet contains over 600 elements and set it as a background image and clear the HashSet, but after ~30 screen shoots it gets a bit blurred. Do you have any idea how to make it better?

推荐答案

您可以使用 WriteableBitmap .这非常快,但是可以通过将单个字节写入位图来工作,因此,如果需要将效果应用于图形,则必须自己编写效果.这是如何使用 WriteableBitmap 的示例.在调试模式下,大约需要100毫秒才能在计算机上的1600 x 1200 px图像上绘制1000条线(每条线由1600点组成),但是我敢肯定这是可以优化的.

You can use WriteableBitmap. This is very fast, but it works by writing individual bytes to bitmap, so if you need to apply effects to the drawing, then you have to write them yourself. This is an example of how you can use WriteableBitmap. It takes ~100 ms in debug mode to draw 1000 lines (each made out of 1600 points) on 1600 x 1200 px image on my computer, but I'm sure this can be optimized.

我只是随机画线,但是您可以从 Canvas 中获取事件并捕获手写笔的位置,并在每次笔划后传递它们.

I'm just randomly drawing lines, but you can get events from Canvas and capture positions of stylus and pass them after each stroke.

public partial class MainWindow : Window
{
    private WriteableBitmap _bitmap;
    private readonly Random _random = new Random();
    private readonly Stopwatch _stopwatch = new Stopwatch();
    private const int White = 0x00000000;
    private const int Red = 0x00FF0000;

    private int _width;
    private int _height;

    public MainWindow()
    {
        InitializeComponent();
        CanvasImage.Loaded += OnLoaded;
    }

    private async void OnLoaded(object sender, RoutedEventArgs e)
    {
        _width = (int)DrawableCanvas.ActualWidth;
        _height = (int)DrawableCanvas.ActualHeight;
        _bitmap = new WriteableBitmap(_width, _height, 96, 96, PixelFormats.Bgr32, null);
        CanvasImage.Source = _bitmap;

        while (true)
        {
            unsafe
            {
                for (var index = 0; index < _width * _height; index++)
                    *((int*)_bitmap.BackBuffer + index) = White;
            }

            _stopwatch.Start();

            for (var index = 0; index < 1000; index++)
            {
                var start = _random.Next(0, _width);
                var points = Enumerable.Range(0, _width).Select(x => new Point((x + start) % _width, x % _height));
                UpdateImage(points);
            }

            Debug.WriteLine($"Last 1000 draws took: {_stopwatch.ElapsedMilliseconds} ms");
            _stopwatch.Reset();

            await Task.Delay(300);
        }
    }

    private void UpdateImage(IEnumerable<Point> points)
    {
        _bitmap.Lock();

        foreach (var point in points)
        {
            var x = (int)point.X;
            var y = (int)point.Y;
            var offset = _width * y + x;
            unsafe
            {
                *((int*)_bitmap.BackBuffer + offset) = Red;
            }
        }

        _bitmap.AddDirtyRect(new Int32Rect(0, 0, _width, _height));
        _bitmap.Unlock();
    }
}

然后查看:

<Grid>
    <Border Width="1604" Height="1204" BorderThickness="2" BorderBrush="Blue">
        <Canvas x:Name="DrawableCanvas">
            <Image x:Name="CanvasImage"></Image>
        </Canvas>
    </Border>
</Grid>

这篇关于在WPF画布中书写数千笔画的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆