Voir le numéros des pages où sont vos images

Voir le numéros des pages où sont vos images

Introduction

Il y a quelques temps, dans le cadre de mon activité professionnelle du côté de l’édition, j’ai dû me pencher sur une question plutôt épineuse (pour moi), à savoir de construire une liste dans laquelle il y a les images d’un document créé avec \(\LaTeX\), ainsi que le numéro de la page de chaque image.

Par exemple, si mon document affiche l’image toto.eps à la page 7, je voudrais que cela figure dans ma liste.

Nous allons voir une façon (qui n’est peut-être pas la meilleure, mais toute suggestion est bonne) de procéder avec Python.

Code source \(\LaTeX\)

\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage{lipsum}
\usepackage{graphicx}
	\graphicspath{{img/}}
\begin{document}
\lipsum
\begin{center}
\includegraphics{avatar.eps}
\end{center}
\lipsum
\begin{center}
\includegraphics{nsi.eps}
\end{center}
\lipsum
\begin{center}
\includegraphics{sept.eps}
\end{center}
\lipsum
\begin{center}
\includegraphics[width=0.75\linewidth]{tangente.eps}
\end{center}
\end{document}

Je compile ce code via la chaîne Latex+dvips+ps2pdf et l’obtiens alors un document PS ainsi qu’un DVI.

On passe en ligne de commande

Maintenant, on va dans le répertoire qui contient les fichiers, puis on entre le code suivant (sous Windows) :

dvips -o Essai.ps Essai > logdvi

Sous Linux, le code est le suivant :

dvips -o Essai.ps Essai &> logdvi

Ce code aura pour effet de créer un fichier logdvi dans lequel il y aura :

This is dvips(k) 5.998 Copyright 2018 Radical Eye Software (www.radicaleye.com)
' TeX output 2019.01.19:1350' -> Essai.ps
<C:/Users/mathweb/AppData/Local/Programs/MiKTeX/dvips/base/tex.pro>
<C:/Users/mathweb/AppData/Local/Programs/MiKTeX/dvips/base/texps.pro>
<C:/Users/mathweb/AppData/Local/Programs/MiKTeX/dvips/base/special.pro>.
<C:/Users/mathweb/AppData/Local/Programs/MiKTeX/fonts/type1/public/amsfonts/cm/cmr12.pfb>
[1] [2<./img/avatar.eps>] [3] [4<./img/nsi.eps>] [5] [6<./img/sept.eps>] [7]
[8<./img/tangente.eps>]

Remarquez alors qu’à la fin de ce fichier, la liste des images est présente… avec le numéro des pages juste avant les images ! Le problème est le format…

Du côté de Python

Etape 1 : on lit le fichier dvilog

fichier = open("logdvi", "r")
all_lines = fichier.readlines()
fic = ""
for i in range(len(all_lines)):
    line = all_lines[i].replace('\n','')
    fic += line
fichier.close()

Ce code ouvre d’abord le fichier logdvi puis convertit toutes ses lignes en entrées de liste. La liste ainsi construite est nommée all_lines.

Ensuite, je souhaite créer une chaîne de caractères contenant toutes les lignes à la suite; je vais donc enlever les “\n” (les retours à la ligne) à chacune des lignes (dans la boucle for) et je concatène les lignes avec l’instruction “fic += line”. À la fin de ma boucle, la chaîne de caractères fic contient toute les lignes du fichier logdvi à la suite.

Etape 2 : on créé la liste

crochetOuvrant = False
imgList = []

for c in fic:
    if c == "[":
        crochetOuvrant = True
        container = ""
    else:
        if c == "]":
            crochetOuvrant = False
            imgList.append(container)
            
        else:
            if crochetOuvrant == True:
                container += c

Ici, on parcourt la chaîne de caractères fic (avec la boucle for c in fic) caractère par caractère. Si on rencontre un crochet ouvrant, alors on commence le stockage dans la liste : pour chaque crochet ouvrant, on créé une entrée.

Cette entrée est de la forme “[xx]” ou “[xx<./img/xxx.eps>]”.

Etape 3 : on créé un dictionnaire des images

imgDicoList = []
page = ''

for i in imgList:
    if '<' in i: # si au moins une illus. est présente
        imgDico = {}
        for x in i.split('<'):
            if len(x)<4:
                pageCount = True
                if len(x) == 1:
                    page = '00'+x
                elif len(x) == 2:
                    page = '0'+x
                else:
                    page = x
            else:
                pageCount = False
                name = x[6:]
                name = name[:-5]
            if pageCount == False:
                imgDico['page'] = page
                imgDico['name'] = name
                imgDicoList.append(imgDico)

Je souhaite que ma liste soit composée d’entrées sous la forme d’un dictionnaire qui comporte deux clés, que je vais nommer page et name. Je vais donc parcourir ma liste précédente et je vais avant tout tester la présence d’une image. Si l’entrée de la liste est de la forme “[xx]”, c’est-à-dire s’il n’y a pas de symbole “<“, alors on peut passer à l’entrée suivante.

Si “>” est au contraire présent alors je créé un dictionnaire vide, imgDico. Il faut penser à une chose : 2 images peuvent être sur une même page, donc dans une entrée, il se peut qu’il y ait plusieurs “<“, donc pour chaque entrée, je vais couper selon les caractères “<” (avec la méthode split, qui construit une liste composée de chaque portion comprise entre deux “<“); c’est le principe de la boucle “for x in i.split(‘<‘):” qui fait que l’on parcourt la liste construite par split.

Bon, je passe les détails mais ce dernier code construit des entrées sous la forme de dictionnaires, où le numéro des pages est formaté sur 3 caractères.

Le final

Python nous renvoie :

print(imgDicoList)
[{'page': '002', 'name': 'avatar'}, {'page': '004', 'name': 'nsi'}, {'page': '006', 'name': 'sept'}, {'page': '008', 'name': 'tangente'}]

On a donc ainsi une liste de toutes les illustrations ainsi que leur page.

Alternative

Le début du code peut être simplifié à l’aide du module re. De plus, plutôt que de passer en ligne de commande avant d’exécuter le programme Python, on peut faire appel au module os pour exécuter la ligne “dvips…” directement.

import re
import os

instruction = "dvips -o Essai.ps Essai > logdvi.txt"
os.system(instruction)

regex = re.compile(r'[\n]')
fichier = open("logdvi.txt", "r")
fic = fichier.read()
fic = regex.sub(" ",fic)

fichier.close()

crochetOuvrant = False
imgList = []

for c in fic: 
    if c == "[":
        crochetOuvrant = True
        container = ""
    else:
        if c == "]":
            crochetOuvrant = False
            imgList.append(container)
            
        else:
            if crochetOuvrant == True:
                container += c

imgDicoList = [] 
page = ''

for i in imgList:
    if '<' in i:
        imgDico = {}
        for x in i.split('<'):
            if len(x)<4:
                pageCount = True
                if len(x) == 1:
                    page = '00'+x
                elif len(x) == 2:
                    page = '0'+x
                else:
                    page = x
            else:
                pageCount = False
                name = x[6:]
                name = name[:-5]
            if pageCount == False:
                imgDico['page'] = page
                imgDico['name'] = name
                imgDicoList.append(imgDico)

for i in imgDicoList:
    for key, value in i.items():
        print (key, value)

Les abonnés à ce site pourront télécharger le ZIP contenant le fichier source LaTeX, le code Python et les images EPS sur cette page.

Stéphane Pasquet
Stéphane Pasquet

Laissez votre message