commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

r5963 - in trunk/gnue-common/src: . printing printing/barcodes


From: jcater
Subject: r5963 - in trunk/gnue-common/src: . printing printing/barcodes
Date: Sun, 11 Jul 2004 23:24:24 -0500 (CDT)

Author: jcater
Date: 2004-07-11 23:24:23 -0500 (Sun, 11 Jul 2004)
New Revision: 5963

Added:
   trunk/gnue-common/src/printing/
   trunk/gnue-common/src/printing/__init__.py
   trunk/gnue-common/src/printing/barcodes/
   trunk/gnue-common/src/printing/barcodes/Base.py
   trunk/gnue-common/src/printing/barcodes/README
   trunk/gnue-common/src/printing/barcodes/__init__.py
   trunk/gnue-common/src/printing/barcodes/codabar.py
   trunk/gnue-common/src/printing/barcodes/code39.py
   trunk/gnue-common/src/printing/barcodes/interleaved2of5.py
   trunk/gnue-common/src/printing/barcodes/postnet.py
   trunk/gnue-common/src/printing/barcodes/standard2of5.py
Log:
added my barcode library (still needs some verification)

Added: trunk/gnue-common/src/printing/__init__.py
===================================================================

Added: trunk/gnue-common/src/printing/barcodes/Base.py
===================================================================
--- trunk/gnue-common/src/printing/barcodes/Base.py     2004-07-11 17:35:14 UTC 
(rev 5962)
+++ trunk/gnue-common/src/printing/barcodes/Base.py     2004-07-12 04:24:23 UTC 
(rev 5963)
@@ -0,0 +1,130 @@
+import sys, os
+import Image, ImageDraw
+
+class InvalidBarcode(StandardError):
+  pass
+
+class Barcode:
+  mapping = {}
+  chars = []
+  validLengths = []
+  lineWidth = 1.44 # points (.02")
+  lineHeight = 18 # (.125")
+  spacing = ''
+  start = ''
+  stop = ''
+
+
+  def checkdigit(self, value):
+    """
+    Returns the checkdigit encoding for the given value
+    """
+    return ''
+
+  def calculateLineHeight(self, value, code):
+    return self.lineHeight
+
+  def _buildBinary(self, value):
+    """
+    Returns a string of 0s (no line) and 1s (line).
+    Note that, depending on the barcode type,
+    a single bar could be multiple
+    """
+
+    if self.validLengths and len(value) not in self.validLengths:
+      raise InvalidBarcode
+
+    value = str(value)
+    rv = self.start + self.spacing
+
+    first = True
+    for ch in value + self.checkdigit(value):
+      if first:
+        first = False
+      else:
+        rv += self.spacing
+      try:
+        rv += self.mapping[ch]
+      except KeyError:
+        raise InvalidBarcode
+
+    return rv + self.spacing + self.stop
+
+
+  ###
+  ###
+  ###
+  def generate(self, value, stream=sys.stdout,
+               format='postscript', dpi=300):
+
+    code = self._buildBinary(value)
+    lineWidth = self.lineWidth
+    lineHeight = self.calculateLineHeight(value, code)
+
+    ##
+    ## Vector-based PS/EPS output
+    ##
+    if format in ("postscript",'eps'):
+      # Special case for PostNet
+      lineHeight2 = self.lineHeight*.4
+
+      # Write minimal EPS header
+      if format == 'eps':
+        stream.write('%!PS-Adobe-3.0 EPSF-3.0\n')
+        stream.write('%%%%BoundingBox: 0 0 %s %s\n'% (
+            int(lineWidth*(len(code)+1)+.5),int(lineHeight+.5)))
+
+      # Initialize the graphics
+      stream.write('gsave\n0 setgray\n%s setlinewidth\nnewpath\n0 0 moveto\n' 
% lineWidth)
+
+      # Draw each bar
+      for ch in code:
+        if ch == '1':
+          stream.write('0 %s rlineto %s -%s rmoveto\n' % (
+              lineHeight,  lineWidth, lineHeight))
+
+        # Special case for PostNet as it is
+        # height-sensitive, not width-sensitive
+        elif ch == '2':
+          stream.write('0 %s rlineto %s -%s rmoveto\n' % (
+              lineHeight2,  lineWidth, lineHeight2))
+
+        else:
+          stream.write('%s 0 rmoveto\n' % (
+              lineWidth))
+
+      # Do the actual drawing, and cleanup
+      stream.write('stroke\ngrestore\n')
+
+
+    ##
+    ## Raster-based output using PIL
+    ##
+    elif format in ('png','tiff','ppm','xbm'):
+      lineWidth = int(lineWidth * dpi/72+.5)   # 300dpi
+      lineHeight = int(lineHeight * dpi/72+.5)  # 300dpi
+      # Special case for PostNet
+      lineHeight2 = int(lineHeight * .4+.5)
+
+      # Create a new monochrome image with a white backgint
+      image = Image.new('1',(int(len(code)*lineWidth+.5),
+         int(lineHeight+.5)), 1)
+      draw = ImageDraw.Draw(image)
+      offs = 0
+      for ch in code:
+        if ch == '1':
+          draw.rectangle((offs,0,offs+lineWidth-1,lineHeight),
+                          outline=0, fill=0)
+        # Special case for PostNet
+        elif ch == '2':
+          draw.rectangle((offs,0,offs+lineWidth-1,lineHeight2),
+                          outline=0, fill=0)
+        offs += lineWidth
+
+      image.save(stream, format)
+
+
+  # Line height is .15 * barcode width, but at least .25"
+  # This is used by Code39, Interleaved 2 of 5, etc
+  def _calculate15(self, value, code):
+    return max(18, .15 * len(code) * self.lineWidth)

