¿Cómo puedo convertir de un svg a png, en Python? Yo soy el almacenamiento de la svg en una instancia de StringIO. Debo usar el pyCairo de la biblioteca? ¿Cómo puedo escribir el código?

  • Posiblemente un duplicado de stackoverflow.com/questions/2932408/…
  • Que el hilo de la izquierda el problema sin resolver. El aceptó respuesta vino de la persona que pregunta que estaba compartiendo su código de error intento. La otra respuesta sugerida ImageMagick, pero un comentarista dijo ImageMagick hace «un horrible trabajo de interpretación de SVG.» No quiero que mi png para buscar horrible así que me estoy re-haciendo la pregunta.
  • Trate de cairographics.org/cookbook/librsvgpython
  • Los ejemplos en ese enlace son específicos para Win32. Estoy ejecutando linux.
  • Echa un vistazo a este entrada de blog, que parece que podría ser lo que usted necesita.
InformationsquelleAutor ram1 | 2011-07-05

9 Comentarios

  1. 55

    La respuesta es «pyrsvg» – una pasarela de Python para librsvg.

    Hay un Ubuntu python-rsvg paquete proporciona. Buscar en Google por su nombre es pobre porque su código fuente parece estar contenida dentro de la «gnome-python-escritorio Gnome proyecto repositorio GIT.

    Hice un minimalista «hola mundo» que hace SVG a el cairo
    la superficie y los 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 necesaria para la distribución Fedora Linux es: gnome-python2-rsvg. El fragmento anterior listado de todavía funciona como-es.

    • Genial, funciona muy bien. Pero hay una manera de dejar cairo determinar la ALTURA y la ANCHURA de la imagen en su propia? He mirado en la *.svg archivo, extraer la ALTURA y la ANCHURA de allí, pero es tanto el conjunto a 100%. Por supuesto, puedo mirar en las propiedades de la imagen, pero ya que este es sólo un paso en el procesamiento de la imagen esto no es lo que quiero.
    • Si el «ancho» y «altura» de sus archivos están configurados al 100%, no hay magia, el Cairo o rsvg puede hacer para adivinar el tamaño: tales archivos SVG quedaron independientes del tamaño por el creador de software (por persona). Los alrededores de código HTML para importar el archivo SVG se presentaría el tamaño físico. Sin embargo, el «Mango» objeto de rsvg tienen un .get_dimension_data() método que funcionó para mi archivo de ejemplo (un bien comportado SVG) – darle una oportunidad.
    • a partir de 2014, para ubuntu, se puede utilizar: apt-get install python-rsvg
    • Hay un comando rápido para agregar un fondo blanco a la imagen si su fondo es transparente?
    • Yo uso Windows 8.1 y python 2.7.11 ¿Cómo puedo instalar el cairo y rsvg y hacer que funcione. Yo estaba luchando para hacer este trabajo. Por CIERTO +1 para su explicación detallada.
    • Creo que es mejor que pregunte esto como una cuestión separada en otro foro de Intercambio de la Pila – (no tengo idea). Probablemente superuser.com es su mejor opción. Acabo de poner un enlace a esta pregunta en su pregunta hay que darle un poco más de contexto para quien sepa cómo responder a esto.
    • He utilizado poco antigua versión de tubo para hacerlo. Desde la versión más reciente tuvo algunos problemas
    • tiene constantes (640, 480) en el código…
    • El pyrsvg enlace está muerto.
    • fijo a una ubicación de trabajo. gracias.

  2. 58

    Aquí es lo que yo hice con 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: cairosvg documento

    • Hola. ¿Sabes cómo puedo hacer lo mismo pero sin necesidad de escribir a un archivo? Necesito empujar png contenido al navegador desde un servidor web, de modo que el usuario puede descargar la imagen. Guardar el archivo png no es una opción válida en nuestro proyecto, por eso necesito de esa manera. Gracias
    • He estado haciendo esto por mí mismo. Básicamente depende de qué herramientas o marcos u tiene a la mano cuando el manejo de sus peticiones web, pero no importa lo que sea, la idea básica es que svg2png toma en un stream objeto en el write_to parámetro, y este puede ser su Respuesta HTTP objeto (que en la mayoría de los marcos es un archivo de objeto similar) o algún otro stream, que sirven para el navegador con la Content-Disposition encabezado. ver aquí: stackoverflow.com/questions/1012437/…
    • Sí, gracias, yo era capaz ahora de hacer el trabajo.
    • Para aquellos que las experiencias de los problemas con el código, como me fue: 1). bytestring acepta bytes, para convertir la cadena en primer lugar con bytestring=bytes(svg,'UTF-8') 2). archivo en modo binario, por lo que open('output.png','wb')
    • El equivalente de @SerjZaharchenko la respuesta para Python 2.x es bytestring=svg.encode('utf-8')
    • Si desea establecer la anchura y la altura con cairosvg, el SVG debe tener un viewbox. Usted puede agregar uno con scour.
    • cairosvg sólo soporta Python 3.4+. De que se han caído de Python 2
    • Tenga en cuenta que para python 2.7 necesita pip install cairosvg==1.0.22 , de lo contrario tendrás problemas de instalación.
    • No hay un svg2png para mí, he tenido que utilizar cairosvg.surface.PNGSurface.convert(svg_str, write_to='output.png').

  3. 39

    Instalar Inkscape y llámelo como de la línea de comandos:

    ${INKSCAPE_PATH} -z -f ${source_svg} -w ${width} -j -e ${dest_png}

    También puede complemento específico área rectangular que sólo mediante el parámetro -j, por ejemplo, coordinar «0:125:451:217»

    ${INKSCAPE_PATH} -z -f ${source_svg} -w ${width} -j -a ${coordinates} -e ${dest_png}

    Si desea mostrar sólo un objeto en el archivo SVG, puede especificar el parámetro -i con el identificador de objeto que tiene el programa de instalación en el archivo SVG. Oculta todo lo demás.

    ${INKSCAPE_PATH} -z -f ${source_svg} -w ${width} -i ${object} -j -a ${coordinates} -e ${dest_png}
    • +1 porque esto también es muy útil para la programación en shell script. Consulte inkscape.org/doc/inkscape-man.html por completo docs en Inkscape línea de comandos.
    • Gracias, esta era la forma más fácil que he encontrado para hacer esto. En Windows, para hacerlo de modo que usted no tiene que escribir la ruta completa a Inkscape cada vez, usted puede añadir a tu Ruta en las Variables Ambientales.
    • Esta no es una respuesta. Es una solución. OP pidió una solución Python.
  4. 26

    Estoy usando Varita-py (una implementación de la Vara a la envoltura alrededor de ImageMagick) para importar algunos bastante avanzados SVGs y hasta el momento han visto grandes resultados! Este es todo el código que se necesita:

        with wand.image.Image( blob=svg_file.read(), format="svg" ) as image:
            png_image = image.make_blob("png")

    Acabo de descubrir este hoy, y sentía que valía la pena compartir para cualquier otra persona que podría rezagarse a través de esta respuesta como que ha sido un tiempo desde que la mayoría de estas preguntas fueron respondidas.

    NOTA: Técnicamente en las pruebas he descubierto usted incluso no tiene que aprobar en el parámetro de formato para ImageMagick, así with wand.image.Image( blob=svg_file.read() ) as image: era todo lo que era realmente necesario.

    EDIT: a partir De un intento de editar por qris, he aquí algunos consejos de código que te 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)
    • wow esta es realmente la solución más simple. Una bonita =)
    • Varita trabajado un mucho mejor que el Cairo para mi Png.
    • Gracias @qris – añadió su fondo transparente SVG código de representación a mi respuesta así.
    • este se ve bien, pero ¿dónde se coloca el svg del nombre de archivo??
    • Obtengo el error image.read(blob=svg_file.read(), format="svg") NameError: name 'svg_file' is not defined
    • svg_file se supone que es un «archivo» de objetos en este ejemplo, la configuración de svg_file sería algo como: svg_file = File.open(file_name, "r")
    • Gracias, la cairo y rsvg ‘aceptado’ método no funciona para mi PDF. pip install wand y el fragmento hizo el truco 😉
    • Si usted tiene un svg str, a continuación, usted primero tiene que codificar en binario como este: svg_blob = svg_str.encode('utf-8'). Ahora usted puede utilizar el método anterior mediante la sustitución de blob=svg_file.read() con blob=svg_blob.

  5. 11

    Intente esto: http://cairosvg.org/

    El sitio dice:

    CairoSVG está escrito en python puro y sólo depende de Pycairo. Es
    conocido por trabajar en Python 2.6 y 2.7.

    Actualización 25 de noviembre de 2016:

    2.0.0 es una nueva versión principal, su lista de cambios incluye:

    • Caída de Python 2 apoyo
    • Hay dos problemas con esto, por desgracia. En primer lugar, no maneje el <clipPath><rect ... /></clipPath>. Segundo, no se toma la -d (DPI) de la opción.
    • favor de enviar informes de errores / peticiones de características en el CairoSVG tracker!
    • Puede usted hacerlo por favor? Estoy demasiado ocupado y voy a estar en los próximos 1-2 meses.
    • en realidad la -d / –opción dpi ha estado allí por un tiempo ahora, y me han dicho que el apoyo a la <clippath> se añadió un par de semanas atrás en la versión git.
    • bueno! Gracias! 🙂
    • He tenido algunos problemas con los svg que el uso de opacidad. En mi caso Varita-py demostró ser una mejor solución.

  6. 6

    Otra solución que he encontrado aquí Cómo hacer un modelo a escala de SVG a un 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 de un paquete binario en Windows (y yo lo uso para otras cosas, así que es fácil para mí).

    Sin embargo, me di cuenta de un par de problemas al convertir las banderas de Wikimedia, así que tal vez no el más robusto svg analizador/representador.

  7. 4

    Un poco de extensión en 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)
    • He utilizado el svg anchura y la altura de la extracción. No estoy seguro sobre el estándar svg, pero en algunos de mis archivos svg la anchura o la altura, que fueron seguidas por una cadena numérica como ‘mm’ o ‘px’ (ex: ‘250mm’). El int(‘250 mm’) lanza una excepción y he tenido que hacer algunos ajustes adicionales.
  8. 1

    SVG escala y PNG representación

    Utilizando pycairo y librsvg yo era capaz de lograr SVG escala y la representación en un mapa de bits. Suponiendo que el archivo SVG no es exactamente de 256×256 píxeles, la salida deseada, se puede leer en el SVG a el Cairo contexto rsvg y, a continuación, ajuste la escala 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')

    RSVG C de unión

    Desde el Cario sitio web con alguna modificación menor. También un buen ejemplo de cómo llamar a un C-biblioteca de 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)
    • Gracias por esto, demostró ser muy útil en un proyecto de la mina. Aunque Handle.get_dimension_data no funciona para mí. He tenido que cambiar con una simple captura de self.props.width y self.props.height. Probé por primera vez la definición de la RsvgDimensionData Estructura como se describe en el sitio web de el cairo, pero sin éxito.
    • Estoy intentando usar esta en un proyecto de la mina. ¿Cómo puedo obtener los archivos dll necesarios?
  9. -2

    Aquí es un enfoque en el que Inkscape es llamado por Python.

    Nota que suprime algunos crufty de salida que Inkscape se escribe en la consola (en concreto, stderr y stdout) durante el funcionamiento normal libre de errores de operación. La salida es capturado 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 se ejecuta un trabajo en particular en mi sistema operativo de Mac, out 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

    (La entrada de archivo svg, tenía un tamaño de 339 por 339 píxeles).

    • No es de extremo a extremo de Python si usted confía en Inkscape.
    • La primera línea ha sido modificado para superar su objeción. Pero, por supuesto, incluso un «puro» de Python solución se basa en elementos fuera del núcleo del lenguaje, y es en última instancia que se ejecute con el lenguaje de máquina, así que tal vez no existe tal cosa como de un extremo a nada!

Dejar respuesta

Please enter your comment!
Please enter your name here