Некрасивая проблема с текстом - PullRequest
3 голосов
/ 02 марта 2011

Я пишу код C # в VS2010 для достижения следующего.

Я пытаюсь нарисовать текст на прозрачном растровом изображении и наталкиваюсь на уродливый текст.Ниже приведено изображение из трех текстов (т.е. A, B и C)

Примечание: A и C имеют прозрачный фон, B имеет белый цвет в качестве фона. enter image description here Проблема:

A: Iиметь растровое изображение с форматом пикселей ARGB.И я хочу нарисовать текст в нем.Нарисованный текст имеет острые края и не учитывает прозрачность.

B: Я пишу точно такой же код, но единственное отличие от A состоит в том, что пиксели в растровом изображении больше не являются прозрачными.(Я буду заполнять прямоугольник).Но если вы заметите пиксели текста, вы увидите плавную смесь черного (цвет текста) и белого (цвет фона).

C: Я ожидаю, что текст будет выглядеть, когда ярисование текста на растровом изображении с прозрачными пикселями.

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
    }

    private void UserControl1_Paint(object sender, PaintEventArgs e)
    {
        //e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(0, Color.Red)), e.ClipRectangle);
        e.Graphics.DrawString("0123456789", new Font("Verdana", 20), Brushes.Red, new PointF(5, 10));
        e.Graphics.DrawEllipse(Pens.Black, e.ClipRectangle);
    }

    // This is a public method, using which I want to save my usercontrol to an image to save to file later.
    public Image ToImage(Size size, PixelFormat p)
    {
        Bitmap b = new Bitmap(Width, Height, p);

        using (Graphics g = Graphics.FromImage(b))
        {
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;
            PaintEventArgs e = new PaintEventArgs(g, new Rectangle(0, 0, size.Width, size.Height));
            base.OnPaint(e);
            this.OnPaint(e);
        }

        return b;
    }

Как сделать A похожим на C с прозрачным фоном.Я почти уверен, что это можно сделать, потому что такие программы, как photoshop, paint.net, справляются с этим очень хорошо.

Большое спасибо!

Datte

Ответы [ 3 ]

2 голосов
/ 02 марта 2011

Рисование текста не повлияет на альфа-канал на целевом растровом изображении и всегда будет выглядеть так, если вы рисуете промежуточное растровое изображение ARGB, которое хотите смешать с другим растровым изображением.

Вам нужно манипулировать пикселями растрового изображения после рисования текста, поэтому вы пересчитываете альфа-значение для каждого пикселя, чтобы оно равнялось тексту в градациях серого. Вы можете сделать это либо с помощью комбинации GetPixel / PutPixel при обходе растрового изображения (медленно), либо с помощью части кода unsafe (небезопасно, указатели, быстро).

1 голос
/ 21 июня 2011

Похоже, GDI + не поддерживает это из коробки. Вы можете сделать, чтобы отобразить черный текст на белом фоне, а затем изменить данные пикселей, чтобы преобразовать все пиксели в черный с альфа-значением на основе исходной яркости.

    static void GrayscaleToAlpha(Bitmap image) {
        var lockData = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
        unsafe {
            // Pointer to the current pixel
            uint* pPixel = (uint*)lockData.Scan0;
            // Pointer value at which we terminate the loop (end of pixel data)
            var pLastPixel = pPixel + image.Width * image.Height;

            while (pPixel < pLastPixel) {
                // Get pixel data
                uint pixelValue = *pPixel;
                // Average RGB
                uint brightness = ((pixelValue & 0xFF) + ((pixelValue >> 8) & 0xFF) + ((pixelValue >> 16) & 0xFF)) / 3;

                // Use brightness for alpha value, leave R, G, and B zero (black)
                pixelValue = (255 - brightness) << 24;

                // Copy back to image
                *pPixel = pixelValue;
                // Next pixel
                pPixel++;
            }

        }
        image.UnlockBits(lockData);
    }
1 голос
/ 02 марта 2011

Какой SmoothingMode вы используете для своего графического объекта?

Если вы не установили его, попробуйте изменить его значение:

http://msdn.microsoft.com/en-us/library/system.drawing.graphics.smoothingmode.aspx

...