;;; @Package postnet ;;; @Subtitle USPS POSTNET Barcode Encoding in Scheme ;;; @HomePage http://www.neilvandyke.org/postnet-scheme/ ;;; @Author Neil Van Dyke ;;; @Version 0.3 ;;; @Date 2009-03-03 ;;; @PLaneT neil/postnet:1:0 ;; $Id: postnet.ss,v 1.15 2009/03/03 12:51:12 neilpair Exp $ ;;; @legal ;;; Copyright @copyright{} 2004--2009 Neil Van Dyke. This program is Free ;;; Software; you can redistribute it and/or modify it under the terms of the ;;; GNU Lesser General Public License as published by the Free Software ;;; Foundation; either version 3 of the License (LGPL 3), or (at your option) ;;; any later version. This program is distributed in the hope that it will be ;;; useful, but without any warranty; without even the implied warranty of ;;; merchantability or fitness for a particular purpose. See ;;; @indicateurl{http://www.gnu.org/licenses/} for details. For other licenses ;;; and consulting, please contact the author. ;;; @end legal #lang scheme/base ;;; @section Introduction ;;; This @b{postnet} Scheme library can be used to generate the United States ;;; Postal Service POSTNET barcode binary pattern, as described in Chapter 4 of ;;; USPS Publication 25, ``Designing Letter and Reply Mail,'' dated 2003-06. ;;; This library supports ZIP, ZIP+4, and DBPC codes. ;;; ;;; The generated binary representation is a Scheme list of boolean values. ;;; Separate code must be written to render this representation to a particular ;;; printing devices. ;;; @section Encoding ;;; There are several procedures for encoding POSTNET from various input ;;; representations. It is suspected that most applications will encode from a ;;; string representation, using @code{string->postnet}. ;;; @defproc digit-list->postnet digits ;;; ;;; Yields a POSTNET encoding of a list of digit numbers. For example: ;;; ;;; @lisp ;;; (digit-list->postnet '(1 2 3 4 5)) ;;; @result{} ;;; (#t #f #f #f #t #t #f #f #t #f #t #f #f #t #t #f ;;; #f #t #f #f #t #f #t #f #t #f #f #t #f #t #f #t) ;;; @end lisp (define digit-list->postnet (let ((digit->postnet-bars (let ((postnet-digit-bars-vector '#((#t #t #f #f #f) (#f #f #f #t #t) (#f #f #t #f #t) (#f #f #t #t #f) (#f #t #f #f #t) (#f #t #f #t #f) (#f #t #t #f #f) (#t #f #f #f #t) (#t #f #f #t #f) (#t #f #t #f #f)))) (lambda (digit) (if (and (integer? digit) (<= 0 digit 9)) (vector-ref postnet-digit-bars-vector digit) '()))))) (lambda (digits) (let ((sum 0)) (cons #t (let loop ((digits digits)) (if (null? digits) (append (digit->postnet-bars (- 10 (modulo sum 10))) (list #t)) (let* ((d (car digits)) (bars (digit->postnet-bars d))) (if (null? bars) (loop (cdr digits)) (begin (set! sum (+ sum d)) (append bars (loop (cdr digits))))))))))))) ;;; @defproc char-list->postnet chars ;;; ;;; Yields a POSTNET encoding of a list of characters. For example: ;;; ;;; @lisp ;;; (char-list->postnet '(#\1 #\2 #\3 #\4 #\5)) ;;; @result{} ;;; (#t #f #f #f #t #t #f #f #t #f #t #f #f #t #t #f ;;; #f #t #f #f #t #f #t #f #t #f #f #t #f #t #f #t) ;;; @end lisp (define (char-list->postnet chars) (digit-list->postnet (map (lambda (c) (- (char->integer c) 48)) chars))) ;;; @defproc string->postnet str ;;; ;;; Yields a POSTNET encoding of a string. For example: ;;; ;;; @lisp ;;; (string->postnet "12345-6789 01") ;;; @result{} ;;; (#t #f #f #f #t #t #f #f #t #f #t #f #f #t #t #f ;;; #f #t #f #f #t #f #t #f #t #f #f #t #t #f #f #t ;;; #f #f #f #t #t #f #f #t #f #t #f #t #f #f #t #t ;;; #f #f #f #f #f #f #t #t #f #t #f #f #t #t) ;;; @end lisp (define (string->postnet str) (char-list->postnet (string->list str))) ;;; @section Debugging ;;; Although this package does not render POSTNET for OCR use, for debugging ;;; purposes, the @code{postnet->debug-string} procedure can be used to ;;; approximate the barcode visually, using ASCII characters. ;;; @defproc postnet->debug-string postnet ;;; ;;; Yields a string visual approximation of a POSTNET encoding. For example: ;;; ;;; @lisp ;;; (postnet->debug-string (string->postnet "12345")) ;;; @result{} "|...||..|.|..||..|..|.|.|..|.|.|" ;;; @end lisp (define (postnet->debug-string postnet) (apply string (map (lambda (bar) (if bar #\| #\.)) postnet))) ;;; @unnumberedsec History ;;; @table @asis ;;; ;;; @item Version 0.3 --- 2009-03-03 -- PLaneT @code{(1 0)} ;;; Licensed changed to LGPL 3. Converted to author's new Scheme ;;; administration system. Previous version was erroneously in planet as ;;; package @code{postnet-planet.plt}. ;;; ;;; @item Version 0.2 --- 2005-07-12 ;;; Added Testeez tests. Minor documentation changes. ;;; ;;; @item Version 0.1 --- 2004-04-14 ;;; Wrote as a diversion over dinner. ;;; ;;; @end table (provide char-list->postnet digit-list->postnet postnet->debug-string string->postnet)