¿Cómo convierto un svga pngen Python? Estoy almacenando el svgen una instancia de StringIO. ¿Debo usar la biblioteca de PyCairo? ¿Cómo escribo ese código?
Ese hilo dejó el problema sin resolver. La respuesta aceptada provino del autor de la pregunta que estaba compartiendo su intento fallido de código. La otra respuesta sugirió ImageMagick, pero un comentarista dijo que ImageMagick hace "un trabajo horrible al interpretar SVG". No quiero que mis png se vean horribles, así que vuelvo a hacer la pregunta.
Los ejemplos de ese enlace son específicos de Win32. Estoy ejecutando linux.
ram1
Eche un vistazo a esta publicación de blog, parece que podría ser lo que necesita.
giodamelio
Respuestas:
60
La respuesta es " pyrsvg ", un enlace de Python para librsvg .
Hay un paquete de Ubuntu python-rsvg que lo proporciona. Buscar en Google su nombre es pobre porque su código fuente parece estar contenido dentro del repositorio GIT del proyecto Gnome "gnome-python-desktop".
Hice un "hola mundo" minimalista que renderiza SVG en una superficie de El Cairo y lo escribe en el disco:
Actualización : a partir de 2014 el paquete necesario para la distribución de Fedora Linux es: gnome-python2-rsvg. La lista de fragmentos anterior todavía funciona como está.
Genial, funciona muy bien. Pero, ¿hay alguna manera de permitir cairodeterminar la ALTURA y ANCHO de la imagen por sí sola? He examinado el *.svgarchivo para extraer el ALTO y el ANCHO de allí, pero ambos están configurados en 100%. Por supuesto, puedo analizar las propiedades de la imagen, pero como este es solo un paso en el procesamiento de la imagen, no es lo que quiero.
quapka
1
Si el "ancho" y la "altura" de sus archivos están configurados al 100%, no hay magia que Cairo o rsvg puedan hacer para adivinar el tamaño: el software creador (/ persona) dejó el tamaño de estos archivos SVG independientemente del tamaño. El código HTML circundante para importar el archivo SVG proporcionaría el tamaño físico. Sin embargo, el objeto "Handle" de rsvg tiene un .get_dimension_data()método que funcionó para mi archivo de ejemplo (un SVG con buen comportamiento) - pruébalo.
jsbueno
1
a partir de 2014, para ubuntu, puede usar: apt-get install python-rsvg
t1m0
1
¿Existe un comando rápido para agregar un fondo blanco a la imagen si su fondo actual es transparente?
fiatjaf
@jsbueno Yo uso Windows 8.1 y python 2.7.11 ¿Cómo puedo instalar cairo y rsvg y hacer que funcione? Estaba luchando para que esto funcionara. Por cierto +1 para su explicación detallada.
Hola. ¿Sabes cómo puedo hacer lo mismo pero sin escribir en un archivo? Necesito enviar contenido png al navegador desde un servidor web, para que el usuario pueda descargar la imagen. Guardar el archivo png no es una opción válida en nuestro proyecto, por eso lo necesito de esa manera. Gracias
estemendoza
4
Yo mismo he estado haciendo esto. Básicamente depende de las herramientas o marcos que tenga a mano al manejar sus solicitudes web, pero no importa cuál sea, la idea básica es que svg2pngtome un streamobjeto en el write_toparámetro, y este puede ser su objeto de respuesta HTTP (que en la mayoría de los frameworks es un objeto similar a un archivo) o alguna otra secuencia, que luego sirve al navegador usando el Content-Dispositionencabezado. ver aquí: stackoverflow.com/questions/1012437/…
nemesisfixx
4
Para aquellos que experimentan los problemas con ese código, como yo: 1). bytestringacepta bytes, así que convierta la cadena primero con bytestring=bytes(svg,'UTF-8') 2). el modo de archivo debe ser binario, entoncesopen('output.png','wb')
Serj Zaharchenko
3
cairosvg solo admite Python 3.4+. Han eliminado el soporte de Python 2
Marlon Abeykoon
1
No había un svg2pngpara mí, tenía que usarlo cairosvg.surface.PNGSurface.convert(svg_str, write_to='output.png').
También puede ajustar un área rectangular específica solo 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 solo un objeto en el archivo SVG, puede especificar el parámetro -icon la identificación 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}
+1 porque esto también es extremadamente útil para scripts de shell. Consulte inkscape.org/doc/inkscape-man.html para obtener documentos completos sobre la línea de comandos de Inkscape.
Prime
Gracias, esta fue la forma más fácil que encontré para hacer esto. En Windows, para que no tenga que escribir la ruta completa a Inkscape cada vez, puede agregarla a su Ruta en Variables ambientales .
Alex S
3
Ésta no es una respuesta. Es una solución. OP pidió una solución de Python.
lamino
31
Estoy usando Wand-py (una implementación de la envoltura de Wand alrededor de ImageMagick) para importar algunos SVG bastante avanzados y hasta ahora he visto excelentes 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 esto hoy, y sentí que valía la pena compartirlo con cualquier otra persona que pudiera encontrar 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:
Recibo el error image.read(blob=svg_file.read(), format="svg") NameError: name 'svg_file' is not defined
adrienlucca.wordpress.com
2
svg_filese asume que es un objeto "archivo" en este ejemplo, la configuración svg_filese vería así:svg_file = File.open(file_name, "r")
streetlogics
2
Gracias, el método cairoy rsvg'aceptado' no funcionó para mi PDF. pip install wandy tu fragmento funcionó;)
nmz787
5
Si usted tiene una SVG strentonces primero tiene que codifican en binario de la siguiente manera: svg_blob = svg_str.encode('utf-8'). Ahora puede usar el método anterior reemplazando blob=svg_file.read()con blob=svg_blob.
Hay dos problemas con esto, desafortunadamente. Primero, no maneja el <clipPath><rect ... /></clipPath>. En segundo lugar, no acepta la opción -d (DPI).
@Simon, ¿puedes hacerlo por favor? Estoy demasiado ocupado y lo estaré en los próximos 1-2 meses.
Ray
2
@Ray, en realidad, la opción -d / --dpi ha estado ahí por un tiempo, y me dijeron que el soporte para <clippath> se agregó hace unas semanas en la versión de git.
PySide se instala fácilmente desde un paquete binario en Windows (y lo uso para otras cosas, por lo que es fácil para mí).
Sin embargo, noté algunos problemas al convertir las banderas de países de Wikimedia, por lo que quizás no sea el analizador / renderizador svg más robusto.
Usé la extracción de ancho y alto de svg. No estoy seguro sobre el estándar svg, pero en algunos de mis archivos svg, el ancho o la altura fueron seguidos por una cadena no numérica como 'mm' o 'px' (por ejemplo: '250 mm'). El int ('250 mm') arroja una excepción y tuve que hacer algunos ajustes adicionales.
WigglyWorld
3
No encontré ninguna de las respuestas satisfactoria. Todas las bibliotecas mencionadas tienen algún problema o el otro, como Cairo, que deja de admitir python 3.6 (¡dejaron de admitir Python 2 hace unos 3 años!). Además, instalar las bibliotecas mencionadas en Mac fue una molestia.
Finalmente, encontré que la mejor solución fue svglib + reportlab . ¡Ambos instalados sin problemas usando pip y la primera llamada para convertir de svg a png funcionaron maravillosamente! Muy contento con la solución.
Solo 2 comandos hacen el truco:
from svglib.svglib import svg2rlg
from reportlab.graphics import renderPM
drawing = svg2rlg("my.svg")
renderPM.drawToFile(drawing,"my.png", fmt="PNG")
Usando pycairo y librsvg pude lograr el escalado SVG y el renderizado en un mapa de bits. Suponiendo que su SVG no es exactamente de 256x256 píxeles, la salida deseada, puede leer en el SVG en un contexto de El Cairo usando rsvg y luego escalarlo y escribir en un PNG.
Gracias por esto, resultó muy útil en un proyecto mío. Aunque Handle.get_dimension_datano funcionó para mí. Tuve que reemplazarlo con una simple búsqueda de self.props.widthy self.props.height. Primero intenté definir la RsvgDimensionDataEstructura como se describe en el sitio web de El Cairo, pero sin éxito.
JeanOlivier
Estoy tratando de usar esto en un proyecto mío. ¿Cómo obtengo los archivos dll necesarios?
Andoo
0
Aquí hay un enfoque en el que Python llama a Inkscape.
Tenga en cuenta que suprime cierta salida cruda 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 outy 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:raiseException('Inkscape error: '+(err or'?'))
Por ejemplo, al ejecutar un trabajo en particular en mi sistema Mac OS, outterminó siendo:
Background RRGGBBAA: ffffff00
Area0: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).
No es Python de un extremo a otro si confías en Inkscape.
Joel
1
@Joel: La primera línea ha sido modificada para superar su objeción. Pero, por supuesto, incluso una solución de Python "pura" se basa en elementos fuera del lenguaje central y, en última instancia, se ejecuta con lenguaje de máquina, por lo que tal vez no exista nada de extremo a extremo.
Iron Pillow
0
En realidad, no quería depender de nada más que de Python (Cairo, Ink ..., etc.). Mis requisitos debían ser lo más simples posible, a lo sumo, un simple pip install "savior"sería suficiente, por eso ninguno de los anteriores lo hizo ' me queda bien.
Respuestas:
La respuesta es " pyrsvg ", un enlace de Python para librsvg .
Hay un paquete de Ubuntu python-rsvg que lo proporciona. Buscar en Google su nombre es pobre porque su código fuente parece estar contenido dentro del repositorio GIT del proyecto Gnome "gnome-python-desktop".
Hice un "hola mundo" minimalista que renderiza SVG en una superficie de El Cairo y lo escribe en el disco:
Actualización : a partir de 2014 el paquete necesario para la distribución de Fedora Linux es:
gnome-python2-rsvg
. La lista de fragmentos anterior todavía funciona como está.fuente
cairo
determinar la ALTURA y ANCHO de la imagen por sí sola? He examinado el*.svg
archivo para extraer el ALTO y el ANCHO de allí, pero ambos están configurados en100%
. Por supuesto, puedo analizar las propiedades de la imagen, pero como este es solo un paso en el procesamiento de la imagen, no es lo que quiero..get_dimension_data()
método que funcionó para mi archivo de ejemplo (un SVG con buen comportamiento) - pruébalo.Esto es lo que hice usando cairosvg :
¡Y funciona como un encanto!
Ver más: documento cairosvg
fuente
svg2png
tome unstream
objeto en elwrite_to
parámetro, y este puede ser su objeto de respuesta HTTP (que en la mayoría de los frameworks es un objeto similar a un archivo) o alguna otra secuencia, que luego sirve al navegador usando elContent-Disposition
encabezado. ver aquí: stackoverflow.com/questions/1012437/…bytestring
acepta bytes, así que convierta la cadena primero conbytestring=bytes(svg,'UTF-8')
2). el modo de archivo debe ser binario, entoncesopen('output.png','wb')
svg2png
para mí, tenía que usarlocairosvg.surface.PNGSurface.convert(svg_str, write_to='output.png')
.Instale Inkscape y llámelo como línea de comando:
También puede ajustar un área rectangular específica solo mediante el parámetro
-j
, por ejemplo, coordinar "0: 125: 451: 217"Si desea mostrar solo un objeto en el archivo SVG, puede especificar el parámetro
-i
con la identificación del objeto que ha configurado en el SVG. Oculta todo lo demás.fuente
Estoy usando Wand-py (una implementación de la envoltura de Wand alrededor de ImageMagick) para importar algunos SVG bastante avanzados y hasta ahora he visto excelentes resultados. Este es todo el código que se necesita:
Acabo de descubrir esto hoy, y sentí que valía la pena compartirlo con cualquier otra persona que pudiera encontrar 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:
fuente
image.read(blob=svg_file.read(), format="svg") NameError: name 'svg_file' is not defined
svg_file
se asume que es un objeto "archivo" en este ejemplo, la configuraciónsvg_file
se vería así:svg_file = File.open(file_name, "r")
cairo
yrsvg
'aceptado' no funcionó para mi PDF.pip install wand
y tu fragmento funcionó;)str
entonces primero tiene que codifican en binario de la siguiente manera:svg_blob = svg_str.encode('utf-8')
. Ahora puede usar el método anterior reemplazandoblob=svg_file.read()
conblob=svg_blob
.Prueba esto: http://cairosvg.org/
El sitio dice:
Actualización 25 de noviembre de 2016 :
fuente
<clipPath><rect ... /></clipPath>
. En segundo lugar, no acepta la opción -d (DPI).Otra solución que acabo de encontrar aquí ¿Cómo renderizar un SVG escalado a una QImage?
PySide se instala fácilmente desde un paquete binario en Windows (y lo uso para otras cosas, por lo que es fácil para mí).
Sin embargo, noté algunos problemas al convertir las banderas de países de Wikimedia, por lo que quizás no sea el analizador / renderizador svg más robusto.
fuente
Una pequeña extensión sobre la respuesta de jsbueno:
fuente
No encontré ninguna de las respuestas satisfactoria. Todas las bibliotecas mencionadas tienen algún problema o el otro, como Cairo, que deja de admitir python 3.6 (¡dejaron de admitir Python 2 hace unos 3 años!). Además, instalar las bibliotecas mencionadas en Mac fue una molestia.
Finalmente, encontré que la mejor solución fue svglib + reportlab . ¡Ambos instalados sin problemas usando pip y la primera llamada para convertir de svg a png funcionaron maravillosamente! Muy contento con la solución.
Solo 2 comandos hacen el truco:
¿Hay alguna limitación que deba tener en cuenta?
fuente
Escalado de SVG y renderizado PNG
Usando pycairo y librsvg pude lograr el escalado SVG y el renderizado en un mapa de bits. Suponiendo que su SVG no es exactamente de 256x256 píxeles, la salida deseada, puede leer en el SVG en un contexto de El Cairo usando rsvg y luego escalarlo y escribir en un PNG.
main.py
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
fuente
Handle.get_dimension_data
no funcionó para mí. Tuve que reemplazarlo con una simple búsqueda deself.props.width
yself.props.height
. Primero intenté definir laRsvgDimensionData
Estructura como se describe en el sitio web de El Cairo, pero sin éxito.Aquí hay un enfoque en el que Python llama a Inkscape.
Tenga en cuenta que suprime cierta salida cruda 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
yerr
.Por ejemplo, al ejecutar un trabajo en particular en mi sistema Mac OS,
out
terminó siendo:(El archivo svg de entrada tenía un tamaño de 339 por 339 píxeles).
fuente
En realidad, no quería depender de nada más que de Python (Cairo, Ink ..., etc.). Mis requisitos debían ser lo más simples posible, a lo sumo, un simple
pip install "savior"
sería suficiente, por eso ninguno de los anteriores lo hizo ' me queda bien.Pasé por esto (yendo más allá de Stackoverflow en la investigación). https://www.tutorialexample.com/best-practice-to-python-convert-svg-to-png-with-svglib-python-tutorial/
Se ve bien hasta ahora. Así que lo comparto por si alguien se encuentra en la misma situación.
fuente