1 '''
2 Copyright (C) 2007 Martin Owens
4 Thanks to Lineaire Chez of Inkbar ( www.inkbar.lineaire.net )
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 '''
21 import EAN13
22 from EAN13 import mapLeftFaimly, guardBar, centerBar
23 import sys
25 mapFamily = [ '000111','001011','001101','001110','010011','011001','011100','010101','010110','011010' ]
27 class Object(EAN13.Object):
28 def encode(self, number):
29 result = ''
31 l = len(number)
33 if (l != 6 and l != 7 and l != 11 and l != 12) or not number.isdigit():
34 sys.stderr.write("Can not encode '" + number + "' into UPC-E Barcode, Size must be 6 numbers only, and 1 check digit (optional)\nOr a convertable 11 digit UPC-A number with 1 check digit (also optional).\n")
35 return
37 echeck = None
38 if l==7 or l==12:
39 echeck = number[-1]
40 number = number[:-1]
41 sys.stderr.write("CHECKSUM FOUND!")
42 l -= 1
44 if l==6:
45 number = self.ConvertEtoA(number)
47 if not echeck:
48 echeck = self.getChecksum(number)
49 else:
50 if not self.verifyChecksum(number + echeck):
51 sys.stderr.write("UPC-E Checksum not correct for this barcode, omit last character to generate new checksum.\n")
52 return
54 number = self.ConvertAtoE(number)
55 if not number:
56 sys.stderr.write("UPC-A code could not be converted into a UPC-E barcode, please follow the UPC guide or enter a 6 digit UPC-E number..\n")
57 return
59 number = number
61 result = result + guardBar
62 # The check digit isn't stored as bars but as a mirroring system. :-(
63 family = mapFamily[int(echeck)]
65 i = 0
66 for i in range(0,6):
67 result += mapLeftFaimly[int(family[i])-1][int(number[i])]
69 result = result + centerBar + '2';
71 self.label = '0 ' + number[:6] + ' ' + echeck
72 self.inclabel = self.label
73 return result;
75 def fontSize(self):
76 return '10'
78 def ConvertAtoE(self, number):
79 # Converting UPC-A to UPC-E
81 # All UPC-E Numbers use number system 0
82 if number[0] != '0' or len(number)!=11:
83 # If not then the code is invalid
84 return None
86 # Most of the conversions deal
87 # with the specific code parts
88 manufacturer = number[1:6]
89 product = number[6:11]
91 # There are 4 cases to convert:
92 if manufacturer[2:] == '000' or manufacturer[2:] == '100' or manufacturer[2:] == '200':
93 # Maxium number product code digits can be encoded
94 if product[:2]=='00':
95 return manufacturer[:2] + product[2:] + manufacturer[2]
96 elif manufacturer[3:5] == '00':
97 # Now only 2 product code digits can be used
98 if product[:3]=='000':
99 return manufacturer[:3] + product[3:] + '3'
100 elif manufacturer[4] == '0':
101 # With even more manufacturer code we have less room for product code
102 if product[:4]=='0000':
103 return manufacturer[0:4] + product[4] + '4'
104 elif product[:4]=='0000' and int(product[4]) > 4:
105 # The last recorse is to try and squeeze it in the last 5 numbers
106 # so long as the product is 00005-00009 so as not to conflict with
107 # the 0-4 used above.
108 return manufacturer + product[4]
109 else:
110 # Invalid UPC-A Numbe
111 return None
113 def ConvertEtoA(self, number):
114 # Convert UPC-E to UPC-A
116 # It's more likly to convert this without fault
117 # But we still must be mindful of the 4 conversions
118 if len(number)!=6:
119 return None
121 if number[5]=='0' or number[5]=='1' or number[5]=='2':
122 return '0' + number[:2] + number[5] + '0000' + number[2:5]
123 elif number[5]=='3':
124 return '0' + number[:3] + '00000' + number[3:5]
125 elif number[5]=='4':
126 return '0' + number[:4] + '00000' + number[4]
127 else:
128 return '0' + number[:5] + '0000' + number[5]