как использовать Direct2D для визуализации текста ClearType на прозрачном фоне?

может кто-нибудь сказать мне, почему 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();
                }
            }
        }
    }
}

person Spongman    schedule 10.10.2014    source источник
comment
Такое поведение ожидается, поскольку ваша поверхность предварительно умножена (msdn.microsoft.com/en-us/library/windows/desktop/). Вы должны объяснить, чего вы действительно ожидаете.   -  person aybe    schedule 11.10.2014
comment
Я ожидал, что рендеринг в оттенках серого и четкий тип изображения будут согласованными. Что делать, если вы не можете создать поверхность без предварительного умножения?   -  person Spongman    schedule 12.10.2014


Ответы (1)


Этот неожиданный результат является «нормальным» поведением.

Как это указано в MSDN:

Если вы укажете альфа-режим, отличный от D2D1_ALPHA_MODE_IGNORE для цели рендеринга, режим сглаживания текста автоматически изменится с D2D1_TEXT_ANTIALIAS_MODE CLEARTYPE на D2D1_TEXT_ANTIALIAS_MODE GRAYSCALE.

Итак, ваше первое присвоение renderTarget.TextAntialiasMode оттенкам серого бессмысленно, потому что Grayscale - это его изначально установленное значение.

Еще одна цитата из MSDN:

Вы можете использовать метод SetTextAntialiasMode, чтобы изменить режим сглаживания текста обратно на D2D1_TEXT_ANTIALIAS_MODE CLEARTYPE, но рендеринг текста ClearType на прозрачную поверхность может привести к непредсказуемым результатам. Если вы хотите визуализировать текст ClearType для прозрачной цели визуализации, мы рекомендуем вам использовать один из следующих двух методов.

  • Используйте метод PushAxisAlignedClip, чтобы закрепить цель рендеринга в области, где будет отображаться текст, затем вызовите метод Clear и укажите непрозрачный цвет, а затем визуализируйте текст.
  • Используйте DrawRectangle, чтобы нарисовать непрозрачный прямоугольник за областью, в которой будет отображаться текст.

Вот полный текст статьи: Перечисление D2D1_ALPHA_MODE

Итак, если мне нужно резюмировать:

  1. Не устанавливайте D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE для цели рендеринга с альфа-режимом, отличным от D2D1_ALPHA_MODE_IGNORE
  2. Следуйте приведенным выше методам.
person Peter Kostov    schedule 23.10.2014
comment
благодаря. так что в основном ответ заключается в том, что вы не можете: ни один из описанных «альтернативных» методов не дает желаемых результатов. Думаю, единственный способ сделать это - отрендерить отдельное растровое изображение и выполнить альфа-смешение вручную. - person Spongman; 21.03.2015