在不跟踪的情况下将 PNG 像素艺术转换为 SVG

平面设计 svg PNG 像素艺术 文件转换
2022-01-17 13:55:53

对于个人项目,我将一些图标设计为 PNG 文件,并希望将它们导出为 SVG。

我知道下一个问题:我不需要栅格,我需要矢量。我发现了这个问题,但由于它基于 InkScape,我想这将涉及到tracking

我不要那个。我所希望的更像是pixel2svg提出的。实际上,pixel2svg 几乎是完美的,并且提供了我正在寻找的东西。

从文档:

是我项目中的一个示例。

唯一需要注意的是:我的一些图标需要一个中间 alpha 值。pixel2svg 似乎是相当二元的:要么有一个像素,要么它是透明的。中间什么都没有。在我的项目中, PNGSVG中有问题的示例之一

我试图寻找一个联系地址,看看是否可以更改,但我没有找到。

有谁知道从(相对)小的(和单色的,如果有帮助的话)PNG 生成像素化 SVG 的解决方案吗?

总结一下我的要求

  • 矢量,无光栅
  • 逐像素转换,无追踪
  • 考虑 alpha(具有中间值,不仅是 0/1)
  • 可选:命令行会很棒,因为它允许批量转换

编辑:pixel2svg 的增强版

根据JohnB 的回答,我联系了原作者提交了一些更改(通常在 alpha 既不是 0 也不是 255 时将 RGB 更改为 RGBA)。我还没有答案,所以我创建了一个带有更改的Github 存储库,以使任何人都可以使用它们。

因为,嘿,它是 Github!Python 开发人员应该随时 fork 并使其变得更好(拉取请求将帮助我更好地了解 Python)。下一个重大挑战是将具有相同颜色的像素分组为相同的矢量(尽管 InkScape 添加了许多自定义信息,但在 InkScape 中这样做大大减少了 SVG 大小)。

4个回答

pixel2svg有可能做到这一点,但它需要对脚本进行一些修改。

怎么做

您需要修改svgdoc.addpixel2svg.py 第 125 行的调用以添加 opacity 属性。它应该如下所示:

svgdoc.add(svgdoc.rect(insert = ("{0}px".format(colcount * arguments.squaresize),
                             "{0}px".format(rowcount * arguments.squaresize)),
                       size = ("{0}px".format(arguments.squaresize + arguments.overlap),
                           "{0}px".format(arguments.squaresize + arguments.overlap)),
                       fill = svgwrite.rgb(rgb_tuple[0],
                                       rgb_tuple[1],
                                       rgb_tuple[2]),
                       opacity = rgb_tuple[3]/float(255)))

这是代码更改的差异为了展示它,我制作了这个非常小的图像这是修改后的 pixel2svg 生成的 SVG(或在此处查看实际操作。):

<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:ev="http://www.w3.org/2001/xml-events" xmlns:xlink="http://www.w3.org/1999/xlink" baseProfile="full" height="40px" version="1.1" width="440px">
<defs/>
<rect fill="rgb(255,0,255)" height="40px" opacity="0.101960784314" width="40px" x="40px" y="0px"/>
<rect fill="rgb(255,0,255)" height="40px" opacity="0.2" width="40px" x="80px" y="0px"/>
<rect fill="rgb(255,0,255)" height="40px" opacity="0.301960784314" width="40px" x="120px" y="0px"/>
<rect fill="rgb(255,0,255)" height="40px" opacity="0.4" width="40px" x="160px" y="0px"/>
<rect fill="rgb(255,0,255)" height="40px" opacity="0.501960784314" width="40px" x="200px" y="0px"/>
<rect fill="rgb(255,0,255)" height="40px" opacity="0.6" width="40px" x="240px" y="0px"/>
<rect fill="rgb(255,0,255)" height="40px" opacity="0.701960784314" width="40px" x="280px" y="0px"/>
<rect fill="rgb(255,0,255)" height="40px" opacity="0.8" width="40px" x="320px" y="0px"/>
<rect fill="rgb(255,0,255)" height="40px" opacity="0.901960784314" width="40px" x="360px" y="0px"/>
<rect fill="rgb(255,0,255)" height="40px" opacity="1.0" width="40px" x="400px" y="0px"/>
</svg>

这是怎么回事

pixel2svg 使用PIL处理所提供图像的每个像素。它实际上已经将每个像素的 alpha 值拉为整数 [0-255],它只是没有做太多:

image = PIL.Image.open(positional[0])
print("Converting image to RGBA")
image = image.convert("RGBA")

然后使用svgwrite将像素数据重建为 SVG 。每个像素都被绘制为svgwrite.shapes.Rect允许您将“附加 SVG 属性作为关键字参数”链接的方法。SVG 不透明度值需要一个浮点数 [0.0-1.0],因此我们只需要在将其设置为不透明度之前对 alpha 值进行标准化。


免责声明:这是我第一次使用 Python,所以请随时指出我可能犯的任何初学者错误!

我是一名程序员,在我之前看是否有人这样做(对于像素艺术网页游戏)。我制作了一个网络工具,虽然速度慢,但功能强大。它向您显示结果和 SVG 源代码:https ://codepen.io/tacode/pen/eMaqWG

如果你有 python 和 PIL/Pillow,我刚刚写了这个(@JohnB 的答案中的一个简单的工具版本):

#!/usr/bin/env python2.7
import sys
infile = sys.argv[1]
outfile = sys.argv[2]
from PIL import Image
image = Image.open(infile).convert('RGBA')
data = image.load()
out = open(outfile, "w")
out.write('<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n')
out.write('<svg id="svg2" xmlns="http://www.w3.org/2000/svg" version="1.1" width="%(x)i" height="%(y)i" viewBox="0 0 %(x)i %(y)i">\n' % {'x':image.size[0], 'y':image.size[1]})
for y in range(image.size[1]):
    for x in range(image.size[0]):
        rgba = data[x, y]
        rgb = '#%02x%02x%02x' % rgba[:3]
        if rgba[3] > 0:
            out.write('<rect width="1" height="1" x="%i" y="%i" fill="%s" fill-opacity="%.2f" />\n' % (x, y, rgb, rgba[3]/255.0))
out.write('</svg>\n')
out.close()

用参数调用它,input.png output.svg它应该去。不过,我不会尝试使用大于几百平方像素的东西。

如果您不自动跟踪,则选项是手动进行制作一个网格并开始绘制框。

您的要求:

  • 矢量,无光栅(确定)
  • 逐像素转换,无描摹(OK)一半ok。基于矢量的文件没有像素。
  • 考虑阿尔法(OK)如果你只是不画背景。
  • 可选:命令行会很棒。任何命令行选项都是一个“跟踪”选项,它是可选的。

Svg 也可以在其中包含 png ......但我相信在这种情况下它没有多大意义。