jeudi 16 avril 2015

Produire des figures en png et eps avec scilab et LaTeX

Pour illustrer mes cours  je dois souvent  créer des   figures  et suivant leur utilisation je dois pouvoir les convertir en différents formats, sans perte de qualité.  Comme j'utilise LaTeX j'ai commencé par créer des images postscript , mais avec l'apparition de pdflatex et  beamer ce choix de format n'est plus suffisant ...  Au fils des années j'ai du choisir un format complémentaire, et parmi tous les formats possibles  j'en ai choisi  un semble s'imposer de plus en plus sur le net : le format png.


une belle figure pour un cours de calcul différentiel !


Outils  et formats disponibles 

Pour justifier ce choix commençons par un petit tour d'horizon des formats d'images  les plus courants :
  • le  postscript d'extension *.eps est un format d'image vectoriel (sans compression)  très ancien puisqu'il remonte à 1982! C'est en fait un langage de programmation , développé par adobe, qui permet de décrire  n'importe quel type de page à une imprimante. 
  • Le pdf (portable document format)  est une version "compressée"  du postscript qui permet donc de décrire tout type d'image. Il est  aussi développé par adobe  et est sensé remplacer le postscript depuis 2007
  • le jpeg  bien qu'étant un format compressé avec perte  est bien adapté au partage des photos (c'est le format de stockage par défaut des images sur facebook par exemple) mais la compression est souvent accompagnée d'une forte dégradation de l'image.
  • le gif, même s'il est de moins bonne qualité que le jpeg,  est un format compressé encore plus léger que le jpg, mais qui gère la transparence et en plus il permet de créer des animations à moindre coups (les gif animés). Il  fait un retour en force (par exemple sur google+) depuis que les brevets le concernant sont tombés dans le domaine public.
  • enfin le png qui combine compression sans perte (suivant le niveau de compression demandé)  avec la possibilité de gérer la transparence et même de faire des animations  (via le format méconnu *.apng). Il semble devenir un standard pour toutes les images statiques de type  figures/schéma (par exemple sur wikipédia). 
le gif animé  est un format  très pratique pour produire de petites animations


Pour  créer des figures complexe on est vite amené à programmer,  et pour bien programmer il faut utiliser  le meilleur langage de programmation qui est ... celui qu'on utilise le plus souvent !  Dans mon cas je suis partagé entre plusieurs  outils :

  • Scilab  qui est très adapté pour les graphiques  avec des tracés compliqués, en 2 ou 3 dimensions, et peu de texte
  • LaTeX  qui est plus adapté de concevoir des schémas/diagrammes  contenant   du texte  en utilisant   des extensions comme  pstricks 
  • ImageMagick c'est une bibliothèque plutôt orienté traitement d'image avec sa fonction convert qui peut transformer à peu près n'importe quel format d'image  en un autre  tout en appliquant de très nombreux traitement automatiques (redimensionner, couper, modifier la transparence ...), elle s'utilise très facilement  dans des scripts bash.
