2008-09-23 31 views
19

Trong ứng dụng pyGame, tôi muốn hiển thị các tiện ích GUI không có độ phân giải được mô tả trong SVG.Hiển thị SVG trong ứng dụng PyGame

Tôi có thể sử dụng công cụ và/hoặc thư viện nào để đạt được mục tiêu này?

(Tôi thích toolkit OCEMP GUI nhưng nó có vẻ là bitmap phụ thuộc cho dựng hình của nó)

+2

Có một câu trả lời khác nhau/thư viện áp dụng đến năm 2011 ? (Bởi vì nó đã được 3 năm). Tôi đã nhìn thấy squirtle được sử dụng để tải bản đồ được tạo ra trong ** inkscape **. – ninMonkey

+0

Squirtle vẫn không hỗ trợ nhiều SVG afaik và làm cho nó chạy với PyGame có lẽ cũng đòi hỏi một số công việc. Tôi đang tìm kiếm một thời gian dài để hỗ trợ bản vẽ SVG trong Windows và 64 Bit Python và tôi nghĩ rằng tôi phải từ bỏ. – Trilarion

Trả lời

15

Đây là ví dụ hoàn chỉnh kết hợp gợi ý của người khác tại đây. Nó sẽ hiển thị một tệp gọi là test.svg từ thư mục hiện tại. Nó đã được thử nghiệm trên 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 
+1

bất kỳ lý do cụ thể nào không sử dụng 'screen = pygame.display.set_mode ((WIDTH, HEIGHT))' trực tiếp thay vì tạo đối tượng 'window' này không bao giờ được sử dụng? – MestreLion

4

Bạn có thể sử dụng Cairo (với PyCairo), trong đó có hỗ trợ cho rendering SVGs. Trang web PyGame có HOWTO để hiển thị trong bộ đệm với Cairo và sử dụng bộ đệm đó trực tiếp với PyGame.

4

Tôi nhận thấy điều này không chính xác trả lời câu hỏi của bạn, nhưng có một thư viện được gọi là Squirtle sẽ hiển thị tệp SVG bằng Pyglet hoặc PyOpenGL.

2

Cairo không thể hiển thị SVG ra khỏi hộp. Có vẻ như chúng ta phải sử dụng librsvg.

Chỉ cần tìm thấy những hai trang:

Something như thế này nên có lẽ làm việc (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") 
3

pygamesvg dường như làm những gì bạn muốn (mặc dù tôi chưa thử).

+5

Mô-đun đó đã bị gỡ xuống. Cách tiếp cận cairo + rsvg được liệt kê dưới đây là các giải pháp tốt hơn nhiều. [từ chối trách nhiệm: Tôi nhanh chóng viết pygamesvg cách đây 3 năm] – PAG

1

Nhận xét cuối cùng bị lỗi khi tôi chạy vì svg.render_cairo() đang chờ bối cảnh cairo chứ không phải bề mặt cairo. Tôi đã tạo và thử nghiệm chức năng sau và dường như chạy tốt trên hệ thống của tôi.

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 
0

Dựa trên câu trả lời khác, đây là một chức năng để đọc một tập tin SVG thành một hình ảnh pygame - bao gồm chỉnh thứ tự kênh màu và mở rộng quy mô:

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