2017-09-06 69 views
0

我想将SVG转换成PNG文件。我的主要问题不是转换本身(我可以用几行代码来完成),而是将我想要发送到SVG元素的中心放到呈现的“窗口”中。我使用SVG引擎(https://github.com/vvvv/SVG),我的想法是获取我想渲染的元素,然后在原点重新定位它,然后将svg文档的宽度和高度设置为元素的宽度/高度。 下面的代码:SVG元素与C#PNG文件

var svgDocument = SvgDocument.Open(filename); 
var el =(SvgVisualElement) svgDocument.GetElementById("MyId"); 

// set in the origin 
el.Transforms.Add(new SvgTranslate(-el.Bounds.X, -el.Bounds.Y)); 

// set doc dimensions 
svgDocument.Width = el.Bounds.Width; 
svgDocument.Height = el.Bounds.Height; 

bitmap.Save("PNGFile", ImageFormat.Png); 

Unfortunally它不工作的方式。 这里的SVG不工作的一个例子(它的lenthy,所以我切的相关部分):

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
 

 
<svg 
 
    xmlns:dc="http://purl.org/dc/elements/1.1/" 
 
    xmlns:cc="http://creativecommons.org/ns#" 
 
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
 
    xmlns:svg="http://www.w3.org/2000/svg" 
 
    xmlns="http://www.w3.org/2000/svg" 
 
    xmlns:xlink="http://www.w3.org/1999/xlink" 
 
    xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" 
 
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" 
 
    width="70.125473" 
 
    height="190.98564" 
 
    id="svg6678" 
 
    version="1.1"> 
 
    <g id="MyId"> 
 
    <g 
 
     transform="translate(-2375.7448,475.88408)" 
 
     id="Texture:door_single_rocks_gear"> 
 
     <path 
 
     id="path9179-8-2-8-71-4-2-7" 
 
     d="..." style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#5b3636;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.53245842;marker:none;enable-background:accumulate" /> 
 
     <path 
 
     id="path9179-8-2-8-71-4-6" 
 
     d="..." style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#815656;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.53245842;marker:none;enable-background:accumulate" /> 
 
     <path 
 
     id="path4080-5-2" 
 
     d="..." 
 
     style="fill:#866262;fill-opacity:1;stroke:none" /> 
 
     <path 
 
     id="path7662-1-1-4-9" 
 
     d="..." 
 
     style="fill:#5b3636;fill-opacity:1;stroke:none" /> 
 
     <path 
 
     id="path7662-1-1-4-5-5" 
 
     d="..." 
 
     style="fill:#5b3636;fill-opacity:1;stroke:none" /> 
 
    </g> 
 
    <g 
 
     id="Texture:door_single_rocks" 
 
     inkscape:label="#g5299" 
 
     inkscape:export-filename="C:\Users\stefano.liboni\Dropbox\AndroidStudio\AsteroidRage\scenes_source\door_single_rocks.png" 
 
     inkscape:export-xdpi="199.88191" 
 
     inkscape:export-ydpi="199.88191"> 
 
     <path style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#5b3636;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;marker:none;enable-background:accumulate" 
 
     d="..." 
 
     id="rect4972-3-8-9" /> 
 
     <path 
 
     id="rect4972-9" 
 
     d="..." style="color:#000000;display:inline;overflow:visible;visibility:visible;fill:#815656;fill-opacity:1;fill-rule:nonzero;stroke:#5b3636;stroke-width:1.0026859;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker:none;enable-background:accumulate" /> 
 
     <path 
 
     style="fill:#5b3636;fill-opacity:1;stroke:none" 
 
     d="..." 
 
     id="path7662-1-1-4-5-5-0" /> 
 
     <path 
 
     style="fill:#5b3636;fill-opacity:1;stroke:none" 
 
     d="..." 
 
     id="path7662-1-1-4-5-5-03-9" /> 
 
     <path 
 
     style="fill:#5b3636;fill-opacity:1;stroke:none" 
 
     d="..." 
 
     id="path7662-1-1-4-5-5-03" /> 
 
    </g> 
 
    <g 
 
     id="AnimatedTexture:door_single_rocks_led" 
 
     inkscape:label="#g5295"> 
 
     <path 
 
     id="path9095-7" 
 
     d="..." 
 
     style="fill:#9486ff;fill-opacity:1;stroke:#000000;stroke-width:1.07693017;stroke-opacity:1" /> 
 
     <path 
 
     id="path9095-7-5-1" 
 
     d="..." 
 
     style="fill:#9486ff;fill-opacity:1;stroke:#000000;stroke-width:1.07693017;stroke-opacity:1" /> 
 
    </g> 
 
    </g> 
 
</svg>

正如你可以看到有一个元素身份识别码充满了其他的g元素和一些路径。我添加了它在Inkscape the svg rendered in inkscape中呈现的图像。

一旦我得到的元素的边界(其为在左下方的一个)在我的代码得到: {X = -1502.69763 Y = 668.7914宽度= 2514.11938高度= 870.0564}

这似乎错误的,因为该元素仅仅是宽141px和高度395px ... 如果我运行该文件的输出是代码: enter image description here

所以PNG有很多未使用的空间,两个Y, PNG的宽度和高度是错误的。正确的将是:

svgDocument.X = 0; 
svgDocument.Y = -476; 
svgDocument.Width = 141; 
svgDocument.Height = 395; 

任何想法我做错了什么?

注意:我知道inkscape会做对(我曾经使用过它),但是至少有三年时间他们不打算解决这个问题,这会阻止inkscape以静默模式运行,如果您指定“动词“在命令行中。所以,这是一个痛苦,因为对于每个文件,它打开用户界面,并采取3-4secs做到这一点...

+0

--------------------------------------------- ----------------------------------- UPDATE ------------ ---------------------------------------- 正如我认为它必须做的我想要呈现的元素中** g **元素的transfrom属性。如果我摆脱了所有的转换属性,它可以正常工作,不仅适用于此示例,还适用于更复杂的geomeries。 如何考虑这些转换? –

+0

您能解释一下关于inkscape CLI问题的更多信息吗?我正在成功地使用它来完成与您描述的任务相同的任务。 – ccprog

回答

0

由ccprog的评论推我发现UI是由inkscape openend,因为我也在做其他stu在我运行的同一个命令中。

实际运行Inkscape中为:

MyFile.svg --export-ID = ElementIdToRender --export-ID-仅--export-DPI = 200 --export-PNG = “的TargetFile”

做这份工作。

仍然理解为什么SVG库会给出奇怪的数字作为边界g包含一个或多个具有transform属性集的子元素的元素,但此刻我可以继续。 Tnx

1

我还没有找到,如果有一个文件库。我在源代码中查看过,但主要是我可以解释的是SVG的一部分。也许有更简单的引擎提供的方式。

transformtransform根svg元素上的属性是合法的,但是在您要完成的内容中,它们比有帮助更容易混淆,因为其他属性会导致转换,但会以不同的形式写入。

<svg>元素提供匹配要更直接地完成什么属性:最外面的SVG元素

  • xy属性被忽略。

  • widthheight描述图像被渲染成的尺寸输出。所以他们应该反映最后的“窗口”维度。如果SVG最初的尺寸不符合您的“窗口”,请更改它们。

  • viewBox描述应该渲染SVG视口(根元素的坐标系)内部的哪个部分内部。此不是什么SVGVisualElement.Bounds结构为选定的元素返回。 (相对于元素本身的坐标系统的值,但不包括所有父元素转换​​)我无法在库中找到任何可以获得所需值的函数。

  • preserveAspectRatio描述了渲染零件如何适合输出窗口。例如,默认情况下,XMidYMid meet表示:将视图框区域的大小设置为最大,以便它适合宽度/高度而不会在任何方向溢出,并将其放置在中心位置。

虽然我不知道如何从库中边界框的需要的值,其它程序提供它们没有问题:

  • inkscape -I MyID在命令行中
  • 通过Javascript的浏览器document.getElementById("MyId").getBBox()
+0

Tnx的帮助。我已经改变了svg文档的宽度和高度,但是使用了我想渲染的元素的Bounds属性,这反过来看起来是错误的,因为它提供了太高的值......摆脱所有变换,一切正常,边界得到正确的价值观。 SVG库中应该有一个错误... –

+0

你可以通过使用不同的软件测试它们来确定Bounds的值。打开 。svg直接在现代浏览器中,按打开开发者工具,在集成控制台中键入'document.getElementById(“MyId”)。getBBox()'。结果应该是一个匹配那个元素的Bounds属性的对象。 – ccprog

+0

再次阅读库源代码后,我现在确信Bounds不会提供所需的值 - 这不是错误,但缺少该属性的文档。那么*有一个错误:[界限不代表孩子转换](https://github.com/vvvv/SVG/issues/331),但即使解决这个问题也不会给你你需要的东西。 – ccprog