. Here's a result of the code below: proc c39.tables {} {
set chars {}; set patterns {}
foreach {char pattern} {
0 111221211 1 211211112 2 112211112 3 212211111
4 111221112 5 211221111 6 112221111 7 111211212
8 211211211 9 112211211 A 211112112 B 112112112
C 212112111 D 111122112 E 211122111 F 112122111
G 111112212 H 211112211 I 112112211 J 111122211
K 211111122 L 112111122 M 212111121 N 111121122
O 211121121 P 112121121 Q 111111222 R 211111221
S 112111221 T 111121221 U 221111112 V 122111112
W 222111111 X 121121112 Y 221121111 Z 122121111
- 121111212 . 221111211 " " 122111211 $ 121212111
/ 121211121 + 121112121 % 111212121 * 121121211
} {lappend chars $char; lappend patterns $pattern}
list $chars $patterns
}One sees 9 parts in each symbol (5 bars, 4 gaps), of which three are wide and the rest narrow (hence the name "3 of 9" or 39. This part converts an input string into a bar-gap sequence, with added start and stop characters (both "*") and optionally a checksum character: proc c39 {string {checksum ""}} {
foreach {chars patterns} [c39.tables] break
#-- blank out all undefined characters
regsub -all {[^0-9A-Z.$/+%-]} [string toupper $string] " " string
if {$checksum != ""} {
set sum 0
foreach char [split $string ""] {
incr sum [lsearch -exact $chars $char]
}
append string [lindex $chars [expr {$sum % 43}]]
}
set res ""
foreach char [split *$string* ""] {
append res [lindex $patterns [lsearch -exact $chars $char]] 1
}
set res
}This renders a bar-gap sequence, as from the above code, into a photo image: proc c39img {c39} {
set width [expr {round([string length $c39]*5)}]
set height 60
set im [image create photo -width $width -height $height]
$im put white -to 0 0 $width $height
set x 20
foreach {bar gap} [split $c39 ""] {
set bar [expr {$bar == 1? 2: 6}]
set gap [expr {$gap == 1? 5: 8}]
$im put black -to $x 0 [expr {$x+$bar}] $height
set x [expr {$x+$bar+$gap}]
}
set im
}Debugging tool, this re-translates a bar-gap sequence to ASCII characters: proc c39read c39 {
foreach {chars patterns} [c39.tables] break
set res ""
while {[string length $c39]} {
set pattern [string range $c39 0 8]
append res [lindex $chars [lsearch -exact $patterns $pattern]]
set c39 [string range $c39 10 end]
}
set res
}
# Demo:
set txt "ABCDE-12345"
set bc [ c39 $txt ]
set im [ c39img $bc ]
label .l1 -anchor c -text $txt
label .l2 -anchor c -image $im
label .l3 -anchor c -text $bc
pack .l1 .l2 .l3
----Eric Amundsen May 16, 2005Fixed the encoding for 'A'. In the doc that Richard Suchenwirth referenced the encoding for 'A' was the same as '9', this [1] reference has the correct encoding for 'A'. Otherwise this code works great, tested with a real scanner even!HJG Added some demo-code.
[IceAngel71] - 2015-09-22 00:17:54+++Ice Angel71 I have 11212211 and 112121211 and 21212111 But my code became a formula K(K+1)(K+2)/6K {39} which is saran wrap or base 3 Polymorphism

