为了账号安全,请及时绑定邮箱和手机立即绑定

在 WPF 画布中编写数千笔画的最佳方式

在 WPF 画布中编写数千笔画的最佳方式

C#
慕的地8271018 2021-08-22 18:03:59
我必须通过在 Wacom 平板电脑(如在纸上)上触摸来实现书写,并且我需要在 WPF Canvas 中每秒渲染多达 200 个笔画。问题是,经过大约 20 秒的持续写入后,它会变得有点滞后,并且滞后会增加。我将所有笔画存储在HashSet 中。当 HashSet 包含超过 600 个元素并将其设置为背景图像并清除 HashSet 时,我想进行屏幕拍摄,但是在大约 30 次屏幕拍摄后它变得有点模糊。你知道如何让它变得更好吗?
查看完整描述

1 回答

?
MM们

TA贡献1886条经验 获得超2个赞

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


我只是随机绘制线条,但您可以从Canvas触控笔获取事件并捕获其位置,并在每次笔画后传递它们。


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>


查看完整回答
反对 回复 2021-08-22
  • 1 回答
  • 0 关注
  • 231 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信