mailto: blog -at- heyrick -dot- eu

## Tassimo hacking - ITF-6 barcodes

Okay... So if I'm going to try a variety of different barcodes in the Tassimo, I'm going to need a better way of generating barcodes than getting PNGs from a website.

Which means, education time!

The first step is to know what our encoded number is to be. This is a five digit decimal number followed by a check digit. The five digits correspond to some sort of bitmap in the machine. Purpose unknown, that's why we're hacking. ☺
For the sake of argument, we shall use the five digits "03287". These are the digits that I use in my machine to make tea. The coffee maker thinks it is making endless cups of tea...actually it is, but not via capsule. It's making hot water so I can brew a nice Tetley.

Anyway - the digits are 03287.

### Creating the check digit

In order to create the check digit, we need to add together the values of the odd digits. In this case 0 + 2 + 7 which gives us 9.
This value is then multiplied by three, giving 27.

Next, we add in the even digits, or 3 + 8 giving us 11 which when added to 27 is a grand total of 38.

The next calculation is to obtain the modulus of this value and ten. Essentially we are clipping off the first digit, so 38 becomes 38 or just 8.

Finally, if the result of that was zero, then the check digit is zero.
However, if the result was not zero, then the check digit is ten minus the result. In this case it would be 10 - 8 giving us a check digit of 2.

Which means our final code with check digit added is: 032872.

### Interleaved two of five

ITF, when referring to barcodes (and not the Internet Task Force (wrong! it's actually the IETF), or International Tree Foundation, etc etc) stands for Interleaved Two of Five.

I'll explain what this means. It's actually quite clever.

As you will have noticed, traditional barcodes contain two primary parts. A bunch of lines of various widths. and a bunch of spaces between the lines, also of different widths.

Actually, in ITF, the lines are only two widths - a thin and a thick. The thick is defined as 2-3 times the width of the thin. This is a simpler arrangement than, say, EAN product barcodes (go find a book, can of coke, etc) which appear (visually, not looked it up) to have three widths).
In ITF, just as there are thin lines and thick lines, there can be thin spaces and thick spaces.

Numbers are dealt with in pairs. The first number is represented in the lines using exactly five lines. Exactly two of these lines are thick. This is why it is called "two of five". The arrangement of thick/thin determines the number.
Now here's the clever part. The second number is represented in the spaces, using exactly five spaces, and as for the lines, two will be thick spaces and two will be thin.

The arrangement of lines/spaces to number is as follows, with '0' meaning thin and '1' meaning thick:

0 is 0, 0, 1, 1, 0
1 is 1, 0, 0, 0, 1
2 is 0, 1, 0, 0, 1
3 is 1, 1, 0, 0, 0
4 is 0, 0, 1, 0, 1
5 is 1, 0, 1, 0, 0
6 is 0, 1, 1, 0, 0
7 is 0, 0, 0, 1, 1
8 is 1, 0, 0, 1, 0
9 is 0, 1, 0, 1, 0

Our first two digits are zero and three. This means that we want our lines to be thin, thin, thick, thick, thin and we want our spaces to be thick, thick, thin, thin, thin.

If we can draw a rubbish bit of barcode in ASCII, that would look like this:

##    ##    ####  ####  ##
##    ##    ####  ####  ##
##    ##    ####  ####  ##
##    ##    ####  ####  ##

If we add the run-in, which is two thin lines with two thin spaces, this becomes:

##  ##  ##    ##    ####  ####  ##
##  ##  ##    ##    ####  ####  ##
##  ##  ##    ##    ####  ####  ##
##  ##  ##    ##    ####  ####  ##

Compare this against the actual barcode used in the coffee maker:

You can see it clearly, reading left to right: thin line and thin space, twice. Followed by thin line, big space, thin line, big space, thick line, thin space, thick line, thin space, thin line, thin space.

We now simply repeat this for the third and fourth digits, and once more again for the fifth and sixth digits.

Afterwards, the run-out code of a thick line, thin space, thin line is added.

And, voilà, we have just created ourselves a valid ITF barcode.

Here's the result of my first program to do this:

*ITFgen
Enter numeric code (5 digits) : ?03287
Check digit is 2
Therefore the full code is 032872

Generated barcode:
##  ##  ##    ##    ####  ####  ##  ##    ####  ##  ##    ####  ##  ##    ##  ####  ####    ####  ##
##  ##  ##    ##    ####  ####  ##  ##    ####  ##  ##    ####  ##  ##    ##  ####  ####    ####  ##
##  ##  ##    ##    ####  ####  ##  ##    ####  ##  ##    ####  ##  ##    ##  ####  ####    ####  ##
##  ##  ##    ##    ####  ####  ##  ##    ####  ##  ##    ####  ##  ##    ##  ####  ####    ####  ##
##  ##  ##    ##    ####  ####  ##  ##    ####  ##  ##    ####  ##  ##    ##  ####  ####    ####  ##
##  ##  ##    ##    ####  ####  ##  ##    ####  ##  ##    ####  ##  ##    ##  ####  ####    ####  ##
##  ##  ##    ##    ####  ####  ##  ##    ####  ##  ##    ####  ##  ##    ##  ####  ####    ####  ##
##  ##  ##    ##    ####  ####  ##  ##    ####  ##  ##    ####  ##  ##    ##  ####  ####    ####  ##
##  ##  ##    ##    ####  ####  ##  ##    ####  ##  ##    ####  ##  ##    ##  ####  ####    ####  ##
##  ##  ##    ##    ####  ####  ##  ##    ####  ##  ##    ####  ##  ##    ##  ####  ####    ####  ##
##  ##  ##    ##    ####  ####  ##  ##    ####  ##  ##    ####  ##  ##    ##  ####  ####    ####  ##
##  ##  ##    ##    ####  ####  ##  ##    ####  ##  ##    ####  ##  ##    ##  ####  ####    ####  ##

Done.
*

Zooming this image up 800% in NetSurf and moving the TaskWindow just underneath matched up the ASCII art barcode to the real thing.

Perfect match.

### Making this a useful barcode

First we need to work out how wide our barcode is going to be.

The run-in is two thin lines and two thin spaces. Let's count thin as '1' and thick as '2'. So the run-in gives us 4. The run-out is a thick line, thin space, thin line. This also gives us a value of 4.
Now we know that each number is comprised of two thick lines and three thin lines. 2+2+1+1+1 is 7. Double that because the second number is in the spaces, encoded the same way. So a number pair is a width of 14.

Run-in (4), three number pairs (42), and run-out (4) gives us a raw barcode width of fifty elements.

Here we go...

Okay, it's correct but it's a bit rubbish. It would make a lot more sense to have an image that we can work with. So simply multiply everything by four. A width of 200 pixels instead of fifty.
It'll look like this:

### Creating the sprite

It's not so difficult to turn this into something to create a barcode graphic. What I do is work out what the barcode encoding should be, and write this across the top line of the sprite (line 49, as line zero is the bottom).
Once the encoding has been written, and remember we're writing four pixels for every element across, I will go back and scan each pixel in the top line and copy it to all the other lines.

Doing this, our program when run now looks like this:

*ITFgen
Enter numeric code (5 digits) : ?03287
Check digit is 2; full code is 032872
Creating sprite...generating barcode...replicating...saving as "032872".
*
and the resultant sprite is this:

It's not the same as the previous sprite. This one was generated programmatically, the previous one was created by hand in Paint (because at that time, ITFgen didn't create sprites).

