在MATLAB中将“重”的图形保存为PDF - 渲染问题

5
我用MATLAB生成了一个元素较多的图形(100000+),想将其保存为PDF文件。使用zbuffer或painters渲染器,我得到了非常大且打开缓慢的文件(超过4 Mb)- 所有点都处于矢量格式中。使用OpenGL渲染器将图形光栅化为PDF,对于绘图来说很好,但对于文本标签则不太好。该文件大小约为150 Kb。
例如,请尝试此简化代码:
x=linspace(1,10,100000);
y=sin(x)+randn(size(x));
plot(x,y,'.')
set(gcf,'Renderer','zbuffer')
print -dpdf -r300 testpdf_zb
set(gcf,'Renderer','painters')
print -dpdf -r300 testpdf_pa
set(gcf,'Renderer','opengl')
print -dpdf -r300 testpdf_op

实际数字更加复杂,包含多个轴和不同类型的绘图。

有没有一种方法可以将图像栅格化,但保持文本标签为矢量?

OpenGL的另一个问题是,在Mac OSX的终端模式(-nosplash -nodesktop -nodisplay)下无法使用。看起来OpenGL不被支持。我必须使用终端模式进行自动化操作。我运行的MATLAB版本是2007b。Mac OSX服务器10.4。


实际上,对我来说,“zbuffer”渲染器生成的光栅文件大小与“opengl”相似。 - Amro
是的,我也以为速度相同,但是我认为如果使用更复杂的图形,而且点之间不会被其他点隐藏,那么OpenGL会更快。 - Justin Peel
就OpenGL在终端模式下无法工作而言,当您在Matlab的终端模式下键入“opengl info”时,它会告诉您什么? - Justin Peel
警告:OpenGL 加载失败。 - yuk
zbuffer渲染器生成了一个类似于OpenGL大小的光栅文件。当我没有处于真正的终端模式(没有-nodisplay)时,我也遇到了这个问题。图形窗口出现在桌面上。 - yuk
3个回答

2
这是一个有趣的问题。你的问题不在于Matlab,而在于Ghostscript(至少在Windows上,Matlab通过调用Ghostscript来创建PDF)。当我运行时:
x=linspace(1,10,100000);
y=sin(x)+randn(size(x));
plot(x,y,'.')
print -dpsc2 test.ps

我有一个2Mb的PS文件(当然是全矢量),压缩后变成了164Kb的ZIP。人们预期将PS转换为PDF时会得到差不多的结果,但是ps2pdf test.ps却生成了4Mb的文件!
由于您使用的是Mac,您可能有Distiller。我建议您试一下 - 按照上述方式生成PS文件,然后通过Distiller运行它们; 您应该能够获得一个150K的矢量PDF。
如果您坚持要进行栅格化,我建议将图形打印到tiff上,不带任何轴或标签,然后打开tiff,在其上重新创建轴和标签。

1
矢量格式可以压缩,但是打开文件时仍然会绘制所有矢量元素,导致速度非常慢。这就是为什么我想将图形光栅化的原因。感谢您提供的图像建议。看起来有些复杂,但是可行。 - yuk

1

如果您不想使用2D直方图(即像素亮度对应于点密度的图像)如BlessedKey所建议的那样,看起来唯一好的方法是自己进行光栅化,正如AB所提到的。

getframe接着frame2im似乎是实现这一目的的方法。不幸的是,如果您使用-nodisplay运行,getframe将返回空值。因此,您需要将图形保存为.fig,并在另一台计算机上运行一个脚本,打开图形,获取getframe轴的内容,显示从getframe中获取的图像,然后保存为pdf。

作为简单绘图或二维直方图的替代方案,您可能想要了解一下scattercloud,它将点的绘制与密度信息相结合。

0

如果可能的话,在构建插图之前,您应该尝试对问题进行子采样。如果您正在绘制曲线上的点,则10000个点可能已经超过您的需求。毕竟,现代打印机的分辨率只有约600 DPI。

如果这些点正在说明具有某些密度属性的云,则更好的解决方案可能是首先构建二维直方图,然后使用imshow或imagesc进行说明。

如果要用不同的颜色说明多个云,则您可能需要为每个云构建一个此类图像,并将它们与透明度结合起来。


真实的数据看起来不像云。我需要展示原始数据。我只是用这个简单的例子来展示问题。 - yuk

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