【问题标题】:how do you use Direct2D to render ClearType text on a transparent background?如何使用 Direct2D 在透明背景上呈现 ClearType 文本?
【发布时间】:2014-12-06 04:14:48
【问题描述】:

谁能告诉我为什么 ClearType 在下面的简单 SharpDX 示例中拾取背景的透明度?以及如何阻止它这样做。

它将两行纯黑色文本渲染为半透明位图。第一行用灰度渲染,第二行用 ClearType 渲染。

编辑:有人认为问题在于表面是预乘的。但这并不能解释两种 Grayscale/ClearType 渲染之间的区别。

结果(win7):

public static void Main()
{
    var pixelFormat = SharpDX.WIC.PixelFormat.Format32bppPBGRA;

    using (var wicFactory = new ImagingFactory())
    using (var dddFactory = new SharpDX.Direct2D1.Factory())
    using (var dwFactory = new SharpDX.DirectWrite.Factory())
    using (var textFormat = new TextFormat(dwFactory, "Arial", FontWeight.Bold, FontStyle.Normal, 48))
    using (var textLayout = new TextLayout(dwFactory, "argle-bargle", textFormat, float.PositiveInfinity, float.PositiveInfinity))
    {
        var width = (int) Math.Ceiling(textLayout.Metrics.Width);
        var height = (int) Math.Ceiling(textLayout.Metrics.Height);

        using (var wicBitmap = new SharpDX.WIC.Bitmap(
            wicFactory,
            width, height * 2,
            pixelFormat,
            BitmapCreateCacheOption.CacheOnLoad))
        {
            var renderTargetProperties = new RenderTargetProperties(new SharpDX.Direct2D1.PixelFormat(Format.B8G8R8A8_UNorm, AlphaMode.Premultiplied));
            Color4 textColor = new Color4(0f, 0f, 0f, 1f);

            using (var renderTarget = new WicRenderTarget(dddFactory, wicBitmap, renderTargetProperties))
            using (var textBrush = new SolidColorBrush(renderTarget, textColor))
            {
                renderTarget.BeginDraw();
                renderTarget.Clear(new Color4(1f, 1f, 0f, .25f));

                renderTarget.TextAntialiasMode = TextAntialiasMode.Grayscale;
                renderTarget.DrawTextLayout(new Vector2(0, 0), textLayout, textBrush);

                renderTarget.TextAntialiasMode = TextAntialiasMode.Cleartype;
                renderTarget.DrawTextLayout(new Vector2(0, height), textLayout, textBrush);

                renderTarget.EndDraw();
            }

            var path = Path.Combine(Path.GetTempPath(), "test.png");
            using (var stream = File.OpenWrite(path))
            {
                using (var encoder = new PngBitmapEncoder(wicFactory, stream))
                using (var frameEncoder = new BitmapFrameEncode(encoder))
                {
                    frameEncoder.Initialize();
                    frameEncoder.WriteSource(wicBitmap);
                    frameEncoder.Commit();
                    encoder.Commit();
                }
            }
        }
    }
}

【问题讨论】:

标签: c# direct2d sharpdx cleartype


【解决方案1】:

这种意外结果是一种“正常”行为。

正如 MSDN 中所说:

如果您指定 D2D1_ALPHA_MODE_IGNORE 以外的 alpha 模式 渲染目标,文本抗锯齿模式自动从 D2D1_TEXT_ANTIALIAS_MODE CLEARTYPE 到 D2D1_TEXT_ANTIALIAS_MODE 灰度。

因此,您第一次将 renderTarget.TextAntialiasMode 分配给灰度是没有意义的,因为 Grayscale 是它最初设置的值。

来自 MSDN 的另一句话:

您可以使用 SetTextAntialiasMode 方法来更改文本 抗锯齿模式回到 D2D1_TEXT_ANTIALIAS_MODE CLEARTYPE,但是 将 ClearType 文本渲染到透明表面可以创建 不可预知的结果。如果您想将 ClearType 文本呈现到 透明渲染目标,我们建议您使用其中一种 以下两种技术。

  • 使用 PushAxisAlignedClip 方法将渲染目标剪辑到 文本将被呈现的区域,然后调用 Clear 方法并 指定不透明的颜色,然后渲染您的文本。
  • 使用 DrawRectangle 在将呈现文本的区域后面绘制一个不透明的矩形。

这里是全文:D2D1_ALPHA_MODE enumeration

所以,如果我必须总结一下:

  1. 不要将D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE 设置为具有不同于D2D1_ALPHA_MODE_IGNORE 的alpha 模式的渲染目标
  2. 遵循上面的技巧。

【讨论】:

  • 谢谢。所以基本上答案是你不能:所描述的“替代”技术都没有产生预期的结果。我想这样做的唯一方法是渲染到单独的位图并手动进行 alpha 混合。
猜你喜欢
  • 1970-01-01
  • 2017-02-01
  • 2016-12-02
  • 2018-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多