C# 优化油漆应用程序c的绘图#

C# 优化油漆应用程序c的绘图#,c#,optimization,drawing,gdi+,double-buffering,C#,Optimization,Drawing,Gdi+,Double Buffering,我正在用c#制作一个像photoshop这样的绘画项目。 我在绘图中使用了GDI+。遗憾的是,我不能发布屏幕截图,因为需要声誉点数。 编辑:好的,我有足够的代表上传一张照片。 当画笔大小增加时,我使用鼠标绘制的图形会延迟。 我有一个画布缓冲区,它被绘制到画布面板 protected override void OnPaint(PaintEventArgs e) { if (canvasBuffer != null) { using

我正在用c#制作一个像photoshop这样的绘画项目。 我在绘图中使用了GDI+。遗憾的是,我不能发布屏幕截图,因为需要声誉点数。 编辑:好的,我有足够的代表上传一张照片。

当画笔大小增加时,我使用鼠标绘制的图形会延迟。 我有一个画布缓冲区,它被绘制到画布面板

protected override void OnPaint(PaintEventArgs e)
    {
        if (canvasBuffer != null)
        {
            using (Graphics g = e.Graphics)
            {
                g.DrawImage(canvasBuffer, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel);
            }
        }
    }
这就是绘画完成后的情况

  • 我存储鼠标拖动事件的点列表
  • 我画了一系列从a点到b点的圆,以记录的点为中心,画出一条平滑的线
  • 此绘图是在图层类中笔划列表中存储的位图上完成的。 此绘图还使用CompositingMode.SourceCopy完成,以实现alpha值绘图
  • 我有一个layerBuffer,它存储层的最终图像。我通过使用SourceCopy兼容模式使用透明颜色的图形将其清除,然后使用SourceOver在笔划列表中绘制位图,从而将受笔划影响的更改绘制到此图层缓冲区
  • 由于我正在实现的分层系统,我将所有层缓冲区都绘制到pictureBuffer。 该图片缓冲区最终通过缩放变换绘制到画布缓冲区
  • 注意:画布缓冲区的受影响区域与图层缓冲区的处理方式相同,即清除受影响部分并重新绘制图片缓冲区的整个受影响部分。 如果未清除上一个图形,则具有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();
        }
    
    public void PSF_Painted(PSF_PaintEvent e)
    {
    Layer SelectedLayer=psf.Layers[0];//在此处获取选定层
    如果((笔刷工具)getActiveTool()!=null)
    {
    //从画笔工具获取画笔属性
    BrushTool BrushTool=(BrushTool)getActiveTool();
    Pen-Pen=brushTool.getPen();
    画笔=笔。画笔;
    int brushSize=(int)pen.Width;
    //加载点数据
    列表记录点=null;
    点电流点=新点(0,0);
    上一个点=新点(0,0);
    如果(如记录点!=null)
    {
    记录点=e.记录点;
    如果(recordedPoints.Count>1)
    {
    currentPoint=recordedPoints[recordedPoints.Count-1];
    previousPoint=recordedPoints[recordedPoints.Count-2];
    }
    else if(recordedPoints.Count==1)
    {
    currentPoint=记录点[0];
    前一点=当前点;
    }
    }
    如果(e.PaintEventType==PSF_PaintEvent.StrokeStarted)
    {
    //控制台写入线(“StrokeStarted”);
    SelectedLayer.Strokes.Add(新位图(SelectedLayer.Width,SelectedLayer.Height));
    }
    else if(e.PaintEventType==PSF_PaintEvent.Painting)
    {
    //在图层笔划数据的位图中绘制图形
    使用(Graphics g=Graphics.FromImage(SelectedLayer.Strokes[SelectedLayer.Strokes.Count-1]))
    {
    列表点=Global.GetPointsOnLine(previousPoint.X,previousPoint.Y,currentPoint.X,currentPoint.Y);
    对于(int i=0;ipsf.Width)xb=SelectedLayer.Width;
    如果(yt<0)yt=0;
    如果(yb>psf.Height)yb=SelectedLayer.Height;
    //刷新对画布缓冲区受影响部分的更改
    矩形affectedRect=新矩形(xt,yt,xb-xt,yb-yt);
    float zf=psf.ZoomFactor;
    矩形canvasAffectedRect=新矩形((int)(affectedRect.X*zf),(int)(affectedRect.Y*zf),(int)(affectedRect.Size.Width*zf),(int)(affectedRect.Size.Height*zf));
    SelectedLayer.invalidateLayerBuffer(affectedRect);
    使CanvasBuffer无效(canvasAffectedRect);
    }
    }
    }
    else if(e.PaintEventType==PSF_PaintEvent.StrokeCompleted)
    {
    //Console.WriteLine(“StrokeCompleted”);
    }
    }
    这个。使无效();
    }
    
    好的,我找到了这个优化的解决方案。 我只记录了距离>画笔大小1/5的点。
    我意识到我不需要一条非常完美的线路。因此,为了提高性能,在产品线质量方面的折衷是可以交易的。

    您是如何触发刷新的?是否在MouseMove处理程序中调用刷新?你什么时候怎么称呼PSF_-Painted?@Brannon:我解雇了PSF_-Painted