[barcode] Telepen ASCII Symbology
Markus Kuhn
Markus.Kuhn@cl.cam.ac.uk
Fri, 22 Nov 2002 15:16:00 +0000
Alessandro Rubini wrote on 2002-11-21 22:50 UTC:
> new url: http://www.telepen-barcode.co.uk/barcode_symbol.asp
>
> However, this isn't clear at all to me. They're making quite a bit
> of self-glorification without giving useable information.
Admittedly, the page gives not a really good description, but apart from
the fact that the mod 127 checksum also needs to be inverted, all the
necessary information is indeed there. In a nutshell: To process the bit
sequence, you need a state machine with two states. In the start state,
you accept bit sequences 00, 010, 01, 1 (these transition are
distinguishable by the 4 possible narrow/wide black/white stripe
combinations), and in the second state you accept only bit sequences 10,
1 (anything starting with 0 could have been handled by staying in the
start state). You always make the state transition that accepts most
bits. The sequences 01 and 10 cause a transition between the two states,
all others do not cause the state to change. It's a rather clever
scheme, imho.
> Obviously, you're welcome to contribute the encoding by yourself. As
> an alternative, I'd like to see a useable description of the format so
> I can consider implementing it.
I have written and attached a Perl script that, when I tested it,
successfully encoded both the example on the above web page as well as
numerous of our the University of Cambridge library cards correctly. I
hope that counts as a sufficiently useable description of the Telepen
ASCII barcode.
Best regards,
Markus
--
Markus G. Kuhn, Computer Laboratory, University of Cambridge, UK
Email: mkuhn at acm.org, WWW: <http://www.cl.cam.ac.uk/~mgk25/>
#!/usr/bin/perl
# Markus.Kuhn@cl.cam.ac.uk, 2002-11-22
# Encode 7-bit ASCII string into Telepen barcode
# http://www.telepen-barcode.co.uk/barcode_symbol.asp
# Output: string in which '.' and 'B' represent equally wide white and
# black vertical strokes.
sub telepen
{
my ($text) = @_;
my $bits;
my $barcode;
my $checksum = 0;
# Append checksum byte to $text
for ($i = 0; $i < length($text); $i++) {
$checksum += ord(substr($text, $i, 1)) & 0x7f;
}
$text .= chr(~($checksum % 127) & 0x7f);
# Convert $text to LSB-first bit sequence with even parity
while (length($text) > 0) {
my $char = ord($text);
my $ones = 0;
$text = substr($text, 1);
$checksum += $char;
for ($i = 0; $i < 7; $i++) {
$ones += ($char >> $i) & 1;
$bits .= (($char >> $i) & 1) ? '1' : '0';
}
$bits .= ($ones & 1) ? '1' : '0';
};
# Add start and stop codes
$bits = "11111010${bits}01011111";
# Now apply Telepen encoding state machine
my $state = 0;
while (length($bits) > 0) {
if ($bits =~ /^010/ && $state == 0) {
$barcode .= 'BBB...';
$bits = $';
} elsif ($bits =~ /^00/ && $state == 0) {
$barcode .= 'BBB.';
$bits = $';
} elsif ($bits =~ /^01/ && $state == 0) {
$barcode .= 'B...';
$bits = $';
$state = 1;
} elsif ($bits =~ /^10/ && $state == 1) {
$barcode .= 'B...';
$bits = $';
$state = 0;
} elsif ($bits =~ /^1/) {
$barcode .= 'B.';
$bits = $';
} else {
die("Oops, something impossible happend!\n$bits\n");
}
}
return $barcode;
}
# Convert ./B output format of telepen() into PBM graphics file
sub barcode2pbm
{
my ($barcode) = @_;
my $hborder = 10;
my $vborder = 10;
my $width = length($barcode) + 2*$hborder;
my $rows = 30;
my $height = $rows + 2*$vborder;
$barcode =~ s/B/1 /g;
$barcode =~ s/\./0 /g;
$barcode = ('0 ' x $hborder) . $barcode . ('0 ' x $hborder);
$barcode = "$barcode\n" x $rows;
$barcode = (((("0 " x $width) . "\n") x $vborder) . $barcode .
((("0 " x $width) . "\n") x $vborder));
return "P1\n$width $height\n$barcode";
}
if ($#ARGV < 0) {
print STDERR "Print Telepen barcode as PBM file.\n\n";
print STDERR "Usage: telepen.pl <ascii-string>\n\n";
exit 1;
};
print barcode2pbm(telepen($ARGV[0]));