使用Imagick PHP生成SVG图像的原始数据

5

我正在尝试使用从 fabric js 获取的 svg 原始数据创建 svg 图像。我已经使用以下代码生成了 svg,但它不能正常工作。

public function generate_svg($raw_svg='',$prefix='',$folder_name='card_image')
{
    $file_name = '';       
    if($raw_svg!='')
    {
        try{           
            $file_name = uniqid($prefix).".svg";
            $image = new \Imagick();
            $image->readImageBlob($raw_svg);
            $image->setImageFormat("svg");
            $image->writeImage($folder_name.$file_name);
        } catch (ImagickException $ex) {
            echo $ex->getMessage();
        }
    }
     return $file_name;
}

现在的问题是背景图片看起来像下面这样:enter image description here 那么我该怎么做才能解决这个问题呢?它应该看起来像下面这样(忽略方形和圆形),整个背景应该是bg图像,而不是全黑色:enter image description here 所以问题是背景图像没有加载出来,那么我需要添加额外的库还是其他什么操作呢?Imagick 版本号:6.7.7
    convert -list delegate | grep svg  

    cdr =>          "uniconvertor' '%i' '%o.svg'; /bin/mv '%o.svg' '%o"
    cgm =>          "uniconvertor' '%i' '%o.svg'; /bin/mv '%o.svg' '%o"
    dot =>          "dot' -Tsvg '%i' -o '%o"
    dxf =>          "uniconvertor' '%i' '%o.svg'; /bin/mv '%o.svg' '%o"
    fig =>          "uniconvertor' '%i' '%o.svg'; /bin/mv '%o.svg' '%o"
    svg =>          "rsvg-convert' -o '%o' '%i"

 convert -list format | grep SVG

 MSVG  rw+   ImageMagick's own SVG internal renderer
  SVG  rw+   Scalable Vector Graphics (XML 2.9.1)
 SVGZ  rw+   Compressed Scalable Vector Graphics (XML 2.9.1)

它应该是什么样子?你没有提供图片。 - Mark Setchell
然而,我正在使用相同的原始数据生成 PNG 文件,以上代码唯一的变化是将图像格式设置为 png24。之前我在 PNG 转换方面也遇到了相同的问题,我使用了这个:SVG rw+ 可伸缩矢量图形 (XML 2.9.1)。那么我需要安装其他库来创建 SVG 文件吗? - DS9
这是基本的IM转换器。安装librsvg(首选)或Inkscape。ImageMagick应该能够自动委派其中之一。您可以使用convert -list delegate | grep svg进行测试。 - ccprog
@ccprog更新了问题。 - DS9
我刚刚才注意到你想再次导出为SVG格式 - 抱歉,忽略之前的评论。 - ccprog
显示剩余2条评论
3个回答

1
我最终将字体存储在原始SVG中,并使用fopen创建SVG文件,而不是使用imagick。因此,我的SVG看起来像下面这样:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="600" height="400" viewBox="0 0 600 400" xml:space="preserve">
<desc>Created with Fabric.js 2.0.0-beta7</desc>
<defs>
<style>
    //... base64 data of font
    @font-face {
        font-family: "Elsie";
        src: url("data:application/font-truetype;charset=utf-8;base64,...")
    }
</style>
</defs>

之后我使用以下代码创建了SVG文件:

$file_name = uniqid($prefix).".svg";
$file_handle = fopen("$folder_name/".$file_name, 'w');
fwrite($file_handle, $raw_svg);
fclose($file_handle);

我对以这种方式获得的文件大小很好奇。Base64编码是否会减小ttf文件的大小? - ccprog
@ccprog Base64编码会增加文件大小。但使用该方法,所有字体都将加载到最终的SVG图像中。 - DS9

1
我认为你走错了方向。Image Magick基本上是一个以像素为导向的库。虽然渲染背景图像可能是一个配置问题,但你的图片显示你想要实现的字体“嵌入”并没有发生。这才是真正的问题所在。
你想要实现的是在SVG文件中表示字体信息。有两种方法可以做到这一点,在IM中都没有任何支持:
  • 将字体转换为SVG字体格式,并将其内联嵌入到文件中(生成大文件)
  • 将所有字形转换为路径(文本不再可编辑)
根据你的描述,我认为你应该瞄准第二种变体。你基本上会用<path>元素替换字符串中的<text>元素,并按原样输出SVG文件,包括你收到的嵌入式图像数据。 如何将文本转换为SVG路径?是对这个问题的旧看法。

EasySVG for PHP 是一个库,用于将字形转换为路径,但前提是你已经有了SVG格式的字体。对于像ttf这样的典型桌面字体格式,您可能需要先查看FontForge等字体转换工具。

您可能可以通过Cairo实现直接的svg数据转换,但这只是一种猜测,我没有使用过它。

最后,作为解决方法,您可以将整个任务委托给Inkscape。它可以在不启动GUI的情况下通过命令行调用。

inkscape in.svg --export-text-to-path --export-plain-svg=out.svg

0
除了 @ccprog 的精彩回答之外,我想提醒您可以使用 phantomjs 生成所需的像素,只需将输入的 html 文件作为输入,输出为 png。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接