WPF FormattedText случайно исчезает в изображениях с высоким разрешением

У меня есть требование создать "тройные" изображения с разрешением 600 точек на дюйм, которые имеют размеры 25,5 "x11" (в три раза больше, чем размер страницы Letter). Для этого я использую WPF Imaging через классы DrawingVisual, DrawingContext и RenderTargetBitmap.

Когда я создаю изображение с более низким разрешением, например, 400 точек на дюйм или меньше, весь текст отображается в правильных положениях, как и ожидалось. Однако, как только я увеличиваю разрешение изображения до уровня 500 точек на дюйм и выше, определенный текст, расположенный в крайнем правом углу изображения, просто исчезает, в то время как другой относительно позиционированный текст / фигуры печатаются безупречно. Самое безумное в этом то, что, когда я пытаюсь варьировать DPI, другой текст будет появляться / исчезать. В одном тестовом случае в 600 DPI отсутствует один набор нарисованных FormattedTexts, в 650 DPI отсутствует другой набор нарисованных FormattedTexts, а при 700 DPI все печатается нормально!

Я воссоздал проблему с помощью приведенного ниже фрагмента кода. Запустите как есть (600 точек на дюйм), и вы получите очень большое белое изображение. Измените константу Dpi на 400 или ниже, и текст будет печататься нормально.

Обратите внимание, что я пытался повернуть многие ручки в классе DrawingVisual (например, VisualBitmapScalingMode, VisualTextRenderingMode, VisualEdgeMode и т. Д.), Но безрезультатно. Большинство моих исследований этих настроек показало, что они полезны для исправления «нечеткого» текста, а не для его исчезновения. Мне также не повезло ни с какими настройками направляющих / привязок в DrawingVisual или DrawingContext.

Обратите внимание, что я воссоздал эту проблему как для Win7, так и для Win2008R2, и мое приложение работает под управлением .NET 4.5.

Любые идеи?

        const double ImageWidthInches = 25.5;
        const double ImageHeightInches = 11.0;
        const double Dpi = 600.0;
        const double DeviceIndependentUnits = 96.0;
        const double TypographicUnits = 72.0;

        var visual = new DrawingVisual();
        var drawing = visual.RenderOpen();

        drawing.DrawRectangle(
            Brushes.White,
            null,
            new Rect(0,
                     0,
                     ImageWidthInches*DeviceIndependentUnits,
                     ImageHeightInches*DeviceIndependentUnits));

        var formattedText = new FormattedText(
            "Why doesn't this display?",
            CultureInfo.CurrentUICulture,
            FlowDirection.LeftToRight,
            new Typeface(new FontFamily("Arial Narrow"),
                         FontStyles.Normal,
                         FontWeights.Normal,
                         FontStretches.Normal),
            8.0*DeviceIndependentUnits/TypographicUnits,
            Brushes.Black);
        drawing.DrawText(formattedText,
                         new Point(23.39*DeviceIndependentUnits,
                                   2.6635416666666671*DeviceIndependentUnits));

        drawing.Close();

        var renderTarget = new RenderTargetBitmap(
            (int) (ImageWidthInches*Dpi),
            (int) (ImageHeightInches*Dpi),
            Dpi,
            Dpi,
            PixelFormats.Default);
        renderTarget.Render(visual);

        var tiffEncoder = new TiffBitmapEncoder {Compression = TiffCompressOption.Ccitt4};
        tiffEncoder.Frames.Add(BitmapFrame.Create(renderTarget));

        using (var fileStream = new FileStream(@"c:\recreateWpfTextIssue.tif", FileMode.Create, FileAccess.Write))
            tiffEncoder.Save(fileStream);

person rossbeehler    schedule 21.02.2014    source источник
comment
Вы пробовали использовать RenderOptions?   -  person d.moncada    schedule 22.02.2014
comment
спасибо за ответ @ d.moncada. Я полагаю, что я попытался в основном то же самое, используя мою собственную дочернюю реализацию DrawingVisual, которая устанавливает защищенные свойства, такие как вышеупомянутые VisualBitmapScalingMode, VisualTextRenderingMode, VisualEdgeMode. Тем не менее, я просто попробовал RenderOptions.SetBitmapScalingMode(visual, BitmapScalingMode.HighQuality);, но безуспешно. Как вы думаете, какой вариант (комбинация) мне стоит попробовать?   -  person rossbeehler    schedule 22.02.2014


Ответы (1)


Чтобы обойти эту ошибку, нужно округлить размер шрифта до двух знаков после запятой:

Math.Round(8.0*DeviceIndependentUnits/TypographicUnits, 2),

Эту и некоторую дополнительную информацию можно найти в соответствующем сообщении MSDN: http://social.msdn.microsoft.com/Forums/en-US/98717e53-89f7-4d5f-823b-7184781a7b85/wpf-formattedtext-randomly-Исчезаетвизображенияхсвысокимразрешением

person rossbeehler    schedule 25.02.2014