2009-05-11 2 views
7

OnPaintBackground에서 제공되는 Graphics 객체를 사용하여 TextRenderer.DrawText()를 사용하면 텍스트가 완벽 해 보입니다. 내 자신의 비트 맵을 만들고 내 비트 맵에서 얻은 Graphics 객체를 사용하면 내 텍스트가 끔찍 해 보입니다. 비트 맵의 ​​배경색이 아닌 검은 색을 사용하여 텍스트에 앤티 앨리어싱을 적용한 것처럼 보입니다. Graphics.DrawString()을 사용하면이 문제를 피할 수 있지만이 메서드는 커닝 문제가 심각합니다. 어떻게해야합니까? 비트 맵의 ​​내용을 사용하여 TextRenderer.DrawText()를 올바르게 앤티 앨리어스로 변환하려면 어떻게해야합니까?Bitmap의 TextRenderer.DrawText 대 OnPaintBackground

은 끔찍 : NOT 컨트롤의 표면에, 비트 맵에

Bitmap bmp = new Bitmap(100, 100, PixelFormat.Format32bppArgb); 
using (Graphics g = Graphics.FromImage(bmp)) 
{ 
g.Clear(Color.Red); 
TextFormatFlags tf = TextFormatFlags.Left; 
TextRenderer.DrawText(g, @"C:\Development\Testing\blag", font, clip, Color.White, Color.Transparent, tf); 
} 

좋아 보인다,하지만이 렌더링 할 :

protected override void OnPaintBackground(PaintEventArgs e) 
{ 
e.Graphics.Clear(Color.Red); 
TextFormatFlags tf = TextFormatFlags.Left; 
TextRenderer.DrawText(e.Graphics, @"C:\Development\Testing\blag", font, clip, Color.White, Color.Transparent, tf); 
} 

차이점은 무엇입니까?

답변

9

대답은 TextRenderer를 사용하지 않는 것입니다. TextRenderer는 GDI (GDI +가 아닌) 텍스트 렌더링의 구현을위한 래퍼입니다. 많은 기능이 있지만 사용자가 발견 한대로 메모리 내 DC와 상호 운용되지 않습니다.

Graphics.DrawString & Graphics.MeasureString을 사용하지만 정확한 크기와 위치를 얻으려면 StringFormat.GenericTypographic을 전달해야합니다.

TextRenderer가 처음 소개 된 이유는 GDI +에서 Uniscribe 엔진이 수행 한 모든 복잡한 스크립트를 GDI +가 지원하지 않았기 때문입니다. 그러나 시간이 지남에 따라 복잡한 스크립트에 대한 GDI + 지원이 확장되어 요즘에는 TextRenderer를 사용하는 데 남은 좋은 이유가 없습니다. 더 이상 두 가지가 빠르지는 않습니다. 실제로는 그 반대입니다.

심각하지만 측정 가능한 성능 문제가없는 한 실제로 Graphics.DrawString을 사용하십시오.

+0

'TextRenderer faster' ?? 확실합니까? 이 기사는 GDI +보다 느리다 고 말했습니다 : http://theartofdev.com/2014/04/21/text-rendering-methods-comparison-or-gdi-vs-gdi-revised/ – qakmak

+0

