【问题标题】:SVG output of ImageMagick appears malformedImageMagick 的 SVG 输出出现格式错误
【发布时间】:2020-03-17 15:19:39
【问题描述】:

我有一个使用 ImageMagick 生成图标并以各种格式返回它们的 php 脚本。像 JPG、PNG 甚至 ICO 这样的位图格式就像一个魅力,但是 SVG 输出做了一些奇怪的事情。这是一个说明案例的最小脚本:

<?php

$format = 'jpg';

$im = new Imagick;
$im->newImage(300, 300, new ImagickPixel('#ffffff'));
$im->setImageFormat($format);

$draw = new ImagickDraw();
$draw->setStrokeWidth(0);
$draw->setFillColor(new ImagickPixel('#ff0000'));
$draw->setFillOpacity(.5);
$draw->rectangle(50, 50, 249, 249);

$im->drawImage($draw);

header('Content-Type: ' . $im->getImageMimeType());

echo $im->getImageBlob();

示例输出:

如果我将$format 的值更改为pngico,图像仍然可以正常工作,并使用正确的MIME 类型标头发送。当我将格式切换为svg 时,会发送正确的 MIME 类型标头,并且它确实返回了 some 类型的 SVG,但它似乎格式不正确。这是上面示例脚本的输出:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
  "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="300" height="300">
stroke-width:0;fill:#FFFF00000000;fill-opacity:0.5;  <rect x="50" y="50" width="199" height="199"/>
</svg>

值得注意的是,svg 元素上的 xmlns 属性缺失。也许更奇怪的是,矩形属性实际上并没有应用于矩形,而是作为某种内联 CSS 转储(没有适当的上下文让它如此行事)。

可行的输出(并且我有点预期)将是:

<?xml version="1.0" standalone="no"?>
<svg width="300" height="300" xmlns="http://www.w3.org/2000/svg">
    <rect x="50" y="50" width="199" height="199" stroke-width="0" fill="#FF0000" fill-opacity="0.5"/>
</svg>

此外,具有正确尺寸的 viewBox 属性会很好,但这不会破坏交易。

我错过了什么吗?也许在渲染为矢量格式之前需要应用一些操作?也许这是一个错误?我找不到任何关于它的信息,任何指向正确方向的指针将不胜感激。

2019 年 11 月 25 日更新

情节转折。我以前没有注意到这一点,但是当我在示例中省略 drawImage 步骤时,我会得到完全不同的输出:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="300px" height="300px" viewBox="0 0 300 300" enable-background="new 0 0 300 300" xml:space="preserve">  <image id="image0" width="300" height="300" x="0" y="0"
    xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsAQAAAABRBrPYAAAABGdBTUEAALGPC/xhBQAAACBjSFJN
AAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAd2KE6QAAAA+SURB
VGje7coxAQAACAOg9U9rA1dBf7jJXkw0TdM0TdM0TdM0TdM0TdM0TdM0TdM0TdM0TdM0TdM0TdO0
fytHkUx5BCDW7AAAAABJRU5ErkJggg==" />
</svg>

它现在创建了一个 PNG 背景图像,由于某种原因它会内联解析,但它还引入了以前缺少的方面;尤其是xmlnsviewBox

整个标记看起来与 Inkscape 将产生的东西相同。这可能是有道理的,因为我在某处读到这是 ImageMagick 可以用来渲染 SVG 的库之一。

这几乎就像drawImage 方法破坏了 Inkscape 解析器,它回退到一些劣质引擎或其他东西。我希望这会缩小解决方案的路径。

【问题讨论】:

  • 您是否安装了libmagickcore6-extra?我之所以这么认为是因为它已经走到了这一步,但也许它是一个支持较少的旧版本?
  • 老实说我不知道​​,@JeremyHarris。我目前在 Windows 机器上运行这个脚本(是的,我知道)。 php 说imagick module version3.4.4RC2,而Imagick compiled with ImageMagick version 的值是ImageMagick 7.0.7-11 Q16 x64 2017-11-23 http://www.imagemagick.org。差不多就是这样。 libmagickcore6-extra 是我可以包含 php 的东西吗?
  • 我的理解是库添加了 SVG 支持。也许制作一个 docker 容器并使用 libmagickcore-6.q16-6-extra 包运行 linux?
  • 我希望在这个开发环境中找到一个解决方案,因为这是一个更大的应用程序的一部分,但我一定会研究它。谢谢,@JeremyHarris。
  • 是的,对不起,我帮不上忙。

标签: php svg imagemagick


【解决方案1】:

根据这个ImageMagic board,导出到 SVG 是相当有问题的,因为该库是为光栅图像而不是矢量图形设计的。据我了解,SVG 输出始终是带有 base64 编码二进制数据的图像标签。您的要求的解决方法可能如下所示:

$im = new Imagick;
$im->newImage(300, 300, new ImagickPixel('#ffffff'));
$im->setImageFormat('svg');

$im1 = new Imagick();
$im1->newImage(300, 300, new ImagickPixel('#ffffff'));
$im1->setImageFormat('png');
$fillColor = new ImagickPixel('#ff0000');
$draw = new ImagickDraw();
$draw->setFillColor($fillColor);
$draw->setStrokeWidth(0);
$draw->setFillOpacity(.5);
$draw->rectangle(50, 50, 249, 249);
$im1->drawImage($draw);

$im->compositeImage($im1->getimage(), Imagick::COMPOSITE_COPY, 0, 0);

header('Content-Type: image/svg+xml');

echo $im->getImageBlob();

【讨论】:

  • 谢谢。我的印象是 ImageMagick 可以输出 SVG。尽管这在技术上似乎是正确的,但它的执行方式并不是特别有用。我想我会回到我的软件中的一个 ol' 开关,它会根据请求的 MIME 类型触发完全不同的逻辑,就像我一直在做的那样。不是我所希望的,但你的答案很明确,赏金是你的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-28
相关资源
最近更新 更多