最近遇到了一个大规模图片输出的问题,在这里分享一下调参经验。问题描述如下。我有一个 CRAN package,在 vignettes 和 README.Rmd 中各输出大约 30 张示例图片。R CMD check
对于 installed size > 5Mb 的 package 会给出如下 note:
installed size is 5.1Mb
sub-directories of 1Mb or more:
doc 2.7Mb
help 2.3Mb
其中 doc/
包含了嵌入了图片的 HTML vignette,help/
包含了 README.Rmd
在 man/figures/
的图片输出。为了避免这个 check note,我的目标是在保证图片清晰度的前提下,尽量压缩输出的图片大小。
我首先尝试了 SVG。对于我的图片,相比 grDevices::svg()
和 gridSVG,svglite 能给出最小的文件 (100 Kb vs. 300 Kb),这可能是因为 svglite 没有把字体作为图形嵌入的原因。但是,每张图 100 Kb 依然过大。由于我的例子中有散点较多的散点图,如果想继续缩小 SVG 文件的体积,只能通过修改示例大量减少散点的数量。于是我放弃了这个路线。
接着我就尝试了针对 PNG 输出的优化。最后发现 ragg::ragg_png
可以提供最小的 PNG 输出,大约每图 120Kb,再使用 pngquant 有损压缩可以显著减小到每图大约 30 Kb。我的 knitr 配置参数如下,可能不是最优,欢迎拍砖:
knitr::knit_hooks$set(pngquant = knitr::hook_pngquant)
knitr::opts_chunk$set(
dev = "ragg_png",
dpi = 72,
fig.retina = 2,
fig.width = 10.6667,
fig.height = 3.3334,
fig.align = "center",
out.width = "100%",
pngquant = "--speed=1 --quality=50"
)
对于没有安装 pngquant 的环境,使用了 pngquant 选项的 knitr 依然可以正常执行,所以在 CRAN 的机器上不会出现问题。而且由于 CRAN 不会重新渲染 vignette 而会直接重用 tarball 中的 vignette,只需要在执行 R CMD build
的机器上安装 pngquant,保证提交的 tarball 包含了最小化的图片即可。README.Rmd
的输出同理。