Sharp 读取 SVG 报像素超限,检查物理单位与 density
Sharp 0.35.5所用libvips8.18.7可能对SVG物理宽高重复应用DPI,高density让尺寸异常增大。核对输入单位和实际库,保留像素保护并明确受控导出的画布约定。
SVG 文件不大,Sharp 却在读取时返回 Input image exceeds pixel limit。如果根元素的宽高使用 pt、in 等物理单位,同时给输入设置了较高 density,应先核对实际栅格尺寸,不要直接关掉像素上限。
Sharp 0.35.5 搭配 libvips 8.18.7 的这一分支,会在物理尺寸换算和后续渲染缩放中再次应用 DPI。700pt 的正方形在 density 144 时可能被解释成约 2800 像素边长,而非预期的 1400;继续提高 density,尺寸增长会更明显。文件字节数小,不代表渲染后的像素和内存也小。
先对照单位、density 和实际依赖
Sharp 将 density 作为 dpi 传给 libvips 的 SVG 加载器。8.18.7 的实现先按 DPI 把物理长度换算为像素,又乘上含 dpi / 72 的缩放系数,因此这条物理单位路径会重复放大。单位为普通像素或无单位数字时,换算过程不同,不能把所有 SVG 高分辨率输入都归为同一故障。
检查原 SVG 的根宽高、viewBox、输入 density,以及运行环境中的 sharp.versions。系统安装的 libvips 与随包分发的版本可能不同,仅看 package.json 中 Sharp 的范围还不够。
上游已经调整 DPI 与渲染缩放的分工,但截至 2026 年 10 月 25 日,正式 libvips 8.18.7 及 Sharp 0.35.5 仍不能按已经包含后续修正处理。更新依赖时,核对实际正式发行及所携原生库,不按尚未进入产物的代码判断。
能控制 SVG 导出时,明确画布的像素约定
对于自己生成、按 viewBox 坐标绘制的图标,可以在导出环节采用明确的像素画布,避免根尺寸继续使用物理单位。下面是独立的示例输入:
import sharp from 'sharp';
const svg = Buffer.from(
'<svg xmlns="http://www.w3.org/2000/svg" width="700" height="700" viewBox="0 0 700 700">' +
'<rect width="700" height="700" fill="black"/></svg>',
);
const image = sharp(svg, { density: 144 });
在这份画布约定下,按 72 DPI 基准提高到 144,目标边长是 1400 像素。先核对 metadata,再按原有输出流程生成结果。示例没有写出文件,也没有移除输入像素限制。
这不适合对任意外来 SVG 批量删除单位。文档内部可能仍有毫米、英寸、字体大小或依赖物理尺寸的布局;只改根宽高可能改变比例和排版。不能控制导出时,应保留原件,用能够正确解释原单位的既有转换流程,或在受控范围降低输入 density 后检查质量与尺寸。降低后再 resize 放大是位图插值,不会补回原本希望高 DPI 取得的细节。
输出 resize 不能替代输入保护
在链尾加 resize(),不代表加载器在创建输入图像前就跳过了异常尺寸。若已经在读取阶段触发像素上限,输出目标再小也不一定能绕开。
不要为这条错误统一设置 limitInputPixels: false 或 unlimited: true。异常放大的输入可能消耗远超预期的内存;保留既有容量限制,先纠正尺寸来源。对于不可信文件,还应沿项目既有规则控制输入大小、处理并发和运行资源。
完成调整后,对照原画面、宽高、透明区域及细节,并确认物理单位输入不会再次膨胀;同时回查正常像素单位文件,避免修一个导出器却改变其他资源的约定。部署前核实实际携带的原生库版本,不能只依赖开发机上一次成功转换。


