Question

Dans une application pyGame , je souhaite effectuer le rendu des widgets d'interface graphique sans résolution décrits dans SVG.

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

(J'aime le kit d'outils de l'interface graphique OCEMP , mais il semble dépendre de l'image pour son rendu.)

Était-ce utile?

La solution

Ceci est un exemple complet qui combine les conseils d’autres personnes ici. Il devrait rendre un fichier appelé test.svg à partir du répertoire en cours. 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

Autres conseils

La question est assez ancienne, mais 10 ans se sont écoulés et il existe une nouvelle possibilité qui fonctionne et ne nécessite plus librsvg . Il existe un enveloppe Cython 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 à installer car les dépendances sont difficiles à installer.

Vous pouvez utiliser Cairo (avec PyCairo), qui prend en charge le rendu des fichiers SVG. La page Web PyGame a un HOWTO pour être rendu dans un tampon avec Cairo et utilisé directement par celui-ci avec PyGame.

Je réalise que cela ne répond pas exactement à votre question, mais il existe une bibliothèque appelée Squirtle qui rendra les fichiers SVG en utilisant soit Pyglet, soit PyOpenGL.

pygamesvg semble faire ce que vous voulez (bien que je ne l'aie pas essayé).

Cairo ne peut pas rendre SVG immédiatement. Il semble que nous devions utiliser librsvg.

Je viens de trouver ces deux pages:

Quelque chose comme cela devrait probablement fonctionner (convertissez test.svg en 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")

Le dernier commentaire a été bloqué lorsque je l'ai exécuté car 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

Sur la base d'autres réponses, voici une fonction permettant de 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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top