2014-10-10 5 views
2

может ли кто-нибудь сказать мне, почему ClearType подбирает прозрачность фона в простом примере SharpDX ниже? И как остановить это от этого.Как вы используете Direct2D для визуализации текста ClearType на прозрачном фоне?

он отображает две строки сплошного черного текста в полупрозрачное растровое изображение. первая строка отображается с оттенками серого, а вторая - с помощью ClearType.

EDIT: было высказано предположение, что проблема заключается в том, что поверхность предварительно умножается. но это не объясняет разницу между двумя визуализацией Grayscale/ClearType.

результат (win7):

enter image description here

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(); 
       } 
      } 
     } 
    } 
} 
+0

Такое поведение ожидается, так как ваша поверхность предварительно умножена (http: // msdn.microsoft.com/en-us/library/windows/desktop/dd368058(v=vs.85).aspx). Вы должны объяснить, что вы действительно ожидаете. – Aybe

+0

Я ожидаю, что оттенки серого и прозрачные визуализации будут согласованы. Что делать, если вы не можете создать непремультиплексную поверхность? – Spongman

ответ

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 enumeration

Так что, если я должен подвести итог:

  1. Не устанавливайте D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE к цели визуализации с альфа-режиме, отличном от D2D1_ALPHA_MODE_IGNORE
  2. Следуйте методам сверху.
+0

спасибо. так что в основном ответ заключается в том, что вы не можете: ни один из «альтернативных» методов не дает желаемых результатов. Я предполагаю, что единственный способ сделать это - визуализировать отдельное растровое изображение и делать альфа-смесь вручную. – Spongman