Экспорт векторного формата в формате WPF (XPS?) - PullRequest
5 голосов
/ 27 июня 2011

Наш инструмент позволяет экспортировать в PNG, который работает очень хорошо. Теперь я хотел бы добавить экспорт в некоторый векторный формат. Я попробовал XPS, но результаты не удовлетворяют вообще.

Посмотрите на сравнение http://www.jakubmaly.cz/xps-vs-png.png. Снимок слева получен при экспорте в XPS, справа - при экспорте в PNG, при открытии в XPS Viewer изображение XPS заметно размыто и увеличено на 100%.

Есть какие-то настройки, которые мне не хватает или почему так?

Спасибо, Якуб.

Пример вывода xps можно найти здесь: http://www.jakubmaly.cz/files/a.xps. Это код, который выполняет экспорт XPS:

if (!boundingRectangle.HasValue)
{
    boundingRectangle = new Rect(0, 0, frameworkElement.ActualWidth, frameworkElement.ActualHeight);
}

// Save current canvas transorm
Transform transform = frameworkElement.LayoutTransform;
// Temporarily reset the layout transform before saving
frameworkElement.LayoutTransform = null;


// Get the size of the canvas
Size size = new Size(boundingRectangle.Value.Width, boundingRectangle.Value.Height);
// Measure and arrange elements
frameworkElement.Measure(size);
frameworkElement.Arrange(new Rect(size));

// Open new package
System.IO.Packaging.Package package = System.IO.Packaging.Package.Open(filename, FileMode.Create);
// Create new xps document based on the package opened
XpsDocument doc = new XpsDocument(package);
// Create an instance of XpsDocumentWriter for the document
XpsDocumentWriter writer = XpsDocument.CreateXpsDocumentWriter(doc);
// Write the canvas (as Visual) to the document
writer.Write(frameworkElement);
// Close document
doc.Close();
// Close package
package.Close();

// Restore previously saved layout
frameworkElement.LayoutTransform = transform;

Ответы [ 2 ]

3 голосов
/ 08 февраля 2012

Интересная (и раздражающая) проблема - вы можете захотеть проверить длительный ответ от Jo0815 до Печать XpsDocument вызывает передискретизированные изображения (96 точек на дюйм?) - FixedDocument печатает резкие , цитируяОтвет службы поддержки Microsoft - пара выдержек:

Некоторые векторные функции из WPF нельзя эмулировать в нашем коде GDI, и мы прибегаем к преобразованию подмножеств сцены в растровые изображения GDI.Эти растровые изображения являются причиной размытого масштабирования.

[...]

Эти растровые изображения являются причиной размытого масштабирования.Проблема в том, что WPF растеризуется до растрового изображения с-неправильным разрешением.Путь печати предназначен для растеризации неподдерживаемых функций в растровое изображение, но он должен делать это с разрешением устройства.Вместо растеризация всегда выполняется при 96dpi.Это нормально для экрана, но дает размытый вывод для принтера 600 точек на дюйм . [выделение мое]

Обратите внимание, что последнее будет применяться и в настоящее время к экранам с более высоким DPI, конечно, я сталкивался с таким размытием уже много раз - вышанс использовать монитор с высоким разрешением?

Теперь, очевидно, Microsoft не полностью контролирует устройство в связи с этим:

Кроме того, проблема возникает только при печати XPS, а непроблема при печати XAML напрямую.Я почти уверен, что где-то есть документация, в которой говорится, что XPS будет печатать с разрешением устройства.[...] Это то, что мы планируем улучшить в следующей версии продукта, но не для Win 7. Проблема в том, что при печати XAML он будет правильно отображать изображение с разрешением 600 точек на дюйм, но при печатиXPS по-прежнему будет отображать изображение с разрешением 96 точек на дюйм. Поскольку XAML перед печатью преобразуется в XPS, кажется весьма странным, что один метод печати XPS дает результаты, отличающиеся от другого метода печати XPS. [выделение]

[...]

Пользовательский интерфейс для настройки DPI XI Document Writer отсутствует.Если впоследствии вы распечатаете сгенерированный документ XPS с разрешением, отличным от DPI по умолчанию, заданным внутренним модулем записи, вы можете получить плохие результаты для растрового содержимого.С помощью GDI-принтеров вы можете контролировать окончательное значение DPI, а окончательное назначение - это, как правило, бумага - нет шансов перепечатать документ. PrintTicket.PageResolution Свойство в рамках подхода Néstor Sánchez (+1), если ваш сценарий использования позволяет это (хотя я удаленно вспоминаю чтение где-то, что это не имеет никакого эффекта, так какЧто ж);section Разрешение растрового изображения и формат пикселей в Использование службы растеризации XPS подтверждает проблему, с которой он столкнулся при FixedDocument :

Растеризатор XPS-объектадля фиксированной страницы необходимо знать разрешение, при котором страница будет отображаться.Фильтр XPSDrv указывает это разрешение в точках на дюйм (DPI) в качестве входного параметра [...] Например, если устройство отображения имеет разрешение 600 DPI, а фиксированная страница описывает стандартную страницу формата Letter,растровое изображение всей страницы имеет следующие размеры [...]

Обходной путь

В качестве потенциального обходного пути вы можете изучить решение александруда для соответствующего вопроса Как преобразовать файл XPS в изображение с высоким качеством (а не с размытым низким разрешением)? , в котором рекомендуется использовать XPS (XML Paper Specification) документ для набора изображенийутилита преобразования. В частности это Позволяет указать размер изображения или DPI , что может помочь в зависимости от решения пути печати, применяемого по очереди.

Удачи!

2 голосов
/ 25 января 2012

У меня была похожая проблема.Мое изображение было очень размытым при передаче через XPS через FixedDocument.Решение состояло в том, чтобы записать изображение непосредственно в XPS ...

/// <summary>
/// Saves the supplied visual Source, within the specified Bounds, as XPS in the specified File-Name.
/// Returns error message or null when succeeded.
/// </summary>
public static string SaveVisualAsXPS(Visual Source, Size Bounds, string FileName)
{
    string ErrorMessage = null;

    try
    {
        using (var Container = Package.Open(FileName, FileMode.Create))
        {
            using (var TargetDocument = new XpsDocument(Container, CompressionOption.Maximum))
            {
                var Writer = XpsDocument.CreateXpsDocumentWriter(TargetDocument);
                var Ticket = GetPrintTicketFromPrinter();
                if (Ticket == null)
                    return "No printer is defined.";

                Ticket.PageMediaSize = new PageMediaSize(Bounds.Width, Bounds.Height);
                var SourceVisual = Source;
                Writer.Write(SourceVisual, Ticket);
            }
        }
    }
    catch (Exception Problem)
    {
        ErrorMessage = "Cannot export document to XPS.\nProblem: " + Problem.Message;
    }

    return ErrorMessage;
}

. Предоставление билета на печать с точной шириной и высотой позволяет избежать масштабирования (что я и хотел в моем случае).Получить функцию из примера в: http://msdn.microsoft.com/en-us/library/system.printing.printticket.aspx

...