如何在不调整其内容大小的情况下使 SVG 图像的视口变为正方形?

How to make the viewport of an SVG image square, without resizing its contents?

我有一个 SVG 图像(可以说是一个简单的图标),其中包含以下内容:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M436 160c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-20V48c0-26.51-21.49-48-48-48H48C21.49 0 0 21.49 0 48v416c0 26.51 21.49 48 48 48h320c26.51 0 48-21.49 48-48v-48h20c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-20v-64h20c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-20v-64h20zm-74 304H54a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h308a6 6 0 0 1 6 6v404a6 6 0 0 1-6 6zM128 208c0-44.183 35.817-80 80-80s80 35.817 80 80-35.817 80-80 80-80-35.817-80-80zm208 133.477V360c0 13.255-10.745 24-24 24H104c-13.255 0-24-10.745-24-24v-18.523c0-22.026 14.99-41.225 36.358-46.567l35.657-8.914c29.101 20.932 74.509 26.945 111.97 0l35.657 8.914C321.01 300.252 336 319.452 336 341.477z"/></svg>

视图框不是正方形 (448!=512) 我需要使较短的边与较长的边相等,以使其内容不会失去其原始比例的方式(=> 不要拉伸),他们需要到达 canvas.

的正中心

示例:将左侧图像转换为右侧图像。 (边框不是实际路径而是视图框)

编程语言和工具无所谓。我只需要可以应用于许多文件的东西(在 bash 脚本中)。因此,欢迎使用带有第三方库解决方案的 imagemagick、inkscape、python。

如果使用 ImageMagick 7,您可以执行以下操作:

magick -density X -colorspace sRGB file.svg -background white -gravity center -extent "%[fx:max(w,h)]x%[fx:max(w,h)]" result.png


如果使用 ImageMagick 6,你需要先计算最大尺寸,所以

maxsize=$(convert -density X -colorspace sRGB file.svg format "%[fx:max(w,h)]" info:)
convert -density X -colorspace sRGB file.svg -background white -gravity center -extent ${max_size}x${max_size} result.png

这不会放大任何边界框线,只会放大图像。

玩你的测试 svg(使用 internet explorer 作为查看器)显示改变 viewBox 没有定义 width,height 的 SVG 不会改变它们的方面(没有拉伸只是缩放和平移)所以不需要使用矩阵都可以单独在 viewBox 中完成。这是你的例子:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
 <path d="M436 160c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-20V48c0-26.51-21.49-48-48-48H48C21.49 0 0 21.49 0 48v416c0 26.51 21.49 48 48 48h320c26.51 0 48-21.49 48-48v-48h20c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-20v-64h20c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-20v-64h20zm-74 304H54a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h308a6 6 0 0 1 6 6v404a6 6 0 0 1-6 6zM128 208c0-44.183 35.817-80 80-80s80 35.817 80 80-35.817 80-80 80-80-35.817-80-80zm208 133.477V360c0 13.255-10.745 24-24 24H104c-13.255 0-24-10.745-24-24v-18.523c0-22.026 14.99-41.225 36.358-46.567l35.657-8.914c29.101 20.932 74.509 26.945 111.97 0l35.657 8.914C321.01 300.252 336 319.452 336 341.477z"/>
</svg>

所以您想将 448 更改为 512 但我们仍然希望使图像居中因此我们也需要调整 x0 位置(在相反的方向上差值的一半 (512-448)/2 = 32).所以将 viewBox 更改为:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="-32 0 512 512">
 <path d="M436 160c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-20V48c0-26.51-21.49-48-48-48H48C21.49 0 0 21.49 0 48v416c0 26.51 21.49 48 48 48h320c26.51 0 48-21.49 48-48v-48h20c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-20v-64h20c6.627 0 12-5.373 12-12v-40c0-6.627-5.373-12-12-12h-20v-64h20zm-74 304H54a6 6 0 0 1-6-6V54a6 6 0 0 1 6-6h308a6 6 0 0 1 6 6v404a6 6 0 0 1-6 6zM128 208c0-44.183 35.817-80 80-80s80 35.817 80 80-35.817 80-80 80-80-35.817-80-80zm208 133.477V360c0 13.255-10.745 24-24 24H104c-13.255 0-24-10.745-24-24v-18.523c0-22.026 14.99-41.225 36.358-46.567l35.657-8.914c29.101 20.932 74.509 26.945 111.97 0l35.657 8.914C321.01 300.252 336 319.452 336 341.477z"/>
</svg>

所以假设原始参数是:viewBox(x0,y0,xs0,ys0) 那么新参数将是 viewBox(x1,y1,xs1,ys1) 其中:

xs1= ys1 = max(xs0,ys0);
x1 = x0 + (xs0 - xs1)/2;
y1 = y0 + (ys0 - ys1)/2;

因为 SVG 只是文本文件 (XML) 如果你没有 R/W 在您的环境中访问 SVG::viewBox 然后只需编写一个脚本 search/parse/replace viewBox 文本文件中的文本...我不在 [=52 中编写代码=] 但在 C++ 中只是 "few" 行代码(注意一些 SVGASCII 有些是 UNICODE).