@qakmak [9 년 전 ] (http://blogs.msdn.com/b/cjacks/archive/2006/05/19/602021.aspx)하지만 변경되었을 수도 있습니다. 링크 된 기사의 코드는 내 컴퓨터에서 훨씬 빨라지는 DrawString을 보여줍니다. –

-1

비트 맵의 ​​크기가 표시 영역 크기와 다른 경우 크기 조정 문제가 발생할 수 있습니다. .NET에서 비트 맵을 표시 크기로 조정하면 재미있는 텍스트가 표시됩니다.

표시 영역과 동일한 크기로 만든 비트 맵으로 테스트 할 수 있습니까?

+0

둘 다 크기가 같고 DPI입니다. –

+0

저는 비트 맵에 투명도가 내장되어 있지 않으므로 다른 Image 클래스를 메모리 상 캔버스로 사용해 볼 수도 있다고 생각합니다. 이 경우 Color.Transparent는 아마도 Color.Black으로 해석 될 것입니다. 가치가있는 시도? – Mike

+0

이미지 또는 비트 맵을 사용하고 다양한 PixelFormats를 사용하여 시도해 보았습니다. 진짜 문제는 TextRenderer가 텍스트를 비트 맵에있는 텍스트로 앤티 앨리어싱하지 않고 대신에 검정색을 사용한다는 것입니다 (어떤 이유로). –

-1

이 문제로 가장 작은 프로그램을 게시 할 수 있습니까? 나는이처럼 재현 할 수없는 - 안티 앨리어싱 잘 보이는 :

using System.Drawing; 
using System.Drawing.Imaging; 
using System.Windows.Forms; 

public class Program 
{ 
    public static void Main() 
    { 
     Bitmap bmp = new Bitmap(100, 100, PixelFormat.Format32bppArgb); 
     using (Font font = new Font("Arial", 10, GraphicsUnit.Point)) 
     using (Graphics g = Graphics.FromImage(bmp)) 
     { 
      Rectangle clip = Rectangle.FromLTRB(0, 0, 100, 100); 
      g.Clear(Color.Red); 
      TextFormatFlags tf = TextFormatFlags.Left; 
      TextRenderer.DrawText(g, @"C:\Development\Testing\blag", font, clip, Color.White, Color.Transparent, tf); 
     } 

     Form form = new Form(); 
     form.BackgroundImage = bmp; 
     Application.Run(form); 
    } 
} 
+2

다음 행을 추가하십시오. g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; 또한 "Color.LightBlue"를 배경으로 사용하면 문제가 훨씬 더 잘 보입니다. 그것을 지우는 텍스트 앤티 앨리어싱입니다. –

+0

또한 "Application.SetCompatibleTextRenderingDefault (false);" true 또는 false로 설정됩니다. –

0

또 다른 가능한 해결책 : 전체를 화면에 그리고 텍스트를 비트 맵 위에 놓은 다음 화면의 해당 부분을 '화면 캡처'에 코드를 작성하십시오. 모든 경우에 실용적이지는 않지만 당신 말이 맞습니다. DrawString은 이상한 텍스트를 만들고 DrawText는 비트 맵에 끔찍하게 보입니다.

3

배경이 투명하면 클리어 타입 텍스트 렌더링이 작동하지 않는다고 생각합니다. 가능한 몇 가지 해결책.

옵션 1. 비트 맵의 ​​배경을 색상으로 채 웁니다.

Tim Robinson이 위의 코드 예제에서 g.Clear (Color.Red)를 사용하여 수행 한 것처럼 clear type이 올바른 작업을 수행합니다. 그러나 귀하의 비트 맵은 완전히 투명하지 않을 수도 있습니다. Graphics.MeasureText를 사용하는 경우 원한다면 텍스트 주위에 사각형 만 채울 수 있습니다.

옵션 2. TextRenderingHint = TextRenderingHintAntiAliasGridFit이 클리어 타입을 끌 것으로 보인다

. 텍스트는 배경의 선명한 형식보다 낮은 품질로 렌더링되지만 배경이없는 혼잡없는 형식보다 훨씬 좋습니다.

옵션 3. 텍스트 직사각형을 흰색으로 채우고 텍스트를 그린 다음 텍스트가 아닌 모든 픽셀을 찾아 다시 투명하게 놓습니다.

using (Bitmap bmp = new Bitmap(someWidth, someHeight)) 
{ 
    using (Graphics g = Graphics.FromImage(bmp)) 
    { 
     // figure out where our text will go 
     Point textPoint = new Point(someX, someY); 
     Size textSize = g.MeasureString(someText, someFont).ToSize(); 
     Rectangle textRect = new Rectangle(textPoint, textSize); 

     // fill that rect with white 
     g.FillRectangle(Brushes.White, textRect); 

     // draw the text 
     g.DrawString(someText, someFont, Brushes.Black, textPoint); 

     // set any pure white pixels back to transparent 
     for (int x = textRect.Left; x <= textRect.Left + textRect.Width; x++) 
     { 
      for (int y = textRect.Top; y <= textRect.Top + textRect.Height; y++) 
      { 
       Color c = bmp.GetPixel(x, y); 
       if (c.A == 255 && c.R == 255 && c.G == 255 && c.B == 255) 
       { 
        bmp.SetPixel(x, y, Color.Transparent); 
       } 
      } 
     } 
    } 
} 

아시다시피, 그것은 끔찍한 해킹이지만 작동하는 것처럼 보입니다.