Série d'exercices 3

Dans cette série d'exercices (de un exercice...), nous allons nous créer un générateur de codes-barres. Contrairement aux QR codes que nous abordons durant le projet (et qui sont aussi un type de code-barres), les codes-barres qui vont nous intéresser sont unidimensionnels et n'utilisent pas de correction (ni même de détection) d'erreurs.

Ressources :

Exercice 1

Pour ce premier et unique exercice, vous aller concevoir un générateur de code-barres de type Code 39.

Introduction

Le format Code 39 a été créé en 1974 et est encore utilisé de nos jours, bien que l'usage de ce format diminue avec le temps au profit d'autres types de codes-barres.

Un code-barres Code 39 qui contient le message *BONJOUR*,
ici avec les délimiteurs de début et de fin de message explicitement affichés.

Alphabet

Les codes-barres de type Code 39 peuvent contenir des messages constitués de lettres majuscules, de chiffres, ainsi que de quelques caractères spéciaux (-, ., espace), soit un total de 39 possibilités. On compte un 40ième caractère, *, qui délimite le début et la fin du message. Ce caractère ne peut pas faire partie du reste du message.

Les 40 caractères de l'alphabet supporté par le format sont listés ci-dessous. À chaque caractère correspond un index entre 0 et 39.

Caractère Index Caractère Index Caractère Index Caractère Index
1 00 A 10 K 20 U 30
2 01 B 11 L 21 V 31
3 02 C 12 M 22 W 32
4 03 D 13 N 23 X 33
5 04 E 14 O 24 Y 34
6 05 F 15 P 25 Z 35
7 06 G 16 Q 26 - 36
8 07 H 17 R 27 . 37
9 08 I 18 S 28 espace 38
0 09 J 19 T 29 * 39

Encodage des caractères

À chacun des caractères correspond une séquence de barres : 5 barres noires séparées par 4 barres blanches. Parmi les barres noires, 2 barres sont plus épaisses et 3 sont fines (soit 10 combinaisons différentes possibles). Parmi les blanches, une seule barre est de plus grande largeur (soit 4 combinaisons possibles).

L'index du caractère dans la liste des symboles indique de manière unique la paire de combinaisons choisie: les dizaines indiquent la combinaison pour les barres blanches, les unités indiquent la combinaison pour les barres noires.

Le tableau suivant liste les différentes combinaisons de largeurs utilisées en fonction de l'index du caractère à encoder :

Index Barres Index Barres Index Barres Index Barres
00 10 20 30
01 11 21 31
02 12 22 32
03 13 23 33
04 14 24 34
05 15 25 35
06 16 26 36
07 17 27 37
08 18 28 38
09 19 29 39

Encodage des messages

Pour encoder un message, le caractère délimiteur * est ajouté au début et à la fin du message. Ensuite, les caractères du message sont convertis de manière indépendante en une série de barres de largeurs variables tel que l'on a pu le voir plus haut. Le message est affiché de gauche à droite. Entre chaque deux caractères est intercallé une barre blanche de largeur simple.

Définitions pour vous aider

Pour cet exercice, vous pouvez, si vous le souhaitez, vous aider des définitions suivantes :

# Liste des symboles
symboles = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ-. *"

# Largeur des barres noires (1 = fin, 2 = épais)
noirs = [
    [2, 1, 1, 1, 2],  # Pour les index X0
    [1, 2, 1, 1, 2],  # Pour les index X1
    [2, 2, 1, 1, 1],  # Pour les index X2
    [1, 1, 2, 1, 2],  # Pour les index X3
    [2, 1, 2, 1, 1],  # Pour les index X4
    [1, 2, 2, 1, 1],  # Pour les index X5
    [1, 1, 1, 2, 2],  # Pour les index X6
    [2, 1, 1, 2, 1],  # Pour les index X7
    [1, 2, 1, 2, 1],  # Pour les index X8
    [1, 1, 2, 2, 1],  # Pour les index X9
]

# Largeur des barres blanches (1 = fin, 2 = épais)
blancs = [
    [1, 2, 1, 1],  # Pour les index 0X
    [1, 1, 2, 1],  # Pour les index 1X
    [1, 1, 1, 2],  # Pour les index 2X
    [2, 1, 1, 1],  # Pour les index 3X
]

Étape 1 - Encodage des caractères

Comme première étape, implémentez la fonction encode_caractere qui prend en argument un caractère et retourne une liste contenant la largeur des barres qui encodent ce caractère. Dans la liste de retour, on utilisera le nombre 1 pour indiquer une barre fine et le nombre 2 pour une barre épaisse.

Comme les barres alternent entre le noir et le blanc, nous n'avons pas besoin d'inclure l'information de la couleur de manière explicite dans la valeur de retour de la fonction: le premier élément correspond toujours à la couleur noire, le deuxième à la couleur blanche, et ainsi de suite.

Pour donner quelques exemples des résultats attendus :

Indice : Utilisez la méthode index pour retourner l'index d'un élément dans une liste ou un chaîne de caractère.

Étape 2 - Encodage des messages

Dans un deuxième temps, définissez la fonction encode_message pour encoder une chaîne de caractères. Attention aux points suivants :

En guise d'exemple, le résultat attendu pour la chaîne EPFL est :

[1, 2, 1, 1, 2, 1, 2, 1, 1, 1, 2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1, 2, 1, 1, 2, 1, 2, 1, 1]

Étape 3 - Affichage des codes-barres

Dans cette troisième et dernière étape, le but sera de définir la fonction affiche_code_barres. La fonction prend en argument une liste de 1 et de 2 (telle que retournée par la fonction encode_message par exemple). En retour, la fonction retourne une image de la librairie Pillow qui représente le code-barres.

Le format spécifie que les barres épaisses doivent être entre deux et trois fois plus large que les fines. Dans les exemples affichés plus haut, nous avons utilisé une largeur double pour les barres épaisses.

Indice : Calculez les dimensions de l'images en inspectant la liste passée en argument.

Suggestion d'interface

Vous pouvez ajouter les lignes suivantes à votre programme afin d'offrir une interface minimaliste. Libre à vous d'en fournir une meilleure !

if __name__ == "__main__":
    print("Entrez votre message: ", end="")
    message = input()
    tailles = encode_message(message)
    img = affiche_code_bar(tailles)
    img.show()

Aller plus loin

Voici quelques idées d'amélioration :