【问题标题】:Converting svg to png without changing the pixel values在不更改像素值的情况下将 svg 转换为 png
【发布时间】:2017-12-20 23:48:09
【问题描述】:

我已经被这个问题困扰了一段时间了。本质上,我有一堆 svg 图像。 svg 文件中的每个“孩子”都标有一些像素值。目前这个值的数量非常少,所有东西都标记为 rgb(0.0, 0.0, 0.0), rgb(1.0, 1.0, 1.0) ... rgb(9.0, 9.0, 9.0),所以基本上我有 10 种不同的类型像素。

现在,我想将这些图像转换为 png 格式,更重要的是我需要像素值的映射为 1 对 1。本质上,所有在 svg 文件中具有 rgb(0.0, 0.0, 0.0) 值的像素,都需要在 png 文件中具有 rgb(x,x,x) 值(甚至更好的 L(x)); svg 文件上的 rgb(1.0, 1.0, 1.0) 需要转换为 png 文件上的 rgb(y,y,y) (甚至更好的 L(y))等等。这种一对一映射对我的应用程序来说是个大问题,因为这本质上是我工作的基本事实。

只需在控制台中编写:

    convert test.svg test.png

没有给我我想要的。检查值的直方图,似乎我有 248 个唯一值而不是 10 个,这对我不利(尽管它们中的绝大多数只有几个像素)。

有谁知道:

  • 如果可以的话。
  • 如何做到这一点。

到目前为止,我已经尝试过使用 Python 的 cairosvg 等其他库,但效果似乎更糟。是的,我知道 svg 和 png 是完全不同的格式。

为了澄清,添加一个 svg 和一个 png 文件:

svg:https://drive.google.com/open?id=0B_vhcDz1zxeYeGVDSnhfeWplOWs

png:https://drive.google.com/open?id=0B_vhcDz1zxeYUnYzZUtIUmVqVWM

在 Python 中打开文件,似乎有 248 个唯一像素值,而应该只有 4 个(背景 + 三个符号)。

谢谢!

【问题讨论】:

  • 我认为你需要更具体一些,实际展示一个文件,而不是抽象地谈论 "children"Lx 和 “像素类型” 特别是考虑到svg 文件甚至没有像素。
  • 没有看到您的测试文件,我只能猜测您看到的是缩放效果,其中 PNG 像素是从 SVG 数据点插入的。
  • 公平点,我添加了一个svg文件,以及对应的png文件。 @MarkSetchell
  • @GlennRanders-Pehrson
  • 谢谢。我正在看一看。 GraphicsMagick 产生与您的 png 相同的输出。由于某种原因,我的 ImageMagick v6 和 v7 都拒绝了 svg 文件。

标签: python svg imagemagick png


【解决方案1】:

您的请求没有多大意义。据我所知,您的示例 SVG 文件只有两种颜色:黑色和白色 (rgb(255.0, 255.0, 255.0))。那么这 10 种颜色的想法是从哪里来的呢?

另外,SVG 标准并没有具体说明如何将矢量形状转换为像素。 SVG 渲染器之间会有细微差别。

请记住,穿过像素中间的矢量形状边缘会产生灰色像素。这称为抗锯齿。它旨在使边缘看起来更平滑。我想这就是为什么您看到的像素值比您预期的要多。


也许您的意思是您想要一种禁用抗锯齿的方法?一些转换程序可能有执行此操作的选项。或者,您可以尝试将 shape-rendering 属性添加到文件的根 <svg> 标记:

<ns0:svg ...(snip)... shape-rendering="crispEdges">

但是一些 SVG 转换程序可能不支持这个属性。但是,如果您在大多数浏览器中尝试一下,就会发现它可以正常工作。

关闭抗锯齿生成的输出看起来不太好。但也许出于您的目的,您并不关心这一点。


或者,也许您想知道如何将 SVG 转换为位图,同时将抗锯齿限制为 10 个特定的灰色级别? Imagemagick 可以让你做到这一点。我不是 Imagemagick 用户,但显然您可以通过使用 -map 参数传递调色板图像来告诉 imagemagick 使用特定的调色板。

【讨论】:

  • 在整个数据集上,我使用了 10 种颜色(9 种黑色,白色作为背景)。在我上传的图片上,应该有 4 种不同的颜色(一种白色,三种黑色,每个符号一个)。当然,三个黑色的对于人眼是无法区分的,但是如果以数组的形式打开文件,它们的值是不同的。我使用了抗锯齿,但它没有改变任何东西,我仍然获得了比我应该的更多的颜色。
  • Control-F fill="rgb(2.0, 2.0, 2.0)" fill="rgb(3.0, 3.0, 3.0)" fill="rgb(9.0, 9.0, 9.0)" 你会找出其他三种颜色。
  • 还要注意rgb() 颜色中的值应该是整数。一些渲染器不支持像 2.0 这样的小数 - 例如。铬。
  • shape-rendering="crispEdges" 似乎有点用。现在,我得到了正确的颜色数量。另一方面,现在白色似乎是 65535 而不是 255(一个数字似乎用 2 个字节而不是 1 表示)。它不是一个破坏者(毕竟,我可以为此使用映射),但是有没有一种简单的方法可以让所有内容都在 [0, 255] 范围内?
  • 我不知道 rgb() 值应该是整数。改变了这一点,虽然它似乎在输出中没有任何区别。 @保罗勒博
【解决方案2】:

3 年,但没有很好的解决方案 gg:

我找到了 2 个不错的:

  1. 您可以在 ImageMagick 命令行中使用:

    "转换 in.svg +antialias out.png"

但要小心,我的消息来源说“+”会停用 AA,而“-”会激活它。但是来源很老,这看起来很奇怪。我不能试试这个

  1. Inkscape 在更新中带来了一个很好的解决方案(我在版本 1.0.1 中尝试过): 在“导出 png”的高级设置中,您可以直接选择抗锯齿 "CAIRO_ANTIALIAS_NONE" 非常适合我

【讨论】:

    猜你喜欢
    • 2013-12-07
    • 2012-07-20
    • 1970-01-01
    • 2019-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-30
    相关资源
    最近更新 更多