C#을 사용하여 Photoshop과 같은 페인트 프로젝트를 만들고 있습니다. 나는 그림을 그리기 위해 GDI +를 사용했다. 슬프게도 필요한 평판 포인트의 스크린 샷을 게시 할 수 없습니다. 편집 : 좋아요. 사진을 업로드 할 충분한 담당자가 있습니다. 페인트 응용 프로그램 용 도면 최적화 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을 그리고 이것은 어떤 그림이 완료되면 발생하는 것입니다.
- 마우스 끌기 이벤트의 포인트 목록을 저장합니다.
- 기록 된 점을 중심으로 점 a에서 점 b까지 일련의 원을 그립니다.
- 이 도면은 레이어 클래스의 획 목록에 저장된 비트 맵에서 수행됩니다. 이 그림은 또한 CompositingMode.SourceCopy를 사용하여 알파 값 그림을 구현합니다.
- 레이어의 최종 이미지를 저장하는 layerBuffer가 있습니다. 스트로크에 영향을받는 변경 사항을 SourceCopy 호환 모드를 사용하여 투명 색상 드로잉으로 지우고 SourceOver를 사용하여 스트로크 목록에 비트 맵을 그립니다.
- 구현중인 레이어링 시스템 때문에 모든 레이어 버퍼를 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();
}
Daniel에게 감사를드립니다! –
새로 고침을 어떻게 시작하나요? MouseMove 핸들러에서 새로 고침을 호출합니까? 언제 어떻게 PSF_Painted를 부르십니까? – Brannon
@Brannon : mouseclick, mouseUp, mouseDown 및 mouseMove에서 PSF_Painted를 실행합니다. 또한 각 PSF_Painted가 실행 된 후에 패널 컨트롤 인 캔버스를 무효화합니다. –