Transformer un Livret papier (pages format paysage pliées) en fichier PDF

.

Une interface graphique permet de sélectionner le dossier où les fichiers images (scannés) sont placés : il s'agit d'images scannées en paysage recto/verso d'un livret plié et relié par son milieu.

Choisir si les images doivent être converties en Niveaux de gris ou conservés dans le format d'origine.

Possibilité de nommer les fichiers images et le fichier PDF.

Méthode

"Défaire" le livret en pages séparées afin d'être scannées.

Dans un premier temps, choisir le format d'image puis lancer "Découpe !"

Le programme crée un dossier "decoupe" où il place les images coupées par la moitié et les numérote.

Dans un deuxième temps, les images sont placées dans un fichier PDF.

Simulation

1
# Python 3.7
2
import PIL.Image
3
from PIL import ImageOps
4
import os
5
from tkinter.messagebox import * # boîte de dialogue
6
from tkinter import *
7
from tkinter import filedialog
8
import tkinter as tk
9
import glob
10
import sys
11
from fpdf import FPDF
12
13
def jpgtopdf(Nom):
14
    listeimage =  glob.glob('decoupe/*.jpg')
15
    listeimage.sort()
16
17
    pdf = FPDF(orientation = 'P', format = 'A4')
18
    pdf.set_auto_page_break(0)
19
20
    for image in listeimage:
21
        pdf.add_page()
22
        pdf.image(image, x = 0, y = 0, w = 210, h = 297, type = '', link = '')
23
    pdf.output("decoupe"+"/"+Nom+".pdf", "F")
24
25
def CoupeI(file,i,Nom,coul):
26
    original =  PIL.Image.open(file)
27
    largeur, hauteur = original.size
28
    if coul=="1":
29
        original = ImageOps.grayscale(original)
30
        original = ImageOps.autocontrast(original,
31
        cutoff=3)
32
    os.makedirs('decoupe', exist_ok=True)
33
34
    compteur=0
35
    objet = os.scandir()
36
    for entry in objet:
37
        if entry.is_file():
38
            compteur=compteur+1
39
40
    if (i % 2) == 0:
41
        if i>=9:
42
            zero = str('')
43
        else:
44
            zero = str('0')
45
        # Page Gauche
46
        image1 = ImageOps.fit(original,
47
        size=(original.size[0]//2, original.size[1]),centering=(0.0, 0.0))
48
        chemin1='decoupe'+'/'+Nom+'_p'+ f"{(2*compteur-i):04d}.jpg"
49
        image1.save(chemin1)
50
        # Page Droite
51
        image2 = ImageOps.fit(original,
52
        size=(original.size[0]//2, original.size[1]),centering=(1, 0.0))
53
        chemin2='decoupe'+'/'+Nom+'_p'+f"{(i+1):04d}.jpg"
54
        image2.save(chemin2)
55
    else:
56
        if i>=9:
57
            zero = str('')
58
        else:
59
            zero = str('0')
60
        # Page Gauche
61
        image1 = ImageOps.fit(original,
62
        size=(original.size[0]//2, original.size[1]),centering=(0.0, 0.0))
63
        chemin1='decoupe'+'/'+Nom+'_p'+f"{(i+1):04d}.jpg"
64
        image1.save(chemin1)
65
        # Page Droite
66
        image2 = ImageOps.fit(original,
67
        size=(original.size[0]//2, original.size[1]),centering=(1, 0.0))
68
        chemin2='decoupe'+'/'+Nom+'_p'+ f"{(2*compteur-i):04d}.jpg"
69
        image2.save(chemin2)
70
71
def valgris(v):
72
    coul=str(v.get())
73
74
    tk.Label(Mafenetre, text = 'Préfixe Fichier(s) extraits ?', bg='white', font=("Arial", 11)).grid(row=6)
75
    NomF = tk.Entry(Mafenetre, bg='white', fg='blue', font=("Arial", 11))
76
    NomF.grid(row=6, column=1)
77
78
    LancerPrg = tk.Button(Mafenetre, text ='Découpe !', fg='blue', font=("Arial", 12, "bold"), command=lambda: Lancer(NomF,coul))
79
    LancerPrg.grid(row=7, column=1, sticky='ew' )
80
81
def Lancer(NomF, coul):
82
    Nom=str(NomF.get())
83
    print('Découpe en cours')
84
    i = 0
85
    for file in glob.glob("*.jpg"):
86
        CoupeI(file,i,Nom,coul)
87
        i=i+1
88
89
    jpgtopdf(Nom)
90
    print('Fini !')
91
92
def Fin():
93
    Mafenetre.destroy
94
    Mafenetre.mainloop()
95
    sys.exit()
96
97
def ChangeD():
98
    Dossier = tk.filedialog.askdirectory ( title = "Sélectionnez un dossier ...")
99
    os.chdir(Dossier)
100
101
    compteur=0
102
    objet = os.scandir()
103
    for entry in objet:
104
        if entry.is_file():
105
            compteur=compteur+1
106
107
    titre = StringVar()
108
    titre.set('Nombre de fichiers :'+str(compteur))
109
    monAffichage = Label(Mafenetre, textvariable = titre,  bg='lightgreen', font=("Arial", 12, 'bold'))
110
    monAffichage.grid(row=3, columnspan=3, sticky='ew' )
111
112
    # Niveaux de Gris ?
113
    couleur = StringVar()
114
    couleur.set('Mode couleur :')
115
    monAffichage = Label(Mafenetre, textvariable = couleur,bg='white', font=("Arial", 11))
116
    monAffichage.grid(row=4,column=0, sticky='ew' )
117
118
    v = IntVar()
119
    B1 = Radiobutton(Mafenetre, text="Niveaux de Gris", variable=v, value=1,bg='white',
120
    command=lambda: valgris(v))
121
    B1.grid(row=4,column=1, sticky='ew')
122
123
    B2 = Radiobutton(Mafenetre, text="Normal", variable=v, value=2,bg='white',
124
    command=lambda: valgris(v))
125
    B2.grid(row=5,column=1, sticky='ew' )
126
127
# Programme  Princpipal
128
129
# Création de la fenêtre principale (main window)
130
Mafenetre = tk.Tk()
131
Mafenetre.title('Découpe de fichiers JPG')
132
# Taille de la fenêtre
133
Mafenetre.geometry('450x300')
134
Mafenetre.configure(bg='white')
135
Mafenetre.columnconfigure ( 0 , minsize = 200 , weight = 1 )
136
Mafenetre.columnconfigure ( 1 , minsize = 100 , weight = 1 )
137
138
debut = StringVar()
139
debut.set('Récupération du Dossier')
140
monAffichage = Label(Mafenetre, textvariable = debut,  bg='lightblue', font=("Arial", 12, 'bold'))
141
monAffichage.grid(row=0, columnspan=3, sticky='ew' )
142
143
# widget bouton Changer de Fichier
144
ChangeDossier = tk.Button(Mafenetre, text ='Dossier', fg='blue', font=("Arial", 12, "bold"), command= ChangeD)
145
ChangeDossier.grid(row=1, column=0, sticky='ew' )
146
# widget bouton Quitter
147
Quitter = tk.Button(Mafenetre, text ='Quitter', font=("Arial", 12, "bold"), command = Mafenetre.destroy)
148
Quitter.grid(row=1, column=2)
149
150
Mafenetre.mainloop()
151