python - cairosvg install ubuntu
Convierte SVG a PNG en Python (9)
Escalado SVG y representación PNG
Usando pycairo y librsvg pude lograr escalar SVG y renderizar en un mapa de bits. Suponiendo que su SVG no sea exactamente 256x256 píxeles, el resultado deseado, puede leer en el SVG a un contexto de El Cairo utilizando rsvg y luego escalarlo y escribir en un archivo PNG.
main.py
import cairo
import rsvg
width = 256
height = 256
svg = rsvg.Handle(''cool.svg'')
unscaled_width = svg.props.width
unscaled_height = svg.props.height
svg_surface = cairo.SVGSurface(None, width, height)
svg_context = cairo.Context(svg_surface)
svg_context.save()
svg_context.scale(width/unscaled_width, height/unscaled_height)
svg.render_cairo(svg_context)
svg_context.restore()
svg_surface.write_to_png(''cool.png'')
Enlace RSVG C
Desde el sitio web de Cario con algunas modificaciones menores. También es un buen ejemplo de cómo llamar a una biblioteca C desde Python
from ctypes import CDLL, POINTER, Structure, byref, util
from ctypes import c_bool, c_byte, c_void_p, c_int, c_double, c_uint32, c_char_p
class _PycairoContext(Structure):
_fields_ = [("PyObject_HEAD", c_byte * object.__basicsize__),
("ctx", c_void_p),
("base", c_void_p)]
class _RsvgProps(Structure):
_fields_ = [("width", c_int), ("height", c_int),
("em", c_double), ("ex", c_double)]
class _GError(Structure):
_fields_ = [("domain", c_uint32), ("code", c_int), ("message", c_char_p)]
def _load_rsvg(rsvg_lib_path=None, gobject_lib_path=None):
if rsvg_lib_path is None:
rsvg_lib_path = util.find_library(''rsvg-2'')
if gobject_lib_path is None:
gobject_lib_path = util.find_library(''gobject-2.0'')
l = CDLL(rsvg_lib_path)
g = CDLL(gobject_lib_path)
g.g_type_init()
l.rsvg_handle_new_from_file.argtypes = [c_char_p, POINTER(POINTER(_GError))]
l.rsvg_handle_new_from_file.restype = c_void_p
l.rsvg_handle_render_cairo.argtypes = [c_void_p, c_void_p]
l.rsvg_handle_render_cairo.restype = c_bool
l.rsvg_handle_get_dimensions.argtypes = [c_void_p, POINTER(_RsvgProps)]
return l
_librsvg = _load_rsvg()
class Handle(object):
def __init__(self, path):
lib = _librsvg
err = POINTER(_GError)()
self.handle = lib.rsvg_handle_new_from_file(path.encode(), byref(err))
if self.handle is None:
gerr = err.contents
raise Exception(gerr.message)
self.props = _RsvgProps()
lib.rsvg_handle_get_dimensions(self.handle, byref(self.props))
def get_dimension_data(self):
svgDim = self.RsvgDimensionData()
_librsvg.rsvg_handle_get_dimensions(self.handle, byref(svgDim))
return (svgDim.width, svgDim.height)
def render_cairo(self, ctx):
"""Returns True is drawing succeeded."""
z = _PycairoContext.from_address(id(ctx))
return _librsvg.rsvg_handle_render_cairo(self.handle, z.ctx)
¿Cómo convierto un svg
a png
en Python? Estoy almacenando el svg
en una instancia de StringIO
. ¿Debería usar la biblioteca pyCairo? ¿Cómo escribo ese código?
Aquí hay un ejemplo de Python de extremo a extremo.
Tenga en cuenta que suprime ciertos resultados crudos que Inkscape escribe en la consola (específicamente, stderr y stdout) durante el funcionamiento normal sin errores. La salida se captura en dos variables de cadena, out
y err
.
import subprocess # May want to use subprocess32 instead
cmd_list = [ ''/full/path/to/inkscape'', ''-z'',
''--export-png'', ''/path/to/output.png'',
''--export-width'', 100,
''--export-height'', 100,
''/path/to/input.svg'' ]
# Invoke the command. Divert output that normally goes to stdout or stderr.
p = subprocess.Popen( cmd_list, stdout=subprocess.PIPE, stderr=subprocess.PIPE )
# Below, < out > and < err > are strings or < None >, derived from stdout and stderr.
out, err = p.communicate() # Waits for process to terminate
# Maybe do something with stdout output that is in < out >
# Maybe do something with stderr output that is in < err >
if p.returncode:
raise Exception( ''Inkscape error: '' + (err or ''?'') )
Por ejemplo, cuando ejecuté un trabajo en particular en mi sistema Mac OS, terminé siendo:
Background RRGGBBAA: ffffff00
Area 0:0:339:339 exported to 100 x 100 pixels (72.4584 dpi)
Bitmap saved as: /path/to/output.png
(El archivo svg de entrada tenía un tamaño de 339 por 339 píxeles).
Esto es lo que hice usando cairosvg :
from cairosvg import svg2png
svg_code = """
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"/>
<line x1="12" y1="8" x2="12" y2="12"/>
<line x1="12" y1="16" x2="12" y2="16"/>
</svg>
"""
svg2png(bytestring=svg_code,write_to=''output.png'')
¡Y funciona como un encanto!
Ver más: documento de cairosvg
Estoy usando Wand-py (una implementación de Wand wrapper alrededor de ImageMagick) para importar algunos SVG bastante avanzados y ¡hasta ahora hemos visto excelentes resultados! Este es todo el código que toma:
with wand.image.Image( blob=svg_file.read(), format="svg" ) as image:
png_image = image.make_blob("png")
Acabo de descubrir esto hoy, y sentí que valía la pena compartirlo con cualquier otra persona que pudiera regatear esta respuesta, ya que ha pasado un tiempo desde que se respondieron la mayoría de estas preguntas.
NOTA: Técnicamente en las pruebas descubrí que ni siquiera tiene que pasar el parámetro de formato para ImageMagick, por lo que with wand.image.Image( blob=svg_file.read() ) as image:
era todo lo que realmente se necesitaba.
EDITAR: A partir de un intento de edición por qris, aquí hay un código útil que le permite usar ImageMagick con un SVG que tiene un fondo transparente:
from wand.api import library
import wand.color
import wand.image
with wand.image.Image() as image:
with wand.color.Color(''transparent'') as background_color:
library.MagickSetBackgroundColor(image.wand,
background_color.resource)
image.read(blob=svg_file.read(), format="svg")
png_image = image.make_blob("png32")
with open(output_filename, "wb") as out:
out.write(png_image)
Instala Inkscape y llámalo como línea de comando:
${INKSCAPE_PATH} -z -f ${source_svg} -w ${width} -j -e ${dest_png}
También puede ajustar el área rectangular específica solo usando el parámetro -j
, por ejemplo, la coordenada "0: 125: 451: 217"
${INKSCAPE_PATH} -z -f ${source_svg} -w ${width} -j -a ${coordinates} -e ${dest_png}
Si desea mostrar solo un objeto en el archivo SVG, puede especificar el parámetro -i
con el ID del objeto que ha configurado en el SVG. Oculta todo lo demás.
${INKSCAPE_PATH} -z -f ${source_svg} -w ${width} -i ${object} -j -a ${coordinates} -e ${dest_png}
La respuesta es " pyrsvg " - un enlace de Python para librsvg .
Existe un paquete Ubuntu python-rsvg que lo proporciona. Buscar su nombre en Google es pobre porque su código fuente parece estar contenido dentro del repositorio GIT del proyecto Gnome "gnome-python-desktop".
Hice un "mundo de hola" minimalista que convierte a SVG en una superficie de cairo y lo escribe en el disco:
import cairo
import rsvg
img = cairo.ImageSurface(cairo.FORMAT_ARGB32, 640,480)
ctx = cairo.Context(img)
## handle = rsvg.Handle(<svg filename>)
# or, for in memory SVG data:
handle= rsvg.Handle(None, str(<svg data>))
handle.render_cairo(ctx)
img.write_to_png("svg.png")
Actualización : a partir de 2014, el paquete necesario para la distribución de Fedora Linux es: gnome-python2-rsvg
. El listado de fragmentos anterior todavía funciona tal como está.
Otra solución que acabo de encontrar aquí ¿Cómo renderizar un SVG escalado a una QImage?
from PySide.QtSvg import *
from PySide.QtGui import *
def convertSvgToPng(svgFilepath,pngFilepath,width):
r=QSvgRenderer(svgFilepath)
height=r.defaultSize().height()*width/r.defaultSize().width()
i=QImage(width,height,QImage.Format_ARGB32)
p=QPainter(i)
r.render(p)
i.save(pngFilepath)
p.end()
PySide se instala fácilmente desde un paquete binario en Windows (y lo uso para otras cosas, así que es fácil para mí).
Sin embargo, noté algunos problemas al convertir banderas de países de Wikimedia, por lo que quizás no sea el analizador / procesador de svg más robusto.
Pruebe esto: cairosvg
El sitio dice:
CairoSVG está escrito en python puro y solo depende de Pycairo. Se sabe que funciona en Python 2.6 y 2.7.
Actualización 25 de noviembre de 2016 :
2.0.0 es una nueva versión principal, su registro de cambios incluye:
- Soporte de Drop Python 2
Una pequeña extensión sobre la respuesta de jsbueno:
#!/usr/bin/env python
import cairo
import rsvg
from xml.dom import minidom
def convert_svg_to_png(svg_file, output_file):
# Get the svg files content
with open(svg_file) as f:
svg_data = f.read()
# Get the width / height inside of the SVG
doc = minidom.parse(svg_file)
width = int([path.getAttribute(''width'') for path
in doc.getElementsByTagName(''svg'')][0])
height = int([path.getAttribute(''height'') for path
in doc.getElementsByTagName(''svg'')][0])
doc.unlink()
# create the png
img = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
ctx = cairo.Context(img)
handler = rsvg.Handle(None, str(svg_data))
handler.render_cairo(ctx)
img.write_to_png(output_file)
if __name__ == ''__main__'':
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument("-f", "--file", dest="svg_file",
help="SVG input file", metavar="FILE")
parser.add_argument("-o", "--output", dest="output", default="svg.png",
help="PNG output file", metavar="FILE")
args = parser.parse_args()
convert_svg_to_png(args.svg_file, args.output)