2008-09-23 20 views
19

In einer pyGame Anwendung möchte ich Auflösung-freie GUI-Widgets rendern, die in SVG beschrieben sind.SVG-Rendering in einer PyGame-Anwendung

Mit welchem ​​Tool und/oder welcher Bibliothek kann ich dieses Ziel erreichen?

(Ich mag die OCEMP GUI Toolkit, aber es scheint Bitmap abhängig für seine Rendering zu sein)

+2

Gibt es eine andere Antwort/Bibliothek, die bis 2011 gilt ? (Weil es schon 3 Jahre her ist). Ich habe Squirtle zum Laden von Karten gesehen, die in ** inkscape ** erstellt wurden. – ninMonkey

+0

Squirtle unterstützt immer noch nicht viel von SVG afaik und es erfordert wahrscheinlich auch etwas Arbeit, es mit PyGame laufen zu lassen. Ich suche lange nach Unterstützung für SVG-Zeichnen unter Windows und 64 Bit Python und ich denke, ich muss aufgeben. – Trilarion

Antwort

15

Dies ist ein vollständiges Beispiel, das Hinweise anderer Leute hier kombiniert. Es sollte eine Datei namens test.svg aus dem aktuellen Verzeichnis rendern. Es wurde auf Ubuntu 10.10, Python-Cairo 1.8.8, Python-Pygame 1.9.1, Python-Rsvg 2.30.0 getestet.

#!/usr/bin/python 

import array 
import math 

import cairo 
import pygame 
import rsvg 

WIDTH = 512 
HEIGHT = 512 

data = array.array('c', chr(0) * WIDTH * HEIGHT * 4) 
surface = cairo.ImageSurface.create_for_data(
    data, cairo.FORMAT_ARGB32, WIDTH, HEIGHT, WIDTH * 4) 

pygame.init() 
window = pygame.display.set_mode((WIDTH, HEIGHT)) 
svg = rsvg.Handle(file="test.svg") 
ctx = cairo.Context(surface) 
svg.render_cairo(ctx) 

screen = pygame.display.get_surface() 
image = pygame.image.frombuffer(data.tostring(), (WIDTH, HEIGHT),"ARGB") 
screen.blit(image, (0, 0)) 
pygame.display.flip() 

clock = pygame.time.Clock() 
while True: 
    clock.tick(15) 
    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: 
      raise SystemExit 
+1

einen bestimmten Grund nicht zu verwenden 'screen = pygame.display.set_mode ((WIDTH, HEIGHT))' direkt anstelle der Erstellung dieses 'window' Objekt, das nie benutzt wird? – MestreLion

4

Sie Cairo (mit PyCairo) verwenden können, die Unterstützung für das Rendern SVGs hat. Die PyGame-Webseite hat eine HOWTO für das Rendern in einen Puffer mit einem Cairo und das Verwenden dieses Puffers direkt mit PyGame.

4

Ich weiß, dass dies nicht genau Ihre Frage beantwortet, aber es gibt eine Bibliothek namens Squirtle, die SVG-Dateien mit Pyglet oder PyOpenGL rendern wird.

2

Kairo kann SVG nicht aus der Box rendern. Es scheint, wir müssen librsvg verwenden.

gefunden Gerade diese beiden Seiten:

so etwas wahrscheinlich (machen test.svg zu test.png) funktionieren sollte:

import cairo 
import rsvg 

WIDTH, HEIGHT = 256, 256 
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, WIDTH, HEIGHT) 

ctx = cairo.Context (surface) 

svg = rsvg.Handle(file="test.svg") 
svg.render_cairo(ctx) 

surface.write_to_png("test.png") 
3

pygamesvg scheint zu tun, was Sie wollen (obwohl ich es nicht versucht habe).

+5

Dieses Modul wurde entfernt. Die unten aufgelisteten Ansätze von cairo + rsvg sind viel bessere Lösungen. [Disclaimer: Ich schrieb schnell pygamesvg vor 3 Jahren] – PAG

1

Der letzte Kommentar abgestürzt, als ich es lief, weil svg.render_cairo() einen kairo Kontext und keine kairo Oberfläche erwartet. Ich habe die folgende Funktion erstellt und getestet und es scheint auf meinem System gut zu laufen.

import array,cairo, pygame,rsvg 

def loadsvg(filename,surface,position): 
    WIDTH = surface.get_width() 
    HEIGHT = surface.get_height() 
    data = array.array('c', chr(0) * WIDTH * HEIGHT * 4) 
    cairosurface = cairo.ImageSurface.create_for_data(data, cairo.FORMAT_ARGB32, WIDTH, HEIGHT, WIDTH * 4) 
    svg = rsvg.Handle(filename) 
    svg.render_cairo(cairo.Context(cairosurface)) 
    image = pygame.image.frombuffer(data.tostring(), (WIDTH, HEIGHT),"ARGB") 
    surface.blit(image, position) 

WIDTH = 800 
HEIGHT = 600 
pygame.init() 
window = pygame.display.set_mode((WIDTH, HEIGHT)) 
screen = pygame.display.get_surface() 

loadsvg("test.svg",screen,(0,0)) 

pygame.display.flip() 

clock = pygame.time.Clock() 
while True: 
    clock.tick(15) 
    event = pygame.event.get() 
    for e in event: 
     if e.type == 12: 
      raise SystemExit 
0

auf anderen Antworten Basierend, hier ist eine Funktion, um eine SVG-Datei in ein pygame Bild zu lesen - Farbkanal Ordnung und Skalierung einschließlich Korrektur:

def pygame_svg(svg_file, scale=1): 
    svg = rsvg.Handle(file=svg_file) 
    width, height= map(svg.get_property, ("width", "height")) 
    width*=scale; height*=scale 
    data = array.array('c', chr(0) * width * height * 4) 
    surface = cairo.ImageSurface.create_for_data(data, cairo.FORMAT_ARGB32, width, height, width*4) 
    ctx = cairo.Context(surface) 
    ctx.scale(scale, scale) 
    svg.render_cairo(ctx) 

    #seemingly, cairo and pygame expect channels in a different order... 
    #if colors/alpha are funny, mess with the next lines 
    import numpy 
    data= numpy.fromstring(data, dtype='uint8') 
    data.shape= (height, width, 4) 
    c= data.copy() 
    data[::,::,0]=c[::,::,1] 
    data[::,::,1]=c[::,::,0] 
    data[::,::,2]=c[::,::,3] 
    data[::,::,3]=c[::,::,2] 

    image = pygame.image.frombuffer(data.tostring(), (width, height),"ARGB") 
    return image