Bitmap与OnPaintBackground中的TextRenderer.DrawText
如果我使用OnPaintBackground中提供的Graphics对象使用TextRenderer.DrawText(),我的文本看起来很完美。 如果我创建自己的Bitmap并使用从我的Bitmap获得的Graphics对象,我的文本看起来很糟糕。 看起来它使用黑色来消除锯齿,而不是位图的背景颜色。 如果我使用Graphics.DrawString(),我可以避免这个问题,但这种方法有可怕的字距调整问题。 我该怎么办? 如何使用Bitmap的内容正确地将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:DevelopmentTestingblag", 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:DevelopmentTestingblag", font, clip, Color.White, Color.Transparent, tf); }
有什么不同?
答案是不要使用TextRenderer
。 TextRenderer是文本呈现的GDI(而不是GDI +)实现的包装器,它具有许多function,但是与您发现的内存DC不能很好地互操作。
使用Graphics.DrawString
和Graphics.MeasureString
,但请记住将其传递给StringFormat.GenericTypographic以获得准确的大小和位置。
最初引入TextRenderer的原因是GDI +不支持GDI的Uniscribe引擎所做的所有复杂脚本。 然而,随着时间的推移,GDI +对复杂脚本的支持已经扩展,现在没有任何好的理由可以使用TextRenderer(它甚至不再是两者中更快的,事实上它恰好相反)。
但实际上,除非遇到严重的,可衡量的性能问题,否则只需使用Graphics.DrawString
。
我认为问题是如果背景是透明的,清晰类型的文本渲染不起作用。 一些可能的解决方案。
选项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 (cA == 255 && cR == 255 && cG == 255 && cB == 255) { bmp.SetPixel(x, y, Color.Transparent); } } } } }
我知道,这是一个可怕的黑客,但它似乎工作。
答案是使用BuffersGraphicsContext
。 当您在ControlStyles.OptimizedDoubleBuffer
上设置ControlStyles.OptimizedDoubleBuffer
样式时,这与.NET在内部使用的系统相同。
有关.NET中双缓冲的更多信息,请参见https://msdn.microsoft.com/en-us/library/b367a457.aspx 。
另一种可能的解决方案:将整个事物绘制到屏幕上,在顶部显示文本的位图,然后将一些代码写入“屏幕捕获”屏幕的那一部分。 在所有情况下都不实用,但你是对的,DrawString创建奇怪的文本,DrawText到位图看起来很糟糕。
如果您的位图与显示区域的大小不同,那么它可能只是一个resize的问题,.NET会将位图缩放到显示大小,并且您会看到有趣的文本。
您可以使用与显示区域相同大小创建的位图进行测试吗?
你能发布遭受这个问题的最小程序吗? 我无法像这样重现它 – 抗锯齿看起来很好:
上述就是C#学习教程:Bitmap与OnPaintBackground中的TextRenderer.DrawText分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注---计算机技术网(www.ctvol.com)!
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:DevelopmentTestingblag", font, clip, Color.White, Color.Transparent, tf); } Form form = new Form(); form.BackgroundImage = bmp; Application.Run(form); } }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/954736.html