Wie konvertiere ich ein svgin pngin Python? Ich speichere das svgin einer Instanz von StringIO. Soll ich die pyCairo-Bibliothek verwenden? Wie schreibe ich diesen Code?
Dieser Thread hat das Problem ungelöst gelassen. Die akzeptierte Antwort kam von dem Fragesteller, der seinen fehlgeschlagenen Codeversuch teilte. Die andere Antwort schlug ImageMagick vor, aber ein Kommentator sagte, ImageMagick mache "einen schrecklichen Job bei der Interpretation von SVG". Ich möchte nicht, dass meine PNGs schrecklich aussehen, also stelle ich die Frage erneut.
Die Beispiele in diesem Link sind spezifisch für Win32. Ich verwende Linux.
Ram1
Schauen Sie sich diesen Blog-Beitrag an, es sieht so aus, als ob er genau das ist, was Sie brauchen.
Giodamelio
Antworten:
58
Die Antwort lautet " pyrsvg " - eine Python-Bindung für librsvg .
Es gibt ein Ubuntu python-rsvg-Paket, das es bereitstellt. Das Durchsuchen von Google nach seinem Namen ist schlecht, da der Quellcode im GIT-Repository des Gnome-Projekts "gnome-python-desktop" enthalten zu sein scheint.
Ich habe eine minimalistische "Hallo Welt" erstellt, die SVG auf eine Kairo-Oberfläche rendert und auf die Festplatte schreibt:
Update : Ab 2014 ist das erforderliche Paket für die Fedora Linux-Distribution : gnome-python2-rsvg. Die obige Snippet-Liste funktioniert weiterhin wie sie ist.
Großartig, funktioniert gut. Aber gibt es eine Möglichkeit, cairodie Höhe und Breite des Bildes selbst bestimmen zu lassen ? Ich habe in die *.svgDatei geschaut , um die HÖHE und BREITE von dort zu extrahieren, aber beide sind auf eingestellt 100%. Natürlich kann ich mir die Eigenschaften des Bildes ansehen, aber da dies nur ein Schritt in der Bildverarbeitung ist, ist dies nicht das, was ich will.
Quapka
1
Wenn die "Breite" und "Höhe" Ihrer Dateien auf 100% eingestellt ist, gibt es keine Magie, die Cairo oder rsvg tun können, um die Größe zu erraten: Solche SVG-Dateien wurden von der Erstellungssoftware (/ person) unabhängig von der Größe belassen. Der umgebende HTML-Code zum Importieren der SVG-Datei würde die physische Größe liefern. Das "Handle" -Objekt von rsvg verfügt jedoch über eine .get_dimension_data()Methode, die für meine Beispieldatei (eine gut erzogene SVG) funktioniert - probieren Sie es aus.
Jsbueno
1
Ab 2014 können Sie für Ubuntu Folgendes verwenden: apt-get install python-rsvg
t1m0
1
Gibt es einen Schnellbefehl zum Hinzufügen eines weißen Hintergrunds zum Bild, wenn der aktuelle Hintergrund transparent ist?
Fiatjaf
@jsbueno Ich verwende Windows 8.1 und Python 2.7.11. Wie kann ich cairo und rsvg installieren und es zum Laufen bringen? Ich hatte Mühe, diese Arbeit zu machen. Übrigens +1 für Ihre ausführliche Erklärung.
Hallo. Wissen Sie, wie ich das gleiche tun kann, ohne in eine Datei zu schreiben? Ich muss PNG-Inhalte von einem Webserver an den Browser senden, damit der Benutzer das Bild herunterladen kann. Das Speichern der PNG-Datei ist in unserem Projekt keine gültige Option. Deshalb brauche ich sie so. Danke
estemendoza
4
Ich habe das selbst gemacht. Es hängt im Wesentlichen davon ab, über welche Tools oder Frameworks Sie bei der Bearbeitung Ihrer Webanforderungen verfügen. Unabhängig davon, um was es sich handelt, besteht die Grundidee darin, svg2pngein streamObjekt im write_toParameter aufzunehmen, und dies kann entweder Ihr HTTP-Antwortobjekt sein (welches in Die meisten Frameworks sind ein dateiähnliches Objekt oder ein anderer Stream, den Sie dann mithilfe des Content-DispositionHeaders an den Browser senden. siehe hier: stackoverflow.com/questions/1012437/…
nemesisfixx
4
Für diejenigen, die Probleme mit diesem Code haben, wie ich es war: 1). bytestringakzeptiert Bytes, also konvertiere den String zuerst mit bytestring=bytes(svg,'UTF-8') 2). open('output.png','wb')
Dateimodus
3
cairosvg unterstützt nur Python 3.4+. Sie haben Python 2-Unterstützung eingestellt
Marlon Abeykoon
1
Es gab kein svg2pngfür mich, ich musste es benutzen cairosvg.surface.PNGSurface.convert(svg_str, write_to='output.png').
tobltobs
39
Installieren Sie Inkscape und rufen Sie es als Befehlszeile auf:
Sie können einen bestimmten rechteckigen Bereich auch nur mit Parametern fangen -j , z. B. mit der Koordinate "0: 125: 451: 217".
${INKSCAPE_PATH}-z -f ${source_svg}-w ${width}-j -a ${coordinates}-e ${dest_png}
Wenn Sie nur ein Objekt in der SVG-Datei anzeigen möchten, können Sie den Parameter -imit der Objekt-ID angeben, die Sie in der SVG eingerichtet haben. Es verbirgt alles andere.
${INKSCAPE_PATH}-z -f ${source_svg}-w ${width}-i ${object}-j -a ${coordinates}-e ${dest_png}
Dies ist keine Antwort. Es ist eine Problemumgehung. OP fragte nach einer Python-Lösung.
Lamino
29
Ich verwende Wand-py (eine Implementierung des Wand-Wrappers um ImageMagick), um einige ziemlich fortgeschrittene SVGs zu importieren, und habe bisher großartige Ergebnisse erzielt! Dies ist der gesamte Code, den es braucht:
with wand.image.Image( blob=svg_file.read(), format="svg")as image:
png_image = image.make_blob("png")
Ich habe das heute erst entdeckt und hatte das Gefühl, dass es sich lohnt, es für alle anderen zu teilen, die sich über diese Antwort hinwegsetzen könnten, da die meisten dieser Fragen schon eine Weile beantwortet wurden.
HINWEIS: Technisch gesehen habe ich beim Testen festgestellt, dass Sie nicht einmal den Formatparameter für ImageMagick übergeben müssen with wand.image.Image( blob=svg_file.read() ) as image: war alles, was wirklich benötigt wurde.
BEARBEITEN: Nach einem Bearbeitungsversuch von qris finden Sie hier einen hilfreichen Code, mit dem Sie ImageMagick mit einer SVG-Datei mit transparentem Hintergrund verwenden können:
Wand hat für meine PNGs viel besser funktioniert als Kairo.
Qris
3
Ich bekomme den Fehler image.read(blob=svg_file.read(), format="svg") NameError: name 'svg_file' is not defined
adrienlucca.wordpress.com
2
svg_fileIn diesem Beispiel wird angenommen, dass es sich um ein "Datei" -Objekt handelt. Die Einstellung svg_filewürde svg_file = File.open(file_name, "r")
ungefähr
2
Vielen Dank, die cairound rsvg"akzeptierte" Methode hat bei meinem PDF nicht funktioniert. pip install wandund dein Snippet hat es geschafft;)
nmz787
5
Wenn Sie ein SVG haben, müssen strSie zuerst wie folgt in eine Binärdatei codieren : svg_blob = svg_str.encode('utf-8'). Jetzt können Sie die oben beschriebene Methode verwenden , durch das Ersetzen blob=svg_file.read()mit blob=svg_blob.
Es gibt leider zwei Probleme damit. Erstens geht es nicht darum <clipPath><rect ... /></clipPath>. Zweitens wird die Option -d (DPI) nicht verwendet.
Ray
2
@ Ray, bitte senden Sie Fehlerberichte / Feature-Anfragen an den CairoSVG-Tracker !
Simon Sapin
@ Simon, kannst du es bitte tun? Ich bin zu beschäftigt und werde in den nächsten 1-2 Monaten sein.
Ray
2
@ Ray, eigentlich gibt es die Option -d / --dpi schon eine Weile, und mir wurde gesagt, dass die Unterstützung für <clippath> vor einigen Wochen in der Git-Version hinzugefügt wurde.
PySide kann einfach von einem Binärpaket in Windows installiert werden (und ich verwende es für andere Dinge, daher ist es für mich einfach).
Beim Konvertieren von Länderflaggen aus Wikimedia sind mir jedoch einige Probleme aufgefallen, daher möglicherweise nicht der robusteste SVG-Parser / Renderer.
Ich habe die SVG-Extraktion für Breite und Höhe verwendet. Ich bin mir über den SVG-Standard nicht sicher, aber in einigen meiner SVG-Dateien folgte auf die Breite oder Höhe eine nicht numerische Zeichenfolge wie 'mm' oder 'px' (z. B. '250 mm'). Das int ('250mm') löst eine Ausnahme aus und ich musste einige zusätzliche Verbesserungen vornehmen.
WigglyWorld
3
Ich fand keine der Antworten zufriedenstellend. Alle erwähnten Bibliotheken haben das eine oder andere Problem, wie Kairo, das die Unterstützung für Python 3.6 aufgibt (sie haben die Unterstützung von Python 2 vor etwa 3 Jahren eingestellt!). Auch die Installation der genannten Bibliotheken auf dem Mac war mühsam.
Schließlich fand ich die beste Lösung war svglib + reportlab . Beide wurden ohne Probleme mit pip installiert und der erste Aufruf zur Konvertierung von svg nach png funktionierte wunderbar! Sehr zufrieden mit der Lösung.
Nur 2 Befehle reichen aus:
from svglib.svglib import svg2rlg
from reportlab.graphics import renderPM
drawing = svg2rlg("my.svg")
renderPM.drawToFile(drawing,"my.png", fmt="PNG")
Gibt es irgendwelche Einschränkungen bei diesen, die ich beachten sollte?
Mit pycairo und librsvg ich die SVG-Skalierung und das Rendern einer Bitmap erreichen. Angenommen, Ihr SVG hat nicht genau 256 x 256 Pixel, die gewünschte Ausgabe, können Sie das SVG mit rsvg in einen Kairoer Kontext einlesen, es dann skalieren und in ein PNG schreiben.
Vielen Dank dafür, es hat sich in einem meiner Projekte als sehr nützlich erwiesen. Obwohl Handle.get_dimension_dataes bei mir nicht funktioniert hat. Ich musste es durch ein einfaches Abrufen von self.props.widthund ersetzen self.props.height. Ich habe zuerst versucht, die RsvgDimensionDataStruktur wie auf der cairo-Website beschrieben zu definieren , aber ohne Erfolg.
JeanOlivier
Ich versuche dies in einem meiner Projekte zu verwenden. Wie erhalte ich die erforderlichen DLL-Dateien?
Andoo
0
Hier ist ein Ansatz, bei dem Inkscape von Python aufgerufen wird.
Beachten Sie, dass bestimmte Crufty-Ausgaben, die Inkscape während des normalen fehlerfreien Betriebs in die Konsole schreibt (insbesondere stderr und stdout), unterdrückt werden. Die Ausgabe wird in zwei Zeichenfolgenvariablen outund erfasst 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'?'))
Wenn Sie beispielsweise einen bestimmten Job auf meinem Mac OS-System outausführen, erhalten Sie Folgendes:
Background RRGGBBAA: ffffff00
Area0:0:339:339 exported to 100 x 100 pixels (72.4584 dpi)Bitmap saved as:/path/to/output.png
(Die Eingabe-SVG-Datei hatte eine Größe von 339 x 339 Pixel.)
Es ist kein End-to-End-Python, wenn Sie sich auf Inkscape verlassen.
Joel
1
@ Joel: Die erste Zeile wurde geändert, um Ihren Einwand zu überwinden. Aber natürlich basiert auch eine "reine" Python-Lösung auf Elementen außerhalb der Kernsprache und wird letztendlich mit Maschinensprache ausgeführt. Vielleicht gibt es also kein End-to-End-Verfahren!
Eisen - Kissen
0
Eigentlich wollte ich von nichts anderem als Python abhängig sein (Kairo, Tinte usw.). Meine Anforderungen sollten so einfach wie möglich sein, höchstens ein einfaches pip install "savior"würde ausreichen, deshalb hat keiner der oben genannten nicht ' passt nicht zu mir.
Antworten:
Die Antwort lautet " pyrsvg " - eine Python-Bindung für librsvg .
Es gibt ein Ubuntu python-rsvg-Paket, das es bereitstellt. Das Durchsuchen von Google nach seinem Namen ist schlecht, da der Quellcode im GIT-Repository des Gnome-Projekts "gnome-python-desktop" enthalten zu sein scheint.
Ich habe eine minimalistische "Hallo Welt" erstellt, die SVG auf eine Kairo-Oberfläche rendert und auf die Festplatte schreibt:
Update : Ab 2014 ist das erforderliche Paket für die Fedora Linux-Distribution :
gnome-python2-rsvg
. Die obige Snippet-Liste funktioniert weiterhin wie sie ist.quelle
cairo
die Höhe und Breite des Bildes selbst bestimmen zu lassen ? Ich habe in die*.svg
Datei geschaut , um die HÖHE und BREITE von dort zu extrahieren, aber beide sind auf eingestellt100%
. Natürlich kann ich mir die Eigenschaften des Bildes ansehen, aber da dies nur ein Schritt in der Bildverarbeitung ist, ist dies nicht das, was ich will..get_dimension_data()
Methode, die für meine Beispieldatei (eine gut erzogene SVG) funktioniert - probieren Sie es aus.Folgendes habe ich mit cairosvg gemacht :
Und es funktioniert wie ein Zauber!
Weitere Informationen : cairosvg document
quelle
svg2png
einstream
Objekt imwrite_to
Parameter aufzunehmen, und dies kann entweder Ihr HTTP-Antwortobjekt sein (welches in Die meisten Frameworks sind ein dateiähnliches Objekt oder ein anderer Stream, den Sie dann mithilfe desContent-Disposition
Headers an den Browser senden. siehe hier: stackoverflow.com/questions/1012437/…bytestring
akzeptiert Bytes, also konvertiere den String zuerst mitbytestring=bytes(svg,'UTF-8')
2).open('output.png','wb')
svg2png
für mich, ich musste es benutzencairosvg.surface.PNGSurface.convert(svg_str, write_to='output.png')
.Installieren Sie Inkscape und rufen Sie es als Befehlszeile auf:
Sie können einen bestimmten rechteckigen Bereich auch nur mit Parametern fangen
-j
, z. B. mit der Koordinate "0: 125: 451: 217".Wenn Sie nur ein Objekt in der SVG-Datei anzeigen möchten, können Sie den Parameter
-i
mit der Objekt-ID angeben, die Sie in der SVG eingerichtet haben. Es verbirgt alles andere.quelle
Ich verwende Wand-py (eine Implementierung des Wand-Wrappers um ImageMagick), um einige ziemlich fortgeschrittene SVGs zu importieren, und habe bisher großartige Ergebnisse erzielt! Dies ist der gesamte Code, den es braucht:
Ich habe das heute erst entdeckt und hatte das Gefühl, dass es sich lohnt, es für alle anderen zu teilen, die sich über diese Antwort hinwegsetzen könnten, da die meisten dieser Fragen schon eine Weile beantwortet wurden.
HINWEIS: Technisch gesehen habe ich beim Testen festgestellt, dass Sie nicht einmal den Formatparameter für ImageMagick übergeben müssen
with wand.image.Image( blob=svg_file.read() ) as image:
war alles, was wirklich benötigt wurde.BEARBEITEN: Nach einem Bearbeitungsversuch von qris finden Sie hier einen hilfreichen Code, mit dem Sie ImageMagick mit einer SVG-Datei mit transparentem Hintergrund verwenden können:
quelle
image.read(blob=svg_file.read(), format="svg") NameError: name 'svg_file' is not defined
svg_file
In diesem Beispiel wird angenommen, dass es sich um ein "Datei" -Objekt handelt. Die Einstellungsvg_file
würdesvg_file = File.open(file_name, "r")
cairo
undrsvg
"akzeptierte" Methode hat bei meinem PDF nicht funktioniert.pip install wand
und dein Snippet hat es geschafft;)str
Sie zuerst wie folgt in eine Binärdatei codieren :svg_blob = svg_str.encode('utf-8')
. Jetzt können Sie die oben beschriebene Methode verwenden , durch das Ersetzenblob=svg_file.read()
mitblob=svg_blob
.Versuchen Sie dies: http://cairosvg.org/
Die Seite sagt:
Update 25. November 2016 :
quelle
<clipPath><rect ... /></clipPath>
. Zweitens wird die Option -d (DPI) nicht verwendet.Eine andere Lösung, die ich gerade hier gefunden habe Wie rendere ich eine skalierte SVG in ein QImage?
PySide kann einfach von einem Binärpaket in Windows installiert werden (und ich verwende es für andere Dinge, daher ist es für mich einfach).
Beim Konvertieren von Länderflaggen aus Wikimedia sind mir jedoch einige Probleme aufgefallen, daher möglicherweise nicht der robusteste SVG-Parser / Renderer.
quelle
Eine kleine Erweiterung der Antwort von jsbueno:
quelle
Ich fand keine der Antworten zufriedenstellend. Alle erwähnten Bibliotheken haben das eine oder andere Problem, wie Kairo, das die Unterstützung für Python 3.6 aufgibt (sie haben die Unterstützung von Python 2 vor etwa 3 Jahren eingestellt!). Auch die Installation der genannten Bibliotheken auf dem Mac war mühsam.
Schließlich fand ich die beste Lösung war svglib + reportlab . Beide wurden ohne Probleme mit pip installiert und der erste Aufruf zur Konvertierung von svg nach png funktionierte wunderbar! Sehr zufrieden mit der Lösung.
Nur 2 Befehle reichen aus:
Gibt es irgendwelche Einschränkungen bei diesen, die ich beachten sollte?
quelle
SVG-Skalierung und PNG-Rendering
Mit pycairo und librsvg ich die SVG-Skalierung und das Rendern einer Bitmap erreichen. Angenommen, Ihr SVG hat nicht genau 256 x 256 Pixel, die gewünschte Ausgabe, können Sie das SVG mit rsvg in einen Kairoer Kontext einlesen, es dann skalieren und in ein PNG schreiben.
main.py.
RSVG C-Bindung
Von der Cario-Website mit einigen geringfügigen Änderungen. Auch ein gutes Beispiel für das Aufrufen einer C-Bibliothek aus Python
quelle
Handle.get_dimension_data
es bei mir nicht funktioniert hat. Ich musste es durch ein einfaches Abrufen vonself.props.width
und ersetzenself.props.height
. Ich habe zuerst versucht, dieRsvgDimensionData
Struktur wie auf der cairo-Website beschrieben zu definieren , aber ohne Erfolg.Hier ist ein Ansatz, bei dem Inkscape von Python aufgerufen wird.
Beachten Sie, dass bestimmte Crufty-Ausgaben, die Inkscape während des normalen fehlerfreien Betriebs in die Konsole schreibt (insbesondere stderr und stdout), unterdrückt werden. Die Ausgabe wird in zwei Zeichenfolgenvariablen
out
und erfassterr
.Wenn Sie beispielsweise einen bestimmten Job auf meinem Mac OS-System
out
ausführen, erhalten Sie Folgendes:(Die Eingabe-SVG-Datei hatte eine Größe von 339 x 339 Pixel.)
quelle
Eigentlich wollte ich von nichts anderem als Python abhängig sein (Kairo, Tinte usw.). Meine Anforderungen sollten so einfach wie möglich sein, höchstens ein einfaches
pip install "savior"
würde ausreichen, deshalb hat keiner der oben genannten nicht ' passt nicht zu mir.Ich bin durchgekommen (weiter als Stackoverflow in der Forschung). https://www.tutorialexample.com/best-practice-to-python-convert-svg-to-png-with-svglib-python-tutorial/
Sieht soweit gut aus. Also teile ich es für den Fall, dass sich jemand in der gleichen Situation befindet.
quelle