Added: trunk/gnue-common/src/printing/barcodes/README
===================================================================
--- trunk/gnue-common/src/printing/barcodes/README      2004-07-11 17:35:14 UTC 
(rev 5962)
+++ trunk/gnue-common/src/printing/barcodes/README      2004-07-12 04:24:23 UTC 
(rev 5963)
@@ -0,0 +1,9 @@
+
+Specs:
+ * http://www.adams1.com/pub/russadam/info.html#Specs
+   General line width specs, min sizes
+   (also has link to an online barcode generator to compare against)
+
+ * http://barcodeisland.com/symbolgy.phtml
+   A lot of encodings for barcodes, but no spacing specs
+

Added: trunk/gnue-common/src/printing/barcodes/__init__.py
===================================================================

Added: trunk/gnue-common/src/printing/barcodes/codabar.py
===================================================================
--- trunk/gnue-common/src/printing/barcodes/codabar.py  2004-07-11 17:35:14 UTC 
(rev 5962)
+++ trunk/gnue-common/src/printing/barcodes/codabar.py  2004-07-12 04:24:23 UTC 
(rev 5963)
@@ -0,0 +1,41 @@
+from Base import Barcode
+
+class Codabar(Barcode):
+  chars = '0123456789-$:/.+'
+  mapping = {
+    '0': '10101001100',
+    '1': '10101100100',
+    '2': '10100101100',
+    '3': '11001010100',
+    '4': '10110100100',
+    '5': '11010100100',
+    '6': '10010101100',
+    '7': '10010110100',
+    '8': '10011010100',
+    '9': '11010010100',
+    '-': '10100110100',
+    '$': '10110010100',
+    ':': '110101101100',
+    '/': '110110101100',
+    '.': '110110110100',
+    '+': '10110011001100'
+  }
+
+  start = '100100101100'
+  stop  = '1010011001'
+
+  calculateLineHeight = Barcode._calculate15
+
+if __name__ == '__main__':
+
+  codabar = Codabar()
+
+  def test(value, format, file):
+    f = open(file,'wb')
+    codabar.generate(value,f, format)
+    f.close()
+
+  test('0123456789-$:/.+','png','test1.png')
+  test('+./:$-9876543210','tiff','test1.tif')
+  test('+./:$-9876543210','postscript','test1.ps')
+  test('0123456789-$:/.+','eps','test1.eps')

