【问题标题】:PHP: SVG to PNG conversion results in wrong imagePHP:SVG到PNG的转换导致错误的图像
【发布时间】:2023-03-25 14:08:01
【问题描述】:

我有一个由 wordpress 插件生成的 SVG 图像。 我想将其转换为 PNG 以进行进一步操作。

插件可以通过JS成功做到这一点。结果是这个图像:

当我使用 imagick 将 SVG 转换为 png 时,结果如下:

SVG 代码如下所示:

<svg xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink" data-zoom="11.81102361" height="290" width="210" data-main="1">
<svg y="62" x="17" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" preserveAspectRatio="none" width="178" height="133"><g><image x="0" y="0" width="178" preserveAspectRatio="none" height="133" xlink:href="[BASE64 IMAGE CODE]"/></g></svg>
</svg>

完整版在这里:https://pastebin.com/vzn7BP2d

我正在使用此代码进行转换:

$svg = file_get_contents('front-test.svg');

$im = new Imagick();
$im->setBackgroundColor(new ImagickPixel('transparent'));
$im->setResolution(300, 300); // for 300 DPI example
$im->readImageBlob('<?xml version="1.0" encoding="UTF-8" standalone="no"?>'.$svg);

$im->setImageFormat("png24");
//$im->resizeImage(250, 250, imagick::FILTER_LANCZOS, 1);

$im->writeImage('front-test.png');
$im->clear();
$im->destroy();

有谁知道为什么会发生这种情况以及我该如何解决? 图像在“画布”上的位置必须正确,因为它是 T 恤的打印模板,需要准确。

【问题讨论】:

  • 您没有提供链接图像供我们测试。但是您的问题很可能是 ImageMagick 使用的是哪个 SVG 渲染器。 ImageMagick 可以使用自己内部的 MSVG/XML 渲染,这和你现在使用的一样,不是很好。然后你可以安装 RSVG 委托,这样会更好。但最好的解决方案是安装 Inkscape,ImageMagick 会自动使用它。是最好的选择。
  • 感谢您的回复。我在我的帖子中添加了 svg 的完整版本。我在共享主机上,不支持推荐的附加组件
  • 您确定不能让他们安装 Inkscape 吗?它不是需要与 ImageMagick 一起安装的委托。
  • 我使用 ImageMagick 对 MSVG、RSVG 和 Inkscape 进行了测试以转换为 PNG。 MSVG 给出了与你得到的结果相同的结果。 RSVG 给出了一个空白图像。 Inkscape 工作正常。
  • 如果您不能使用 Inkscape,那么可以在错误论坛 imagemagick.org/discourse-server 上发布有关 MSVG 的错误报告

标签: php image svg imagemagick png


【解决方案1】:

您拥有的 SVG 文件并不是真正的矢量图像。它只是一个包装在 SVG 中的 PNG。这使得获取图像变得微不足道:读取构成图像的数据 url,对其进行解码并将结果写入文件。不需要 ImageMagick,只需 gd。

$svg = simplexml_load_file('front-test.svg');
$data_url = $svg->svg->g->image['xlink:href'];
$encoded = $data_url.explode(',')[1];
$data = base64_decode($encoded);
$im = imagecreatefromstring($data);
imagepng($im, 'front-test.png');

【讨论】:

  • 感谢您的调查。我的例子非常简单。 SVG 可能非常复杂,具有不同类型的节点。由于我需要将图片放置在底层画布上,因此您的代码只会提取图像。
【解决方案2】:

感谢 fmw42 提供有关不同渲染器的建议。经过对这个问题的一些研究,我发现即使是imagemagick也建议使用另一个渲染器并用won't fix关闭了这个问题:

我们推荐 libRSVG 委托库或 inkscape 委托程序作为首选 SVG 渲染器。内部渲染器不太健壮,可能永远不会支持所有 SVG 标准。

来源:https://github.com/ImageMagick/ImageMagick/issues/335

为了解决这个问题,我尝试了不同的在线转换器,看看他们是否也有这个问题。他们中的大多数人只给了我一张空画布,其他人的结果与我问题中的第二张图片相同。

我在找到https://convertio.co/de/ 后停止搜索转换器 他们能够给我正确的输出图像。他们有一个 API,可以每天免费使用 25 分钟转换:https://developers.convertio.co/

这是我的唯一方案,因为我希望项目灵活,因为某些用户可能无法在他们的服务器上安装inkscape。

【讨论】:

    猜你喜欢
    • 2021-05-28
    • 2019-03-23
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    • 2018-10-08
    • 2021-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多