Convertir du PDF en JPG avec Python

Si vous avez une base de documents en PDF, il peut être utile de générer un aperçu de son contenu en JPG pour, par exemple, afficher une miniature sur un site web.

Article mis à jour, inutile de lire la suite , une nouvelle version en 5 lignes est dispo ici

Diverses solutions sont mentionnées sur Stackoverflow que j'ai a peu près toutes essayé. Celle avec les bindings Imagemagick de Python est à proscrire: quand vous lancez la conversion, python lance imagemagick qui lui même lance ghostscript, tout ça mange beaucoup de mémoire, c'est lent et la qualité n'est pas forcement au rendez-vous.

Une bonne solution est d'utiliser directement ghostscript via la librairie «commands» de python. Malheureusement sous certaines distributions la version de la librairie est un peu vieillotte et ne gère pas certains types de PDF.

Dans le package poppler-utils se cache un petit utilitaire appelé pdftoppm plutôt à l'aise avec ce type de tache et il est très rapide. Reste à l'interfacer avec python.

Une des propriété intéressante de pdftoppm est qu'il renvoie le résultat de sa conversion en binaire directement sur la sortie standard quand on ne spécifie pas de fichier de sortie. On peut donc récupérer tout ça dans un cStringIO et le traiter avec PIL qui gère le format ppm sans soucis.

Voici un exemple de code à adapter selon vos besoins :


import os, subprocess, shlex, cStringIO 
from PIL import Image , ImageFile 

ImageFile.MAXBLOCK = 2**20 


def pdftojpg(pdfFilePath, subpath = ""/img/""): 
    outpoutejpg = pdfFilePath.replace("".pdf"","".jpg"") 
    head,tail = os.path.split(outpoutejpg) 
    head = head+subpath 
    if not os.path.exists(head): 
        os.makedirs(head) 
    command_line = ""pdftoppm -l 1 ""+pdfFilePath 
    args = shlex.split(command_line) 
    proc = subprocess.Popen(args, stdout=subprocess.PIPE) 
    (out, err) = proc.communicate() 
     
    mystrimage = cStringIO.StringIO(out) 
    image = Image.open(mystrimage) 
        image.save(outpoutejpg, ""JPEG"", quality=90, optimize=True, progressive=True) 
    return outpoutejpg


Sources :