UPC-5 is a variation on the UPC-A barcode designed to contain 5 digits of data.
The checksum (or parity) for the UPC-5 format is used only to encode the barcode, and therefore is not coded directly.
Calculating the parity uses the same modulo 10 method as the UPC-A, except that the weightings are different. Odd-numbered positions are weighted 3, while even-numbered positions are weighted 9.
Once we have the weighted sum, we apply a modulo 10 to the weighted sum, which gets the remainder after applying a modulo of 10 to the weighted sum.
The parity is then 10 – (modulo 10 of the weighted sum).
UPC-5 only has a left guard and centre guard (which is places after the third digit), which are encoded as 1011 and 01 respectively.
The 5 digits are then encoded using either odd or even encoding, which is determined by the parity string.
0 | 00111 |
1 | 01011 |
2 | 01101 |
3 | 01110 |
4 | 10011 |
5 | 11001 |
6 | 11100 |
7 | 10101 |
8 | 10110 |
9 | 11010 |
The odd and even encodings are the same as the ones for the UPC-E format
Digit | Odd | Even |
0 | 0001101 | 0100111 |
1 | 0011001 | 0110011 |
2 | 0010011 | 0011011 |
3 | 0111101 | 0100001 |
4 | 0100011 | 0011101 |
5 | 0110001 | 0111001 |
6 | 0101111 | 0000101 |
7 | 0111011 | 0010001 |
8 | 0110111 | 0001001 |
9 | 0001011 | 0010111 |
Here is the code to encode the barcode. The full source code is available here
namespace BarcoderLib { public class BarcodeUPC5 { private string gLeftGuard = "1011"; private string gCentreGuard = "01"; private string[] gOdd = { "0001101", "0011001", "0010011", "0111101", "0100011", "0110001", "0101111", "0111011", "0110111", "0001011" }; private string[] gEven = { "0100111", "0110011", "0011011", "0100001", "0011101", "0111001", "0000101", "0010001", "0001001", "0010111" }; private string[] gParity = {"00111", "01011", "01101", "01110", "10011", "11001", "11100", "10101", "10110", "11010"}; private int[] gWeighting = { 3, 9, 3, 9, 3}; public Bitmap Encode(string message) { string encodedMessage; Bitmap barcodeImage = new Bitmap(250, 100); Graphics g = Graphics.FromImage(barcodeImage); Validate(message); encodedMessage = EncodeBarcode(message); PrintBarcode(g, encodedMessage, message, 250, 100); return barcodeImage; } private void Validate(string message) { Regex reNum = new Regex(@"^\d+$"); if (reNum.Match(message).Success == false) { throw new Exception("Encode string must be numeric"); } if (message.Length != 5) { throw new Exception("Encode string must be 5 digits long"); } } private void PrintBarcode(Graphics g, string encodedMessage, string message, int width, int height) { SolidBrush whiteBrush = new SolidBrush(Color.White); SolidBrush blackBrush = new SolidBrush(Color.Black); Font textFont = new Font(FontFamily.GenericMonospace, 10, FontStyle.Regular); g.FillRectangle(whiteBrush, 0, 0, width, height); int xPos = 20; int yTop = 20; int barHeight = 50; for (int i = 0; i < encodedMessage.Length; i++) { if (encodedMessage[i] == '1') { g.FillRectangle(blackBrush, xPos, yTop, 1, barHeight); } xPos += 1; } xPos = 20; yTop -= 17; for (int i = 0; i < message.Length; i++) { g.DrawString(message[i].ToString(), textFont, blackBrush, xPos, yTop); xPos += 7; } } private string EncodeBarcode(string message) { int i; int parityCode = CalcParity(message); char parity; string encodedString = gLeftGuard; for (i = 0; i < 5; i++) { parity = gParity[parityCode][i]; if (parity == '1') { encodedString += gOdd[Convert.ToInt32(message[i].ToString())]; } else{ encodedString += gEven[Convert.ToInt32(message[i].ToString())]; } if (i < 4) { encodedString += gCentreGuard; } } return encodedString; } private int CalcParity(string message) { int sum = 0; int parity = 0; for (int i = 0; i < 5; i++) { sum += Convert.ToInt32(message[i].ToString()) * gWeighting[i]; } parity = 10 - (sum % 10); if (parity == 10) { parity = 0; } return parity; } } }
Comments