【问题标题】:Optimize drawing to buffer C#优化绘图以缓冲 C#
【发布时间】:2012-04-15 19:21:26
【问题描述】:

我正在尝试用 c# 为我的大学项目制作一个类似 Photoshop 的应用程序 到目前为止,我已经创建了一个名为canvas 的自定义面板,并重载了paint 方法来绘制canvasBuffer。 该项目被称为油漆锋利。 我有一个类 PaintSharpFile 存储图像的各个层。 在 Canvas 控件上,我将选中的透明背景绘制到 canvasBuffer 上,然后绘制清晰文件中的图层。我终于画了这个缓冲区(双缓冲)。

现在,我正在编写画笔工具的代码。 我记录了前一个点和当前点,然后在 canvasBuffer 本身上使用 Bresenham 的线算法在这两个点之间绘制一系列圆圈。这似乎工作得又快又好。

现在,由于画笔工具将在选定的活动图层上工作,我尝试将点绘制到图层的缓冲区。然后绘制所有图层的缓冲区canvasBuffer。这样做会使绘图变得非常缓慢。

这是代码

    public void PSF_Painted(PSF_PaintEvent e) 
    {
        Graphics g = null;
        Bitmap layerBuffer = psf.Layers[0].LayerBuffer;//Get selected layer here
        g = Graphics.FromImage(layerBuffer);
        Brush blackBrush = new SolidBrush(Color.Black);
        Pen blackPen = new Pen(blackBrush);
        blackPen.Width = 2;

        List<Point> recordedPoints = e.RecordedPoints;
        Point currentPoint = new Point(0,0);
        Point previousPoint = new Point(0, 0); ;
        if(recordedPoints.Count > 0)
        {
            currentPoint = recordedPoints[recordedPoints.Count - 1];
            if(recordedPoints.Count == 1)
            {
                previousPoint = recordedPoints[0];
            }
            else
            {
                previousPoint = recordedPoints[recordedPoints.Count - 2];
            }
        }

        if (e.PaintEventType == PSF_PaintEvent.Painting)
        {
            List<Point> points = Global.GetPointsOnLine(previousPoint.X, previousPoint.Y, currentPoint.X, currentPoint.Y);
            for (int i = 0; i < points.Count ; i++)
            {
                g.FillEllipse(blackBrush, new Rectangle(points[i].X, points[i].Y, (int)blackPen.Width, (int)blackPen.Width));
            }
        }
        Global.drawToBuffer(canvasBuffer, layerBuffer);//Replaced with redraw the full picture from the List of layer to the canvasBuffer
        g.Dispose();
        this.Invalidate();
    }

这是我的 onPaint 代码

    protected override void OnPaint(PaintEventArgs e) 
    {
        if (canvasBuffer != null)
        {
            Graphics g = e.Graphics;
            g.DrawImage(canvasBuffer, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel);
            g.Dispose();
        }
    }

这里是绘制到缓冲区的图片

public static void drawToBuffer(Bitmap buffer, Bitmap image)
    {
        if (image != null && buffer != null)
        {
            Graphics g = Graphics.FromImage(buffer);
            g.DrawImage(image, new Rectangle(0, 0, buffer.Width, buffer.Height));
            g.Dispose();
        }
    }

请告诉我如何防止油漆滞后。

我尝试制作了几个画布,每个画布都有一个图层图像。但是由于不是双缓冲的,所以会导致闪烁。

【问题讨论】:

    标签: c# drawing paint doublebuffered


    【解决方案1】:

    让我大吃一惊的是,您在每次更新时都复制了整个图层。尝试将复制限制在受影响的区域。

    与性能无关,您直接在 Graphics 对象上调用 Dispose,但不处理您创建的 Brush 和 Pen 对象。 using 块有什么问题?

    【讨论】:

    • 谢谢 .. 我刚刚读到 using 语句语法 .. 我会尝试更新矩形的一小部分。但这是解决问题的方法吗?我的意思是绘图应用程序的概念。
    • 我从未编写过绘图应用程序,但我怀疑使用 System.Drawing 命名空间(GDI+ 的包装器)可能无法为您提供最佳性能。直接针对位图操作的绘图库可能会更好。在编写太多代码之前还值得考虑的一些事情是如何实现撤消/重做缓冲区以及在哪里存储有关用户选择的绘图工具的详细信息?
    • Andrew Kennan,是的,我使用 GDI+ 进行绘图,但它没有给我想要的性能。我通过使用一些数组和 FIFO 堆栈存储的笔画位图来考虑撤消和重做缓冲区。我想让你看看这个stackoverflow.com/questions/10126862/…我已经尝试按照你的建议优化它,只画受影响的部分。如果,我直接在画布缓冲区上绘制并且没有 alpha 就可以了。但由于分层系统和 alpha 彩色绘图,我在性能方面陷​​入困境。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-19
    • 1970-01-01
    • 2014-04-07
    • 2012-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多