Xaringan中PNG/JPEG画质模糊及SVG体积优化相关问题咨询
我发现Xaringan(
xaringan::moon_reader())生成的HTML幻灯片中,PNG/JPEG格式的图片视觉上比SVG更绵软模糊,示例截图见下:
与之相反,这三种格式在标准HTML报告(rmarkdown::html_document())中的视觉表现基本一致,截图见下:
最直接的解决方案是使用SVG,但复杂图形的SVG体积会急剧膨胀,因此在模板中作为默认格式存在一定风险。比如下方的复杂图形,SVG版本体积为7MB,而对应的PNG仅为50kB,若存在大量这类SVG图形,最终生成的文档体积可能达到数百MB。
我通过在线工具将7MB的SVG压缩至1.6MB,压缩率超过75%,无明显画质损失,但体积仍远高于PNG。
现咨询以下问题:
- 为什么Xaringan中PNG画质较差?有什么优化方案?
- R中是否有工具或绘图设备可以缩小SVG体积?比如简化/扁平化路径之类的功能?
- 还有其他相关的优化思路或建议吗?
附测试代码:--- title: "Image quality" output: xaringan::moon_reader --- ## dev="svg",fig.height=5,fig.width=5 ```{r,dev="svg",fig.height=4.8,fig.width=4.8} plot(1:5,1:5)dev="png",fig.height=6,fig.width=6
plot(1:5,1:5)dev="jpeg",fig.height=6,fig.width=6
plot(1:5,1:5)R version 4.1.0 (2021-05-18)Platform: x86_64-conda-linux-gnu (64-bit)Running under: Ubuntu 20.04.3 LTSrmarkdown_2.10xaringan_0.22
问题解答
1. Xaringan PNG画质差的原因与优化方案
画质差主要来自两个核心原因:
- Xaringan幻灯片默认会拉伸图片适配页面宽度,要是原始PNG分辨率不足,浏览器拉伸后自然会出现模糊
- R默认的png设备DPI只有96,远达不到现在的屏幕显示要求,再加xaringan默认没有给图片加渲染优化的CSS,显示效果就会比html_document里的差很多
优化方案落地很简单: - 优先用
ragg::agg_png作为绘图设备,比默认png设备画质好很多,同时把DPI调到200~300,开启retina适配:代码块参数加dev="ragg_png", dpi=300, fig.retina=2 - 手动指定输出图片宽度,比如加
out.width="80%",让图片生成时就适配幻灯片尺寸,避免浏览器自动拉伸 - 可以在YAML配置下方加一段自定义CSS优化图片渲染:
img { image-rendering: -webkit-optimize-contrast; image-rendering: crisp-edges; }
2. R端压缩SVG体积的可用工具
不需要依赖外部工具,R生态里有成熟的处理方案:
- 首先把默认的svg设备换成
svglite,它输出的SVG自动简化了冗余路径和无效样式,体积比默认设备小一半左右 - 如果是ggplot绘制的复杂散点、热力图,可以用
ggrastr包的rasterize函数把数据点图层转成栅格,文字、坐标轴这些元素保留矢量属性,体积直接砍90%以上,清晰度基本不受影响 - 还可以用
minisvg包读取生成好的SVG,自动清理空节点、注释、重复属性,再做一轮压缩 - 本地安装了SVGO工具的话,还可以配置knitr的
fig.process参数,自动给所有生成的SVG做批量压缩,不用手动逐个处理
3. 其他优化思路
- 两种格式混合使用:简单的柱状图、折线图用SVG保证清晰度,数据点多的复杂图用高DPI PNG或者WebP,WebP比同画质PNG体积小30%以上,ragg设备直接支持输出
- 要是不需要把所有资源打包进单个HTML,可以在输出配置里加
self_contained: false,图片会单独存储,最终HTML体积会小非常多 - 生成SVG的时候尽量用系统通用字体,不要内嵌字体文件,能省很大一部分体积
内容的提问来源于stack exchange,提问作者mindlessgreen
相关产品推荐
相关产品推荐




