8

テキストで提供されているオブジェクトを使用TextRenderer.DrawText()すると、完璧に見えます。独自のオブジェクトを作成して、テキストから取得したオブジェクトを使用すると、見栄えが悪くなります。ビットマップの背景色ではなく、黒を使用してテキストをアンチエイリアス処理しているようです。を使用すればこの問題は回避できますが、この方法には恐ろしいカーニングの問題があります。私は何をすべきか?ビットマップのコンテンツを使用して適切にアンチエイリアスを取得するにはどうすればよいですか?GraphicsOnPaintBackgroundBitmapGraphicsBitmapGraphics.DrawString()TextRenderer.DrawText()

ひどく見える:

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);
}

違いはなんですか?

4

6 に答える 6

9

答えは、使用しないことTextRendererです。TextRenderer は、テキスト レンダリングの GDI (GDI+ ではない) 実装のラッパーです。これには多くの機能がありますが、ご存じのとおり、インメモリ DC とはうまく相互運用できません。

Graphics.DrawString&を使用Graphics.MeasureStringしますが、正確なサイズと位置を取得するために StringFormat.GenericTypographic を渡すことを忘れないでください。

TextRenderer が最初に導入された理由は、GDI の Uniscribe エンジンがサポートしていたすべての複雑なスクリプトを GDI+ がサポートしていなかったためです。しかし、時間が経つにつれて、複雑なスクリプトに対する GDI+ のサポートが拡張され、最近では TextRenderer を使用する正当な理由は何も残っていません (2 つのうちのどちらよりも高速ではなく、実際にはまったく逆のように見えます)。

ただし、重大で測定可能なパフォーマンスの問題が発生していない限り、Graphics.DrawString.

于 2009-10-16T13:31:51.540 に答える
3

背景が透明な場合、クリアタイプのテキストレンダリングが機能しないことが問題だと思います。いくつかの可能な解決策。

オプション 1. ビットマップの背景を色で塗りつぶします。

これを行うと (Tim Robinson が上記のコード例で g.Clear(Color.Red) を使用して行ったように)、clear 型は正しいことを行います。ただし、ビットマップは完全に透明ではなく、受け入れられない場合があります。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);
                }
            }
        }
    }
}

私は知っています、それは恐ろしいハックですが、うまくいくようです.

于 2010-07-15T20:29:36.723 に答える
2

答えは、を使用することBuffersGraphicsContextです。ControlStyles.OptimizedDoubleBufferこれは、コントロールにスタイルを設定するときに .NET が内部的に使用するシステムと同じです。

.NET でのダブル バッファリングの詳細については、http://msdn.microsoft.com/en-us/library/b367a457.aspxを参照してください。

于 2011-10-28T12:04:43.380 に答える
0

もう 1 つの考えられる解決策: 全体を画面に描画し、ビットマップの上にテキストを配置してから、画面のその部分を「画面キャプチャ」するコードを記述します。すべての場合に実用的ではありませんが、そのとおりです。DrawString は奇妙なテキストを作成し、ビットマップへの DrawText は恐ろしく見えます。

于 2010-04-08T20:55:54.977 に答える
-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);
    }
}
于 2009-05-11T21:39:37.687 に答える