【问题标题】:Plot as bitmap in PDF在 PDF 中绘制为位图
【发布时间】:2011-12-24 08:10:26
【问题描述】:

我目前正在研究 CGH 数组结果,其中涉及数个数十万点的图,我希望从 PDF 设备的多页功能和 PNG 图像格式的亮度中受益。

问题在于 PDF 设备将绘图存储为矢量图,因此 PDF 文件很大,需要几分钟才能打开。我想知道 R 是否可以绘制为嵌入在单个 PDF 文件中的多个位图,因为我知道 PDF 格式能够处理它。

这是一个简单的例子,PDF 文件大约 2 Mo,而 png 文件大约 10 Ko,所以我想要一个大约 20 Ko 的 PDF 文件。

png("test%i.png")
plot(rnorm(2e4), rnorm(2e4), pch="+", cex=0.6)
plot(rnorm(2e4), rnorm(2e4), pch="+", cex=0.6)
dev.off()

pdf("test.pdf", onefile=TRUE)
plot(rnorm(2e4), rnorm(2e4), pch="+", cex=0.6)
plot(rnorm(2e4), rnorm(2e4), pch="+", cex=0.6)
dev.off()

【问题讨论】:

  • 我看到了这篇文章,它基本上暗示了其他人所说的:使用光栅。光栅文件打开起来更轻、更快,但仍然比经典的嵌入 PNG 的 PDF 文件重得多。
  • 这是因为 R 版本,在 R 2.14.0 中它工作正常。真丢人。

标签: r pdf graphics bitmap


【解决方案1】:

使用 png 驱动程序创建可接受分辨率的 PNG 文件。让你的阴谋。关闭 png 设备。

然后使用 package:png 中的 readPNG 将其读入。

接下来打开一个 PDF 驱动程序,在 (0,0) (1,1) 创建一个没有边距和边界的空白图,然后使用 rasterImage 将 png 绘制到该图上。通过创建新图来添加额外页面。关闭 PDF 驱动程序。

这应该会给你一个带有位图版本的 PDF。正确设置绘图有一些棘手的问题,png 分辨率至关重要,但我认为以上内容具备所有要素。

> png("plot.png")
> makeplot(100000) # simple function that plots 100k points 
> dev.off()
X11cairo 
       2 
> plotPNG = readPNG("plot.png")
> pdf("plot.pdf")
> par(mai=c(0,0,0,0))
> plot(c(0,1),c(0,1),type="n")
> rasterImage(plotPNG,0,0,1,1)
> dev.off()

然后检查 plot.pdf...

【讨论】:

  • 我在之前创建的“test1.png”图像上使用了您的代码,它生成了一个 1362 Ko 的 PDF 文件。打开似乎更快,但仍然太重了。作为比较,我使用 OpenOffice.org Draw 生成了一个 13 Ko 的 PDF,包括 test1.png 手动(不压缩)。
  • 呃,是的,看起来 pdf() 使用了一种非常低效的像素图编码方法。
  • 如果我通过 ImageMagick 的“转换”运行生成的 PDF,它会将 PDF 重新编码为大约十分之一的大小 - 你所做的只是“转换 file.pdf file2.pdf”和魔法发生。
  • 看来问题在 R 2.14.0 中已得到纠正。当我在 R 2.13.1 中运行您的示例时,我得到一个 1362 Ko 的 PDF,在 R 2.14.0 中,PDF 文件约为 18 Ko,这对我来说很好。所以你的解决方案很好,但我更喜欢 O'Brien 的解决方案,因为它涉及标准 R 函数并且没有中间文件。再次感谢您的帮助。
【解决方案2】:

这是一个解决方案,可让您接近 (50kb) 到所需的文件大小 (25kb),而无需安装 LaTeX 和/或学习 Sweave。 (从长远来看,并不是说其中任何一个都是不可取的!)

它使用grid 函数grid.cap()grid.raster()。更多细节和想法在a recent R-Journal article by Paul Murrell (warning : PDF)

require(grid)
# Make the plots
dev.new()  # Reducing width and height of this device will produce smaller raster files
    plot(rnorm(2e4), rnorm(2e4), pch="+", cex=0.6)
    cap1 <- grid.cap()
    plot(rnorm(2e4), rnorm(2e4), pch="+", cex=0.6, col="red")
    cap2 <- grid.cap()
dev.off()

# Write them to a pdf
pdf("test.pdf", onefile=TRUE)
     grid.raster(cap1)
     plot.new()
     grid.raster(cap2)
dev.off()

生成的pdf 图像似乎比您的文件test1.pngtest2.png 保留了更多细节,因此您可以通过降低它们的分辨率来更接近您的目标。

【讨论】:

  • 我尝试了 grid.cap() 和 grid.raster(),但它也产生了巨大的 PDF 文件,所以我放弃了。实际上,这是因为我没有使用 R 的最新版本,而这个解决方案正是我想要的。非常感谢。
  • 哦,太好了。这个人自己说“另一种方法是生成一个 PNG 文件并将其读入,但 grid.cap() 更便于交互使用”。我将来会使用它。 png() 的唯一 + 是您无法在没有打开的图形设备的情况下执行 grid.cap,因此您只能使用屏幕分辨率。但整洁。
  • @Spacedman -- 是的,我很高兴这个问题,因为它给了我一个去阅读那篇文章的借口。起初我认为可能有一个使用base::cairo_pdf 的解决方案,它的帮助文件中有这个有趣的注释:“请注意,与'postscript' 和'pdf' 不同,cairo_pdf' 和'cairo_ps' 有时会记录位图 i> 而不是矢量图形:使用 72dpi 的分辨率。”对于cairo_ps,您可以通过使用透明度来强制执行该行为,但我找不到为cairo_pdf '触发开关'的简单方法。
【解决方案3】:

要在您的 pdf 中包含多个绘图,请设置 onefile = TRUE

pdf("test.pdf", onefile = TRUE)
plot(1:5)
plot(6:10)
dev.off()

要制作这些图 PNG 而不是原生 PDF 图将需要更多的努力。将所有绘图创建为 PNG,如下所示:

png("test%01d.png")
plot(1:5)
plot(6:10)
dev.off()

然后创建一个包含这些 PNG 的 LaTeX 文档。您可以使用 Sweave 从 R 中做到这一点(但如何做到这一点足以成为它自己的问题)。有一个不错的介绍性示例here

【讨论】:

  • 谢谢,我不熟悉 LaTeX 并且在无法安装它的 Windows 工作站上工作,所以我更喜欢仅 R 的解决方案,但我牢记你的。
【解决方案4】:

Sweave 解决方案怎么样?

\documentclass[a4paper]{article}
\usepackage[OT1]{fontenc}
\usepackage{Sweave}
\SweaveOpts{pdf = FALSE, eps = FALSE}
\DeclareGraphicsExtensions{.png}

\begin{document}

\title{Highly imaginative title}
\author{romunov}

\maketitle

<<fig = TRUE, png = TRUE, echo = FALSE>>=
    plot(1:10, 1:10)
@

\end{document}

【讨论】:

  • 非常感谢这个完整的例子,正如我所说,避免安装 pdflatex 会让我的生活更轻松。如果我无法避免,我想我会花一些时间在 sweave 上,这似乎是一个有趣的功能。
  • 如果你冒险尝试,这里有一个小小的开始:r-bloggers.com/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-31
  • 1970-01-01
相关资源
最近更新 更多