= 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 == {{{ #!python # courbB08.pil PIL Font file uuencoded courB08_pil ="""eJztl91rFkcUxp+Zt7vGFYzVtiJKICgYlLRWkaBBVGgDraFGCH5gsQp+QMBqabAVRYJYAlakCkoh CpYgxaLkIu1NvLBeSAStglpqL6xQAsVe2AuL5u2buH3mzGaYPf9AKWTl8d3nl7MzZ2bnazvea9+9 7+PurFWut5e0Zu+s7VybYfKavP7LK3X/5TlM4Q3/OWbyf1ARD/6mgb2SjwtPhbpnq0iKZ6ahrmCj wqbxdgamRnHOA69jimN5zvIS8cDcUEeVdYzRAw1FHcJYXgPvG4s6Jlgj7xeEequS3wLeNvGvnrEO tq+Jt82szT+b86+WHlgS2jHGuHF6YHnog1zaupxqCcy3t4X3rVG9iXhgjW+bsFQ80BaxRDywTrF1 VId6toPaqOI2UlsV20ptV2w7tUuxXVSXYl3UvoIZ9kFFPPBJ6D/HLD3QXbwjyDjI6YHPiz5FXiN7 SQ8cDu/N9/1h3veEOP/Oe6gvQnmuvYYe+NL3qYyNVDxw2seF8XKa+jrKJREPnFdx56l+xfqpS4pd ogZUeQPU91FcKh64GveBeOCaKu8adUM9e4O6reJuU/cUu0c9VM8+pB6r/B5TI+rZEerPUpyhB/6K 5lsqHniuyntO1VR5Nb5CU86FHqZOsTqqXrF66o2ojlQ8zDwVN4+aX86FHqYpXg9YLeevWRzPc7LF ZG+V1wN6mKXxvMzH6GFaJua5zGNLD7MqmtNcc+hh1oT1oCb5cf6aNj92mbPMGXqY9jCPasLaqQ1h jMv8pYfZpOI2UR9GcYl4mB1RnMtvB9me8N583B5qb3mNoIf5NGJc1+hhPvPrrjybioc5op49Qh0L dfj8jlHHQ3s9O059Fc3zRDzMmVKcpYfpU+3oI/umxJyH+TYqLxUPc0X13xVqMMovFQ8zpPIbon6M WCoeZljVMUz9VIqz9DAP1Dt6QP0a9gpZ7+lhHhXjysreaOhhfiv1vaGH+T2Mv5rbU+hh/uAaOnlN Xv+Hy4/7mtv3OW5hnpTODIYe5mm0xqbiYf4OcbLv08NU1ZyuuqKLOEvm6sjhJkd8TjRustgkrO3u vFGjh60r1uyiPHrY6eH84tb7l/SwM8vrAT3snHgNY9wcsoby+Y8edn5UxxTxsIuitrlcFpG9GcVx /6CHXRrKk72MHrYl3stYB/ceu7I4X02wlWSrCmaF1ehhV7NrovWKHrattI4betj20Fc8r7E87kf2 g+gcy32BHnZDfKZmHPco2xnl4vqlk2yz6r/N1EfRPpiKh90d7VGpeNi9inGPst2lNdbSwx4McS8k 7iDVE/Ytz3qoXsV6qZOKnaTOBDYqjPuRPRfOkz7uHNUf4uQMQg/7XekMYulhB6JnE/GwP0T1JuJh ryrGM6G9HuWSiIcdDnPmhTs70sPeCuPes1vUXcXuUvcDGxV2n/olOisn4mEfhfOVby/3KDsSlZeI h32iGOe0faoY57R9ptgzajTKJREPOx7aJnOfHhUbxov0Mz0qU8v50aMyo/wu6VGZrdhsqqH8fnll HEEz4zj6DNMxK+4X+gyv8cszyoU+4zfmjNAO9zuXrNGXF1gj2ULFFpI1K9ZMtiww//22jGwFXg39 535XkK0O+cl5gz7Du6iP5wd9hvfDs9LP9BnWR/U6tp6sU7FOsi1RLo5tIdsWled+t5HtVO3YSdal WBfZftW2/WQHVH4HyA6F9+GfPUR2VOV3lKxXsV6yE4qdIDul2Cmys6ptZ8n6Qi7+m7OP7ELoU/8t dIHsoo8L+V0ku6xyvkw2qNgg2VBgvg+GyK6XyrP0GW5ydE3EuXd5k+xOeOdVibtD9jNm/Qv15O4i""" # courbB08.pbm font file uuencoded courB08_pbm ="""eJxNkntM01cUx8+P2/1apUAZEpECq4KRjKhF0E55FYEp4yG6mglz2Q8Q1BhERhhls/zKI+CID4wb IAPKpk4GAzqZPKKMX2GIUwGJG+ImtKwKjIzXcGuBtncV0Hn+uLnn5Nzv55xv7mdRkbusVjquBACr 0N3B+wCQi/m+ijAf4LGl/wgAiwkNDpRIyyABSjGkBQ/fa3c1bfLs4U8ulDcYUs/502rTpIlO9pyc Kp/Buql6f3rmZ1NqvpO2SZXf0duY3j0563zjoZpW8AvHRmVeZ/Co36mFR8bERzlsxOMJ+oJshsS5 7rlfzFzmnZFEFnIEZjTGizgLsLzjl4QtrNprBRu10e+u9GgePHjG63bPDw/H87uix0Vtsvkqg9qO lUimPLiOM4z69YfqIu5Pa2Sr/io6n9Xmf9e+57W1Iapo4lLQBdLSWc/z3KOSlgznDXTW/Flh21kX IeUIX8FZVL9dwP4NBH5jglYxkBNFmWgMcfsAxM/9gEL5TTwYpnfElR8qQ+WiCgeTHOAfb2bW/cQC /FozFOOQzAebtjRvQLI7HBtXvaZe25a3Q/1vZpPa+kd1XXKuflr5Cm48YUsUcjMXjsm/sf+22s6z QAbGZ8mEXMzSE4y9AHhRpltwB1N9ynz5H2MOi0MEi4E5O1ov9ogrFU5cMWAcdgQb3xHFtFK+0pkh VnYWxltx92j69p6jJ9OnHr+Cq5x5X6Mz70JcX2tEG5LIShM4EHIGoLIRsHzcvEuGwMYA4DZPn7gP MA1QIgltnt82cTu7j5n76mmz3TU5Bh3PFRTHku52aBgaTnJD7m1c0a3hNjbWWjBtMsP/OFac/LYA NAAWepdYodB58NBFIuOjNSQ4cgXplqP2RyOe8fd999T8weqBRwLwNFdQobHgA1/YTV8PH+TwV59v Bo7Y1J4rmHFv3T9e8rmmXdGSuPpSbBnhYJ7V8ICz6AfGcdTpRkpCUU8WcOT8wb+dSHIb6QZapx0M Y2DO4i7jYV2AUNkkErpQFHVYmFRmYD7OJhDyQSiow4IkrS3TbpQqFA9slE4jnj6peXMTC+N8buJ2 0Uv5eOothuGIiluyCDtff3miBzJHjncOIC3bPT8FLabRPd0TCWy346Mmn9Rz23WyNMJcsnqhQani 3CMFOZuYU7c20zTNVqNbGPNxALWnybeLEcTvXWpc10leI5ae/CI9qBqI686cnO6P6F33e2vAp0nz 9+hnbNeueh/261UJK5aVeSf73ZSXA7dOBXvkXODEb9hVww4KtPNAbPvaZbi0q9kICCl+CiBJSzLv a8TlntYlC4UHvCRTlaXOy13VAbN0eae2v3hNesWXLsWPkjfOPq7e6zd1fOfc1TckDaylrvleinnT 8Ui87ScLMVhhEx7SUJ8U2zKrRR2Z1dEqZlkr7kDTuhFjpkvse9ZXN0R9H+DlYA4TXVm6/kXDQMyT eGnJFXlLlSgva5iLUEcbiyDzNqf4Wr9kKYVUIcY40DrnsW4E4zW9QxnHVYx+bo64mIskDWjZgCrq eVQFrS7Sh/uFLftIidKWbgj6Oq652d4c3v88Dw2JDK7bSWX/ByuaLZI=""" class EanBarCode: """ Compute the EAN bar code """ def __init__(self): A = {0 : "0001101", 1 : "0011001", 2 : "0010011", 3 : "0111101", 4 : "0100011", 5 : "0110001", 6 : "0101111", 7 : "0111011", 8 : "0110111", 9 : "0001011"} B = {0 : "0100111", 1 : "0110011", 2 : "0011011", 3 : "0100001", 4 : "0011101", 5 : "0111001", 6 : "0000101", 7 : "0010001", 8 : "0001001", 9 : "0010111"} C = {0 : "1110010", 1 : "1100110", 2 : "1101100", 3 : "1000010", 4 : "1011100", 5 : "1001110", 6 : "1010000", 7 : "1000100", 8 : "1001000", 9 : "1110100"} self.groupC = C 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), 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)} def makeCode(self, code): """ Create the binary code return a string which contains "0" for white bar, "1" for black bar, "L" for long bar """ # Convert code string in integer list self.EAN13 = [] for digit in code: self.EAN13.append(int(digit)) # If the code has already a checksum if len(self.EAN13) == 13: # Verify checksum self.verifyChecksum(self.EAN13) # If the code has not yet checksum elif len(self.EAN13) == 12: # Add checksum value self.EAN13.append(self.computeChecksum(self.EAN13)) # Get the left codage class left = self.family[self.EAN13[0]] # Add start separator strCode = 'L0L' # Compute the left part of bar code for i in range(0,6): strCode += left[i][self.EAN13[i+1]] # Add middle separator strCode += '0L0L0' # Compute the right codage class for i in range (7,13): strCode += self.groupC[self.EAN13[i]] # Add stop separator strCode += 'L0L' return strCode def computeChecksum(self, arg): """ Compute the checksum of bar code """ # UPCA/EAN13 weight=[1,3]*6 magic=10 sum = 0 for i in range(12): # checksum based on first 12 digits. sum = sum + int(arg[i]) * weight[i] z = ( magic - (sum % magic) ) % magic if z < 0 or z >= magic: return None return z def verifyChecksum(self, bits): """ Verify the checksum """ computedChecksum = self.computeChecksum(bits[:12]) codeBarChecksum = bits[12] if codeBarChecksum != computedChecksum: raise Exception ("Bad checksum is %s and should be %s"%(codeBarChecksum, computedChecksum)) def getImage(self, value, height = 50, extension = "PNG"): """ Get an image with PIL library value code barre value height height in pixel of the bar code extension image file extension""" from PIL import Image, ImageFont, ImageDraw # Create a missing font file decodeFontFile(courB08_pil ,"courB08.pil") decodeFontFile(courB08_pbm ,"courB08.pbm") # Get the bar code list bits = self.makeCode(value) # Get thee bar code with the checksum added code = "" for digit in self.EAN13: code += "%d"%digit # Create a new image position = 8 im = Image.new("1",(len(bits)+position,height)) # Load font font = ImageFont.load("courB08.pil") # Create drawer draw = ImageDraw.Draw(im) # Erase image draw.rectangle(((0,0),(im.size[0],im.size[1])),fill=256) # Draw first part of number draw.text((0, height-9), code[0], font=font, fill=0) # Draw first part of number draw.text((position+7, height-9), code[1:7], font=font, fill=0) # Draw second part of number draw.text((len(bits)/2+6+position, height-9), code[7:], font=font, fill=0) # Draw the bar codes for bit in range(len(bits)): # Draw normal bar if bits[bit] == '1': draw.rectangle(((bit+position,0),(bit+position,height-10)),fill=0) # Draw long bar elif bits[bit] == 'L': draw.rectangle(((bit+position,0),(bit+position,height-3)),fill=0) # Save the result image im.save(code+"."+extension.lower(), extension.upper()) def getHtml(self, value, height = 50): """ Build an HTML bar code """ result = "" # Get the bar code list bits = self.makeCode(value) # Get thee bar code with the checksum added code = "" for digit in self.EAN13: code += "%d"%digit result += '
'%height bitsList = [] previousBit = "" for bit in bits: if bit == previousBit: if bit == "0": bitsList[-1] -= 1 else: bitsList[-1] += 1 else: if bit == "0": bitsList.append(-1) else: bitsList.append(1) previousBit = bit result += '' for bit in bitsList: if bit < 0: result += ''%(-bit) else: result += ''%(+bit) result += '' result += "
%s
"%(code) return result def decodeFontFile(data, file): """ Decode font file embedded in this script and create file """ from zlib import decompress from base64 import decodestring from os.path import exists # If the font file is missing if not exists(file): # Write font file open (file, "wb").write(decompress(decodestring(data))) def testWithChecksum(): """ Test bar code with checksum """ bar = EanBarCode() assert(bar.makeCode('0000000000000')== 'L0L0001101000110100011010001101000110100011010L0L0111001011100101110010111001011100101110010L0L' ) assert(bar.makeCode('1111111111116')== 'L0L0011001001100101100110011001011001101100110L0L0110011011001101100110110011011001101010000L0L' ) assert(bar.makeCode('2222222222222')== 'L0L0010011001001100110110011011001001100110110L0L0110110011011001101100110110011011001101100L0L' ) assert(bar.makeCode('3333333333338')== 'L0L0111101011110101000010100001010000101111010L0L0100001010000101000010100001010000101001000L0L' ) assert(bar.makeCode('4444444444444')== 'L0L0100011001110101000110100011001110100111010L0L0101110010111001011100101110010111001011100L0L' ) assert(bar.makeCode('5555555555550')== 'L0L0110001011100101110010110001011000101110010L0L0100111010011101001110100111010011101110010L0L' ) assert(bar.makeCode('6666666666666')== 'L0L0101111000010100001010000101010111101011110L0L0101000010100001010000101000010100001010000L0L' ) assert(bar.makeCode('7777777777772')== 'L0L0111011001000101110110010001011101100100010L0L0100010010001001000100100010010001001101100L0L' ) assert(bar.makeCode('8888888888888')== 'L0L0110111000100101101110001001000100101101110L0L0100100010010001001000100100010010001001000L0L' ) assert(bar.makeCode('9999999999994')== 'L0L0001011001011100101110001011001011100010110L0L0111010011101001110100111010011101001011100L0L' ) def testWithoutChecksum(): """ Test bar code without checksum """ bar = EanBarCode() assert(bar.makeCode('000000000000')== 'L0L0001101000110100011010001101000110100011010L0L0111001011100101110010111001011100101110010L0L' ) assert(bar.makeCode('111111111111')== 'L0L0011001001100101100110011001011001101100110L0L0110011011001101100110110011011001101010000L0L' ) assert(bar.makeCode('222222222222')== 'L0L0010011001001100110110011011001001100110110L0L0110110011011001101100110110011011001101100L0L' ) assert(bar.makeCode('333333333333')== 'L0L0111101011110101000010100001010000101111010L0L0100001010000101000010100001010000101001000L0L' ) assert(bar.makeCode('444444444444')== 'L0L0100011001110101000110100011001110100111010L0L0101110010111001011100101110010111001011100L0L' ) assert(bar.makeCode('555555555555')== 'L0L0110001011100101110010110001011000101110010L0L0100111010011101001110100111010011101110010L0L' ) assert(bar.makeCode('666666666666')== 'L0L0101111000010100001010000101010111101011110L0L0101000010100001010000101000010100001010000L0L' ) assert(bar.makeCode('777777777777')== 'L0L0111011001000101110110010001011101100100010L0L0100010010001001000100100010010001001101100L0L' ) assert(bar.makeCode('888888888888')== 'L0L0110111000100101101110001001000100101101110L0L0100100010010001001000100100010010001001000L0L' ) assert(bar.makeCode('999999999999')== 'L0L0001011001011100101110001011001011100010110L0L0111010011101001110100111010011101001011100L0L' ) def testImage(): """ Test images generation with PIL """ bar = EanBarCode() bar.getImage("9782212110708",50,"gif") bar.getImage("978221211070",50,"png") def testHtml(): """ Test HTML generation """ bar = EanBarCode() open("9782212110708.html","w").write(bar.getHtml("9782212110708",50)) assert(bar.getHtml("9782212110708",50) == '
9782212110708
') def test(): """ Execute all tests """ testWithChecksum() testWithoutChecksum() testHtml() testImage() if __name__ == "__main__": test() }}} == Teste == {{{ #!python # -*- coding: utf-8 -*- """ EanBarCode.py """ from PIL import Image from EANBarCode import EanBarCode bar = EanBarCode() bar.getImage("9782212110708",50,"gif") }}} ---- Volta para o CookBook