2012-04-12 2 views
2

C#을 사용하여 Photoshop과 같은 페인트 프로젝트를 만들고 있습니다. 나는 그림을 그리기 위해 GDI +를 사용했다. 슬프게도 필요한 평판 포인트의 스크린 샷을 게시 할 수 없습니다. 편집 : 좋아요. 사진을 업로드 할 충분한 담당자가 있습니다. enter image description here페인트 응용 프로그램 용 도면 최적화 C#

브러쉬 크기가 커지면 마우스를 사용한 내 그림이 뒤쳐집니다. 나는 캔버스 패널

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

에 그려진 canvasBuffer을 그리고 이것은 어떤 그림이 완료되면 발생하는 것입니다.

  1. 마우스 끌기 이벤트의 포인트 목록을 저장합니다.
  2. 기록 된 점을 중심으로 점 a에서 점 b까지 일련의 원을 그립니다.
  3. 이 도면은 레이어 클래스의 획 목록에 저장된 비트 맵에서 수행됩니다. 이 그림은 또한 CompositingMode.SourceCopy를 사용하여 알파 값 그림을 구현합니다.
  4. 레이어의 최종 이미지를 저장하는 layerBuffer가 있습니다. 스트로크에 영향을받는 변경 사항을 SourceCopy 호환 모드를 사용하여 투명 색상 드로잉으로 지우고 SourceOver를 사용하여 스트로크 목록에 비트 맵을 그립니다.
  5. 구현중인 레이어링 시스템 때문에 모든 레이어 버퍼를 pictureBuffer에 그립니다. 그림 축소 그림 확대 변형을 사용하여 버퍼가 마지막으로 canvasBuffer에 그려집니다.

참고 : 캔버스 버퍼의 영향을받는 영역은 레이어 버퍼와 마찬가지로, 영향을받는 부분을 지우고 그림 버퍼의 영향을받은 부분 전체를 다시 다시 그려서 수행됩니다. 이전 그림을 지우지 않으면 알파 값을 사용한 그리기가 예상대로 작동하지 않습니다.

이 코드를 최적화하거나 마우스를 사용하여 그리는 동안 성능을 향상시키고 지연을 줄일 수있는 몇 가지 새로운 방법을 제안하십시오. 또한 스레드 코드를 사용하여 버퍼의 드로잉 코드와 점 및 드로잉을 분리 할 수 ​​있습니까?

다음은 코드입니다.

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(); 
    } 
+0

Daniel에게 감사를드립니다! –

+0

새로 고침을 어떻게 시작하나요? MouseMove 핸들러에서 새로 고침을 호출합니까? 언제 어떻게 PSF_Painted를 부르십니까? – Brannon

+0

@Brannon : mouseclick, mouseUp, mouseDown 및 mouseMove에서 PSF_Painted를 실행합니다. 또한 각 PSF_Painted가 실행 된 후에 패널 컨트롤 인 캔버스를 무효화합니다. –

답변

0

좋아,이 최적화를위한 해결책을 찾았습니다. 브러시 크기의 1/5보다 큰 거리에있는 점만 기록했습니다. 나는 완벽한 라인이 필요 없다는 것을 깨달았다. 따라서 성능을위한 회선 품질의 절충을 교환 할 수 있습니다.

관련 문제