Tanto la especificacion EAN 13 (13 dígitos), como la EAN 8 (8 dígitos) se basan en el mismo sistema de codificación numérica.
El número es dividido en 2 zonas diferenciables, la parte izq. y la parte derecha. Dichas zonas son delimitadas por una barras de inicio de código, separación de código y fin de código. Estas barras son fácilmente diferenciables dentrop del código de barras pues su longitud es algo mayor.
Así tenemos un EAN 13: 8 429359 002008
donde: 8 y 4 son dígitos de codificación, 29539 es la zona izq. de código t 00200 la zona drcha. y 8 el dígito de control.
Así tenemos un EAN 8: 8416 0089
donde: 8 y 4 son dígitos de codificación, 8416 es la zona izq. de código t 008 la zona drcha. y 9 el dígito de control.
** Cada nº es codificado en una secuencia de 7 digitos binarios (1 o 0), dependiendo de la zona en que se encuentra.
En el tipo EAN 13, el primer dígito de codificación influye tambien en el método de codificación de la parte izq. del código.
Definiremos primero, las secuencias de 7 dígitos que codifican cada número en cada zona.
Denominaremos EAN_izqA y EAN_izqB a 2 matrices que contienen las secuencias de codificación de la parte izq. del código
Denominaremos EAN_dcha a la matriz que contiene las secuencias de codificación de la parte dcha. del código
Las barras de inicio, separación y fin de código se codifican siempre igual:
Barras inicio de código -> codificadas como 101
Barras separación central -> codificadas como 01010
Barras fin de código -> codificadas como 101
const
EAN_izqA : array[0..9] of PChar=('0001101','0011001','0010011','0111101','0100011','0110001','0101111','0111011','0110111','0001011');
EAN_izqB : array[0..9] of PChar=('0100111','0110011','0011011','0100001','0011101','0111001','0000101','0010001','0001001','0010111');
EAN_dcha : array[0..9] of PChar=('1110010','1100110','1101100','1000010','1011100','1001110','1010000','1000100','1001000','1110100');
El indice 0 de la matriz será la secuencia de codificación del nº 0, el índice 1 del número 1 y así sucesivamente..............
¿ Cuándo se codifica un nº con la secuencia de la matriz EAN_lA o con la EAN-lB ?
Como se comentó antes, esto solo se aplica a los códigos EAN-13 y dependerá del primer dígito de codificación. Para ello definimos la
matriz CodificaIzq.
CodificaIzq : array[0..9] of PChar=('AAAAA','ABABB','ABBAB','ABBBA','BAABB','BBAAB','BBBAA','BABAB','BABBA','BBABA');
Aplicando esto, codificaremos el código EAN13 anterior para entender mejor el método: 8 429359 002008
8 --> no se codifica, marca el tipo de codificación, o sea CodificaIzq[8]='BABBA';
Barras inicio
4 --> se codifica siempre de la forma A, en este caso EAN_izqA[4]
2 --> EANizqB[2] \
9 --> EANizqA[9] \
3 --> EANizqB[3] |---------> codificados según manda CodificaIzq[8]
5 --> EANizqB[5] /
9 --> EANizqA[9] /
Barras separación central
0 --> EANdcha[0]
0 --> EANdcha[0]
2 --> EANdcha[2]
0 --> EANdcha[0]
0 --> EANdcha[0]
8 --> EANdcha[8]
Barras fin de código
Los códigos EAN 8 son más sencillos de codificar:
La parte izq. siempre con el método EAN_izqA y la derecha con EAN_dcha: 8416 0089
Barras inicio de código
8 --> EANizqA[8]
4 --> EANizqA[4]
1 --> EANizqA[1]
6 --> EANizqA[6]
Barras separación central
0 --> EANdcha[0]
0 --> EANdcha[0]
8 --> EANdcha[8]
9 --> EANdcha[9]
Barras fin de código
El método de validación de dígito de control (el último nº en ambos casos) es sencillo:
Para EAN 13:
Sumamos todos los dígitos impares -->
Sumamos todos los dígitos pares y multiplicamos por 3 -->
Sumamos ambas cifras -->
El dígito de control será 10 menos las unidades del número anterior, si es 0 será 0 -->
Para EAN 8:
Sumamos todos los dígitos impares y multiplicamos por 3 -->
Sumamos todos los dígitos pares -->
Sumamos ambas cifras -->
El dígito de control será 10 menos las unidades del número anterior, si es 0 será 0 -->
Para el dibujado, los "1" equivaldrán a una línea de grosor entre 0.33 mm y los "0" a un especio del mismo grosor.
Se permite un margen error entre 0.23 y 0.33 mm en todos los grosores, pero eso no será necesario en nuestra implementación pues 0.33 mm equivalen al grosor de 1 pixel.
Creo que es bien sencillo de comprender, y una vez comprendidos estos 2 es sencillo conseguir información por la red para el resto de tipos, UPC, JAN,...
Para cualquier duda o aclaración no dudéis en poneros en contacto conmigo: [email protected]
Espero que os haya servido para ver que la dificaultad que entrañan es mínima.
A continuación veremos un pequeño ejemplo de todo esto implementado en Delphi:
unit EAN;
interface
uses
Windows, SysUtils, Forms, Dialogs, StdCtrls, ExtCtrls, Classes, Controls;
const
EAN_izqA : array[0..9] of PChar=('0001101','0011001','0010011','0111101','0100011','0110001','0101111','0111011','0110111','0001011');
EAN_izqB : array[0..9] of PChar=('0100111','0110011','0011011','0100001','0011101','0111001','0000101','0010001','0001001','0010111');
EAN_dcha : array[0..9] of PChar=('1110010','1100110','1101100','1000010','1011100','1001110','1010000','1000100','1001000','1110100');
CodificaIzq : array[0..9] of PChar=('AAAAA','ABABB','ABBAB','ABBBA','BAABB','BBAAB','BBBAA','BABAB','BABBA','BBABA');
type
TFCodigoBarras = class(TForm)
Label1: TLabel;
Edit1: TEdit;
Panel1: TPanel;
PaintBox1: TImage;
procedure Edit1KeyPress(Sender: TObject; var Key: Char);
private
{ Private declarations }
public
{ Public declarations }
// procedimiento que codifica el número en un nº binario
procedure Codifica(num : string);
// procedimiento para dibujar el cód. de barras a partir del nº binario
procedure Dibujar(matrix : string);
// procedimiento para validar-corregir los códigos
procedure EANCorrecto(var num : string);
end;
var
FCodigoBarras: TFCodigoBarras;
implementation
{$R *.DFM}
procedure TFCodigoBarras.EANCorrecto(var num : string);
var
i,N : byte;
sum : integer;
flag : byte;
begin
sum:=0;
N:=Length(num)-1;
for i:=1 to N do
begin
if (i mod 2)=0 then
begin
if N=12 then
sum:=sum+StrToInt(num[i])*3
else
sum:=sum+StrToInt(num[i]);
end
else
begin
if N=12 then
sum:=sum+StrToInt(num[i])
else
sum:=sum+StrToInt(num[i])*3;
end;
end;
if sum>99 then
Flag:=10-(sum mod 100)
else
Flag:=10-(sum mod 10);
if Flag=10 then Flag:=0;
if not(StrToInt(num[N+1])=flag) then
num:=copy(num,1,length(num)-1)+IntToStr(Flag);
end;
procedure TFCodigoBarras.Codifica(num : string);
var
matrix : string;
i : integer;
begin
num:=Edit1.Text;
matrix:='';
case Length(num) of
13: begin
EANCorrecto(num);
Edit1.Text:=num;
matrix:=matrix+'x0x'; // barra inicio
matrix:=matrix+EAN_izqA[StrToInt(num[2])];
for i:=3 to 7 do
if CodificaIzq[StrToInt(num[1])][i-3]='A' then
matrix:=matrix+EAN_izqA[StrToInt(num[i])]
else
matrix:=matrix+EAN_izqB[StrToInt(num[i])];
matrix:=matrix+'0x0x0'; // barra central
matrix:=matrix+EAN_dcha[StrToInt(num[8])];
matrix:=matrix+EAN_dcha[StrToInt(num[9])];
matrix:=matrix+EAN_dcha[StrToInt(num[10])];
matrix:=matrix+EAN_dcha[StrToInt(num[11])];
matrix:=matrix+EAN_dcha[StrToInt(num[12])];
matrix:=matrix+EAN_dcha[StrToInt(num[13])];
matrix:=matrix+'x0x'; // barra final
Dibujar(Matrix);
end;
8: begin
EANCorrecto(num);
Edit1.Text:=num;
matrix:=matrix+'x0x';
matrix:=matrix+EAN_izqA[StrToInt(num[1])];
matrix:=matrix+EAN_izqA[StrToInt(num[2])];
matrix:=matrix+EAN_izqA[StrToInt(num[3])];
matrix:=matrix+EAN_izqA[StrToInt(num[4])];
matrix:=matrix+'0x0x0';
matrix:=matrix+EAN_dcha[StrToInt(num[5])];
matrix:=matrix+EAN_dcha[StrToInt(num[6])];
matrix:=matrix+EAN_dcha[StrToInt(num[7])];
matrix:=matrix+EAN_dcha[StrToInt(num[8])];
matrix:=matrix+'x0x';
Dibujar(Matrix);
end
else
ShowMessage('LONGITUD DE CODIGO NO VALIDA');
end;
end;
procedure TFCodigoBarras.Dibujar(matrix : string);
var
i : integer;
begin
PaintBox1.Canvas.Brush.Color:=clWhite;
PaintBox1.Canvas.FillRect(Rect(0,0,PaintBox1.Width,PaintBox1.Height));
PaintBox1.Canvas.Pen.Color:=clBlack;
for i:=1 to Length(Matrix) do
if matrix[i]='1' then
PaintBox1.Canvas.PolyLine([Point(10+i,10),Point(10+i,50)])
else
if matrix[i]='x' then
PaintBox1.Canvas.PolyLine([Point(10+i,10),Point(10+i,55)]);
if Length(Edit1.Text)=13 then
begin
PaintBox1.Canvas.TextOut(3,50,Edit1.Text[1]);
PaintBox1.Canvas.TextOut(17,50,copy(Edit1.Text,2,6));
PaintBox1.Canvas.TextOut(63,50,copy(Edit1.Text,8,6));
end
else
if Length(Edit1.Text)=8 then
begin
PaintBox1.Canvas.TextOut(16,50,copy(Edit1.Text,1,4));
PaintBox1.Canvas.TextOut(48,50,copy(Edit1.Text,5,4));
end;
PaintBox1.Picture.SaveToFile('c:\windows\escritorio\BarCode\'+Edit1.Text+'.bmp');
end;
procedure TFCodigoBarras.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
if Key=#13 then
begin
Codifica(Edit1.Text);
Edit1.SelStart:=0;
Edit1.SelLength:=Length(Edit1.Text);
end;
end;
end.
José Rubén
[email protected]