Added: trunk/gnue-common/src/printing/barcodes/code39.py
===================================================================
--- trunk/gnue-common/src/printing/barcodes/code39.py   2004-07-11 17:35:14 UTC 
(rev 5962)
+++ trunk/gnue-common/src/printing/barcodes/code39.py   2004-07-12 04:24:23 UTC 
(rev 5963)
@@ -0,0 +1,91 @@
+from Base import Barcode
+
+class Code39(Barcode):
+  """
+  Code 39 without a check digit
+  """
+  chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-. $/+%'
+  mapping = {
+    '0': '1010011011010',
+    '1': '1101001010110',
+    '2': '1011001010110',
+    '3': '1101100101010',
+    '4': '1010011010110',
+    '5': '1101001101010',
+    '6': '1011001101010',
+    '7': '1010010110110',
+    '8': '1101001011010',
+    '9': '1011001011010',
+    'A': '1101010010110',
+    'B': '1011010010110',
+    'C': '1101101001010',
+    'D': '1010110010110',
+    'E': '1101011001010',
+    'F': '1011011001010',
+    'G': '1010100110110',
+    'H': '1101010011010',
+    'I': '1011010011010',
+    'J': '1010110011010',
+    'K': '1101010100110',
+    'L': '1011010100110',
+    'M': '1101101010010',
+    'N': '1010110100110',
+    'O': '1101011010010',
+    'P': '1011011010010',
+    'Q': '1010101100110',
+    'R': '1101010110010',
+    'S': '1011010110010',
+    'T': '1010110110010',
+    'U': '1100101010110',
+    'V': '1001101010110',
+    'W': '1100110101010',
+    'X': '1001011010110',
+    'Y': '1100101101010',
+    'Z': '1001101101010',
+    '-': '1001010110110',
+    '.': '1100101011010',
+    ' ': '1001101011010',
+    '$': '1001001010010',
+    '/': '1001001010010',
+    '+': '1001010010010',
+    '%': '1010010010010',
+  }
+
+  start= '1001011011010'
+  stop = '100101101101'
+
+  lineWidth = .72 # points (1.0mil)
+  lineHeight = 18 # Actually dependent on the width
+
+  calculateLineHeight = Barcode._calculate15
+
+
+######################################
+##
+##
+class Code39CheckDigit(Code39):
+  """
+  Code 39 with a Mod 43 check digit
+  """
+
+  # Calculate a Mod-43 check digit
+  def checkdigit(self, value):
+    v = 0
+    for ch in value:
+      v += self.chars.index(ch)
+    return self.mapping[self.chars[divmod(chv,43)[1]]]
+
+
+if __name__ == '__main__':
+
+  code39 = Code39()
+
+  def test(value, format, file):
+    f = open(file,'wb')
+    code39.generate(value,f, format)
+    f.close()
+
+  test('0123456789ABCDEF','png','test1.png')
+  test('0123456789ABCDEF','tiff','test1.tif')
+  test('0123456789','postscript','test1.ps')
+  test('0123456789ABCDEF','eps','test1.eps')

Added: trunk/gnue-common/src/printing/barcodes/interleaved2of5.py
===================================================================
--- trunk/gnue-common/src/printing/barcodes/interleaved2of5.py  2004-07-11 
17:35:14 UTC (rev 5962)
+++ trunk/gnue-common/src/printing/barcodes/interleaved2of5.py  2004-07-12 
04:24:23 UTC (rev 5963)
@@ -0,0 +1,77 @@
+from Base import Barcode
+
+class Interleaved2of5(Barcode):
+  chars = '0123456789'
+
+  # Interleaved works differently than the others
+  mapping = {
+    '0': 'NNWWN',
+    '1': 'WNNNW',
+    '2': 'NWNNW',
+    '3': 'WWNNN',
+    '4': 'NNWNW',
+    '5': 'WNWNN',
+    '6': 'NWWNN',
+    '7': 'NNNWW',
+    '8': 'WNNWN',
+    '9': 'NWNWN'
+  }
+
+  lineWidth = .54 # points (7.5mil)
+  lineHeight = 18 # Actually dependent on the width
+
+  start = '1010'
+  stop  = '1101'
+
+  calculateLineHeight = Barcode._calculate15
+
+  # Since this is interleaved, we do
+  # our own custom buildBinary.
+  def _buildBinary(self, value):
+    """
+    Returns a string of 0s (no line) and 1s (line).
+    Note that, depending on the barcode type,
+    a single bar could be multiple
+    """
+
+    value = str(value)
+    if len(value)/2.0 != int(len(value)/2.0):
+      raise InvalidBarcode, \
+          'Interleaved 2of5 must have an even number of digits'
+
+    rv = self.start
+
+    even = False
+    for i in range(len(value)/2):
+      try:
+        bar = self.mapping[value[i]]
+        space = self.mapping[value[i+1]]
+      except KeyError:
+        raise InvalidBarcode
+
+      for j in xrange(5):
+        if bar[j] == 'W':
+          rv += '11'
+        else:
+          rv += '1'
+        if space[j] == 'W':
+          rv += '00'
+        else:
+          rv += '0'
+
+    return rv + self.stop
+
+
+if __name__ == '__main__':
+
+  testbar = Interleaved2of5()
+
+  def test(value, format, file):
+    f = open(file,'wb')
+    testbar.generate(value,f, format)
+    f.close()
+
+  test('0123456789','png','test1.png')
+  test('9876543210','tiff','test1.tif')
+  test('9876543210','postscript','test1.ps')
+  test('0123456789','eps','test1.eps')

