\section{Application in Python} \label{sec:barcode_python} In this section, we will implement barcode generation in Python. We will first program a "Code-39" encoder, then an EAN-8 and finally an EAN-13. \subsection{Code-39} \label{ssec:code39_py} This type of code being just a matter of translating each character to a particular group of wide and narrow stripes, the implementation is quite simple. We first create a dictionary holding the codes for each character. \begin{minted}[frame=single]{python} code39_dict = { "A": "100001001", "B": "001001001", "C": "101001000", "D": "000011001", "E": "100011000", "F": "001011000", "G": "000001101", "H": "100001100", "I": "001001100", "J": "000011100", "K": "100000011", "L": "001000011", "M": "101000010", "N": "000010011", "O": "100010010", "P": "001010010", "Q": "000000111", "R": "100000110", "S": "001000110", "T": "000010110", "U": "110000001", "V": "011000001", "W": "111000000", "X": "010010001", "Y": "110010000", "Z": "011010000", "0": "000110100", "1": "100100001", "2": "001100001", "3": "101100000", "4": "000110001", "5": "100110000", "6": "001110000", "7": "000100101", "8": "100100100", "9": "001100100", " ": "011000100", "-": "010000101", "$": "010101000", "%": "000101010", ".": "110000100", "/": "010100010", "+": "010001010", "*": "010010100" } \end{minted} To convert a string, we map each character to its corresponding binary representation and join the resulting codes with "0" in between. \begin{minted}[frame=single]{python} def code39(text): text = text.upper() text = map(lambda c: code39_dict[c], text) return "0".join(text) \end{minted} We will also need a function to render the barcode. For this, we will use the Pygame module. \begin{minted}[frame=single]{python} def draw_barcode(barcode, win): barcode = list(map(int, barcode)) width = win.get_width()*0.8 height = win.get_height()*0.5 thicks = sum(barcode) thins = len(barcode)-thicks bar_w = width/(thicks*2+thins) win.fill((255,255,255)) x = win.get_width()*0.1 y = win.get_height()*0.25 for i, c in enumerate(barcode): w = 2*bar_w if c else bar_w if i%2 == 0: pygame.draw.rect(win, (0,0,0), [x, y, w, height]) x += w \end{minted} The full python script can be found in appendix \ref{app:code39_py} or on \hreffn{https://github.com/LordBaryhobal/5D\_Heredero\_Louis\_TM2022/blob/main/python/code39.py}{GitHub}. \subsection{EAN-8} \label{ssec:ean8_py} The first step to create an EAN-8 barcode is to compute the check digit with Luhn's formula. To make this function also usable for EAN-13, we need to redefine the formula as such: \begin{enumerate} \item Multiply each digit by the alternating factors 1 and 3 starting with 3 \textbf{from the end}. \item Add them together then take the modulo ten and subtract the result from 10. \item If the result is equal to 10, change it to 0. \end{enumerate} %Since this function will also be used for EAN-13, with only the factors changing, we will make it general enough. In python, the function multiplies the i\textsuperscript{th} to last digit by: \[ \text{factor} = 3 - (i\ mod\ 2) * 2 \] which basicly is step 1 above. \def\arraystretch{1.5} \begin{table}[H] \centering \begin{tabu}{|[2pt]c|[2pt]c|c|c|c|c|c|[2pt]} \tabucline[2pt]{-} i & ... & 4 & 3 & 2 & 1 & 0 \\ \hline factor & ... & 3 & 1 & 3 & 1 & 3 \\ \tabucline[2pt]{-} \end{tabu} \caption{Python Luhn formula example} \label{tab:luhn_py_ex} \end{table} \def\arraystretch{1} %\begin{minipage}{\linewidth} \begin{minted}[frame=single]{python} 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 \end{minted} %\end{minipage} Both code types also need the table of elements: \begin{minted}[frame=single]{python} 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)) \end{minted} The following function converts a number to the list of its bits: \begin{minted}[frame=single]{python} def bin_list(n): return list(map(int, f"{n:07b}")) \end{minted} Finally, the encoding function: \begin{minted}[frame=single]{python} 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 \end{minted} We will use a similar function as in \autoref{ssec:code39_py} to render the barcode \begin{minted}[frame=single]{python} def draw_barcode(barcode, win): width = win.get_width()*0.8 height = win.get_height()*0.5 bar_w = width/len(barcode) 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, bar_w, height]) x += bar_w \end{minted} The full python script can be found in appendix \ref{app:ean_py} or on \hreffn{https://github.com/LordBaryhobal/5D\_Heredero\_Louis\_TM2022/blob/main/python/ean.py}{GitHub} \subsection{EAN-13} \label{ssec:ean13_py} The main difference with EAN-8 is the encoding of the first digit, using an A/B pattern. We will create a list of these patterns: \begin{minted}[frame=single]{python} ean13_patterns = [ "AAAAAA", "AABABB", "AABBAB", "AABBBA", "ABAABB", "ABBAAB", "ABBBAA", "ABABAB", "ABABBA", "ABBABA" ] \end{minted} And the appropriate encoding function: \begin{minted}[frame=single]{python} 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 \end{minted} The full python script can be found in appendix \ref{app:ean_py} or on \hreffn{https://github.com/LordBaryhobal/5D\_Heredero\_Louis\_TM2022/blob/main/python/ean.py}{GitHub}