Receita para gerar código de barras
Geração de código padrão EAN-13 (utilizado em produtos de venda no varejo). Para outros tipos (por exemplo: código de barras para boleto bancário), esta receita não serve.
A imagem final pode ser em .gif ou .png e é necessária a instalação do PIL (http://www.pythonware.com/products/pil/).
* Este artigo é uma tradução da página: http://wikipython.flibuste.net/moin.py/GenerateurCodeBarre
( FIXME: e a licença dessas fontes (tipográficas) abaixo? Elas podem ser colocada assim ?)
EanBarCode.py
1 # courbB08.pil PIL Font file uuencoded
2 courB08_pil ="""eJztl91rFkcUxp+Zt7vGFYzVtiJKICgYlLRWkaBBVGgDraFGCH5gsQp+QMBqabAVRYJYAlakCkoh
3 CpYgxaLkIu1NvLBeSAStglpqL6xQAsVe2AuL5u2buH3mzGaYPf9AKWTl8d3nl7MzZ2bnazvea9+9
4 7+PurFWut5e0Zu+s7VybYfKavP7LK3X/5TlM4Q3/OWbyf1ARD/6mgb2SjwtPhbpnq0iKZ6ahrmCj
5 wqbxdgamRnHOA69jimN5zvIS8cDcUEeVdYzRAw1FHcJYXgPvG4s6Jlgj7xeEequS3wLeNvGvnrEO
6 tq+Jt82szT+b86+WHlgS2jHGuHF6YHnog1zaupxqCcy3t4X3rVG9iXhgjW+bsFQ80BaxRDywTrF1
7 VId6toPaqOI2UlsV20ptV2w7tUuxXVSXYl3UvoIZ9kFFPPBJ6D/HLD3QXbwjyDjI6YHPiz5FXiN7
8 SQ8cDu/N9/1h3veEOP/Oe6gvQnmuvYYe+NL3qYyNVDxw2seF8XKa+jrKJREPnFdx56l+xfqpS4pd
9 ogZUeQPU91FcKh64GveBeOCaKu8adUM9e4O6reJuU/cUu0c9VM8+pB6r/B5TI+rZEerPUpyhB/6K
10 5lsqHniuyntO1VR5Nb5CU86FHqZOsTqqXrF66o2ojlQ8zDwVN4+aX86FHqYpXg9YLeevWRzPc7LF
11 ZG+V1wN6mKXxvMzH6GFaJua5zGNLD7MqmtNcc+hh1oT1oCb5cf6aNj92mbPMGXqY9jCPasLaqQ1h
12 jMv8pYfZpOI2UR9GcYl4mB1RnMtvB9me8N583B5qb3mNoIf5NGJc1+hhPvPrrjybioc5op49Qh0L
13 dfj8jlHHQ3s9O059Fc3zRDzMmVKcpYfpU+3oI/umxJyH+TYqLxUPc0X13xVqMMovFQ8zpPIbon6M
14 WCoeZljVMUz9VIqz9DAP1Dt6QP0a9gpZ7+lhHhXjysreaOhhfiv1vaGH+T2Mv5rbU+hh/uAaOnlN
15 Xv+Hy4/7mtv3OW5hnpTODIYe5mm0xqbiYf4OcbLv08NU1ZyuuqKLOEvm6sjhJkd8TjRustgkrO3u
16 vFGjh60r1uyiPHrY6eH84tb7l/SwM8vrAT3snHgNY9wcsoby+Y8edn5UxxTxsIuitrlcFpG9GcVx
17 /6CHXRrKk72MHrYl3stYB/ceu7I4X02wlWSrCmaF1ehhV7NrovWKHrattI4betj20Fc8r7E87kf2
18 g+gcy32BHnZDfKZmHPco2xnl4vqlk2yz6r/N1EfRPpiKh90d7VGpeNi9inGPst2lNdbSwx4McS8k
19 7iDVE/Ytz3qoXsV6qZOKnaTOBDYqjPuRPRfOkz7uHNUf4uQMQg/7XekMYulhB6JnE/GwP0T1JuJh
20 ryrGM6G9HuWSiIcdDnPmhTs70sPeCuPes1vUXcXuUvcDGxV2n/olOisn4mEfhfOVby/3KDsSlZeI
21 h32iGOe0faoY57R9ptgzajTKJREPOx7aJnOfHhUbxov0Mz0qU8v50aMyo/wu6VGZrdhsqqH8fnll
22 HEEz4zj6DNMxK+4X+gyv8cszyoU+4zfmjNAO9zuXrNGXF1gj2ULFFpI1K9ZMtiww//22jGwFXg39
23 535XkK0O+cl5gz7Du6iP5wd9hvfDs9LP9BnWR/U6tp6sU7FOsi1RLo5tIdsWled+t5HtVO3YSdal
24 WBfZftW2/WQHVH4HyA6F9+GfPUR2VOV3lKxXsV6yE4qdIDul2Cmys6ptZ8n6Qi7+m7OP7ELoU/8t
25 dIHsoo8L+V0ku6xyvkw2qNgg2VBgvg+GyK6XyrP0GW5ydE3EuXd5k+xOeOdVibtD9jNm/Qv15O4i"""
26
27 # courbB08.pbm font file uuencoded
28 courB08_pbm ="""eJxNkntM01cUx8+P2/1apUAZEpECq4KRjKhF0E55FYEp4yG6mglz2Q8Q1BhERhhls/zKI+CID4wb
29 IAPKpk4GAzqZPKKMX2GIUwGJG+ImtKwKjIzXcGuBtncV0Hn+uLnn5Nzv55xv7mdRkbusVjquBACr
30 0N3B+wCQi/m+ijAf4LGl/wgAiwkNDpRIyyABSjGkBQ/fa3c1bfLs4U8ulDcYUs/502rTpIlO9pyc
31 Kp/Buql6f3rmZ1NqvpO2SZXf0duY3j0563zjoZpW8AvHRmVeZ/Co36mFR8bERzlsxOMJ+oJshsS5
32 7rlfzFzmnZFEFnIEZjTGizgLsLzjl4QtrNprBRu10e+u9GgePHjG63bPDw/H87uix0Vtsvkqg9qO
33 lUimPLiOM4z69YfqIu5Pa2Sr/io6n9Xmf9e+57W1Iapo4lLQBdLSWc/z3KOSlgznDXTW/Flh21kX
34 IeUIX8FZVL9dwP4NBH5jglYxkBNFmWgMcfsAxM/9gEL5TTwYpnfElR8qQ+WiCgeTHOAfb2bW/cQC
35 /FozFOOQzAebtjRvQLI7HBtXvaZe25a3Q/1vZpPa+kd1XXKuflr5Cm48YUsUcjMXjsm/sf+22s6z
36 QAbGZ8mEXMzSE4y9AHhRpltwB1N9ynz5H2MOi0MEi4E5O1ov9ogrFU5cMWAcdgQb3xHFtFK+0pkh
37 VnYWxltx92j69p6jJ9OnHr+Cq5x5X6Mz70JcX2tEG5LIShM4EHIGoLIRsHzcvEuGwMYA4DZPn7gP
38 MA1QIgltnt82cTu7j5n76mmz3TU5Bh3PFRTHku52aBgaTnJD7m1c0a3hNjbWWjBtMsP/OFac/LYA
39 NAAWepdYodB58NBFIuOjNSQ4cgXplqP2RyOe8fd999T8weqBRwLwNFdQobHgA1/YTV8PH+TwV59v
40 Bo7Y1J4rmHFv3T9e8rmmXdGSuPpSbBnhYJ7V8ICz6AfGcdTpRkpCUU8WcOT8wb+dSHIb6QZapx0M
41 Y2DO4i7jYV2AUNkkErpQFHVYmFRmYD7OJhDyQSiow4IkrS3TbpQqFA9slE4jnj6peXMTC+N8buJ2
42 0Uv5eOothuGIiluyCDtff3miBzJHjncOIC3bPT8FLabRPd0TCWy346Mmn9Rz23WyNMJcsnqhQani
43 3CMFOZuYU7c20zTNVqNbGPNxALWnybeLEcTvXWpc10leI5ae/CI9qBqI686cnO6P6F33e2vAp0nz
44 9+hnbNeueh/261UJK5aVeSf73ZSXA7dOBXvkXODEb9hVww4KtPNAbPvaZbi0q9kICCl+CiBJSzLv
45 a8TlntYlC4UHvCRTlaXOy13VAbN0eae2v3hNesWXLsWPkjfOPq7e6zd1fOfc1TckDaylrvleinnT
46 8Ui87ScLMVhhEx7SUJ8U2zKrRR2Z1dEqZlkr7kDTuhFjpkvse9ZXN0R9H+DlYA4TXVm6/kXDQMyT
47 eGnJFXlLlSgva5iLUEcbiyDzNqf4Wr9kKYVUIcY40DrnsW4E4zW9QxnHVYx+bo64mIskDWjZgCrq
48 eVQFrS7Sh/uFLftIidKWbgj6Oq652d4c3v88Dw2JDK7bSWX/ByuaLZI="""
49
50
51 class EanBarCode:
52 """ Compute the EAN bar code """
53 def __init__(self):
54 A = {0 : "0001101", 1 : "0011001", 2 : "0010011", 3 : "0111101", 4 : "0100011",
55 5 : "0110001", 6 : "0101111", 7 : "0111011", 8 : "0110111", 9 : "0001011"}
56 B = {0 : "0100111", 1 : "0110011", 2 : "0011011", 3 : "0100001", 4 : "0011101",
57 5 : "0111001", 6 : "0000101", 7 : "0010001", 8 : "0001001", 9 : "0010111"}
58 C = {0 : "1110010", 1 : "1100110", 2 : "1101100", 3 : "1000010", 4 : "1011100",
59 5 : "1001110", 6 : "1010000", 7 : "1000100", 8 : "1001000", 9 : "1110100"}
60 self.groupC = C
61
62 self.family = {0 : (A,A,A,A,A,A), 1 : (A,A,B,A,B,B), 2 : (A,A,B,B,A,B), 3 : (A,A,B,B,B,A), 4 : (A,B,A,A,B,B),
63 5 : (A,B,B,A,A,B), 6 : (A,B,B,B,A,A), 7 : (A,B,A,B,A,B), 8 : (A,B,A,B,B,A), 9 : (A,B,B,A,B,A)}
64
65
66 def makeCode(self, code):
67 """ Create the binary code
68 return a string which contains "0" for white bar, "1" for black bar, "L" for long bar """
69
70 # Convert code string in integer list
71 self.EAN13 = []
72 for digit in code:
73 self.EAN13.append(int(digit))
74
75 # If the code has already a checksum
76 if len(self.EAN13) == 13:
77 # Verify checksum
78 self.verifyChecksum(self.EAN13)
79 # If the code has not yet checksum
80 elif len(self.EAN13) == 12:
81 # Add checksum value
82 self.EAN13.append(self.computeChecksum(self.EAN13))
83
84 # Get the left codage class
85 left = self.family[self.EAN13[0]]
86
87 # Add start separator
88 strCode = 'L0L'
89
90 # Compute the left part of bar code
91 for i in range(0,6):
92 strCode += left[i][self.EAN13[i+1]]
93
94 # Add middle separator
95 strCode += '0L0L0'
96
97 # Compute the right codage class
98 for i in range (7,13):
99 strCode += self.groupC[self.EAN13[i]]
100
101 # Add stop separator
102 strCode += 'L0L'
103
104 return strCode
105
106
107 def computeChecksum(self, arg):
108 """ Compute the checksum of bar code """
109 # UPCA/EAN13
110 weight=[1,3]*6
111 magic=10
112 sum = 0
113
114 for i in range(12): # checksum based on first 12 digits.
115 sum = sum + int(arg[i]) * weight[i]
116 z = ( magic - (sum % magic) ) % magic
117 if z < 0 or z >= magic:
118 return None
119 return z
120
121
122 def verifyChecksum(self, bits):
123 """ Verify the checksum """
124 computedChecksum = self.computeChecksum(bits[:12])
125 codeBarChecksum = bits[12]
126
127 if codeBarChecksum != computedChecksum:
128 raise Exception ("Bad checksum is %s and should be %s"%(codeBarChecksum, computedChecksum))
129
130
131 def getImage(self, value, height = 50, extension = "PNG"):
132 """ Get an image with PIL library
133 value code barre value
134 height height in pixel of the bar code
135 extension image file extension"""
136 from PIL import Image, ImageFont, ImageDraw
137
138 # Create a missing font file
139 decodeFontFile(courB08_pil ,"courB08.pil")
140 decodeFontFile(courB08_pbm ,"courB08.pbm")
141
142 # Get the bar code list
143 bits = self.makeCode(value)
144
145 # Get thee bar code with the checksum added
146 code = ""
147 for digit in self.EAN13:
148 code += "%d"%digit
149
150 # Create a new image
151 position = 8
152 im = Image.new("1",(len(bits)+position,height))
153
154 # Load font
155 font = ImageFont.load("courB08.pil")
156
157 # Create drawer
158 draw = ImageDraw.Draw(im)
159
160 # Erase image
161 draw.rectangle(((0,0),(im.size[0],im.size[1])),fill=256)
162
163 # Draw first part of number
164 draw.text((0, height-9), code[0], font=font, fill=0)
165
166 # Draw first part of number
167 draw.text((position+7, height-9), code[1:7], font=font, fill=0)
168
169 # Draw second part of number
170 draw.text((len(bits)/2+6+position, height-9), code[7:], font=font, fill=0)
171
172 # Draw the bar codes
173 for bit in range(len(bits)):
174 # Draw normal bar
175 if bits[bit] == '1':
176 draw.rectangle(((bit+position,0),(bit+position,height-10)),fill=0)
177 # Draw long bar
178 elif bits[bit] == 'L':
179 draw.rectangle(((bit+position,0),(bit+position,height-3)),fill=0)
180
181 # Save the result image
182 im.save(code+"."+extension.lower(), extension.upper())
183
184
185 def getHtml(self, value, height = 50):
186 """ Build an HTML bar code """
187 result = ""
188
189 # Get the bar code list
190 bits = self.makeCode(value)
191
192 # Get thee bar code with the checksum added
193 code = ""
194 for digit in self.EAN13:
195 code += "%d"%digit
196
197 result += '<table><tr><td><center><table cellspacing="0" cellpadding="0" border="0" bgcolor="white"><tr height=%d >'%height
198
199 bitsList = []
200 previousBit = ""
201 for bit in bits:
202 if bit == previousBit:
203 if bit == "0":
204 bitsList[-1] -= 1
205 else:
206 bitsList[-1] += 1
207 else:
208 if bit == "0":
209 bitsList.append(-1)
210 else:
211 bitsList.append(1)
212
213 previousBit = bit
214
215 result += '<td width=10></td>'
216 for bit in bitsList:
217 if bit < 0:
218 result += '<td width=%d></td>'%(-bit)
219 else:
220 result += '<td bgcolor="black" width=%d></td>'%(+bit)
221
222 result += '<td width=10></td>'
223 result += "</tr></table></center></td></tr><tr><td><center>%s</center></td></tr></table>"%(code)
224
225 return result
226
227
228 def decodeFontFile(data, file):
229 """ Decode font file embedded in this script and create file """
230 from zlib import decompress
231 from base64 import decodestring
232 from os.path import exists
233
234 # If the font file is missing
235 if not exists(file):
236 # Write font file
237 open (file, "wb").write(decompress(decodestring(data)))
238
239
240 def testWithChecksum():
241 """ Test bar code with checksum """
242 bar = EanBarCode()
243 assert(bar.makeCode('0000000000000')== 'L0L0001101000110100011010001101000110100011010L0L0111001011100101110010111001011100101110010L0L' )
244 assert(bar.makeCode('1111111111116')== 'L0L0011001001100101100110011001011001101100110L0L0110011011001101100110110011011001101010000L0L' )
245 assert(bar.makeCode('2222222222222')== 'L0L0010011001001100110110011011001001100110110L0L0110110011011001101100110110011011001101100L0L' )
246 assert(bar.makeCode('3333333333338')== 'L0L0111101011110101000010100001010000101111010L0L0100001010000101000010100001010000101001000L0L' )
247 assert(bar.makeCode('4444444444444')== 'L0L0100011001110101000110100011001110100111010L0L0101110010111001011100101110010111001011100L0L' )
248 assert(bar.makeCode('5555555555550')== 'L0L0110001011100101110010110001011000101110010L0L0100111010011101001110100111010011101110010L0L' )
249 assert(bar.makeCode('6666666666666')== 'L0L0101111000010100001010000101010111101011110L0L0101000010100001010000101000010100001010000L0L' )
250 assert(bar.makeCode('7777777777772')== 'L0L0111011001000101110110010001011101100100010L0L0100010010001001000100100010010001001101100L0L' )
251 assert(bar.makeCode('8888888888888')== 'L0L0110111000100101101110001001000100101101110L0L0100100010010001001000100100010010001001000L0L' )
252 assert(bar.makeCode('9999999999994')== 'L0L0001011001011100101110001011001011100010110L0L0111010011101001110100111010011101001011100L0L' )
253
254
255 def testWithoutChecksum():
256 """ Test bar code without checksum """
257 bar = EanBarCode()
258 assert(bar.makeCode('000000000000')== 'L0L0001101000110100011010001101000110100011010L0L0111001011100101110010111001011100101110010L0L' )
259 assert(bar.makeCode('111111111111')== 'L0L0011001001100101100110011001011001101100110L0L0110011011001101100110110011011001101010000L0L' )
260 assert(bar.makeCode('222222222222')== 'L0L0010011001001100110110011011001001100110110L0L0110110011011001101100110110011011001101100L0L' )
261 assert(bar.makeCode('333333333333')== 'L0L0111101011110101000010100001010000101111010L0L0100001010000101000010100001010000101001000L0L' )
262 assert(bar.makeCode('444444444444')== 'L0L0100011001110101000110100011001110100111010L0L0101110010111001011100101110010111001011100L0L' )
263 assert(bar.makeCode('555555555555')== 'L0L0110001011100101110010110001011000101110010L0L0100111010011101001110100111010011101110010L0L' )
264 assert(bar.makeCode('666666666666')== 'L0L0101111000010100001010000101010111101011110L0L0101000010100001010000101000010100001010000L0L' )
265 assert(bar.makeCode('777777777777')== 'L0L0111011001000101110110010001011101100100010L0L0100010010001001000100100010010001001101100L0L' )
266 assert(bar.makeCode('888888888888')== 'L0L0110111000100101101110001001000100101101110L0L0100100010010001001000100100010010001001000L0L' )
267 assert(bar.makeCode('999999999999')== 'L0L0001011001011100101110001011001011100010110L0L0111010011101001110100111010011101001011100L0L' )
268
269
270 def testImage():
271 """ Test images generation with PIL """
272 bar = EanBarCode()
273 bar.getImage("9782212110708",50,"gif")
274 bar.getImage("978221211070",50,"png")
275
276
277 def testHtml():
278 """ Test HTML generation """
279 bar = EanBarCode()
280 open("9782212110708.html","w").write(bar.getHtml("9782212110708",50))
281 assert(bar.getHtml("9782212110708",50) == '<table><tr><td><center><table cellspacing="0" cellpadding="0" border="0" bgcolor="white"><tr height=50 ><td width=10></td><td bgcolor="black" width=1></td><td width=1></td><td bgcolor="black" width=1></td><td width=1></td><td bgcolor="black" width=3></td><td width=1></td><td bgcolor="black" width=2></td><td width=3></td><td bgcolor="black" width=1></td><td width=2></td><td bgcolor="black" width=1></td><td width=2></td><td bgcolor="black" width=2></td><td width=1></td><td bgcolor="black" width=2></td><td width=2></td><td bgcolor="black" width=1></td><td width=2></td><td bgcolor="black" width=2></td><td width=1></td><td bgcolor="black" width=2></td><td width=2></td><td bgcolor="black" width=2></td><td width=2></td><td bgcolor="black" width=1></td><td width=2></td><td bgcolor="black" width=2></td><td width=1></td><td bgcolor="black" width=1></td><td width=1></td><td bgcolor="black" width=1></td><td width=1></td><td bgcolor="black" width=2></td><td width=2></td><td bgcolor="black" width=2></td><td width=1></td><td bgcolor="black" width=2></td><td width=2></td><td bgcolor="black" width=2></td><td width=1></td><td bgcolor="black" width=3></td><td width=2></td><td bgcolor="black" width=1></td><td width=1></td><td bgcolor="black" width=1></td><td width=3></td><td bgcolor="black" width=1></td><td width=2></td><td bgcolor="black" width=3></td><td width=2></td><td bgcolor="black" width=1></td><td width=1></td><td bgcolor="black" width=1></td><td width=2></td><td bgcolor="black" width=1></td><td width=3></td><td bgcolor="black" width=1></td><td width=1></td><td bgcolor="black" width=1></td><td width=10></td></tr></table></center></td></tr><tr><td><center>9782212110708</center></td></tr></table>')
282
283 def test():
284 """ Execute all tests """
285 testWithChecksum()
286 testWithoutChecksum()
287 testHtml()
288 testImage()
289
290 if __name__ == "__main__":
291 test()
Teste
Volta para o CookBook