### ITFgen

Here's a listing of the software. It isn't designed to be efficient, it's designed to get a job done and be readable.

REM >ITFgen
REM
REM by Rick Murray
REM
REM Friday, 10th August 2018

RESTORE +0
DIM bars%(10, 5)
FOR l% = 0 TO 9
READ bars%(l%, 1), bars%(l%, 2), bars%(l%, 3), bars%(l%, 4), bars%(l%, 5)
NEXT

REM Get the code
INPUT "Enter numeric code (5 digits) : ";code\$

REM Validate
IF (LEN(code\$) <> 5) THEN PRINT "Incorrect length." : END
FOR l% = 1 TO 5
a% = (ASC(MID\$(code\$, l%, 1)) - 48)
IF ((a% < 0) OR (a% > 9)) THEN PRINT "Numbers only." : END
NEXT

REM Work out the check digit
a% = (ASC(MID\$(code\$, 1, 1)) - 48)
b% = (ASC(MID\$(code\$, 2, 1)) - 48)
c% = (ASC(MID\$(code\$, 3, 1)) - 48)
d% = (ASC(MID\$(code\$, 4, 1)) - 48)
e% = (ASC(MID\$(code\$, 5, 1)) - 48)
f% = ((a% + c% + e%) * 3) + (b% + d%)
f% = f% MOD 10
IF (f% = 0) THEN
check% = 0
ELSE
check% = 10 - f%
ENDIF
code\$ = code\$ + STR\$(check%)
PRINT "Check digit is "+STR\$(check%)+"; full code is "+code\$