Added: trunk/gnue-common/src/printing/barcodes/postnet.py
===================================================================
--- trunk/gnue-common/src/printing/barcodes/postnet.py  2004-07-11 17:35:14 UTC 
(rev 5962)
+++ trunk/gnue-common/src/printing/barcodes/postnet.py  2004-07-12 04:24:23 UTC 
(rev 5963)
@@ -0,0 +1,51 @@
+from Base import Barcode, InvalidBarcode
+
+class PostNet(Barcode):
+  """
+  PostNet
+  """
+  validLengths = [5,9,11]
+  chars = '0123456789'
+  mapping = {
+    '0': '1010202020',
+    '1': '2020201010',
+    '2': '2020102010',
+    '3': '2020101020',
+    '4': '2010202010',
+    '5': '2010201020',
+    '6': '2010102020',
+    '7': '1020202010',
+    '8': '1020201020',
+    '9': '1020102020'
+  }
+
+  start = '10'
+  stop  = '1'
+
+  lineWidth = 1.44 # points (.02")
+  lineHeight = 9 # (.125")
+
+  # Calculate a Mod-10 check digit
+  def checkdigit(self, value):
+    v = 0
+    for ch in value:
+      try:
+        v += int(ch)
+      except ValueError:
+        raise InvalidBarcode
+    return self.mapping[self.chars[divmod(v,10)[1]]]
+
+
+if __name__ == '__main__':
+
+  postnet = PostNet()
+
+  def test(value, format, file):
+    f = open(file,'wb')
+    postnet.generate(value,f, format)
+    f.close()
+
+  test('381072456','png','test1.png')
+  test('381172459','tiff','test1.tif')
+  test('381072456','postscript','test1.ps')
+  test('381072456','eps','test1.eps')

Added: trunk/gnue-common/src/printing/barcodes/standard2of5.py
===================================================================
--- trunk/gnue-common/src/printing/barcodes/standard2of5.py     2004-07-11 
17:35:14 UTC (rev 5962)
+++ trunk/gnue-common/src/printing/barcodes/standard2of5.py     2004-07-12 
04:24:23 UTC (rev 5963)
@@ -0,0 +1,36 @@
+from Base import Barcode
+
+class Standard2of5(Barcode):
+  chars = '0123456789'
+  mapping = {
+    '0': '10101110111010',
+    '1': '11101010101110',
+    '2': '10111010101110',
+    '3': '11101110101010',
+    '4': '10101110101110',
+    '5': '11101011101010',
+    '6': '10111011101010',
+    '7': '10101011101110',
+    '8': '11101010111010',
+    '9': '10111010111010'
+  }
+
+  start = '11011010'
+  stop  = '1101011'
+
+  calculateLineHeight = Barcode._calculate15
+
+
+if __name__ == '__main__':
+
+  testbar = Standard2of5()
+
+  def test(value, format, file):
+    f = open(file,'wb')
+    testbar.generate(value,f, format)
+    f.close()
+
+  test('0123456789','png','test1.png')
+  test('9876543210','tiff','test1.tif')
+  test('9876543210','postscript','test1.ps')
+  test('0123456789','eps','test1.eps')





reply via email to

[Prev in Thread] Current Thread [Next in Thread]