2013-01-13 7 views
0

나는 WinForm 응용 프로그램 '튀는 공'이 있고, 나는 bitmap에 볼 페인트이 양식에 비트 맵을 제시 할 필요가있다.사용하여 비트 맵

나는 새로운 공을 추가하는 plusButton을 가지고 있으며, 나는 각각의 새로운 공을리스트에 저장하고 있습니다.

: 거기에 공을 많이하고 모든 응용 프로그램이 매우 느리게 될 때까지 이제

에서, Form_Paint 방법은 자신을 그리는 각각의 볼을 말하고, 여기

내 코드입니다 .. 잘 를 작동

양식 코드의 페인트 방법 :

private void Form1_Paint(object sender, PaintEventArgs e) 
{ 
    ballsArray.drawImage(bmp,e, ClientRectangle); 
} 

참고 :이 클래스가 ballsArray 유형 AllBalls에서입니다이다 w 그 각 공을 유지하는 목록을 만드는 중입니다. bmp은 양식을로드 할 때 생성됩니다 (Form_Load() 메소드). ballsArray 코드의

의 drawImage :

public void drawImage(Bitmap bmp,PaintEventArgs e, Rectangle r) 
{ 
    foreach (Ball b in allBalls) 
    { 
     b.drawImage(bmp,e, r); 
    } 
} 

볼 코드의 drawImage :

public void drawImage(Bitmap bmp, PaintEventArgs e, Rectangle r) 
    { 
     using (Graphics g = Graphics.FromImage(bmp)) 
     { 
      e.Graphics.FillEllipse(brush, ballLocation); 
      g.DrawImage(bmp, 0, 0); 
     } 
    } 

참고 :ballLocation는 각 단계에서 공의 위치를 ​​나타냅니다 직사각형이다 움직임 ..

내가 wro하고있는 것 응? 응용 프로그램을 느리게 만드는 원인은 무엇입니까?

비트 맵에 모든 것을 그려서 양식에 표시하는 데 제약이 있습니다. 폼을로드 할 때 생성 한 비트 맵을 전달하기 때문에 각각을 그릴 필요가 있습니다.

+0

당신은'drawImage' 방법으로'Form1_Paint' 이벤트의'Graphics' 객체를 전달하고 그것을 직접 타원을 그림 대신 각각의 볼에 대한 새로운'Graphics'를 작성하여 훨씬 더 나은 성능을 얻을 것이다. – Rotem

+0

@Rotem는 확인 그래서 당신은 내가 ** Form1_Paint **에 ** 그래픽 g = Graphics.FromImage (BMP) **를 이동의 drawImage 메소드에이 객체를 전송해야한다는 것을 의미? – Elior

+0

정확하지 않습니다. 당신의 코드를 다시 살펴보면 왜'Graphics' 객체가 아닌 비트 맵에 그림을 그려야하는지 잘 모르겠습니다. – Rotem

답변

3

몇 가지 기본 기술은 빠른이 만들려면 :

  • 자신을 두 번 버퍼링하지 특히 ​​두 번 더블 버퍼를하지 마십시오. 폼의 DoubleBuffer 속성을 true로 설정하여 얻는 이중 버퍼링은 사용자가 수행하는 대부분의 이중 버퍼링보다 우수합니다. 버퍼는 비디오 어댑터의 설정으로 효율적으로 작동하도록 고도로 최적화되어 있습니다. 따라서 bmp 변수를 완전히 삭제하고 Paint 이벤트 처리기 인수에서 가져온 e.Graphics에 그립니다.

  • 당신은 통과 r 인수를 사용하고 있지 않습니다. 아마도 보이지 않는 볼을 클리핑하는 것을 지원하기위한 것입니다. 전달하고자하는 것은 e.ClipRectangle입니다.이 직사각형 외부에있는 페인트 공은 건너 뛸 수 있습니다. 이것이 최적화이지만 Aero 테마를 사용할 때 일반적으로 유용한 것은 아니며 일관성없는 다시 그리기 속도를 얻지 않아도되므로 건너 뛸 수 있습니다. 당신이 공을 그릴 때 Graphics.FillEllipse 및 Graphics.DrawImage 모두를 사용하는 이유

  • 그것은 매우 분명하지 않다. 이미지가 원과 겹쳐 져야하므로 FillEllipse 만 제거하면됩니다.

  • 공 그래픽을 저장하는 Bitmap 객체에 많은주의를 기울이십시오. 먼저 이미지의 정확한 크기로 그려 지므로 크기를 재조정 할 필요가 없습니다. 재조정은 매우 비쌉니다. DrawImage() 호출에서 어떤 크기 조절도하지 않지만 비트 맵의 ​​해상도가 비디오 어댑터의 해상도와 같지 않은 경우에도 여전히 크기가 조절됩니다. 다음 단계는 그것을 해결할 것입니다

  • 볼 비트 맵의 ​​픽셀 형식은 매우입니다. 비트 맵을 형식 변환없이 비디오 메모리로 직접 복사 할 수있는 것이 필요합니다. 현대의 모든 컴퓨터에서 그 형식은 PixelFormat.Format32bppPArgb입니다. 그 차이는 엄청납니다. 다른 어떤 것보다 10 배 더 빠릅니다. 추가 한 이미지 리소스에서이 형식을 얻지 못할 것이므로 프로그램을 시작할 때 비트 맵을 만들어야합니다. 필요한 코드는 this answer을 확인하십시오.

이러한 지침을 따를 때 적어도 15 배 더 빠르게 렌더링 할 수 있어야합니다. 그래도 충분하다면 DirectX를 사용해야 할 필요가 있습니다. 볼 그래픽을 비디오 메모리에 저장할 수있어 주 메모리에서 비디오 메모리로 비싼 blt를 얻지 못하는 탁월한 이점이 있습니다.

+0

'Format32bppArgb'가 빠르지 만'Format32bppPArgb'가 빠르다는 말을하고 있습니까? – Rotem

+0

예, Argb는 테스트 한 모든 시스템에서 10 배 느립니다. –

+0

와우, 잘 알고 있습니다! 감사! – Rotem

0

DrawImagePaint (또는 해당 내용은 MouseMove)은 매우 나쁜 디자인입니다.

Graphics.DrawImage은 값 비싼 작업이며 화면이 너무 비싸다. 사용자 환경 (느려짐)을 향상 시키려면 MouseDown/MouseUp 이벤트에 페인트해야합니다.

또한 drawImage 메서드에서 MemoryBuffer에 먼저 그려야하며 최종 이미지를 준비한 후 UI에 한 번 그립니다. 이 기술은 double buffering으로 알려져 있습니다.

Don't Flicker! Double Buffer! - CodeProject

은 또한 당신은 또한 화면에 빠르게 색상/이미지 전송을위한 BitBlit 네이티브 API 볼 수 있습니다.

최소한의 C# 예제는 here

+0

유 감사합니다,하지만 난 이중 버퍼링을 활성화 당신이 제안한 것과 똑같은 일을해야합니까? – Elior

+0

수동으로해야합니다.'e.Graphics.FillEllipse (brush, ballLocation);'는 집중해야하는 선입니다. – Tilak

0

이 양식 (DoubleBuffered = true) 더블 버퍼링을 사용합니다.

+0

이미 활성화되어있어 도움이되지 않았다. – Elior