2017-09-06 104 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