|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionThis article investigates the POSTNET barcode system, and demonstrates some basic functionality to create POSTNET barcodes using C# 2005 and GDI+. BackgroundMany employers these days are fairly frugal, so having them purchase something as simple as postal barcode fonts sometimes can prove to be extremely difficult. Being in this position a time or two, I decided to investigate the postal barcode system and create a simple library that could draw the POSTNET barcodes when given the zip code. POSTNET Barcode OverviewPOSTNET barcodes can be composed of several pieces of information: frame bars, zip code, +4, delivery point code, and correction character (see image below).
Frame bars signify the beginning and the end of the barcode. The frame bars are mandatory, and are composed of a single Full Bar. The zip code is also mandatory, and is represented by 25 bars. The +4 is composed of 20 bars and is optional. The delivery point code is represented by 10 bars, is optional, and is normally the last two digits of the street address, post office box, rural route number, or highway contract route number. The correction character is mandatory, and is basically a check sum (I use the terms correction character and check sum interchangeably in this article).
Correction CharacterThe correction character is a simple check sum which is calculated by adding each of the numbers in the zip code together, takes the modulus of the summed numbers by 10, and then subtracts this result from 10. Example: Zip code + 4 is 12345-6789 with a delivery point of 01. 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 0 + 1 = 46 46 % 10 = 6 10 - 6 = 4 4 % 10 = 4 So the correction character is 4; the last modulus is for the special case when the summed zip code is a multiple of 10. CodeThe Using the CodeThe // Create an instance of the Postnet class and send it
// the zip code, +4, and delivery point. The Postnet class will
// calculate the correction character.
Postnet ps = new Postnet( "12345", "6789", "01" );
// Create a Graphics object handle from a picture box.
System.Drawing.Graphics g = this.pictureBox1.CreateGraphics( );
// Send a handle to the Graphics object and the starting
// point to begin drawing the barcode.
ps.DrawPOSTNET( g, new System.Drawing.Point( 0, 0 ) );
// Handle any other drawing necessary.
// Clean up.
g.Dispose( );
The second functionality that the // Create an instance of the Postnet class and send it
// the zip code, +4, and delivery point. The Postnet class will
// calculate the correction character.
Postnet ps = new Postnet( "12345", "6789", "01" );
// Call the CreateBitmap function passing in the width and height for the
// newly created bitmap.
pictureBox1.Image = ps.CreateBitmap( this.pictureBox1.Width,
this.pictureBox1.Height );
How the code worksThe When an instance of the class is created, it initializes the bar specifications by calling the private void InitBarSpecifications( )
{
// Set the Bar specifications with the default values.
di = new DRAWING_INFO( );
_fBarWidth = .022f;
_fTallBarHeight = 0.125f;
_fShortBarHeight = 0.05f;
_fBarSpacing = 0.02f;
}
The private struct DRAWING_INFO
{
public System.Drawing.SolidBrush brush;
public float xStart;
public float yStart;
}
The public void DrawPOSTNET( System.Drawing.Graphics g,
System.Drawing.Point startPt )
{
// Calculate the Check Sum.
CalculateCorrectionCharacter( );
// Save the user's graphics state, just in case they are doing
// something special.
System.Drawing.Drawing2D.GraphicsState gs = g.Save( );
// Failure to set the PageUnit and PageScale will result
// in odd results.
g.PageUnit = System.Drawing.GraphicsUnit.Inch;
g.PageScale = 1f;
di.brush = new System.Drawing.SolidBrush( System.Drawing.Color.Black );
di.xStart = startPt.X;
di.yStart = startPt.Y;
// Print Frame Bar
g.FillRectangle( di.brush, di.xStart, di.yStart,
_fBarWidth, _fTallBarHeight );
di.xStart += ( _fBarWidth + _fBarSpacing );
// Print Zip Code
string sTempValue = ZipCode.ToString( );
DrawBars( g, sTempValue, ref di );
// Print Plus4
if( Plus4.Length == 4 )
{
sTempValue = Plus4.ToString( );
DrawBars( g, sTempValue, ref di );
// Print Delivery Point
if( this.DeliveryPoint.Length > 0 && this.DeliveryPoint.Length < 3 )
{
sTempValue = DeliveryPoint.ToString( );
DrawBars( g, sTempValue, ref di );
}
}
// Print Correction Character
sTempValue = this.CorrectionCharacter.ToString( );
DrawBars( g, sTempValue, ref di );
// Print Frame Bar
g.FillRectangle( di.brush, di.xStart, di.yStart,
_fBarWidth, _fTallBarHeight );
// Restore the saved user's graphics state, just incase they are doing
// something special.
g.Restore( gs );
}
The private void CalculateCorrectionCharacter( )
{
string sZipCode;
sZipCode = ZipCode.ToString( );
int iCorrectionCharacter = 0;
for( int i = 0; i < sZipCode.Length; i++ )
{
iCorrectionCharacter +=
Convert.ToInt32( sZipCode.Substring( i, 1 ) );
}
if( this.Plus4.Length == 4 )
{
string sPlus4 = Plus4.ToString( );
for( int i = 0; i < sPlus4.Length; i++ )
{
iCorrectionCharacter +=
Convert.ToInt32( sPlus4.Substring( i, 1 ) );
}
if( this.DeliveryPoint.Length > 0
&& this.DeliveryPoint.Length < 3 )
{
string sDeliveryPoint = this.DeliveryPoint.ToString( );
for( int i = 0; i < sDeliveryPoint.Length; i++ )
{
iCorrectionCharacter +=
Convert.ToInt32( sDeliveryPoint.Substring( i, 1 ) );
}
}
}
int iLeftOver = iCorrectionCharacter % 10;
this._iCorrectionCharacter = ( 10 - iLeftOver ) % 10;
}
The string [] _aBarcodeValues = { "11000", // 0
"00011", // 1
"00101", // 2
"00110", // 3
"01001", // 4
"01010", // 5
"01100", // 6
"10001", // 7
"10010", // 8
"10100" }; // 9
...
private void DrawBars( System.Drawing.Graphics g,
string sNumber, ref DRAWING_INFO di )
{
string sTempValue;
for( int i = 0; i < sNumber.Length; i++ )
{
sTempValue =
_aBarcodeValues[Convert.ToInt32( sNumber.Substring( i, 1 ) )];
for( int j = 0; j < sTempValue.Length; j++ )
{
if( sTempValue.Substring( j, 1 ) == "0" )
g.FillRectangle( di.brush, di.xStart, di.yStart +
( _fTallBarHeight - _fShortBarHeight ),
_fBarWidth, _fShortBarHeight );
else
g.FillRectangle( di.brush, di.xStart, di.yStart,
_fBarWidth, _fTallBarHeight );
di.xStart += ( _fBarWidth + _fBarSpacing );
}
}
}
The final function is the public System.Drawing.Bitmap CreateBitmap( int width, int height )
{
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap( width, height );
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage( bmp );
this.DrawPOSTNET( g, new System.Drawing.Point( 0, 0 ) );
g.Dispose( );
return bmp;
}
All done!Well, that's it for the History
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||