在 PHP 中使用 Imagick 将 svg 转换为 png 时出现奇怪的裁剪问题
Strange cropping issue while converting svg to png using Imagick in PHP
我正在尝试将一堆 svg 图像转换为 png。以下是 Imagick 部分的片段:
$im = new Imagick();
$im->setBackgroundColor(new ImagickPixel($options->iconsBgColor)); //$options->iconsBgColor is like #00ff00
$im->readImageBlob( $svg );
$im->setImageResolution(288,288);
$im->resizeImage(512, 512, imagick::FILTER_LANCZOS, 1);
$im->setImageFormat( "png32" );
$im->setImageCompression(\Imagick::COMPRESSION_UNDEFINED);
$im->setImageCompressionQuality(0);
$im->writeImage( $imageSrcPngDir );
$im->clear();
$im->destroy();
这基本上按预期工作。但是在图像的顶部和底部有一个大的白色 space 的图像中,它在 png 文件的底部被裁剪。就像下面的例子:
这是上述 png 的 svg:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg filter="url(#shadow)" style="width:512px; height:512px;" xmlns="http://www.w3.org/2000/svg" viewBox="-215 -215 942 942">
<defs>
<style type="text/css">.cls-1{fill:none;stroke:#0000ff;stroke-miterlimit:10;stroke-width:18px;}</style>
<filter id="shadow" x="0" y="0" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="11.636363636364"/>
<feOffset dx="17.454545454546" dy="17.454545454546" result="offsetblur"/>
<feFlood flood-color="#04040C" flood-opacity="1"/>
<feComposite in2="offsetblur" operator="in"/>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<title>imdb-icon</title>
<g id="imdb-icon">
<g id="imdb-icon-2" data-name="imdb-icon">
<path class="cls-1" d="M506,327.03028v-92.721c-4.04258-27.411-33.82293-27.27624-33.82293-27.27624-15.82225-.146-26.0971,6.27726-32.20589,12.24007V157.67979H386.74382v193.606h48.7356a24.443,24.443,0,0,1,1.97638-11.88071c5.6147,6.513,16.4735,15.08106,34.72127,14.91266C472.17707,354.31776,506,354.32222,506,327.03028Zm-48.91524-15.96816a12.39325,12.39325,0,0,1-12.39722,12.39722H437.9499V236.13963h6.73764a12.39321,12.39321,0,0,1,12.39722,12.39723Z"/>
<path class="cls-1" d="M339.32932,157.6843H250.7142V351.31552h88.61512a31.23974,31.23974,0,0,0,31.2418-31.2418V188.92611A31.23971,31.23971,0,0,0,339.32932,157.6843ZM320.94825,303.87277a15.40325,15.40325,0,0,1-15.40086,15.41087h-3.80027V191.73627h3.80027a15.40328,15.40328,0,0,1,15.40086,15.41086Z"/>
<polygon class="cls-1" points="233.833 157.68 233.833 351.286 189.062 351.286 189.062 228.346 170.151 351.286 139.978 351.286 120.944 227.538 120.944 351.286 74.185 351.286 74.185 157.68 141.191 157.68 154.666 245.28 168.141 157.68 233.833 157.68"/>
<rect class="cls-1" x="6" y="157.67984" width="53.15995" height="193.63967"/>
</g>
</g>
</svg>
现在,当我通过操纵 viewBox 属性增加绘图的大小来减少顶部和底部的填充时,图像会按预期呈现,如下所示。
下面是上述 png 的 svg(按预期工作):
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg filter="url(#shadow)" style="width:512px; height:512px;" xmlns="http://www.w3.org/2000/svg" viewBox="-31 -31 573 573">
<defs>
<style type="text/css">.cls-1{fill:none;stroke:#0000ff;stroke-miterlimit:10;stroke-width:18px;}</style>
<filter id="shadow" x="0" y="0" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="11.636363636364"/>
<feOffset dx="17.454545454546" dy="17.454545454546" result="offsetblur"/>
<feFlood flood-color="#04040C" flood-opacity="1"/>
<feComposite in2="offsetblur" operator="in"/>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<title>imdb-icon</title>
<g id="imdb-icon">
<g id="imdb-icon-2" data-name="imdb-icon">
<path class="cls-1" d="M506,327.03028v-92.721c-4.04258-27.411-33.82293-27.27624-33.82293-27.27624-15.82225-.146-26.0971,6.27726-32.20589,12.24007V157.67979H386.74382v193.606h48.7356a24.443,24.443,0,0,1,1.97638-11.88071c5.6147,6.513,16.4735,15.08106,34.72127,14.91266C472.17707,354.31776,506,354.32222,506,327.03028Zm-48.91524-15.96816a12.39325,12.39325,0,0,1-12.39722,12.39722H437.9499V236.13963h6.73764a12.39321,12.39321,0,0,1,12.39722,12.39723Z"/>
<path class="cls-1" d="M339.32932,157.6843H250.7142V351.31552h88.61512a31.23974,31.23974,0,0,0,31.2418-31.2418V188.92611A31.23971,31.23971,0,0,0,339.32932,157.6843ZM320.94825,303.87277a15.40325,15.40325,0,0,1-15.40086,15.41087h-3.80027V191.73627h3.80027a15.40328,15.40328,0,0,1,15.40086,15.41086Z"/>
<polygon class="cls-1" points="233.833 157.68 233.833 351.286 189.062 351.286 189.062 228.346 170.151 351.286 139.978 351.286 120.944 227.538 120.944 351.286 74.185 351.286 74.185 157.68 141.191 157.68 154.666 245.28 168.141 157.68 233.833 157.68"/>
<rect class="cls-1" x="6" y="157.67984" width="53.15995" height="193.63967"/>
</g>
</g>
</svg>
我比较了 2 个 svg 文件,viewBox 是唯一不同的地方。
知道我该如何解决这个问题吗?
好的,我对更改后的 viewBox 的怀疑是没有根据的。看起来不错。
但是你添加的滤镜效果是怎么回事?你没有提到那个。它基本上是一个 unconfigured/misconfigured 投影滤镜。但是它缺少很多属性。例如 stdDeviation
未在 <feGaussianBlur>
过滤器元素中设置。 ImageMagick 可能不喜欢那样。当您从 SVG 中删除滤镜(即删除 filter="url(#shadow)"
)时,它是否仍然剪辑?
将 filter
区域的高度从 200% 增加到 300% 解决了这个问题。
<filter id="shadow" x="0" y="0" width="200%" height="300%">
我正在尝试将一堆 svg 图像转换为 png。以下是 Imagick 部分的片段:
$im = new Imagick();
$im->setBackgroundColor(new ImagickPixel($options->iconsBgColor)); //$options->iconsBgColor is like #00ff00
$im->readImageBlob( $svg );
$im->setImageResolution(288,288);
$im->resizeImage(512, 512, imagick::FILTER_LANCZOS, 1);
$im->setImageFormat( "png32" );
$im->setImageCompression(\Imagick::COMPRESSION_UNDEFINED);
$im->setImageCompressionQuality(0);
$im->writeImage( $imageSrcPngDir );
$im->clear();
$im->destroy();
这基本上按预期工作。但是在图像的顶部和底部有一个大的白色 space 的图像中,它在 png 文件的底部被裁剪。就像下面的例子:
这是上述 png 的 svg:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg filter="url(#shadow)" style="width:512px; height:512px;" xmlns="http://www.w3.org/2000/svg" viewBox="-215 -215 942 942">
<defs>
<style type="text/css">.cls-1{fill:none;stroke:#0000ff;stroke-miterlimit:10;stroke-width:18px;}</style>
<filter id="shadow" x="0" y="0" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="11.636363636364"/>
<feOffset dx="17.454545454546" dy="17.454545454546" result="offsetblur"/>
<feFlood flood-color="#04040C" flood-opacity="1"/>
<feComposite in2="offsetblur" operator="in"/>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<title>imdb-icon</title>
<g id="imdb-icon">
<g id="imdb-icon-2" data-name="imdb-icon">
<path class="cls-1" d="M506,327.03028v-92.721c-4.04258-27.411-33.82293-27.27624-33.82293-27.27624-15.82225-.146-26.0971,6.27726-32.20589,12.24007V157.67979H386.74382v193.606h48.7356a24.443,24.443,0,0,1,1.97638-11.88071c5.6147,6.513,16.4735,15.08106,34.72127,14.91266C472.17707,354.31776,506,354.32222,506,327.03028Zm-48.91524-15.96816a12.39325,12.39325,0,0,1-12.39722,12.39722H437.9499V236.13963h6.73764a12.39321,12.39321,0,0,1,12.39722,12.39723Z"/>
<path class="cls-1" d="M339.32932,157.6843H250.7142V351.31552h88.61512a31.23974,31.23974,0,0,0,31.2418-31.2418V188.92611A31.23971,31.23971,0,0,0,339.32932,157.6843ZM320.94825,303.87277a15.40325,15.40325,0,0,1-15.40086,15.41087h-3.80027V191.73627h3.80027a15.40328,15.40328,0,0,1,15.40086,15.41086Z"/>
<polygon class="cls-1" points="233.833 157.68 233.833 351.286 189.062 351.286 189.062 228.346 170.151 351.286 139.978 351.286 120.944 227.538 120.944 351.286 74.185 351.286 74.185 157.68 141.191 157.68 154.666 245.28 168.141 157.68 233.833 157.68"/>
<rect class="cls-1" x="6" y="157.67984" width="53.15995" height="193.63967"/>
</g>
</g>
</svg>
现在,当我通过操纵 viewBox 属性增加绘图的大小来减少顶部和底部的填充时,图像会按预期呈现,如下所示。
下面是上述 png 的 svg(按预期工作):
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg filter="url(#shadow)" style="width:512px; height:512px;" xmlns="http://www.w3.org/2000/svg" viewBox="-31 -31 573 573">
<defs>
<style type="text/css">.cls-1{fill:none;stroke:#0000ff;stroke-miterlimit:10;stroke-width:18px;}</style>
<filter id="shadow" x="0" y="0" width="200%" height="200%">
<feGaussianBlur in="SourceAlpha" stdDeviation="11.636363636364"/>
<feOffset dx="17.454545454546" dy="17.454545454546" result="offsetblur"/>
<feFlood flood-color="#04040C" flood-opacity="1"/>
<feComposite in2="offsetblur" operator="in"/>
<feMerge>
<feMergeNode/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
</defs>
<title>imdb-icon</title>
<g id="imdb-icon">
<g id="imdb-icon-2" data-name="imdb-icon">
<path class="cls-1" d="M506,327.03028v-92.721c-4.04258-27.411-33.82293-27.27624-33.82293-27.27624-15.82225-.146-26.0971,6.27726-32.20589,12.24007V157.67979H386.74382v193.606h48.7356a24.443,24.443,0,0,1,1.97638-11.88071c5.6147,6.513,16.4735,15.08106,34.72127,14.91266C472.17707,354.31776,506,354.32222,506,327.03028Zm-48.91524-15.96816a12.39325,12.39325,0,0,1-12.39722,12.39722H437.9499V236.13963h6.73764a12.39321,12.39321,0,0,1,12.39722,12.39723Z"/>
<path class="cls-1" d="M339.32932,157.6843H250.7142V351.31552h88.61512a31.23974,31.23974,0,0,0,31.2418-31.2418V188.92611A31.23971,31.23971,0,0,0,339.32932,157.6843ZM320.94825,303.87277a15.40325,15.40325,0,0,1-15.40086,15.41087h-3.80027V191.73627h3.80027a15.40328,15.40328,0,0,1,15.40086,15.41086Z"/>
<polygon class="cls-1" points="233.833 157.68 233.833 351.286 189.062 351.286 189.062 228.346 170.151 351.286 139.978 351.286 120.944 227.538 120.944 351.286 74.185 351.286 74.185 157.68 141.191 157.68 154.666 245.28 168.141 157.68 233.833 157.68"/>
<rect class="cls-1" x="6" y="157.67984" width="53.15995" height="193.63967"/>
</g>
</g>
</svg>
我比较了 2 个 svg 文件,viewBox 是唯一不同的地方。
知道我该如何解决这个问题吗?
好的,我对更改后的 viewBox 的怀疑是没有根据的。看起来不错。
但是你添加的滤镜效果是怎么回事?你没有提到那个。它基本上是一个 unconfigured/misconfigured 投影滤镜。但是它缺少很多属性。例如 stdDeviation
未在 <feGaussianBlur>
过滤器元素中设置。 ImageMagick 可能不喜欢那样。当您从 SVG 中删除滤镜(即删除 filter="url(#shadow)"
)时,它是否仍然剪辑?
将 filter
区域的高度从 200% 增加到 300% 解决了这个问题。
<filter id="shadow" x="0" y="0" width="200%" height="300%">