This article and its code provides a way for developers to put barcodes into their applications. It allows for the generation of barcode images without the use of "barcode fonts". This need arose out of the necessity for one of my own projects to use barcodes and the lack of free libraries on the web to do the job.
To give an idea of what happens in this library: it first turns the data into a series of 1s and 0s representing equal-width bars and spaces. This string of binary information is then sent to a drawing function that converts it to an image representing the desired barcode. This approach allows for one common drawing method to be used on all symbologies.
Code 128 | Code11 | Code 39 (Extended / Full ASCII) |
Code 93 | EAN-8 | EAN-13 |
UPC-A | UPC-E | JAN-13 |
MSI | ISBN | Standard 2 of 5 |
Interleaved 2 of 5 | PostNet | UPC Supplemental 2 |
UPC Supplemental 5 | Codabar | ITF-14 |
Telepen |
** Keep in mind that some symbologies go by more than one name, so make sure the one you are using isn't listed above by a different name before contacting me to add it. If it isn't listed above and you would like me to look at adding it to this library, please post a comment below, and I will take a look at it as soon as possible. (Bugs are always a priority, so please send me bug reports.)
The library contains a class called BarcodeLib
. There are three constructors:
Barcode();Barcode(string);Barcode (string, BarcodeLib.TYPE);
If you decide to create an instance with parameters, the parameters are as follows: The string
is the data to be encoded into the barcode, and the BarcodeLib.TYPE
is the symbology to encode the data with. If you do not choose to specify the data and type at the time the instance is created, you may specify them through the appropriate property later on (but before you encode).
BarCodeLib.Barcode b = new BarCodeLib.Barcode(BarCodeLib.TYPE.UPCA, "038000356216", Color.Black, Color.White, 300, 150);
To get the image representing the data generated, you must then call one of the many Encode
functions.
public Image Encode(TYPE iType, string StringToEncode, int Width,
int Height)
public Image Encode(TYPE iType, string StringToEncode, Color
ForeColor, Color BackColor, int Width, int Height)
public Image Encode(TYPE iType, string StringToEncode, Color
ForeColor, Color BackColor)
public Image Encode(TYPE iType, string
StringToEncode)
Encode(TYPE iType)
Encode()
The resulting Image
contains the barcode in image format. More functionality has been added, so you can save the Image
once it is encoded.
public void SaveImage(string Filename, SaveTypes FileType)
This function can be used by specifying the full path (filename included) of the location you would like to save the image to as a string
. The second parameter is an enumerator (BarcodeLib.SaveTypes
) that represents the supported types (JPG, BMP, PNG, GIF, TIFF) of files you can save. Functionality has been added so that you can now set the IncludeLabel
parameter to allow it to draw the data that's encoded in the barcode, below the image, as a label. Keep in mind that this will take up some of the space you specify for the size of the image.
b.IncludeLabel = true;
This is used to put the data encoded at the bottom of the image. If you do not set this parameter, it will just generate the barcode without the data at the bottom.
Writing this library offered me the chance to become intimately familiar with how barcode symbologies work and how the symbologies differ from one another.
A new property has been added to allow exportation of the image and properties in XML format. Keep in mind that the barcode must be encoded first before this property is read, otherwise an error will be thrown to notify you of this mistake.
b.XML
Encode_Code39()
to fix a bug that didn't include inter-character spaces. Also updated the function Generate_Image(Color, Color)
, and replaced the section using SetPixel
with the following:
using (Graphics g = Graphics.FromImage(b)){ g.DrawLine(new Pen(c), x, 0, x, b.Height); g.DrawLine(new Pen(c), x + 1, 0, x + 1, b.Height);}//using
Generate_Image(Color, Color)
function again to be a little more efficient. Instead of drawing two lines, it just uses a 2px-wide pen now. Thanks for the comments; they continue to make this library better.
using (Graphics g = Graphics.FromImage(b)){ g.DrawLine(new Pen(c, (float)2), new Point(x, 0), new Point(x, b.Height));}//using
Also, functionality was added so that if you call BarcodeLib.Generate_Labels(Image)
, it will add the label showing the data encoded at the bottom of the barcode.
Fixed a bug in the Test application where, if you encoded with PostNet
as the type, it would automatically try to put the label at the bottom and labels aren't available on PostNet images. This caused it to throw an error that a try{}catch{}
can handle for now.
Took c0ax_lx's advice and moved...
using (Graphics g = Graphics.FromImage(b))
... outside the while
loop to improve resource usage.
CheckNumericOnly()
to be 1 line of code instead of a massive O^2 complicated take. (Thanks, Pete!) int pos = 0;
This library is getting better with the help of people like Luca and Pete. Keep up the good work, friends.
I also had to change the CheckNumericOnly()
back to a more complex task because some data being encoded was longer than what Int64.TryParse(string, out)
could handle ... so back to a more complex, but still a faster, task than comparing each char
. Now, I break the string
into pieces and test each piece.
InsertStartandCodeCharacters()
. The other was when trying to encode an apostrophe, it needed an escape character when selecting the data for it from the dataset. This should fix all the bugs for now ... if you find any more, let me know so I can try to track them down. Thanks again for your support. Bitmap Generate_Image(Color DrawColor, Color BackColor)
that caused the drawing to be off by one horizontal pixel. This caused the drawing to cut 1 pixel width off the first bar that was drawn if it was drawn up against the edge of the image. The drawing function also changed a bit to eliminate the variable int x;
from the function. All positions are now calculated off the variable int pos;
which cuts out one unnecessary and confusing variable. init_Code128()
that caused .Select(string filterExpression)
to return the wrong rows due to case insensitivity. So, the following was added:
this.C128_Code.CaseSensitive = true;
Another function byte[] GetImageData(SaveTypes savetype)
was added so that users may request the bytes of the image easily. (Useful if using Crystal Reports, etc.)
case
statements from the Generate_Image()
to simplify it. Updated the article to reflect the changes to the Encode
functions and the changes to the drawing functions. There may be some bugs due to the size of the changes made in this version. Please report any you find, in the comments below. FormattedData
. This value is what is actually encoded. It is formatted for certain types of barcodes, for example, Code 39 requires * in front and behind the barcode. bEncoded
from BarcodeLib.cs Static
methods now support generating the data label (required addition of a parameter to 3 of the 5 static
methods used to encode). EncodingTime
) it took to encode and generate the image. (Might be helpful for diagnostics) Barcode
class now inherits from IDisposable
- XML export functionality added to BarcodeLib
to allow the data, encoded data and other properties to be exported in XML along with the Image in Base64String
format. This includes functionality to GetXML()
and GetImageFromXML(BarcodeXML)
. ImageFormat
is now a property to set to select what type of image you want returned (JPEG is default). This can help speed of transferring data if using a webservice. GetEncoding()
for C128. This would allow Code128-B to switch and dynamically use Code128-A if it couldn't find a char in its set. Pen
object that was not disposed of. This was not causing a problem, just bad technique. BarcodeLib.Errors
properties which is a list of separate errors encountered. BarcodeLib.Symbologies
namespace for better organization. FormattedData
property was not being used, so it was removed. Version
property was added to BarcodeLib
to allow reading the libraries version number. CodeA
and CodeC
should have been used. Version
property static
so it can be read without creating an instance. LabelFont
property to allow the labels font to be changed. IsNumeric
function in C128-C to better separate that functionality. Replaced Int64
with Int32
to better allow compatibility with x86 processors. EncodingTime
now includes the time to draw the image and not just the encoding.