À partir de ces différents outils
  • je génère toute mes figures en double : une au format *.png et une  au format *.eps  suivant que je les utilise ensuite avec latex ou pdflatex  
  • chaque figure est associée à un fichier source qui peut être au format *.sce si l'image est générée avec scilab ou *.tex si elle est générée avec latex
  • dans mes documents LaTeX  les images  sont appelé par une commande \includegraphics{figure}  sans mention de l'extension de telle sorte que je puisse compiler les documents  en utilisant indifféremment latex ou pdflatex

    avec Scilab

    Pour les figures avec  peu de texte et beaucoup d'entités graphiques j'utilise toujours Scilab  qui me permet d'exporter vers tous les formats qu'ils soient matriciels (png,jpg,gif,bmp,ppm) ou vectoriels (ps,eps,pdf,svg,emf). L'export de n'importe quel graphique généré avec scilab se fait depuis le menu fichier de la fenêtre graphique  ou depuis la console en ligne de commande. Par exemple pour un export en png on utilisera  la commande 

    xs2png(n,'figure.png')  

    où n est le numéro de la fenêtre graphique à exporter. Scilab possède des fonctions xs2*  pour la pluspart des formats *=jpg,gif,pdf,eps,... les figures sont par défaut entourées d'une marge blanche assez grande, mais  on peut la supprimer de plusieurs manières :
    • dans scilab  en récupérant le pointeur graphique correspondant aux axes courants et en modifiant la propriété "margin" :
      A=gca();                 //axes courants
      A.margins=zeros(1,4);  // marge à 0
    • avec convert  en utilisant l'option -trim qui  rognera l'image jusqu'à obtenir le cadre le plus petit possible : 
      convert figure1.png -trim figure2.png
    • pour les figures postscript  il y a aussi la commande
      ps2epsi  figure.eps

    résultat de la commande surf()  dans scilab avec ou sans marges

     chaque figure  créée avec scilab est associée à un fichier *.sce  qui contient à la fin les appels à xs2png et xs2eps  et éventuellement les appels à convert ou ps2epsi  lancés depuis scilab par la commande unix(cmd)  qui fait directement exécuter la commande bash "cmd" par le shell du système. Ca marche aussi sous windows en utilisant des commandes compatibles  avec l'interpréteur de commande de cet OS (dont en autre bash si vous avez installé cygwin  pour bénéficier d'un shell linux sous windows!)
    .

    avec LaTeX

    là il y a beaucoup de chaînes de compilation possibles pour obtenir une image  dans un format donné, le problème est d'en choisir une qui soit la plus générale et qui donne une définition d'image suffisante à la fin.

    • pour le postscript la solution logique est latex-->dvips-->ps2epsi  ( à cause des éventuelles marges à rogner)
    • pour le png la solution logique est de remplacer dvips par dvipng   puis éventuellement d'utiliser convert ensuite pour rogner les marges, sauf que dvipng ne marche pas avec du code pstricks  donc dans ce cas il vaut mieux convertir le fichier *.eps  en *.png avec convert
    pour insérer des algorithmes écrit avec le package program.sty
    je les transforme en images avec la méthode décrite ici

    pour la cas du png j'ai rencontré plusieurs difficultés pas très bien documentées (peut être par ce que peu de gens utilisent ces fonctionnalités  ...) :
    • les images  obtenues  avec convert  semblent légèrement floues (comme l'algorithme de Dijkstra juste au-dessus), c'est parce qu'il faut forcer convert à utiliser  une meilleure définition avec l'option -density :
      convert image.eps -density 200 image.png
    • de même pour dvipng on peut utiliser l'option -D  pour améliorer la définition de l'image, on notera aussi que la couleur de fond des images obtenues avec dvipng  n'est pas   "transparente", là encore il faut ajouter l'option -bg pour rendre se fond transparent :
      dvipng image.dvi -bg 'transparent' -D 200 -o image.png

    Pour finir j'ai automatisé  le processus en créant de petits script bash enchaînant les fonctions dans le bon ordre :

    #!/bin/sh
    ### syntaxe 
    ### tex2png fichier 
    ### on part de fichier.tex pour obtenir fichier.eps et fichier.png
    fichier=${1}
    if [ -n "$fichier" ]
    then 
     fichier=${fichier%%.*} 
     echo "##traitement du fichier : ${fichier}##"
     cp  ${fichier}.tex essai.tex
     latex essai.tex
     dvips essai.dvi
     ps2epsi essai.ps essai.eps
     dvipng essai.dvi -bg 'Transparent' -D 200 -o essai.png
     mv essai.png ${fichier}.png
     mv essai.eps ${fichier}.eps
     rm essai.*
     echo '##############fini!####################'
    else    ### affichage du manuel si pas d'argument
     echo "tex2png fichier.tex"
     echo "genère fichier.png et ficier.eps"
    fi
    


    et pour les fichier contenant du pstrick :

    #!/bin/sh
    ### syntaxe 
    ### pst2png fichier 
    ### on part de fichier.tex pour obtenir fichier.eps et fichier.png
    fichier=${1}
    if [ -n "$fichier" ]
    then
     fichier=${fichier%%.*} 
     echo "##traitement du fichier : ${fichier}##"
     cp  ${fichier}.tex essai.tex
     latex essai.tex
     dvips essai.dvi
     ps2epsi essai.ps essai.eps
     convert -density 200 essai.eps  essai.png 
     mv essai.png ${fichier}.png
     mv essai.eps ${fichier}.eps
     rm essai.*
     echo '##############fini!####################'
    else    ### affichage du manuel si pas d'argument
     echo "pst2png fichier.tex"
     echo "génère fichier.png et ficier.eps"
    fi
    

    Aucun commentaire:

    Enregistrer un commentaire

    Pour écrire des formules mathématiques vous pouvez utiliser la syntaxe latex en mettant vos formules entre des "dollars" $ \$....\$ $ par exemple :
    - $\sum_{n=1}^\infty {1\over n^2}={\pi^2\over 6}$ s'obtient avec \sum_{n=1}^\infty {1\over n^2}={\pi^2\over 6}
    - $\mathbb R$ s'obtient avec {\mathbb R} et $\mathcal D$ s'obtient avec {\mathcal D}
    - pour les crochets $\langle .,. \rangle$ dans les commentaires utilisez \langle .,. \rangle
    vous pouvez écrire du html dans les commentaires :
    - italique <i> ... </i> gras <b> ... </b>
    - lien <a href="http://adresse "> .... </a>