Last active
August 29, 2015 14:05
-
-
Save iljamaas/9741965d373cb2ed94ea to your computer and use it in GitHub Desktop.
Simple code to create a very clean SVG EAN13 code.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Ean13BarcodeException(Exception): | |
pass | |
class Ean13Barcode(object): | |
"""Generate a SVG for a given EAN13 code with a specified width and height""" | |
def __init__(self, width, height, colorstring='rgb(0,0,0)'): | |
self.width = width | |
self.height = height | |
self.colorstring = colorstring | |
self.codes = { | |
'A': ['0001101', '0011001', '0010011', '0111101', '0100011', | |
'0110001', '0101111', '0111011', '0110111', '0001011'], | |
'B': ['0100111', '0110011', '0011011', '0100001', '0011101', | |
'0111001', '0000101', '0010001', '0001001', '0010111'], | |
'C': ['1110010', '1100110', '1101100', '1000010', '1011100', | |
'1001110', '1010000', '1000100', '1001000', '1110100'], | |
} | |
self.parities = [ | |
('A', 'A', 'A', 'A', 'A', 'A'), | |
('A', 'A', 'B', 'A', 'B', 'B'), | |
('A', 'A', 'B', 'B', 'A', 'B'), | |
('A', 'A', 'B', 'B', 'B', 'A'), | |
('A', 'B', 'A', 'A', 'B', 'B'), | |
('A', 'B', 'B', 'A', 'A', 'B'), | |
('A', 'B', 'B', 'B', 'A', 'A'), | |
('A', 'B', 'A', 'B', 'A', 'B'), | |
('A', 'B', 'A', 'B', 'B', 'A'), | |
('A', 'B', 'B', 'A', 'B', 'A') | |
] | |
def generate(self, barcode, generate_controldigit=True): | |
"""the controldigit is the 13th digit which is a checksum. | |
Most likely you want this code to calculate it for you""" | |
barcode = str(barcode) | |
# Some sanity first. | |
if generate_controldigit and len(barcode) > 12: | |
raise Ean13BarcodeException('Length already 13 digits, cannot add controldigit') | |
if generate_controldigit and len(barcode) <= 12: | |
barcode = barcode.rjust(12, '0') | |
barcode = "%s%s" % (barcode, self.create_controldigit(barcode)) | |
elif len(barcode) < 13: | |
barcode = barcode.rjust(13, '0') | |
if not generate_controldigit and not self.check_controldigit(barcode): | |
raise Ean13BarcodeException('Control digit is not correct! (13th digits)') | |
# Generate 'bit'-range | |
code = ['101'] | |
p = self.parities[int(barcode[0])] | |
for i in range(1, 7): | |
code.append(self.codes[p[i-1]][int(barcode[i])]) | |
code.append('01010') | |
for i in range(7, 13): | |
code.append(self.codes['C'][int(barcode[i])]) | |
code.append('101') | |
# Create the svg | |
return self._svg(self._stack(''.join(code))) | |
def _svg(self, stack): | |
x = 0 | |
bars = [] | |
sbw = self.width / sum(stack) | |
for i, e in enumerate(stack): | |
w = e * sbw | |
if not i % 2: # only 'odd' ones should be painted | |
bars.append('<rect width="%s" height="%s" x="%s" y="0" style="fill:%s;"/>' % | |
(w, self.height, x, self.colorstring)) | |
x += w | |
return '<svg width="%s" height="%s">%s</svg>' % (self.width, self.height, "\n".join(bars)) | |
@staticmethod | |
def _stack(bitseries): | |
currentbit = '1' | |
rv = [0] | |
for i in bitseries: | |
if i == currentbit: | |
rv[len(rv)-1] += 1 | |
else: | |
currentbit = i | |
rv.append(1) | |
return rv | |
@classmethod | |
def check_controldigit(cls, code): | |
assert(len(code) == 13) | |
c = code[0:12] | |
r = int(code[12:13]) | |
return r == cls.create_controldigit(c) | |
@classmethod | |
def create_controldigit(cls, code): | |
assert(len(code) == 12) | |
s = 0 | |
for i in range(1, 12, 2): | |
s += 3 * int(code[i]) | |
for i in range(0, 11, 2): | |
s += int(code[i]) | |
r = s % 10 | |
if r > 0: | |
r = 10 - r | |
return r |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment