associação pythonbrasil[11] django zope/plone planet Início Logado como (Entrar)

CodigoBarras

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

   1 # -*- coding: utf-8 -*-
   2 """
   3 EanBarCode.py
   4 """
   5 
   6 from PIL import Image
   7 
   8 from EANBarCode import EanBarCode
   9 bar = EanBarCode()
  10 bar.getImage("9782212110708",50,"gif")


Volta para o CookBook