SVG rendering in a PyGame application

2019-01-16 13:14发布

In a pyGame application, I would like to render resolution-free GUI widgets described in SVG.

What tool and/or library can I use to reach this goal ?

(I like the OCEMP GUI toolkit but it seems to be bitmap dependent for its rendering)

8条回答
乱世女痞
2楼-- · 2019-01-16 13:25

Cairo cannot render SVG out of the box. It seems we have to use librsvg.

Just found those two pages:

Something like this should probably work (render test.svg to 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")
查看更多
Root(大扎)
3楼-- · 2019-01-16 13:27

The last comment crashed when I ran it because svg.render_cairo() is expecting a cairo context and not a cairo surface. I created and tested the following function and it seems to run fine on my system.

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
查看更多
Anthone
4楼-- · 2019-01-16 13:34

pygamesvg seems to do what you want (though I haven't tried it).

查看更多
疯言疯语
5楼-- · 2019-01-16 13:35

I realise this doesn't exactly answer your question, but there's a library called Squirtle that will render SVG files using either Pyglet or PyOpenGL.

查看更多
够拽才男人
6楼-- · 2019-01-16 13:37

You can use Cairo (with PyCairo), which has support for rendering SVGs. The PyGame webpage has a HOWTO for rendering into a buffer with a Cairo, and using that buffer directly with PyGame.

查看更多
我想做一个坏孩纸
7楼-- · 2019-01-16 13:39

Based on other answers, here's a function to read a SVG file into a pygame image - including correcting color channel order and scaling:

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
查看更多
登录 后发表回答