Pygame 응용 프로그램에서 SVG 렌더링
해결책
이것은 여기 다른 사람들의 힌트를 결합한 완전한 예입니다. 현재 디렉토리에서 test.svg라는 파일을 렌더링해야합니다. 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
다른 팁
질문은 꽤 오래되었지만 10 년이 지났고 효과가 있고 필요하지 않은 새로운 가능성이 있습니다. librsvg
더 이상. 거기 있습니다 NANOSVG 라이브러리 위의 Cython 래퍼 그리고 그것은 작동합니다 :
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)
Cairo/RSVG 솔루션은 종속성 때문에 작업하기에 너무 복잡한 것을 발견했습니다.
나는 이것이 당신의 질문에 정확히 대답하지 않는다는 것을 알고 있지만, 다람쥐 Pyglet 또는 Pyopengl을 사용하여 SVG 파일을 렌더링합니다.
pygamesvg 당신이 원하는 것을하는 것 같습니다 (내가 시도하지는 않았지만).
카이로는 SVG를 상자 밖으로 렌더링 할 수 없습니다. LIBSVG를 사용해야하는 것 같습니다.
방금 두 페이지를 찾았습니다.
이와 같은 것이 작동해야합니다 (렌더링 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")
svg.render_cairo ()가 카이로 표면이 아닌 카이로 컨텍스트를 기대하고 있기 때문에 마지막 주석이 추락했습니다. 다음 기능을 만들고 테스트했으며 시스템에서 잘 실행되는 것 같습니다.
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
다른 답변을 기반으로, 다음은 색상 채널 순서 수정 및 스케일링을 포함하여 SVG 파일을 Pygame 이미지로 읽는 기능입니다.
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