REM Create the sprite
PRINT "Creating sprite...";
DIM spr% 2048 : REM Size is 200x50 at 1bpp, or 1250 bytes, plus header
FOR loop% = 0 TO 2047 STEP 4 : spr%!loop% = 0 : NEXT : REM Clear to white
spr%!0 = 2048
spr%!8 = 16
SYS "OS_SpriteOp", (9 + 256), spr%
SYS "OS_SpriteOp", (15 + 256), spr%, code\$, 0, 200, 50, (1<<27)+(90<<14)+(90<<1)+1
REM                                                     1bpp,   y=90dpi, x=90dpi
pos% = 0

REM Run-in: Narrow bar, narrow space, narrow bar, narrow space
PRINT "generating barcode...";

REM Now generate the code
FOR loop% = 1 TO 5 STEP 2
REM Get our two digits
first%  = (ASC(MID\$(code\$, loop%, 1)) - 48)
second% = (ASC(MID\$(code\$, (loop%+1), 1)) - 48)

REM Now step through the barcode data elements
FOR recurse% = 1 TO 5
line%  = bars%(first%, recurse%)  : REM Line
space% = bars%(second%, recurse%) : REM Space

IF (line% = 1) THEN
ELSE
ENDIF

IF (space% = 1) THEN
ELSE
ENDIF
NEXT
NEXT

REM Run-out: Wide bar, narrow space, narrow bar

REM That was across line 49. So now replicate to fill the sprite.
PRINT "replicating...";
FOR pos% = 0 TO 199
SYS "OS_SpriteOp", (41 + 256), spr%, code\$, pos%, 49 TO ,,,,,col%,tint%
FOR loop% = 0 TO 48
SYS "OS_SpriteOp", (42 + 256), spr%, code\$, pos%, loop%, col%, tint%
NEXT
NEXT

REM Save the sprite
PRINT "saving as """+code\$+"""."
SYS "OS_SpriteOp", (12 + 256), spr%, code\$

END

REM Barcode data (0-9)
DATA 0, 0, 1, 1, 0
DATA 1, 0, 0, 0, 1
DATA 0, 1, 0, 0, 1
DATA 1, 1, 0, 0, 0
DATA 0, 0, 1, 0, 1
DATA 1, 0, 1, 0, 0
DATA 0, 1, 1, 0, 0
DATA 0, 0, 0, 1, 1
DATA 1, 0, 0, 1, 0
DATA 0, 1, 0, 1, 0

LOCAL skip%, count%

IF (thick% = 1) THEN count% = 8 ELSE count% = 4

FOR skip% = 1 TO count%
SYS "OS_SpriteOp", (42 + 256), spr%, code\$, pos%, 49, 1, 0
pos% = pos% + 1
NEXT
ENDPROC

LOCAL count%

IF (thick% = 1) THEN count% = 8 ELSE count% = 4
pos% = pos% + count% : REM No need to set pixels to white!
ENDPROC

Now we not only know how ITF barcodes are created, we also have software that we can use to create suitable barcodes.

Here's the software as a zip file: itfgen.zip (!.6KiB)

All of this reminds me... Time for a spot of tea.

Please note that while I check this page every so often, I am not able to control what users write; therefore I disclaim all liability for unpleasant and/or infringing and/or defamatory material. Undesired content will be removed as soon as it is noticed. By leaving a comment, you agree not to post material that is illegal or in bad taste, and you should be aware that the time and your IP address are both recorded, should it be necessary to find out who you are. Oh, and don't bother trying to inline HTML. I'm not that stupid! ☺ ADDING COMMENTS DOES NOT WORK IF READING TRANSLATED VERSIONS.

You can now follow comment additions with the comment RSS feed. This is distinct from the b.log RSS feed, so you can subscribe to one or both as you wish.

Mon Tue Wed Thu Fri Sat Sun «   August 2018   » 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31

(Felicity? Marte? Find out!)

List all b.log entries

 Search Rick's b.log!
PS: Don't try to be clever.
It's a simple substring match.

Last read at 09:54 on 2024/04/25.

 © 2018 Rick Murray This web page is licenced for your personal, private, non-commercial use only. No automated processing by advertising systems is permitted. RIPA notice: No consent is given for interception of page transmission.

 Have you noticed the watermarks on pictures? Read the explanation.
Next entry - 2018/08/15