|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
IntroductionEAN-13 is a Standard - Barcode - format. This code is used to scan articles in stores and other places. For a project I'm working on, I need to print EAN - Codes on a Laser printer and display them on the screen for the user. The printing task is quite easy since most printers support EAN - Codes, if you pass them an escape sequence. The trouble is, that you can pass the escape sequences only if you open the port manually and print the whole page with print-commands, which means, you can not use the The EAN - FormatTo draw an EAN - 13 formatted Barcode you need three tables which tell you how to format each digit. The first and the second are used for the digits 1 - 7 and the third table is used for the digits 8 - 13. Each digit is 12 bits long; if you count the 2 bits separators they are 14 bits long. These are the three tables with the digits and their decimal value in the barcode:
Now the question is: Why do we use two tables for the first 7 digits? Answer: Because the first digit is not really printed, if you look at the code you only see the digits 2-13. First digit is decoded by the variations of the usage for the drawing of digits 2-7. These are the combinations we use to decode the first digit:
Now, the last important thing is the 13th digit. You can't choose it freely. It's a checksum. It's calculated in the following way:
If you code it, it looks like this: private string CreateChecksum(string EAN)
{
int csumTotal = 0; // The checksum working variable starts at zero
// Calculate the checksum value for the message
for( int charPos = EAN.Length - 1; charPos >= 0; charPos--)
{
if( charPos % 2 == 0 )
csumTotal = csumTotal + int.Parse(EAN.Substring(charPos,1));
else
csumTotal = csumTotal + (3 * int.Parse(EAN.Substring(charPos,1)));
}
// Calculate the checksum digit
int remainder = 10-(csumTotal % 10);
remainder = remainder % 10;
return remainder.ToString();
}
The EAN - Classprivate int[] Pool01i; // the Integer Representation of the Tables 1 and 2
private char[] Pool01s; // the char Representation of the tables 1 and 2
private int[] Pool2i; // the Integer Representation of the Table 3
// the Offsets for each digit depending on the first
private int[][] Additions = new int[10][];
private const int p = 112; //ASCII - Value of p
private const int P = 80; // ASCII - Value of P
private Color backcolor; // Backcolor of EAN - Code
// Bitmap, that holds the graphic representation of the Code
private Bitmap tmpCode;
// Graphics - Object to draw the EAN - Code into the Bitmap
private Graphics Renderer;
private int wdth; //Width of EAN - Code
private int hght; //Height of EAN
private Font font //Used font to draw the EAN - String
//Marks the bars which must be longer than the others
private int[] ALengths;
private string CodeVal = ""; // Binary Representation of the EAN - Code
private string eancode = ""; //Decimal Representation of the EAN - Code
// Marks the Code as Valid or invalid depending on the Checksum
private bool valid = true;
private int Seperators = 51; // Decimal Value of the Seperator - Bars
private float brushwidth = 1; // Width of a bar
// Event is fired after the EAN - Code has changed
internal event EventHandler CodeChanged;
In the constructor of my internal EAN13Code(int width, int height, Font fnt, Color BC)
{
backcolor = BC;
tmpCode = new Bitmap(width,height);
Renderer = Graphics.FromImage(tmpCode);
wdth = width;
hght = height;
font = fnt;
// Pool1i holds the Values of Table 1 and 2
Pool01i = new int[]{243,963,783,4083,3087,3843,3327,4047,3903,207,
3135,3855,975,3075,1011,4035,51,771,195,831};
// The Values in Pool01i are Associated with char Values from p-y and P-Y
Pool01s = new char[]{'p','q','r','s','t','u','v','w','x','y','P','Q',
'R','S','T','U','V','W','X','Y'};
Pool2i = new int[]{4035,3855,3900,3075,3324,3135,3264,3084,3120,4044};
// in the Additions we set the Offsets for each digit
// depending on the value of the first Digit.
Additions[0] = new int[]{p,p,p,p,p,p};
Additions[1] = new int[]{p,p,P,p,P,P};
Additions[2] = new int[]{p,p,P,P,p,P};
Additions[3] = new int[]{p,p,P,P,P,p};
Additions[4] = new int[]{p,P,p,p,P,P};
Additions[5] = new int[]{p,P,P,p,p,P};
Additions[6] = new int[]{p,P,P,P,p,p};
Additions[7] = new int[]{p,P,p,P,p,P};
Additions[8] = new int[]{p,P,p,P,P,p};
Additions[9] = new int[]{p,P,P,p,P,p};
ALengths = new int[190];
for (int i= 0; i< ALengths.Length;i++)
{
//We want the Leading bars, the seperator - Bars and the Ending
// Bars to be longer than the others.
ALengths[i] = 0;
if (i == 0 |i == 1 |i == 4 |i == 5 | i==92 | i == 93 |i == 96 |
i == 97 | i == 189 | i == 188 | i == 185 | i == 184)
{
ALengths[i] = 10;
}
}
}
With the property internal string EANCode
{
get
{
return eancode;
}
set
{
// assign the Code no matter if it's valid or not.
eancode = value.Trim();
// if the Length is 12 we calculate the Checksum
if (eancode.Length == 12)
{
eancode += CreateChecksum(eancode);
}
// if the EAN - Code is 13 digits long we check if the code is valid and
// create the binary representation of it.
if (eancode.Length == 13)
{
valid = true;
if (CreateChecksum(eancode.Substring(0,12)) != eancode[12].ToString())
{
valid = false;
}
CodeVal = CreateCode(eancode);
}
// we draw the Code into a bitmap and inform the client that the code is
// now ready for Painting somewhere.
PrepareCode();
if (CodeChanged != null)
{
CodeChanged(this,EventArgs.Empty);
}
}
}
The creation of the binary representation of the EAN - Code is quite simple: private string CreateCode(string ean)
{
string RetVal = "";
// First thing in the code are the 2 leading Seperator - Bars.
RetVal = Dec2Bin(Seperators);
// Get the first Digit of the code. we use
// this number for the Selection of the
// Table we're going to use for the 2nd to the 7th digit.
int Spos = int.Parse(ean.Substring(0,1));
for (int i=1; i<=ean.Length;i++)
{
if (i <= 6)
{
//Each Digit is leaded by 2 empty Bars.
// for the first 6 Digits we use Pool01i with an
// offset depending on the first Digit
int nm = int.Parse(ean.Substring(i,1));
RetVal += "00" + Dec2Bin(Pool01i[IndexOf(nm+Additions[Spos][i-1],
Pool01s)]).PadLeft(12,'0');
}
else if (i == 7)
{
// in the Middle we draw the Seperator
RetVal += "00" + Dec2Bin(Seperators);
}
else
{
// the rest of the digits are defined with Pool2i
int nm = int.Parse(ean.Substring(i-1,1));
RetVal += "00" + Dec2Bin(Pool2i[nm]).PadLeft(12,'0');
}
}
// The Code is finished with the Ending Seperator.
RetVal += "00" + Dec2Bin(Seperators);
return RetVal;
}
After we know what the binary appearance of the code is, we can create a bitmap of it. private void PrepareCode()
{
//Create a Bitmap with the Measurements of the EAN - Code
tmpCode = new Bitmap(wdth,hght);
// Initialize the Graphics object for the Bitmap.
Renderer = Graphics.FromImage(tmpCode);
// Set the Backcolor of the Control.
Renderer.Clear(backcolor);
//Print the EAN into the Bitmap.
WriteEAN(10,0,Renderer,hght*2/3);
}
private void WriteEAN(int x, int y, Graphics g, int Height)
{
// Set the Color of the Bars with 1 depending on if
// the code is valid (black) or invalid (red)
Brush B1 = (Brush)System.Drawing.Brushes.Black.Clone();
if (!valid)
{
B1 = (Brush)Brushes.Red.Clone();
}
// the Bars with 0 are not painted.
Brush B0 = (Brush)Brushes.Transparent.Clone();
Font PFont = font;
// the Barcode is only painted if its length is 13
if (eancode.Length == 13)
{
// First draw the leading Digit.
g.DrawString(eancode.Substring(0,1),PFont, System.Drawing.Brushes.Black,
x-g.MeasureString(eancode.Substring(0,1),PFont).Width-3,y+Height+3);
float F = 0;
// Now Draw all the Bars in black or transparent.
for (int i= 0; i< CodeVal.Length; i++, F+=brushwidth)
{
if (CodeVal.Substring(i,1) == "1")
{
g.FillRectangle(B1,x+F,y,brushwidth,Height+ALengths[i]);
}
else
{
g.FillRectangle(B0,x+F,y,brushwidth,Height+ALengths[i]);
}
}
F = brushwidth;
// Write the decimal Representations of
// each digit on the Position the bars
// were painted before.
for (int i = 1; i<=6; i++, F+=brushwidth)
{
g.DrawString(eancode.Substring(i,1),PFont,
System.Drawing.Brushes.Black,x+(14*(F-1))+8,y+Height+3);
}
F = brushwidth*7;
for (int i = 7; i<13; i++,F+=brushwidth)
{
g.DrawString(eancode.Substring(i,1),PFont,
System.Drawing.Brushes.Black,x+(14*(F-7))+99,y+Height+3);
}
}
}
After I created the Usage of the CodeAdd eaN13CodeCtl1.Text = "012345678901";
So, that's allIf you're interested in EAN13 backgrounds, there's a great article from rainman_63 about that. The code looks a bit strange (naming conventions and things like that), sorry about that.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||