Extraire la couverture d’un fichier ePub

Les ePubs ont déjà pas mal d’historique et d’implémentations divergentes. Je fouillais ces jours ci les différentes méthodes pour trouver l’image de couverture. J’ai probablement du louper des choses, mais ça servira probablement à d’autres.

Avant toute chose, il faut ouvrir l’ePub à l’aide de unzip

unzip exemple.epub

Puis repérer l’adresse de l’OPF dans le fichier META-INF/container.xml. Attention à ne pas rechercher manuellement un fichier content.opf à la racine de l’ePub. Si c’est souvent là qu’il se trouve, ce n’est pas toujours le cas.

L’adresse de l’OPF est dans l’attribut @full-path de la balise <rootfile> avec le media-type « application/oebps-package+xml ». S’il existe plusieurs correspondances, c’est la première qui doit être utilisée.

<?xml version="1.0"?>
<container version="1.0"
xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<rootfiles>
<rootfile full-path="Ops/content.opf"
media-type="application/oebps-package+xml"/>
</rootfiles>
</container>

C’est dans ce fichier OPF que tout va se passer. Voici mes quatre méthodes pour trouver les couvertures, à essayer par ordre de priorité :

1– Rechercher une balise <meta> avec pour nom « cover ». Si elle existe, son contenu référence la balise <item> qui contient la couverture.

En XPath, le chemin de la couverture donnerait quelque chose comme //item[id=//meta[name='cover']/@content]/@href

<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="BookId">
<metadata xmlns:opf="http://www.idpf.org/2007/opf">
  <meta name="cover" content="img1"/>
</metadata>
<manifest>
<item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml"/>
<item id="style" href="style.css" media-type="text/css"/>
<item id="id1" href="1.html" media-type="application/xhtml+xml"/>
<item id="id2" href="2.html" media-type="application/xhtml+xml"/>
<!-- ... -->
<item id="id13" href="13.html" media-type="application/xhtml+xml"/>
<item id="img1" href="images/img1.jpg" media-type="image/jpeg"/>
<item id="img2" href="images/img2.jpg" media-type="image/jpeg"/>
</manifest>
</package>

2– Rechercher, dans la liste des <item> celui qui a « cover-image » dans son attribut @properties. Il faut regarder l’ensemble de l’attribut. Ce dernier peut contenir plusieurs valeurs séparées par des espaces.

En XPath ce serait quelque chose de proche de //item[@properties and contains(@properties,'cover-image')]/@href

<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="BookId">
<metadata xmlns:opf="http://www.idpf.org/2007/opf"></metadata>
<manifest>
<item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml"/>
<item id="style" href="style.css" media-type="text/css"/>
<item id="id1" href="1.html" media-type="application/xhtml+xml"/>
<item id="id2" href="2.html" media-type="application/xhtml+xml"/>
<!-- ... -->
<item id="id13" href="13.html" media-type="application/xhtml+xml"/>
<item properties="cover-image" id="img1" href="images/img1.jpg" media-type="image/jpeg"/>
</manifest>
</package>

3– Rechercher, dans la liste des <reference> du <guide>, la première avec « cover » comme attribut @type. Le fichier référencé pourra être un fichier XHTML. Dans ce cas je considère comme couverture la première <img> de taille égale ou supérieure à 200×200 pixels (oui, c’est moche, mais je n’ai pas trouvé mieux).

En XPath ce serait quelque chose de proche de //reference[@type='cover']/@href en n’oubliant pas ensuite qu’on obtient un fichier XHTML et non une image.

<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="BookId">
<metadata xmlns:opf="http://www.idpf.org/2007/opf"></metadata>
<manifest>
<item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml"/>
<item id="style" href="style.css" media-type="text/css"/>
<item id="id1" href="1.html" media-type="application/xhtml+xml"/>
<!-- ... -->
<item id="id13" href="13.html" media-type="application/xhtml+xml"/>
</manifest>
<guide>
<reference type="cover" title="Cover image" href="1.html"/>
</guide>
</package>

4– Enfin, à défaut de mieux, je descend les trois premiers <item> du <manifest> jusqu’à trouver une <img> de taille égale ou supérieure à 200×200 pixels (oui, c’est encore plus moche que précédemment, je sais)

<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="2.0" unique-identifier="BookId">
<metadata xmlns:opf="http://www.idpf.org/2007/opf"></metadata>
<manifest>
<item media-type="application/x-dtbncx+xml"id="ncx" href="toc.ncx" />
<item media-type="text/css" id="style" href="style.css" />
<item media-type="application/xhtml+xml" id="id1" href="1.html" />
<item media-type="application/xhtml+xml" id="id2" href="2.html" />
<item media-type="application/xhtml+xml" id="id3" href="3.html" />
<item media-type="application/xhtml+xml" id="id4" href="4.html" />
<!-- ... -->
<item id="id13" href="13.html" media-type="application/xhtml+xml"/>
</manifest>
</package>

Malgré cela, certains livres n’ont pas de couverture, et d’autres auront une couverture SVG qui ne sera pas récupérable, même si c’est rare. Si vous voulez compléter ou préciser, n’hésitez pas.

Rejoindre la conversation

3 commentaires

  1. En attendant l’epub3 c’est malheureusement les seuls méthodes.
    Pour la dernière méthode je me suis contenté de considéré que la couverture était le premier html.

    En tout cas une implémentation ruby que j’ai fait pas très documenté pour le moment mais courte est ici https://github.com/banux/ruby-epub si ça peut aider.

  2. N’y-a-t-il pas plus simple pour les novices ?
    1. renommer le fichier epub en ajoutant .zip à la fin
    2. ouvrir le zip (double click ou développer le répertoire qui le contient dans l’explorateur Windows, lequel affiche normalement le contenu des archives zip)
    3. rechercher un fichier avec une extension image (.jpg a priori), normalement il n’y en a pas 36 et c’est la couverture
    4. l’ouvrir pour voir ce que c’est
    Ne pas oublier d’enlever ensuite le .zip pour retrouver un fichier en .epub

    1. Oh bien sûr. Mais je cherchais des traitements automatisés pour des développeurs, pas une procédure pour un ebook unique pour un lecteur final

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

À propos de ce site, du contenu, de l'auteur
Je poste parfois ici des humeurs ou des pensées. Parfois je change, parfois je me trompe, parfois j'apprends, et souvent le contexte lui-même évolue avec le temps. Les contenus ne sont représentatifs que de l'instant où ils ont été écrits. J'efface peu les contenus de ce site, merci de prendre du recul quand les textes sont anciens. Merci

À toutes fins utiles, ce site est hébergé par OVH SAS, joignable par téléphone au +33 (0)9 72 10 10 07 et dont le siège social est au 2 rue Kellermann, 59100 Roubaix, France.