function decode(bar)
% decode(img): Decode barcode in image img

% Barcode 128c: four different run lengths, the relative widths are 1 2 3 4

[barh, barw] = size(bar);
slice = double(bar(round(barh/2),:));
sliceh = interp(slice,16);
thres = mean(sliceh);
sliceb = sliceh > thres;
runs = [];
m = 1;
for k=2:length(sliceb)
	if (sliceb(k)~=sliceb(m))
		runs = [runs k-m];
		m = k;
	end
end
%figure(1),stem(runs);
runsort = sort(runs);
%figure(2),stem(runsort);
runwidths = zeros(0,7);
m = 1;
for k=2:length(runsort)
	rat = runsort(k-1)/runsort(k);
	if (rat<0.9)
		runwidths = [runwidths; k-m min(runsort(m:k-1)) max(runsort(m:k-1)) -1 mean(runsort(m:k-1)) m rat];
		m = k;
	end
end
runwidths = flipud(sortrows(runwidths));

if (length(runwidths(:,1))<4)
	error('Not enough widths');
end
codesort = sortrows(runwidths(1:4,5));	% Sort by Mean
for k=1:4
	for m=1:4
		if runwidths(k,5)==codesort(m)
			runwidths(k,4)=m;
		end
	end
end

disp('    Count    Minimum   Maximum    Code     Mean      Index    Threshold');
runwidths

widths = [];
for k=1:length(runs)
	m=1;
	while runs(k)<runwidths(m,2) | runs(k)>runwidths(m,3)
		m = m+1;
		if m>length(runwidths(:,1))
			m = -1;
			break
		end
	end
	if m~=-1
		widths = [widths runwidths(m,4)];
	else
		widths = [widths -1];
	end
end

widths

codetab = [ ...
2 1 2 2 2 2;	% 00
2 2 2 1 2 2;
2 2 2 2 2 1;
1 2 1 2 2 3;
1 2 1 3 2 2;
1 3 1 2 2 2;
1 2 2 2 1 3;
1 2 2 3 1 2;
1 3 2 2 1 2;
2 2 1 2 1 3;
2 2 1 3 1 2;
2 3 1 2 1 2;
1 1 2 2 3 2;
1 2 2 1 3 2;
1 2 2 2 3 1;
1 1 3 2 2 2;
1 2 3 1 2 2;
1 2 3 2 2 1;
2 2 3 2 1 1;
2 2 1 1 3 2;
2 2 1 2 3 1;
2 1 3 2 1 2;
2 2 3 1 1 2;
3 1 2 1 3 1;
3 1 1 2 2 2;
3 2 1 1 2 2;
3 2 1 2 2 1;
3 1 2 2 1 2;
3 2 2 1 1 2;
3 2 2 2 1 1;
2 1 2 1 2 3;
2 1 2 3 2 1;
2 3 2 1 2 1;
1 1 1 3 2 3;
1 3 1 1 2 3;
1 3 1 3 2 1;
1 1 2 3 1 3;
1 3 2 1 1 3;
1 3 2 3 1 1;
2 1 1 3 1 3;
2 3 1 1 1 3;
2 3 1 3 1 1;
1 1 2 1 3 3;
1 1 2 3 3 1;
1 3 2 1 3 1;
1 1 3 1 2 3;
1 1 3 3 2 1;
1 3 3 1 2 1;
3 1 3 1 2 1;
2 1 1 3 3 1;
2 3 1 1 3 1;
2 1 3 1 1 3;
2 1 3 3 1 1;
2 1 3 1 3 1;
3 1 1 1 2 3;
3 1 1 3 2 1;
3 3 1 1 2 1;
3 1 2 1 1 3;
3 1 2 3 1 1;
3 3 2 1 1 1;
3 1 4 1 1 1;
2 2 1 4 1 1;
4 3 1 1 1 1;
1 1 1 2 2 4;
1 1 1 4 2 2;
1 2 1 1 2 4;
1 2 1 4 2 1;
1 4 1 1 2 2;
1 4 1 2 2 1;
1 1 2 2 1 4;
1 1 2 4 1 2;
1 2 2 1 1 4;
1 2 2 4 1 1;
1 4 2 1 1 2;
1 4 2 2 1 1;
2 4 1 2 1 1;
2 2 1 1 1 4;
4 1 3 1 1 1;
2 4 1 1 1 2;
1 3 4 1 1 1;
1 1 1 2 4 2;
1 2 1 1 4 2;
1 2 1 2 4 1;
1 1 4 2 1 2;
1 2 4 1 1 2;
1 2 4 2 1 1;
4 1 1 2 1 2;
4 2 1 1 1 2;
4 2 1 2 1 1;
2 1 2 1 4 1;
2 1 4 1 2 1;
4 1 2 1 2 1;
1 1 1 1 4 3;
1 1 1 3 4 1;
1 3 1 1 4 1;
1 1 4 1 1 3;
1 1 4 3 1 1;
4 1 1 1 1 3;
4 1 1 3 1 1;
1 1 3 1 4 1;		% 99
1 1 4 1 3 1;		% 100: code B
3 1 1 1 4 1;		% 101: code A
4 1 1 1 3 1;		% 102: FNC 1
2 1 1 4 1 2;		% 103: START code A
2 1 1 2 1 4;		% 104: START code B
2 1 1 2 3 2;		% 105: START code C
2 3 3 1 1 1 ];		% 106: STOP + 2
starta = 103;
startb = 104;
startc = 105;
stop = 106;

for k=1:length(widths)-5
	if max(abs(widths(k:k+5)-codetab(startc+1,:)))==0
		break
	end
end

if k==length(widths-5)
	error('Barcode not detected');
end

k

resultn = [];
results = [];
while k<=length(widths)-5
	m = 1;
	while max(abs(widths(k:k+5)-codetab(m,:)))~=0
		m = m+1;
		if m>length(codetab)
			break
		end
	end
	if m>length(codetab)
		k
		break
	end
	code = m-1;
	resultn = [resultn code];
	if code>=100
		results = [results sprintf('*', code)];
	else
		results = [results sprintf('%02i', code)];
	end
	if code==stop
		break
	end
	k = k + 6;
end

resultn

checksum = startc;
for k=2:length(resultn)-2
	checksum = mod((k-1)*resultn(k)+checksum,103);
end

if checksum ~= resultn(length(resultn)-1)
	warning('CHECKSUM ERROR')
else
	disp('Checksum OK');
end

results

disp(sprintf('Versionumero     : %s', results(2)));
disp(sprintf('Saajan tilinumero: %s', results(3:16)));
disp(sprintf('Markat/eurot     : %s', results(17:22)));
disp(sprintf('Pennit/sentit    : %s', results(23:24)));
disp(sprintf('Viitenumero      : %s', results(25:44)));
disp(sprintf('Eräpäivä         : %s', results(45:50)));
disp(sprintf('Varalla          : %s', results(51:54)));
disp(sprintf('Tarkiste 1       : %s', results(55)));
