% The bar codes used by supermarkets \message{} % Paul Taylor Dept of Computing, Imperial College, London % with the help of Shane Voss Geology, U of Edinburgh % Authoritative version: ftp theory.doc.ic.ac.uk /tex/contrib/Taylor/tex/ % We cracked this code by examining a dozen or so household items. % The following description does not purport to conform to any patent % or official standard for bar codes. % In fact we do not know what the standard is. % COPYRIGHT Paul Taylor & Shane Voss 1994 % You may copy this file as you please, % on condition that you do not alter it or charge a fee for it. % NO WARRANTY % This description and software is supplied "as is" without any warranty, % express or implied, including but not limited to merchantability or % fitness for any purpose. In particular no claim is made that any % output it produces will be readable by bar code reading equipment % or conforms to any standard. No liability will be accepted by the % authors, their employers or any third party through which you have % obtained this file for damages, however caused. You must keep several % backup copies of your files in a place which cannot be overwritten % by this software and check all output before sending it to a publisher % or expensive printer. % LICENSE % This software may NOT be used for any commercial or military purpose. % In particular you may not use it to sell or buy, or to attempt to % sell or buy any item. (These conditions are intended to prevent you % from making a profit from it or using it for fraud.) It MAY be used % for academic or personal purposes, subject to the exclusions above. % HOW TO USE THE MACROS % set the size of the barcode block, anticipating a 300dpi printer \def\BarcodeHeight{12mm} \def\BarcodeWidth {24mm} \newdimen\PixelSize\PixelSize=1in \divide\PixelSize by 300 % (The width will be rounded to ensure that the unit stripe width is % a whole number of pixels - otherwise it cannot be read accurately. % The width of the 12digit code will be a multiple of approx 8mm.) \def\BarcodeDigitFont{\rm} % font command for printing the digits % Print the eight, twelve and thirteen digit versions of the code: % \ProductBarcodeVIII 12345678 % \ProductBarcodeXII 123456789012 % \ProductBarcodeXIII 0123456789012 % If you use non-digits or give the wrong number of them, % the macros will get in a mess - the input is not checked. % HOW THE BARCODE WORKS % First, you must forget that the stripes are black and white: what is % significant is their *width*, which may be 1, 2, 3 or 4 units. % In particular each digit consists of four stripes of total width 7, % white-black-white-black on the left and the opposite on the right. % As a whole, the bar code consists of a start pattern 111 (ie black, % white and black stripes of unit width), four or six digits, the middle % pattern 11111, another four or six digits and an end pattern 111. % The total width is 3+(4x7)+5+(4x7)+3=67 or 3+(6x7)+5+(6x7)+3=95 units. % The digits are coded as four stripes of the following widths: % 0=3211 1=2221 2=2122 3=1411 4=1132 % 5=1231 6=1114 7=1312 8=1213 9=3112 % notice that the first and third stripes total an even width, % the second and fourth odd. This means that we can recognise % these patterns in their reverse form, and also that they are reversed. % This is significant, because the bar code may be presented upside down % to the reader, which may then recognise the fact and correct for it. % The more modern 6+6 digit version of the code may be used to encode % a further digit. The patterns of stripes may be reversed for some of % the digits on the left, but not the right. Writing 0 for the standard % and 1 for the reversed form, the extra digit is encoded as follows: % 0=000111 1=001011 2=001101 3=001110 4=010011 % 5=011001 6=011100 7=010101 8=010110 9=011010 % (We guessed the coding of 0, 1, 2 and 6 without seeing any items % which carry these digits. The most common seem to be 9 for books and % magazines, and 5 for food and household items; maybe 0126 are unused.) % The extra digit is printed to the left of the body of the barcode. % EXAMPLE ISBN 0-521-24665-2 % The last digit is a checksum, which is computed differently for barcodes. % The ISBN is prefixed with 978 to turn it into a general product barcode. % 111 1312 3121 1123 1231 2212 2221 11111 2122 1132 1114 1114 1231 2221 111 % 7 8 0 5 2 1 2 4 6 6 5 1 % 9 = 0 1 1 0 1 0 % This expands to * * *** ** * * * *** ** * ** ** ** * * * etc. % try doing \ProductBarcodeXIII 9780521246651 \makeatletter % \barp@lf@ 4 produces the left forward code for the digit 4 etc \def\barp@lf#1#2#3#4#5{% left forward \barp@white#1\barp@black#2\barp@white#3\barp@black#4\barp@digit#5}% \def\barp@lr#1#2#3#4#5{% left reverse \barp@white#4\barp@black#3\barp@white#2\barp@black#1\barp@digit#5}% \def\barp@rf#1#2#3#4#5{% right forward \barp@black#1\barp@white#2\barp@black#3\barp@white#4\barp@digit#5}% \def\barp@rr#1#2#3#4#5{% right reverse (not used) \barp@black#4\barp@white#3\barp@black#2\barp@white#1\barp@digit#5}% \def\barp@lf@#1{\expandafter\expandafter\expandafter\barp@lf \csname barp@#1\endcsname} \def\barp@lr@#1{\expandafter\expandafter\expandafter\barp@lr \csname barp@#1\endcsname} \def\barp@rf@#1{\expandafter\expandafter\expandafter\barp@rf \csname barp@#1\endcsname} \def\barp@rr@#1{\expandafter\expandafter\expandafter\barp@rr \csname barp@#1\endcsname} \def\barp@timing#1#2#3#4#5{{\divide\dimen0 2 \barp@white#1\barp@black#2\barp@white#3\barp@black#4\barp@white#5}} % the bar encoding of the digits \barp@4 \def\next#1=#2#3#4#5{\expandafter\def\csname barp@#1\endcsname{#2#3#4#5#1}} \next 0=3211 \next 1=2221 \next 2=2122 \next 3=1411 \next 4=1132 \next 5=1231 \next 6=1114 \next 7=1312 \next 8=1213 \next 9=3112 % the reversal encoding of the digits \barp@l4 \def\do#1#2#3{\expandafter\aftergroup\csname barp@#2#3@\endcsname \aftergroup##\aftergroup#1}% \def\next#1#2=#3#4#5#6#7#8{% \begingroup \aftergroup\def\expandafter\aftergroup\csname barp@#1#2\endcsname \aftergroup##\aftergroup1\aftergroup##\aftergroup2% \aftergroup##\aftergroup3\aftergroup##\aftergroup4% \if.#7\else\aftergroup##\aftergroup5\aftergroup##\aftergroup6\fi \aftergroup{% \do1#1#3\do2#1#4\do3#1#5\do4#1#6 \if.#7\else\do5#1#7\do6#1#8\fi \aftergroup}% \endgroup}% \next l0=fffrrr \next l1=ffrfrr \next l2=ffrrfr \next l3=ffrrrf \next l4=frffrr \next l5=frrffr \next l6=frrrff \next l7=frfrfr \next l8=frfrrf \next l9=frrfrf % also do left and right six-digit parts with no extra digit \next l=ffffff %\barp@l \next r=ffffff %\barp@r % similarly four-digit versions \next ls=ffff.. \next rs=ffff.. \let\next\undefined \let\do\undefined % we don't need them any more % the beginning, middle and end of the code % also sets up the dimensions \def\barp@begin#1#2{\hbox\bgroup % calculate unit width as (\BarcodeWidth)/(#1) rounded to \PixelSize \dimen1=\BarcodeWidth\relax \divide\dimen1 #1\relax \advance\dimen1 .5\PixelSize \divide\dimen1 \PixelSize \multiply\dimen1 \PixelSize % calculate allowance for digit height \setbox0\hbox{\BarcodeDigitFont 0}\dimen0 1.2\ht0 % print the extra digit if any, overlapping left \barp@digit{#2}% % and the start code \barp@timing01110% }% \def\barp@middle{\barp@timing11111}% \def\barp@end{\barp@timing01110\egroup} % the user commands: % \ProductBarcodeVIII \ProductBarcodeXII \ProductBarcodeXIII % for the eight, twelve and thirteen digit codes. \def\ProductBarcodeVIII#1#2#3#4#5#6#7#8{% \barp@begin{67}{}\barp@ls#1#2#3#4\barp@middle\barp@rs#5#6#7#8\barp@end}% \def\ProductBarcodeXII{\barp@xii\barp@l{}} \def\ProductBarcodeXIII#1{\expandafter\barp@xii\csname barp@l#1\endcsname{#1}}% \def\barp@xii#1#2#3#4#5#6#7#8{\barp@begin{95}{#2}#1#3#4#5#6#7#8\barp@vi}% \def\barp@vi#1#2#3#4#5#6{\barp@middle\barp@r#1#2#3#4#5#6\barp@end}% % how to print black and white stripes \def\barp@black#1{\vrule depth-\dimen0 width#1\dimen1 height\BarcodeHeight\relax}% \def\barp@white#1{\kern#1\dimen1\relax}% \def\barp@digit#1{\hbox to\z@{\kern-7\dimen1\hss\BarcodeDigitFont#1\hss}}% % for debugging, print the widths as digit, not stripes % \def\barp@black#1{{\bf #1}}\def\barp@white#1{{\it #1}}\def\barp@digit#1{} % also useful for debugging: % \def\showname#1{\expandafter\show\csname #1\endcsname} % \tracingcommands1 \tracingmacros1 \tracingonline1 \makeatother