在透明像素之上使用 DrawString 进行错误的文本渲染
将文本渲染到位图时,我发现在具有非不透明 Alpha 的区域顶部渲染时,文本看起来非常糟糕。随着底层像素变得更加透明,问题变得越来越严重。如果我不得不猜测,我会说当底层像素是透明的时,文本渲染器将任何抗锯齿“灰色”像素绘制为纯黑色。
以下是一些屏幕截图:
在透明像素上绘制的文本:
文本在半透明像素上绘制:
在不透明像素上绘制的文本:
这是用于渲染文本的代码:
g.SmoothingMode = SmoothingMode.HighQuality;
g.DrawString("Press the spacebar", Font, Brushes.Black, textLeft, textTop);
When rendering text into a bitmap, I find that text looks very bad when rendered on top of an area with non-opaque alpha. The problem is progressively worse as the underlying pixels become more transparent. If I had to guess I'd say that when underlying pixels are transparent, the text renderer draws any anti-aliased 'gray' pixels as solid black.
Here are some screenshots:
Text drawn on top of transparent pixels:
Text drawn on top of semi-transparent pixels:
Text drawn on opaque pixels:
Here is the code used to render the text:
g.SmoothingMode = SmoothingMode.HighQuality;
g.DrawString("Press the spacebar", Font, Brushes.Black, textLeft, textTop);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我用来解决此问题的选项是:
TextRenderingHint 中还有其他一些有用的选项
希望它有帮助
The option I used to workaround this problem was:
There are some others useful options in TextRenderingHint
Hope it helps
对此有一个非常简单的答案...
如果您在渲染文本之前设置它,它会变得清晰。此外,该方法支持更多的字体大小(默认最大仅56号)。
感谢您阅读这篇文章。
There is a very simple answer to this...
If you set this before you render your text, it will come out clear. In addition, this methods supports more font sizes (The default only goes up to size 56).
Thanks for reading this post.
第一个输出是在黑色背景上绘制黑色文本时得到的输出,可能是 Color.Transparent。第二个是在几乎黑色的背景上绘制的。第三个是在与显示的背景相同的背景上绘制的。
在透明背景上时,抗锯齿功能无法发挥作用。当文本以不同的背景显示时,用于抗锯齿像素的颜色不会将字母形状混合到背景中。这些像素现在将变得非常引人注目,并使文本看起来非常糟糕。
请注意,SmoothingMode 不会影响文本输出。如果您使用质量较低的 TextRenderingHint 和 alpha 为零的灰色背景颜色,看起来会稍微好一些。只有 TextRenderingHint.SingleBitPerPixelGridFit 可以避免所有抗锯齿问题。
对此进行完美修复非常困难。 Vista 窗口标题栏上的玻璃效果使用非常微妙的阴影来为文本提供明确定义的背景颜色。您需要 SysInternals 的 ZoomIt 工具才能真正看到它。具有非零 iGlowSize 的 DrawThemeTextEx() 函数。
The first output is what you get when you draw black text on a black background, probably Color.Transparent. The 2nd was drawn on an almost-black background. The 3rd was drawn on the same background it is being displayed with.
Anti-aliasing cannot work when on a transparent background. The colors used for the anti-aliasing pixels will not blend the letter shape into the background when the text is displayed with a different background. Those pixels will now become very noticeable and make the text look very bad.
Note that SmoothingMode doesn't affect text output. It will look slightly less bad if you use a lower quality TextRenderingHint and a background color that's grayish with a alpha of zero. Only TextRenderingHint.SingleBitPerPixelGridFit avoids all anti-aliasing troubles.
Getting a perfect fix for this is very difficult. Vista's glass effect on the window title bar uses very subtle shading to give the text a well defined background color. You'd need SysInternals' ZoomIt tool to really see it. DrawThemeTextEx() function with a non-zero iGlowSize.
如果您正在寻找比 GDI+ 默认情况下更好地保留抗锯齿功能的东西,您可以使用色度键调用
Graphics.Clear
,然后手动删除由此产生的色度伪像。 (参见为什么 DrawString 看起来这么糟糕?和难看的文本问题。)这就是我最终的结果解决类似的问题:
很遗憾 GDI/GDI+ 还没有这样做,但这是明智的,不是吗? :)
如果您无法使用
unsafe
上下文,您可以轻松地使用与Bitmap.GetPixel
和Bitmap.SetPixel
相同的逻辑,尽管速度会慢很多。If you're looking for something that preserves antialiasing a bit better than GDI+ does by default, you can call
Graphics.Clear
with a chroma key, then manually remove the chroma artifacts that result. (See Why does DrawString look so crappy? and Ugly looking text problem.)Here's how I ultimately ended up solving a similar problem:
It's a shame GDI/GDI+ doesn't do this already, but that would be sensible, wouldn't it? :)
If you aren't able to use an
unsafe
context, you could easily use the same logic withBitmap.GetPixel
andBitmap.SetPixel
, though it will be significantly slower.