将 WPF 画布保存到文件而不损失质量(不使用位图作为中介)
Posted
技术标签:
【中文标题】将 WPF 画布保存到文件而不损失质量(不使用位图作为中介)【英文标题】:Saving WPF Canvas to file without losing quality (Without using Bitmap as intermediary) 【发布时间】:2019-05-18 08:57:07 【问题描述】:我的任务是为一些动态制冷剂特性创建列线图。 (Nomograph Examples)。具体来说,我必须创建一个程序,该程序接受用户输入,然后生成可打印的列线图图形。我必须与几个外部黑盒 .dll 交互才能获取一些数据,所以我认为 .NET 是我使用的最佳平台。鉴于没有现成的工具可以轻松创建所有 4 个轴都基于用户输入的非常复杂的图形,因此我将其构建为仅在 WPF 画布上绘制线条和文本。一切都很好;缩放,平移,所有这些。不过我有一个问题。
我找到的将 WPF 画布保存到文件(例如 png)的每个答案都使用位图作为到达那里的路径。这个问题,我已经尝试过并让它工作,是生成的图像失去了所有的可伸缩性,并且取决于画布的大小,很多质量。 XAML 应该是全矢量图形,因为这是一个将大量信息打包到一个小区域中的图形,所以我需要一个可扩展的结果。
注意:这不是所有其他“如何将 WPF 画布保存到文件”问题的副本。
我尝试过的事情:
-
所有其他“如何将 WPF 画布保存到文件”的答案。
增加
RenderTargetBitmap()
方法中的dpi 输入。
(注意:这只是放大左上角的图像,使其无法使用)
想法
我想也许如果没有办法按照我的要求做,也可以在保存之前将画布及其所有子元素缩放到非常大的东西,也许制作一个副本,然后保存它?事实是,我完全不知道该怎么做,我宁愿看看有没有办法先保存到矢量图形。
这是我的 XAML:
<Window x:Class="RefGraph.Graph"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:RefGraph"
mc:Ignorable="d"
Title="Graph" Height="1081" Width="1400">
<Grid>
<Viewbox>
<Canvas Height="Binding Path=CanvasHeight" Width="Binding Path=CanvasWidth" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,20,0,0" MouseWheel="Canvas_MouseWheel" MouseMove="Canvas_MouseMove" MouseLeftButtonDown="Canvas_MouseLeftButtonDown" MouseLeftButtonUp="Canvas_MouseLeftButtonUp">
<Canvas.RenderTransform>
<TransformGroup>
<TranslateTransform/>
<MatrixTransform/>
</TransformGroup>
</Canvas.RenderTransform>
<ContentPresenter Content="Binding Canvas"></ContentPresenter>
</Canvas>
</Viewbox>
<Menu x:Name="Menu_Main" Width="Binding ActualWidth, ElementName=DockPanel_Menu" Height="20" VerticalAlignment="Top">
<MenuItem x:Name="Menu_File" Header="_File">
<MenuItem x:Name="MenuItem_Save" Header="_Save" InputGestureText="Ctrl+S" VerticalAlignment="Top" HorizontalAlignment="Left" Click="MenuItem_Save_Click"/>
<MenuItem x:Name="MenuItem_SaveAs" Header="_Save As" InputGestureText="Ctrl+Shift+S" VerticalAlignment="Top" HorizontalAlignment="Left" />
<MenuItem x:Name="MenuItem_Print" Header="_Print" InputGestureText="Ctrl+P" VerticalAlignment="Top" HorizontalAlignment="Left" />
<MenuItem x:Name="MenuItem_PrintPreview" Header="_Print Preview" InputGestureText="Ctrl+Shift+P" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<Separator />
<MenuItem Header="_Exit" InputGestureText="Ctrl+X" VerticalAlignment="Top" HorizontalAlignment="Left" />
</MenuItem>
</Menu>
</Grid>
</Window>
我应该注意到,在保存之前有许多子元素会动态添加到画布中。
另一个说明:出于某种原因,我认为 PNG 是矢量图形。老实说,我不知道为什么。我想这个问题不是专门关于 PNG 的,而是更多关于保存质量不差的画布,这是通过使用本网站上现有的答案所必需的。我已经编辑了这个问题以反映这一点,并且我也发布了一个答案。
【问题讨论】:
没有必要大喊 :) 我已经为你修好了帖子 @CamiloTerevinto 谢谢 :) 我的建议是研究 PDF 或 OpenXPS 等矢量文件格式,这两种格式都可以处理缩放、字体、旋转等。两者都是极其复杂的格式,我不知道有什么简单的方法可以从 XAML 中获取。 @DourHighArch 我想出了一个关于如何在不损失质量的情况下将其保存为 PDF 的答案,但严格来说,这不是对所述问题的答案。我想正确地做到这一点。我应该编辑帖子吗?写我自己的答案?两者都有? 【参考方案1】:要将 Canvas 或大多数其他 XAML 元素保存到 PDF,您需要引用 PresentationFramework 和 System.Printing。
然后,您可以创建一个 PrintDialog,设置您想要的任何首选项,然后使用它保存到 PDF。
void SaveCanvasToPDF(Canvas myCanvas)
PrintDialog pd = new PrintDialog();
pd.PrintQueue = new PrintQueue(new PrintServer(), "Microsoft Print to PDF");
pd.PrintTicket.PageOrientation = PageOrientation.Landscape;
pd.PrintTicket.PageScalingFactor = 100;
pd.PrintVisual(myCanvas, "Nomograph");
【讨论】:
【参考方案2】:既然您在谈论图像的清晰度。您能否尝试将现有的 WPF 画布转换为 SVG(可缩放矢量图形)文件。我还没有尝试过。希望以下链接对您有所帮助。
https://archive.codeplex.com/?p=svg
https://github.com/vvvv/SVG
【讨论】:
以上是关于将 WPF 画布保存到文件而不损失质量(不使用位图作为中介)的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Android 上旋转 JPEG 文件而不损失质量和增加文件大小?