WPF图像矢量格式导出(XPS?)

时间:2011-06-27 08:58:20

标签: wpf image png export xps

我们的工具允许导出到PNG,效果非常好。 现在,我想将导出添加到某种矢量格式。我尝试了XPS,但结果并不令人满意。

查看比较http://www.jakubmaly.cz/xps-vs-png.png。 左边的图片来自XPS导出,PNG导出右边的图片,XPS图片在XPS Viewer中打开并且缩放100%时明显模糊。

是否有任何我缺少的设置或为什么会这样?

谢谢, 的Jakub。

可以在此处找到示例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 个答案:

答案 0 :(得分:3)

有趣(又烦人)的问题 - 您可能需要查看 Jo0815 Printing XpsDocument causes resampled images (96dpi?) - FixedDocument prints sharp的冗长答案,引用微软的支持回复 - 一些摘录:

  

WPF中的某些矢量功能无法在我们的GDI代码中进行模拟   我们求助于将场景的子集转换为GDI位图。这些   位图是缩放模糊的原因。

     

[...]

     

这些位图是模糊缩放的原因。问题是   WPF正在以错误的分辨率光栅化为位图。   打印路径旨在将不支持的功能光栅化为   位图,但它应该在设备分辨率下执行。相反   光栅化总是在96dpi完成。这对于屏幕来说很好   但为600dpi打印机产生模糊输出 [强调我的]

请注意,后者将适用于现在更高的DPI屏幕,当然,我已经遇到过这样的不同时代的模糊 - 你是否偶然使用高DPI显示器?

现在,显然微软并没有完全控制这个设备:

  

此外,问题仅在打印XPS时发生,而不是   直接打印XAML时出现问题。我很确定有   文档某处说XPS将以设备分辨率打印。   [...] 这是我们的事   计划在下一版本的产品中进行改进,但不是为Win 7。   问题是,当打印XAML时,它将正确呈现   图像在600dpi,但在打印XPS时,它仍然会渲染图像   在96dpi。 由于XAML在打印前转换为XPS似乎   很奇怪,一种打印XPS的方法会产生不同的结果   另一种打印XPS的方法。 [强调我的]

     

[...]

     

没有用于配置XPS Document Writer DPI的UI。如果你以后   以与作者不同的DPI打印生成的XPS文档   内部默认您可能会得到位图内容不佳的结果。有了GDI   打印机你可以控制最终的DPI和最终的desitination是   普通纸 - 没有机会重印这份文件。

结论

总之,我仍然会尝试在PrintTicket.PageResolution Property(+1)内调整Néstor Sánchez' approach,如果您的用例确实允许这样做(尽管我远程回忆起在某处阅读,但这没有任何影响); Using the XPS Rasterization Service中的位图分辨率和像素格式部分确认了他遇到的 FixedDocument 问题:

  

固定页面的XPS光栅化器对象必须知道分辨率   页面将被呈现。 XPSDrv过滤器指定了这一点   分辨率,以每英寸点数(DPI)为输入参数[...]例如,如果显示设备具有分辨率   600 DPI,固定页面描述标准的letter尺寸页面,a   整个页面的位图图像具有以下尺寸[...]

解决方法

作为潜在的解决方法,您可能希望探索alexandrud针对相关问题How to convert a XPS file to an image in high quality (rather than blurry low resolution)?的解决方案,该问题建议使用xps2img XPS(XML Paper Specification)文档来设置图像转换实用程序。特别是它允许指定图像大小或DPI ,这可能有所帮助,具体取决于依次应用的打印路径解决方案。

祝你好运!

答案 1 :(得分:2)

我遇到了类似的问题。通过FixedDocument传递给XPS中介时,我的图像非常模糊。 解决方案是将图像直接写入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