167 votes

Convertir SVG en PNG en Python

Comment convertir un svg à png en Python ? Je stocke le svg dans une instance de StringIO . Dois-je utiliser la bibliothèque pyCairo ? Comment écrire ce code ?

3 votes

Peut-être un doublon de stackoverflow.com/questions/2932408/

3 votes

Ce fil laisse le problème non résolu. La réponse acceptée venait de l'auteur de la question qui partageait sa tentative de code ratée. L'autre réponse suggérait ImageMagick mais un commentateur a dit qu'ImageMagick fait "un travail horrible pour interpréter le SVG". Je ne veux pas que mes pngs aient l'air horrible, alors je pose à nouveau la question.

1 votes

150voto

nemesisfixx Points 2447

Voici ce que j'ai fait en utilisant 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')

Et ça marche comme sur des roulettes !

Voir plus : document cairosvg

8 votes

Savez-vous comment je peux faire la même chose mais sans écrire dans un fichier ? J'ai besoin de pousser le contenu png vers le navigateur à partir d'un serveur web, de sorte que l'utilisateur peut télécharger l'image. L'enregistrement du fichier png n'est pas une option valable dans notre projet, c'est pourquoi j'en ai besoin de cette façon. Merci

5 votes

Je l'ai fait moi-même. Cela dépend essentiellement des outils ou des cadres de travail dont vous disposez pour gérer vos requêtes web, mais quel que soit le cadre, l'idée de base est la suivante svg2png prend dans un stream dans le write_to et il peut s'agir de votre objet de réponse HTTP (qui, dans la plupart des frameworks, est un objet de type fichier) ou d'un autre flux, que vous servez ensuite au navigateur à l'aide du paramètre Content-Disposition en-tête. voir ici : stackoverflow.com/questions/1012437/

5 votes

Pour ceux qui rencontrent des problèmes avec ce code, comme je l'ai fait : 1). bytestring accepte les octets, donc convertissez d'abord les chaînes de caractères avec bytestring=bytes(svg,'UTF-8') 2). le mode de fichier doit être binaire, donc open('output.png','wb')

75voto

jsbueno Points 22212

La réponse est " pyrsvg "une liaison Python pour librsvg .

Il existe une version d'Ubuntu paquet python-rsvg le fournir. La recherche de son nom sur Google est pauvre car son code source semble être contenu dans le dépôt GIT du projet Gnome "gnome-python-desktop".

J'ai fait un "hello world" minimaliste qui rend SVG sur une surface cairo et l'écrit sur le disque :

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")

Mise à jour : en 2014, le paquet nécessaire pour la distribution Linux Fedora est le suivant : gnome-python2-rsvg . L'extrait de liste ci-dessus fonctionne toujours tel quel.

1 votes

Super, fonctionne bien. Mais y a-t-il un moyen de laisser cairo déterminer seul la HAUTEUR et la LARGEUR de l'image ? J'ai examiné le *.svg pour extraire la HAUTEUR et la LARGEUR de ce fichier, mais elles sont toutes deux réglées sur 100% . Bien sûr, je peux examiner les propriétés de l'image, mais comme ce n'est qu'une étape du traitement de l'image, ce n'est pas ce que je veux.

1 votes

Si la "largeur" et la "hauteur" de vos fichiers sont fixées à 100%, il n'y a aucune magie que Cairo ou rsvg puisse faire pour deviner la taille : de tels fichiers SVG ont été laissés indépendants de la taille par le logiciel (/la personne) créateur. Le code HTML environnant pour importer le fichier SVG fournira la taille physique. Cependant, l'objet "Handle" de rsvg a une fonction .get_dimension_data() qui a fonctionné pour mon fichier d'exemple (un SVG qui se comporte bien) - essayez-le.

1 votes

À partir de 2014, pour ubuntu, vous pouvez utiliser : apt-get install python-rsvg

51voto

blj Points 151

Installez Inkscape et appelez-le en ligne de commande :

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

Vous pouvez également capturer une zone rectangulaire spécifique en utilisant uniquement le paramètre -j par exemple, la coordonnée "0:125:451:217".

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

Si vous souhaitez afficher un seul objet dans le fichier SVG, vous pouvez spécifier le paramètre -i avec l'identifiant de l'objet que vous avez défini dans le SVG. Tout le reste est masqué.

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

5 votes

+1 parce que c'est aussi extrêmement pratique pour les scripts shell. Voir inkscape.org/doc/inkscape-man.html pour une documentation complète sur la ligne de commande d'Inkscape.

0 votes

Merci, c'est le moyen le plus simple que j'ai trouvé pour le faire. Sous Windows, pour ne pas avoir à taper le chemin complet d'Inkscape à chaque fois, vous pouvez ajoutez-le à votre chemin d'accès dans Variables d'environnement .

7 votes

Ce n'est pas une réponse. C'est une solution de contournement. Le PO a demandé une solution Python.

36voto

streetlogics Points 1558

J'utilise Wand-py (une implémentation de l'enveloppe de Wand autour d'ImageMagick) pour importer des SVG assez avancés et jusqu'à présent, j'ai obtenu d'excellents résultats ! Voici tout le code nécessaire :

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

Je viens de découvrir ceci aujourd'hui, et j'ai pensé que cela valait la peine de le partager pour tous ceux qui pourraient tomber sur cette réponse, car cela fait un moment que la plupart de ces questions n'ont pas reçu de réponse.

NOTE : Techniquement, en testant, j'ai découvert que vous n'avez même pas besoin de passer le paramètre format pour ImageMagick, donc with wand.image.Image( blob=svg_file.read() ) as image: était tout ce qui était vraiment nécessaire.

EDIT : A partir d'une tentative d'édition par qris, voici un code utile qui vous permet d'utiliser ImageMagick avec un SVG qui a un fond transparent :

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)

4 votes

La baguette a travaillé un lot mieux que le Caire pour mes PNGs.

0 votes

Merci @qris - j'ai ajouté votre code de rendu SVG à fond transparent à ma réponse également.

0 votes

Ça a l'air bien, mais où mettez-vous le nom de fichier du svg ?

13voto

user732592 Points 134

Essayez ça : http://cairosvg.org/

Le site dit :

CairoSVG est écrit en pur python et ne dépend que de Pycairo. Il est connu pour fonctionner sur Python 2.6 et 2.7.

Mise à jour 25 novembre 2016 :

2.0.0 est une nouvelle version majeure, dont le journal des modifications comprend les éléments suivants :

  • Suppression du support de Python 2

0 votes

Il y a malheureusement deux problèmes avec cela. Premièrement, elle ne gère pas le <clipPath><rect ... /></clipPath> . Deuxièmement, il ne prend pas l'option -d (DPI).

2 votes

@Ray , veuillez envoyer les rapports de bogues / demandes de fonctionnalités sur le tracker CairoSVG !

0 votes

@Simon, tu peux le faire s'il te plaît ? Je suis trop occupé et je le serai dans les 1-2 mois à venir.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X