116 lines
2.2 KiB
Python
116 lines
2.2 KiB
Python
|
#!/usr/bin/env python
|
||
|
# -*- coding: utf-8 -*-
|
||
|
"""
|
||
|
This module can generate EAN-8 and EAN-13 barcodes
|
||
|
|
||
|
(C) 2022 Louis Heredero louis.heredero@edu.vs.ch
|
||
|
"""
|
||
|
|
||
|
import pygame
|
||
|
|
||
|
A = [
|
||
|
0b0001101,
|
||
|
0b0011001,
|
||
|
0b0010011,
|
||
|
0b0111101,
|
||
|
0b0100011,
|
||
|
0b0110001,
|
||
|
0b0101111,
|
||
|
0b0111011,
|
||
|
0b0110111,
|
||
|
0b0001011
|
||
|
]
|
||
|
|
||
|
# XOR 0b1111111
|
||
|
C = list(map(lambda a: a^127, A))
|
||
|
|
||
|
# Reverse bit order
|
||
|
B = list(map(lambda c: int(f"{c:07b}"[::-1], 2), C))
|
||
|
|
||
|
ean13_patterns = [
|
||
|
"AAAAAA",
|
||
|
"AABABB",
|
||
|
"AABBAB",
|
||
|
"AABBBA",
|
||
|
"ABAABB",
|
||
|
"ABBAAB",
|
||
|
"ABBBAA",
|
||
|
"ABABAB",
|
||
|
"ABABBA",
|
||
|
"ABBABA"
|
||
|
]
|
||
|
|
||
|
def bin_list(n):
|
||
|
return list(map(int, f"{n:07b}"))
|
||
|
|
||
|
def luhn(digits):
|
||
|
checksum = sum([
|
||
|
digits[-i-1]*(3-i%2*2)
|
||
|
for i in range(len(digits))
|
||
|
])
|
||
|
ctrl_key = 10 - checksum%10
|
||
|
if ctrl_key == 10:
|
||
|
ctrl_key = 0
|
||
|
|
||
|
return ctrl_key
|
||
|
|
||
|
def ean8(digits):
|
||
|
digits.append(luhn(digits))
|
||
|
elmts = []
|
||
|
|
||
|
elmts += [1,0,1] #delimiter
|
||
|
for digit in digits[:4]:
|
||
|
elmts += bin_list(A[digit])
|
||
|
|
||
|
elmts += [0,1,0,1,0] #middle delimiter
|
||
|
for digit in digits[4:]:
|
||
|
elmts += bin_list(C[digit])
|
||
|
|
||
|
elmts += [1,0,1] #delimiter
|
||
|
return elmts
|
||
|
|
||
|
def ean13(digits):
|
||
|
pattern = ean13_patterns[digits[0]]
|
||
|
digits.append(luhn(digits))
|
||
|
elmts = []
|
||
|
|
||
|
elmts += [1,0,1] #delimiter
|
||
|
for d in range(1,7):
|
||
|
_ = A if pattern[d-1] == "A" else B
|
||
|
digit = digits[d]
|
||
|
elmts += bin_list(_[digit])
|
||
|
|
||
|
elmts += [0,1,0,1,0] #middle delimiter
|
||
|
for digit in digits[7:]:
|
||
|
elmts += bin_list(C[digit])
|
||
|
|
||
|
elmts += [1,0,1] #delimiter
|
||
|
return elmts
|
||
|
|
||
|
def draw_barcode(barcode, win):
|
||
|
width = win.get_width()*0.8
|
||
|
height = win.get_height()*0.5
|
||
|
bar_w = width/len(barcode)
|
||
|
rnd_bar_w = round(bar_w)
|
||
|
|
||
|
win.fill((255,255,255))
|
||
|
x = win.get_width()*0.1
|
||
|
y = win.get_height()*0.25
|
||
|
|
||
|
for c in barcode:
|
||
|
if c:
|
||
|
pygame.draw.rect(win, (0,0,0), [x, y, rnd_bar_w, height])
|
||
|
|
||
|
x += bar_w
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
import base
|
||
|
|
||
|
b = base.Base(800, 500, "EAN-8 / EAN-13 barcode generator")
|
||
|
|
||
|
#barcode = ean8([8,4,2,7,3,7,2])
|
||
|
barcode = ean13([9,7,8,2,9,4,0,6,2,1,0,5])
|
||
|
|
||
|
draw_barcode(barcode, b.w)
|
||
|
|
||
|
b.main()
|