Rendu SVG dans une application PyGame

Dans une applicationpyGame , je voudrais rendre les widgets GUI sans résolution décrits en SVG.

Quel outil et/ou bibliothèque puis-je utiliser pour atteindre cet objectif ?

(j'aime la boîte à outils OCEMP GUI mais elle semble dépendre du bitmap pour son rendu)

22
demandé sur Pierre-Jean Coudert 2008-09-23 16:13:14

8 réponses

Ceci est un exemple complet qui combine des conseils d'autres personnes ici. Il devrait rendre un fichier appelé test.svg à partir du répertoire courant. Il a été testé sur Ubuntu 10.10, Python-cairo 1.8.8, Python-pygame 1.9.1, Python-rsvg 2.30.0.

#!/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
16
répondu Johan Dahlin 2011-08-14 05:11:29

Vous pouvez utiliser Cairo (avec PyCairo), qui prend en charge le rendu des SVG. La page Web PyGame a un HOWTO pour le rendu dans un tampon avec un Cairo, et l'utilisation de ce tampon directement avec PyGame.

5
répondu Torsten Marek 2008-09-23 12:52:32

Je me rends compte que cela ne répond pas exactement à votre question, mais il y a une bibliothèque appelée Squirtle qui rendra les fichiers SVG en utilisant Pyglet ou PyOpenGL.

4
répondu Alec Thomas 2008-09-23 15:16:51

Pygamesvg semble faire ce que vous voulez (bien que je n'ai pas essayé).

3
répondu Dickon Reed 2008-09-30 08:24:24

Cairo ne peut pas rendre SVG hors de la boîte. Il semble que nous devons utiliser librsvg.

Vient de trouver ces deux pages:

Quelque chose comme ça devrait probablement fonctionner (render test.svg à test.png):

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")
2
répondu Pierre-Jean Coudert 2008-09-23 15:17:06

Le dernier commentaire s'est écrasé quand je l'ai couru parce que svg.render_cairo () attend un contexte cairo et non une surface cairo. J'ai créé et testé la fonction suivante et elle semble fonctionner correctement sur mon système.

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
1
répondu Dave 2011-02-09 21:06:29

La question est assez ancienne mais 10 ans ont passé et il y a une nouvelle possibilité qui fonctionne et ne nécessite plus librsvg. Il y a Cython wrapper sur la bibliothèque nanosvg et cela fonctionne:

from svg import Parser, Rasterizer


def load_svg(filename, surface, position, size=None):
    if size is None:
        w = surface.get_width()
        h = surface.get_height()
    else:
        w, h = size
    svg = Parser.parse_file(filename)
    rast = Rasterizer()
    buff = rast.rasterize(svg, w, h)
    image = pygame.image.frombuffer(buff, (w, h), 'ARGB')
    surface.blit(image, position)

J'ai trouvé la solution Cairo/rsvg trop compliquée pour se mettre au travail car les dépendances sont assez obscures à installer.

1
répondu zgoda 2018-06-27 08:39:54

Basé sur d'autres réponses, voici une fonction pour lire un fichier SVG dans une image pygame - y compris la correction de l'ordre des canaux de couleur et la mise à l'échelle:

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
0
répondu goncalopp 2014-10-04 00:43:37