Domanda

In un'applicazione pyGame , vorrei rendere i widget GUI senza risoluzione descritti in SVG.

Quale strumento e / o libreria posso usare per raggiungere questo obiettivo?

(Mi piace il GUEM OCEMP ma sembra essere bitmap dipendente dal suo rendering)

È stato utile?

Soluzione

Questo è un esempio completo che combina suggerimenti di altre persone qui. Dovrebbe eseguire il rendering di un file chiamato test.svg dalla directory corrente. È stato testato su 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

Altri suggerimenti

La domanda è piuttosto vecchia ma sono passati 10 anni e ci sono nuove possibilità che funzionano e non richiedono più librsvg . C'è wrapper Cython su libreria nanosvg e funziona:

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)

Ho trovato la soluzione Cairo / rsvg troppo complicata per mettersi al lavoro a causa delle dipendenze piuttosto oscure da installare.

Puoi utilizzare Cairo (con PyCairo), che supporta il rendering di SVG. La pagina web di PyGame ha un HOWTO per il rendering in un buffer con un Cairo e per utilizzarlo direttamente con PyGame.

Mi rendo conto che questo non risponde esattamente alla tua domanda, ma c'è una libreria chiamata Squirtle che renderizzerà i file SVG usando Pyglet o PyOpenGL.

pygamesvg sembra fare quello che vuoi (anche se non l'ho provato).

Il Cairo non può rendere SVG pronto all'uso. Sembra che dobbiamo usare librsvg.

Ho appena trovato quelle due pagine:

Probabilmente qualcosa del genere dovrebbe funzionare (render test.svg in 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")

L'ultimo commento è andato in crash quando l'ho eseguito perché svg.render_cairo () si aspetta un contesto di cairo e non una superficie di cairo. Ho creato e testato la seguente funzione e sembra funzionare correttamente sul mio sistema.

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

Sulla base di altre risposte, ecco una funzione per leggere un file SVG in un'immagine pygame, inclusa la correzione dell'ordine dei canali di colore e il ridimensionamento:

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top