K
Ken Roberts
Here's a quick routine that I hacked out to verify UPC-A/E and EAN-13/8 barcodes.
Anyone have any suggestions how to improve it?
================== Test script ==============
import ean
# Below codes taken from http://www.barcodeisland.com examples
# UPC-E codes to expand/verify
e = { 0: '01278907',
1: '01278916',
2: '01278925',
3: '01238935',
4: '01248934',
5: '01258933',
6: '01268932',
7: '01278931',
8: '01288930',
9: '01298939',
10: '01291944',
11: '01291155',
12: '01291162',
13: '01291179',
14: '01291186' }
# UPC-A codes to verify/compress
a = { 0: '012000007897',
1: '012100007896',
2: '012200007895',
3: '012300000895',
4: '012400000894',
5: '012500000893',
6: '012600000892',
7: '012700000891',
8: '012800000890',
9: '012900000899',
10: '012910000094',
11: '012911000055',
12: '012911000062',
13: '012911000079',
14: '012911000086' }
print 'checking upca2e ...'
for i in a.keys():
t1=a
t2=ean.upca2e(t1)
print 'key ', i, ':', t1, ean.upcaValid(t1)
print 'upce', i, ':', t2, ean.upceValid(t2)
print
print 'Checking upce2a ...'
for i in e.keys():
t1=e
print 'key', i, ':', t1, ean.upceValid(t1)
================ Barcode script ==============
"""
ean.py
See http://www.barcodeisland.com for UPC/EAN specs
Routines for verifying UPC/EAN codes and generating check digit
UPC-A is actually EAN13 code with a "0" prepended to it. The Barcode
Association has designated that all programs should be converted to
EAN by Jan 01, 2005.
Routines for UPC-A/UPC-E barcodes.
UPC is basically EAN13 with an extra leading '0' to bring the length
to 13 characters.
Check digit is calculated using ean13CheckDigit('0'+UPCA).
UPC-A is 12 characters in length with [12] being the check digit.
UPC-E is a compressed (convoluted algorithm) UPC-A with extraneous
middle 0 digits removed.
"""
__version__ = "$Revision: 0.4$"
codeLength = { "EAN13": 13,
"EAN8": 8,
"UPCA": 12,
"UPCE": 8 }
def __lenCheck(chk, _type='EAN13'):
return (len(chk) == codeLength[_type]) or \
(len(chk) == codeLength[_type]-1)
def __sumDigits(chk, start=0, end=1, step=2, mult=1):
return reduce(lambda x, y: int(x)+int(y), list(chk[start:end:step])) * mult
def eanCheckDigit(chk, code='EAN13'):
"""Returns the checksum digit of an EAN-13/8 code"""
if chk.isdigit() and __lenCheck(chk):
if code == 'EAN13':
m0=1
m1=3
elif code == 'EAN8':
m0=3
m1=1
else:
return None
_len = codeLength
Anyone have any suggestions how to improve it?
================== Test script ==============
import ean
# Below codes taken from http://www.barcodeisland.com examples
# UPC-E codes to expand/verify
e = { 0: '01278907',
1: '01278916',
2: '01278925',
3: '01238935',
4: '01248934',
5: '01258933',
6: '01268932',
7: '01278931',
8: '01288930',
9: '01298939',
10: '01291944',
11: '01291155',
12: '01291162',
13: '01291179',
14: '01291186' }
# UPC-A codes to verify/compress
a = { 0: '012000007897',
1: '012100007896',
2: '012200007895',
3: '012300000895',
4: '012400000894',
5: '012500000893',
6: '012600000892',
7: '012700000891',
8: '012800000890',
9: '012900000899',
10: '012910000094',
11: '012911000055',
12: '012911000062',
13: '012911000079',
14: '012911000086' }
print 'checking upca2e ...'
for i in a.keys():
t1=a
t2=ean.upca2e(t1)
print 'key ', i, ':', t1, ean.upcaValid(t1)
print 'upce', i, ':', t2, ean.upceValid(t2)
print 'Checking upce2a ...'
for i in e.keys():
t1=e
print 'key', i, ':', t1, ean.upceValid(t1)
================ Barcode script ==============
"""
ean.py
See http://www.barcodeisland.com for UPC/EAN specs
Routines for verifying UPC/EAN codes and generating check digit
UPC-A is actually EAN13 code with a "0" prepended to it. The Barcode
Association has designated that all programs should be converted to
EAN by Jan 01, 2005.
Routines for UPC-A/UPC-E barcodes.
UPC is basically EAN13 with an extra leading '0' to bring the length
to 13 characters.
Check digit is calculated using ean13CheckDigit('0'+UPCA).
UPC-A is 12 characters in length with [12] being the check digit.
UPC-E is a compressed (convoluted algorithm) UPC-A with extraneous
middle 0 digits removed.
"""
__version__ = "$Revision: 0.4$"
codeLength = { "EAN13": 13,
"EAN8": 8,
"UPCA": 12,
"UPCE": 8 }
def __lenCheck(chk, _type='EAN13'):
return (len(chk) == codeLength[_type]) or \
(len(chk) == codeLength[_type]-1)
def __sumDigits(chk, start=0, end=1, step=2, mult=1):
return reduce(lambda x, y: int(x)+int(y), list(chk[start:end:step])) * mult
def eanCheckDigit(chk, code='EAN13'):
"""Returns the checksum digit of an EAN-13/8 code"""
if chk.isdigit() and __lenCheck(chk):
if code == 'EAN13':
m0=1
m1=3
elif code == 'EAN8':
m0=3
m1=1
else:
return None
_len = codeLength
Code:
-1
t = 10 - (( __sumDigits(chk, start=0, end=_len, mult=m0) + \
__sumDigits(chk, start=1, end=_len, mult=m1) ) %10 ) %10
if t == 10:
return 0
else:
return t
return None
def ean13Valid(chk):
"""Verify if code is valid EAN13 barcode. Returns True|False"""
return chk.isdigit() and __lenCheck(chk) and \
(int(chk[-1]) == eanCheckDigit(chk))
def ean8CheckDigit(chk):
"""Returns the checksum digit of an EAN8 code"""
return eanCheckDigit(chk, code='EAN8')
def ean8Valid(chk):
"""Verify if code is valid EAN8 barcode. Returns True|False"""
if chk.isdigit() and len(chk) == codeLength["EAN8"]:
return int(chk[-1]) == ean8CheckDigit(chk)
return False
# UPC codes below
def upcaCheckDigit(chk):
if chk is not None:
return eanCheckDigit('0'+chk)
return None
def upcaValid(chk):
if chk is not None:
return ean13Valid('0'+chk)
return False
def upca2e(chk):
t = None
if chk.isdigit() and __lenCheck(chk, 'UPCA'):
if '012'.find(chk[3]) >= 0 and chk[4:8] == '0000':
t=chk[:3]+chk[8:11]+chk[3]
elif chk[4:9] == '00000':
t=chk[:4]+chk[9:11]+'3'
elif chk[5:10] == '00000':
t = chk[:5]+chk[10]+'4'
elif '5678'.find(chk[10]) >= 0 and chk[6:10] == '0000':
t=chk[:6]+chk[10]
else:
t=None
# Check digit
if t is not None:
if upcaValid(chk):
t=t+chk[-1]
elif len(chk) == codeLength["UPCA"]-1:
t=t+str(upcaCheckDigit(chk))
else:
t=None
return t
def upce2a(chk):
t=None
if chk.isdigit() and __lenCheck(chk, 'UPCE'):
if '012'.find(chk[6]) >= 0:
t=chk[:3]+chk[6]+'0000'+chk[3:6]
elif chk[6] == '3':
t=chk[:4]+'00000'+chk[4:6]
elif chk[6] == '4':
t=chk[:5]+'00000'+chk[5]
elif '5678'.find(chk[6]) >= 0:
t=chk[:6]+'0000'+chk[6]
else:
t=None
if t is not None:
if len(chk) == codeLength["UPCE"] - 1:
t=t+str(upcaCheckDigit(t))
elif len(chk) == codeLength['UPCE'] and \
int(chk[-1]) == upcaCheckDigit(t):
t=t+chk[-1]
else:
t=None
return t
def upceValid(chk):
return len(chk) == codeLength["UPCE"] and upcaValid(upce2a(chk))
def upceCheckDigit(chk):
if chk is not None:
return upcaCheckDigit(upce2a(chk))
return None