6

名前でsvgファイルの一部をレンダリングしたいのですが、私の人生では、その方法がわかりません(python + gtkを使用)。

問題の svg ファイルは次のとおりです: http://david.bellot.free.fr/svg-cards/files/SVG-cards-2.0.1.tar.gz (更新:このファイルはもう存在しませんが、追跡できますhttp://svg-cards.sourceforge.net/でダウン)

彼のサイトで、David は次のように述べています。

ファイルをピックスマップにレンダリングし、各カードを手動でクリッピングするか、DOM インターフェイスを介してカードの名前を使用して、カードを描画できます。すべてのカードは SVG グループに埋め込まれています。

彼がDOMインターフェースで何を意味しているのかわかりません。私はいくつかの検索を行いましたが、私がやりたいことに合っていると思われる最良の結果は次のとおりです。

QSvgRenderer *renderer = new QSvgRenderer(QLatin1String("SvgCardDeck.svg"));
QGraphicsSvgItem *black = new QGraphicsSvgItem();
QGraphicsSvgItem *red   = new QGraphicsSvgItem();

black->setSharedRenderer(renderer);
black->setElementId(QLatin1String("black_joker"));

red->setSharedRenderer(renderer);
red->setElementId(QLatin1String("red_joker"));

ただし、これは Qt 用であり、Python で書かれていないことに注意してください。

これは私がこれまでに持っているものです:

#!/usr/bin/env python

from __future__ import absolute_import

import cairo
import gtk
import rsvg

from xml import xpath
from xml.dom import minidom

window = gtk.Window()
window.set_title("Foo")
window.set_size_request(256, 256)
window.set_property("resizable", False)
window.set_position(gtk.WIN_POS_CENTER)
window.connect("destroy", gtk.main_quit)
window.show()

document = minidom.parse("cards.svg")
element = xpath.Evaluate("//*[@id='1_club']", document)[0]
xml = element.toxml()

svg = rsvg.Handle()
svg.write(xml)

pixbuf = svg.get_pixbuf()

image = gtk.Image()
image.set_from_pixbuf(pixbuf)
image.show()

window.add(image)

gtk.main()

もちろん、うまくいきません。

私は何が欠けていますか?

4

5 に答える 5

9

SVG をレンダリングするための GTK ライブラリは、RSVG と呼ばれます。rsvg_handle_get_pixbuf_sub()Pythonバインディングがありますが、文書化されておらず、通常Cでその目的に使用するand関数をラップしていませんrsvg_handle_render_cairo_sub()。私が知る限り、あなたがしなければならないことは次のとおりです。Adam Crossland が提案したように、XML ノードを抽出します。レンダリングするには、次のようにする必要があります。

import gtk
import rsvg
handle = rsvg.Handle()
handle.write(buffer=xml_data) 
# xml_data is the XML string for the object you want
image = gtk.Image()
image.set_from_pixbuf(handle.get_pixbuf())

でそれがgtk.Image必要な場合は、それ以外の場合は pixbuf で何か他のことを行います。handle.render_cairo(cr)また、Cairo コンテキストの場所を指定して Cairo コンテキストにレンダリングすることもできcrます。

編集:

申し訳ありませんが、最初は Python バインディングを十分に読んでいませんでした。_sub()関数は引数を使用して実装されるためid=、プログラムは次のように要約できます。

#!/usr/bin/env python

import gtk
import rsvg

window = gtk.Window()
window.set_title("Foo")
window.connect("destroy", gtk.main_quit)
window.show()

svg = rsvg.Handle(file='cards.svg')
pixbuf = svg.get_pixbuf(id='#3_diamond')

image = gtk.Image()
image.set_from_pixbuf(pixbuf)
image.show()

window.add(image)

gtk.main()

これをテストしましたが、動作します。ただし、ウィンドウは SVG キャンバス全体のサイズであり、画面サイズに合わせて切り取られています (これが、隅にあるクラブのエースではなく、ダイヤの 3 をレンダリングした理由です)。必要なカードの周りのpixbufをトリミングする方法を見つけるために、それはそれほど難しくありません.

于 2010-02-23T21:34:57.077 に答える
2

彼が「DOMインターフェースを介して」とは、SVGがXMLであるため、SVGファイルをminidomまたはその他のPython XMLパーサーにロードし、探している特定の名前でXMLノードを抽出できることを意味すると思います。 。そのXMLノードは、レンダリング可能なアイテムを表す必要があります。

于 2010-02-23T20:03:23.327 に答える
1

これが、空白スペースのトリミングの問題に対する私の答えです。大まかなハックですが、うまくいきました。これは、Python でカード ゲームを作成する人にとって、カードを入手するための出発点としても役立ちます。

import gtk
import rsvg
svg = rsvg.Handle(file="/usr/share/gnome-games-common/cards/gnomangelo_bitmap.svg")
w, h = 202.5, 315
card_names = map(str, range(1,11)) + ["jack", "queen", "king"]
suites = ["club", "diamond", "heart", "spade"]
specials = [{"name":"black_joker","x":0, "y":4}, {"name":"red_joker","x":1, "y":4}, {"name":"back","x":2, "y":4}]
for suite_number, suite in enumerate(suites):
    for card_number, card in enumerate(card_names):
        print "processing", suite, card, '#'+card+'_'+suite
        pixbuf = svg.get_pixbuf(id='#'+card+'_'+suite)
        pixbuf.subpixbuf(int(w*card_number), int(h*suite_number), int(w), int(h)).save("./"+card+"_"+suite+".png","png", {})
for special in specials:
    print "processing", special["name"]
    pixbuf = svg.get_pixbuf(id='#'+special["name"])
    card_number = special["x"]
    suite_number = special["y"]
    pixbuf.subpixbuf(int(w*card_number), int(h*suite_number), int(w), int(h)).save("./"+special["name"]+".png","png", {})
于 2010-05-26T03:48:58.237 に答える
0

タグを編集することで実現できます。幅と高さを編集し、メインの svg 要素の viewBox 属性を必要な長方形に設定し、レンダリングし、繰り返します。

SVG グラフィックのサブセクションまたは「スライス」を表示する方法を参照してください。およびhttp://dingoskidneys.com/~dholth/svg/

于 2010-02-23T20:13:29.723 に答える