丑陋的文字问题

时间:2011-03-02 13:11:45

标签: c# .net gdi+

我正在VS2010中编写C#代码来实现以下目标。

我正在尝试在透明位图上绘制文本并运行丑陋的文本。 下面是三个文本的图片(即A,B和C)

注意:A和C有透明背景,B有白色作为背景。enter image description here 问题:

答:我有一个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 个答案:

答案 0 :(得分:2)

绘制文本不会影响目标位图上的Alpha通道,如果您绘制到要混合到其他位图的中间ARGB位图,它将始终如此。

您需要在绘制文本后操纵位图的像素,因此您需要为每个像素重新计算Alpha值,使其等于您的灰度文本。在遍历位图(慢)或代码的GetPixel部分时(不安全,指针,快速),您可以使用PutPixel / unsafe组合执行此操作。

答案 1 :(得分:1)

您使用的Graphics对象是什么SmoothingMode?

如果您尚未设置,请尝试更改其值:

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

答案 2 :(得分:1)

看起来GDI +不支持开箱即用。您可以做的是在白色背景上渲染黑色文本,然后修改像素数据,将所有像素转换为黑色,并使用基于原始亮度的Alpha值。

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