Direct2D 渲染到命令列表和打印: 图片压缩

4
我有一个Win32 Direct2D应用程序,用户可以绘制基本图形并加载和操作图片以创建场景。之后,场景可以打印或保存为PDF文件。
这篇文章解释了打印D2D内容的过程,也是我实现的方式:https://learn.microsoft.com/en-us/windows/win32/direct2d/printing-and-command-lists 总之,打印通过将D2D内容渲染到ID2D1CommandList中实现,该列表被设置为ID2D1DeviceContext的目标。在将场景渲染到CommandList之后,我关闭它,将其作为页面添加到ID2D1PrintControl中,关闭ID2D1PrintControl(这会将所有命令发送给打印机),然后恢复我的D2D资源。 PDF文件使用相同的过程创建,但我使用“Microsoft Print to PDF”作为我的打印机。
所有这些都可以。然而,当包含大图片时,我注意到生成的PDF文件变得非常大。例如,我将一个4000 x 3000像素的jpg加载到我的应用程序中(本身有5 MB文件大小),打印成PDF -> 然后PDF将有28 MB,并且打印作业需要几秒钟才能完成。在某些机器上,它甚至会崩溃(我认为ID2D1PrintControl :: AddPage(...)函数或ID2D1PrintControl :: Close()函数有时需要很长时间才能返回,程序无响应)。
现在,我知道D2D不能在内部使用压缩图像,这就是为什么我首先从jpg文件创建ID2D1Bitmap的原因,这也是我打印时所使用的内容。
问题:是否有任何方法可以在D2D中压缩图像,使其在到达打印机之前进行压缩?我假设我的问题来自无法由慢速机器正确处理的大型PrintStreams(?)。我无法缩放图像,因为分辨率很重要!
我意识到,使用一些PDF创建库并执行诸如使用原始压缩的jpg并将其包含在PDF中之类的操作可能可以修复PDF部分,但通常情况下PDF打印机运行良好,我真的想避免使用一些PDF库。
任何关于D2D打印问题的意见都将不胜感激,因为互联网上真的缺乏相关信息。
编辑:我现在找到了一种方法,在发送图片到打印机之前对其进行光栅化,通过将DPI设置较低并绘制到第二个命令列表中使结果PDF文件更小。
最后一个问题是,在某些机器上,ID2D1PrintControl :: AddPage(...)-函数根本不返回/冻结计算机。没有失败,也没有成功,无论何时尝试打印具有多张图片的复杂场景。我还需要研究:打印机驱动程序,我可以尝试的所有各种打印机设置,这些机器上的directX版本(可能与此无关)。是否有任何其他想法可以导致AddPage函数不返回?是否有任何可能缺失的典型安装?可选输入作为第4和第5个参数的D2D1_TAG是否具有任何重要性?

你是否已经查看了以下链接:https://learn.microsoft.com/en-us/windows/win32/direct2d/improving-direct2d-performance#set-the-right-property-values-when-you-create-the-d2d-print-control,你可以尝试使用96 DPI。否则,你是否有一个可复现的示例? - Simon Mourier
谢谢您提供文章和 DPI 设置的提示。我现在已经找到了一种方法,通过显式设置 DPI 并使用第二个命令列表来绘制第一个命令列表,从而将图像光栅化。然后,我打印第二个命令列表。生成的文件要小得多。所以感谢您。在某些机器上仍然存在的问题是 ID2D1PrintControl::AddPage 函数不返回。没有错误,也没有成功,它只是花费很长时间。有什么想法可以让这个函数不返回或者有人遇到过这种行为吗? - CptnAnalysis
2
你可以启用DX调试层。同时启用调试符号进入进程。也许你可以看到它似乎卡住了,对正在发生的事情有一些线索。如果你能重现这个问题,应该将其发布到Microsoft。你还应该回答自己的问题,并创建另一个问题。 - Simon Mourier
1个回答

1
我现在已经找到了一种方法,在将图片发送给打印机之前通过减少PrintControl的DPI并使用第二个CommandList对其进行栅格化。然后,我继续使用第二个CommandList进行打印作业。将第一个CommandList绘制到第二个CommandList中,可以在到达打印机之前强制进行更早和更可控的栅格化,这取决于设置,可以导致更小的PrintStreams。
感谢Simon Mourier的帮助!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接