0

我已经编写了一个将 SVG 转换为 PNG 的脚本,该脚本运行良好,直到 SVG 中的内容“脱离页面”。

例如:

SVG 内容为“页外”

黑线将被很好地转换,但绿框被完全忽略。一些 SVG 文件的内容完全脱离页面并呈现一个空的 PNG 文件。

我当前的命令:

convert -background none "$file" -trim -geometry $size "$target"

我有 2k + SVG 文件,我正在转换至少大约 500 个或更多的文件,因此手动将图像移动到页面上并不是一个选项。

编辑 这里是一个示例文件的链接。实际绘图与左侧页面底部一致。

4

2 回答 2

0

当然,“离页”的内容将在 PNG 中被忽略。与 SVG 不同,PNG 文件格式不知道“离页”概念。

这类似于在一张纸上打印:打印机也无法显示“离页”内容。

有两个选项供您探索。两者的效果是您会将实际页面大小更改为更大的页面:

  1. 可以通过将 SVG 渲染到更大的 PNG 画布,然后自动修剪多余的边缘来获取 PNG 中的“页外”内容。(由于缺少示例文件,我自己无法尝试。)

  2. 您可以尝试通过 2 步或 3 步过程达到预期的结果:

    • 通过增加其画布来修改 SVG,使其包含“页面上”的所有对象;
    • 将修改后的 SVG 转换为 PNG;
    • (可选:修剪 PNG 的边缘)。
于 2012-10-22T05:41:40.023 回答
0

所以我终于得到了这个工作。似乎无法直接使用 ImageMagick 进行操作,因此最终操作了实际的 SVG 数据。

首先是找到对象的边界。使用 PHP 和 simpleXml 我将 SVG 数据转换为数组以便于操作/遍历。

似乎所有坐标都采用 xy 的形式,因此这会将坐标分解为数字,并在 x / y 记录之间切换(如果其高于/低于先前的值)。

/** $line is a <g> object */
protected function _position($line, &$position) {
        if(empty($line['@d'])) {
            if(is_array($line)) {
                foreach($line as $l) {
                    self::_position($l, $position);
                }
                return;
            }
        }

        if(empty($position)) {
            $position = array(
                'min' => array(
                    'x' => null,
                    'y' => null
                ),
                'max' => array(
                    'x' => null,
                    'y' => null
                )
            );
        }

        foreach(array_filter(preg_split('/([a-z])/i', $line['@d'])) as $cord) {
            $coordinate = 'x';
            foreach(explode(' ', $cord) as $value) {
                if(empty($value)) {
                    continue;
                }

                if($position['min'][$coordinate] == null || $position['min'][$coordinate] > $value - 1) {
                    $position['min'][$coordinate] = $value;
                }

                if($position['max'][$coordinate] == null || $position['max'][$coordinate] < $value + 1) {
                    $position['max'][$coordinate] = $value;
                }

                $coordinate = ($coordinate != 'x') ? 'x' : 'y';
            }
        }
    }

一旦你得到了最小/最大界限,我就找到了一个属性transformtranslate它通过指定的 x,y 移动对象。所以只要拿走0 - $min它就会被移动到0它可能的位置0 - -100 - 10

我所有的文件都没有属性,所以我只是简单地替换<g><g transform="translate($widthOffset, $heightOffset)">

还要设置视图框大小:

$xml['svg']['@viewbox'] = sprintf('%s %s %s %s',
    $position['min']['x'],
    $position['min']['y'],
    ($position['max']['x'] - $position['min']['x']),
    ($position['max']['y'] - $position['min']['y'])
);

最后要做的就是将数组转换回 XML 并将新数据保存回文件中。

于 2012-10-22T23:41:12.813 回答