优化涂料应用的绘图c#

时间:2012-04-12 15:32:58

标签: c# optimization drawing gdi+ double-buffering

我正在使用c#制作像photoshop这样的绘画项目。 我使用GDI +绘图。可悲的是,我不能发布屏幕截图所需的声望点。 编辑:好的,我有足够的代表上传图片。 enter image description here

当画笔大小增加时,使用鼠标的绘图会滞后。 我有一个canvasBuffer,它被绘制到画布面板

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

这就是任何绘画完成后会发生的事情。

  1. 我存储鼠标拖动事件的点列表。
  2. 我从点a到点b绘制一系列圆,以记录点为中心绘制一条平滑线
  3. 此绘图是在存储在图层类中笔划列表中的位图上完成的。 此绘图也使用CompositingMode.SourceCopy来实现alpha值绘图
  4. 我有一个layerBuffer,用于存储图层的最终图像。我通过使用SourceCopy兼容模式使用透明颜色的图形清除它,然后使用SourceOver绘制笔划列表中的位图,将此笔划影响的更改绘制到此layerBuffer
  5. 由于我正在实施的分层系统,我将所有图层缓冲区绘制到pictureBuffer。 这个图片缓冲区最终被绘制为带有缩放变换的canvasBuffer。
  6. 注意:画布缓冲区的受影响区域与图层缓冲区的操作方式相同,即清除受影响的部分并再次重新绘制图像缓冲区的整个受影响部分。 如果我不清除上一个图形,使用alpha值绘制将无法按预期工作。

    请帮助我优化此代码或提出一些新方法来改善性能并减少使用鼠标绘制时的延迟。 另外,将使用线程帮助分离绘图代码和点的计算以及绘制缓冲区吗?

    这是代码。

    public void PSF_Painted(PSF_PaintEvent e)
        {
            Layer SelectedLayer = psf.Layers[0];//Get selected layer here
            if ((BrushTool)getActiveTool() != null)
            {
                //getting the pen attributes from the brush tool
                BrushTool brushTool = (BrushTool)getActiveTool();
                Pen pen = brushTool.getPen();
                Brush brush = pen.Brush;
                int brushSize = (int)pen.Width;
                //loading points data
                List<Point> recordedPoints = null;
                Point currentPoint = new Point(0, 0);
                Point previousPoint = new Point(0, 0);
                if (e.RecordedPoints != null)
                {
                    recordedPoints = e.RecordedPoints;
                    if (recordedPoints.Count > 1)
                    {
                        currentPoint = recordedPoints[recordedPoints.Count - 1];
                        previousPoint = recordedPoints[recordedPoints.Count - 2];
                    }
                    else if (recordedPoints.Count == 1)
                    {
                        currentPoint = recordedPoints[0];
                        previousPoint = currentPoint;
                    }
                }
                if (e.PaintEventType == PSF_PaintEvent.StrokeStarted)
                {
                    //Console.WriteLine("StrokeStarted");
                    SelectedLayer.Strokes.Add(new Bitmap(SelectedLayer.Width, SelectedLayer.Height));
                }
                else if (e.PaintEventType == PSF_PaintEvent.Painting)
                {
                    //Draw the drawing in the bitmap of the layer's stroke data
                    using (Graphics g = Graphics.FromImage(SelectedLayer.Strokes[SelectedLayer.Strokes.Count - 1]))
                    {
                        List<Point> points = Global.GetPointsOnLine(previousPoint.X, previousPoint.Y, currentPoint.X, currentPoint.Y);
                        for (int i = 0; i < points.Count; i++)
                        {
                            g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
                            if (pen.Width == 1)
                            {
                                g.FillRectangle(brush, new Rectangle(points[i].X, points[i].Y, brushSize, brushSize));
                            }
                            else
                            {
                                g.FillEllipse(brush, new Rectangle(points[i].X, points[i].Y, brushSize, brushSize));
                            }
                            int xt, xb, yt, yb;
                            xt = points[i].X;
                            xb = points[i].X + brushSize;
                            yt = points[i].Y;
                            yb = points[i].Y + brushSize;
    
                            if (xt < 0) xt = 0;
                            if (xb > psf.Width) xb = SelectedLayer.Width;
                            if (yt < 0) yt = 0;
                            if (yb > psf.Height) yb = SelectedLayer.Height;
    
                            //Refresh changes to the affected part of the canvas buffer
                            Rectangle affectedRect = new Rectangle(xt, yt, xb - xt, yb - yt);
                            float zf = psf.ZoomFactor;
                            Rectangle canvasAffectedRect = new Rectangle((int)(affectedRect.X * zf), (int)(affectedRect.Y * zf), (int)(affectedRect.Size.Width * zf), (int)(affectedRect.Size.Height * zf));
                            SelectedLayer.invalidateLayerBuffer(affectedRect);
                            invalidateCanvasBuffer(canvasAffectedRect);
                        }
                    }
                }
                else if (e.PaintEventType == PSF_PaintEvent.StrokeCompleted)
                {
                    //Console.WriteLine("StrokeCompleted");
                }
            }
            this.Invalidate();
        }
    

1 个答案:

答案 0 :(得分:0)

好的,我找到了这种优化的解决方案。 我只记录了远处的点数&gt;刷子的1/5大小。 我意识到我不需要非常完美的线条。因此,可以交易性能线的质量折衷。