Creating Code128 barcode in C#
Asked Answered
S

2

5

Stupid me I thought, that just writing some text with a barcode font, would make the scanner read it. Seems I was wrong.

So after reading some docs about code128 barcodes, I learned that:

  1. The barcode starts with (103, 104 or 105 dependent of the type)
  2. Then comes the string itself
  3. Then comes the modulo 103 of the calculated sum of each char in the string multiplied with its position
  4. Then 106 is appended

My code is:

public string Str = "MADS";
public string Barcode = null;

public void OnGet()
{

    int start = 104;
    int end = 106;
    int calc = start;
    Barcode = start.ToString();
    for (var i = 0; i < Str.Length; i++)
    {
        calc += (Convert.ToChar(Str[i]) - 32) * (i + 1);
        Barcode += Str[i];
    }

    double rem = calc % 103;
    Barcode += Convert.ToChar((int)rem + 32).ToString() + end;

    Console.WriteLine(Barcode);

}

I'm not sure how much to include in the Barcode string, for the scanner to read it?:

  • MADS,
  • 104MADS,
  • 104MADS,106

Or am I getting it all wrong?

Me references are:

Link 1 Link 2

Especially "Link 1", because I've tested that result with the scanner, and it works. Sadly I can't get my output to look like that.

Conclusion

After reading the comments and answers I think the best way for me is to use an existing library.

I chose NetBarcode GitHub link because it's .Net Core compatible.

Sawicki answered 21/2, 2020 at 17:22 Comment(6)
I've written a Code128 encoding algorithm that outputs a boolean array of the white/black bars - you are missing the encoding table. Each character is encoded as a set of 11 "chunks" of white/black which represent the relative thickness of the black/white bars. Also there are some additional considerations with Code128 such as switching set. There are 3 sets, A/B/C which encode different characters more efficiently (set C is used for encoding pairs of digits so can cut the barcode length down a lot if it contains a lot of digits).Folketing
You also don't want the literal string "104" etc - you choose the character set with the first byte (103, 104, 105) which represent the start of Set A/B/C respectively. This byte should be looked up in the encoding table to determine the width of the bars that make it up the encoding. For example, char 103 = StartA meaning the start of a barcode using character set A (lower case ascii). This is encoded as 11010000100 which means a 2 width thick line, followed by a 1 width thick gap, then a 1 width thick line and so on.Folketing
Also, assuming you still want to do this yourself and not use an external lib/service, you can use RLE compression in your output to keep the file small without requiring any external libs (you can just write a bitmap to the disk with RLE encoding as you write the barcode data). Outputting a bitmap with a 1 thickness line is going to be hard to scan, scaling this up by a multiplication factor works but file sizes can get big quickly so compress. This is all assuming you still can't use a different approach such as a web service or library.Folketing
@Folketing thank you for your inputs. After reading your comments I believe the best way for me is to use an existing library.Sawicki
No probs, just FYI I had no choice since it was for a cloud based ERP system and it doesn't allow you to interop with any programming languages. I could have used Azure Functions but I like a challenge and it's good fun to implement - plus I wanted a version that didn't have any external dependencies for situations where barcodes are critical and would always work 100% without requiring an external service to be 100% available.Folketing
For whatever reason, I could not get the Telerik bar code generator to generate codes that would scan. NetBarCode works though. It even rebuilt flawlessly to .Net 4.8. Thanks!Wrongdoing
F
7

If you are using a barcode font, you need to include the Start character, data string, checksum and Stop character in the string you send to output, so the last in your example would be correct. The font only looks up each symbol and paints the bars and spaces for you. It knows nothing about the barcode symbology and rules itself.

var buttonGen = document.getElementById("btnGen");
buttonGen.onclick = function () {
  var x = document.getElementById("textIn").value;
  var i, j, intWeight, intLength, intWtProd = 0, arrayData = [], fs;
  var arraySubst = [ "Ã", "Ä", "Å", "Æ", "Ç", "È", "É", "Ê" ];

/*
 * Checksum Calculation for Code 128 B
 */
  intLength = x.length;
	arrayData[0] = 104; // Assume Code 128B, Will revise to support A, C and switching.
	intWtProd = 104;
	for (j = 0; j < intLength; j += 1) {
			arrayData[j + 1] = x.charCodeAt(j) - 32; // Have to convert to Code 128 encoding
			intWeight = j + 1; // to generate the checksum
			intWtProd += intWeight * arrayData[j + 1]; // Just a weighted sum
	}
	arrayData[j + 1] = intWtProd % 103; // Modulo 103 on weighted sum
	arrayData[j + 2] = 106; // Code 128 Stop character
  chr = parseInt(arrayData[j + 1], 10); // Gotta convert from character to a number
  if (chr > 94) {
    chrString = arraySubst[chr - 95];
  } else {
    chrString = String.fromCharCode(chr + 32);
  }
  
  // Change the font-size style to match the drop down
  fs = document.getElementsByTagName("option")[document.getElementById("selList").selectedIndex].value;
  document.getElementById("test").style.fontSize = fs  + 'px';
  
  document.getElementById("check").innerHTML =
    'Checksum = ' + chr + ' or character ' + // Make It Visual
    chrString + ', for text = "' + x + '"';
  
  document.getElementById("test").innerHTML =
    'Ì' + // Start Code B
    x + // The originally typed string
    chrString + // The generated checksum
    'Î'; // Stop Code
}
<html>
  <head>
    <link href="https://fonts.googleapis.com/css?family=Libre+Barcode+128+Text" rel="stylesheet">
    <style>
      td, th {
        text-align: center;
        padding: 6px;
      }

      .ss {
        font-family: 'Libre Barcode 128 Text', cursive;
        font-size: 24px;
      }
    </style>
  </head>
  <body>
    &nbsp;Font Size:&nbsp;
    <select id="selList">
      <option value="24" selected>24px</option>
      <option value="30">30px</option>
      <option value="36">36px</option>
      <option value="42">42px</option>
      <option value="48">48px</option>
      <option value="54">54px</option>
      <option value="60">60px</option>
      <option value="66">66px</option>
      <option value="72">72px</option>
      <option value="78">78px</option>
      <option value="84">84px</option>
      <option value="90">90px</option>
      <option value="96">96px</option>
    </select>&nbsp;

    <input type="text" id="textIn"></input>
    <input type="button" id="btnGen" value="Generate Code 128 Checksum" tabindex=4/>
    <div id="check"></div><br /><span id="test" class="ss">ÌMaking the Web Beautiful!$Î</span><br />
    <p>This is a demonstration of use of the Libre Barcode 128 Font.</p>
    <p>Because the Libre Barcode Code 128 font does not generate checksums, you need this component to produce a scanning barcode.</p>
    <p>To use, just enter the text you want to embed in the barcode and press the generate button. Happy barcoding!</p>
    <p>By the way, Libre Barcode 128 Font uses the following high ASCII / unicode characters to implement the control codes symbols. (This is essentially adding 100 to the value, in other words 'Ã' is U+00C3 (195) to 'Î' is U+00CE (206).)</p>
<table border="3">
    <tr>
    <th>Value</th>
    <th>Encoding</th>
    <th>Subst</th>
  </tr>
<tr><td> 95</td><td>A: US, B: DEL, C: 95</td><td>Ã</td></tr>
<tr><td> 96</td><td>A: FNC 3, B: FNC 3, C: 96</td><td>Ä</td></tr>
<tr><td> 97</td><td>A: FNC 2, B: FNC 2, C: 97</td><td>Å</td></tr>
<tr><td> 98</td><td>A: Shift B, B: Shift A, C: 98</td><td>Æ</td></tr>
<tr><td> 99</td><td>A: Code C, B: Code C, C: 99</td><td>Ç</td></tr>
<tr><td>100</td><td>A: Code B, B: FNC 4, C: Code B</td><td>È</td></tr>
<tr><td>101</td><td>A: FNC 4, B: Code A, C: Code A</td><td>É</td></tr>
<tr><td>102</td><td>A: FNC 1, B: FNC 1, C: FNC 1</td><td>Ê</td></tr>
<tr><td>103</td><td>Begin Code A</td><td>Ë</td></tr>
<tr><td>104</td><td>Begin Code B</td><td>Ì</td></tr>
<tr><td>105</td><td>Begin Code C</td><td>Í</td></tr>
<tr><td>106</td><td>Stop Code</td><td>Î</td></tr></table>
  </body>
</html>
Fyke answered 23/2, 2020 at 15:44 Comment(2)
Thank you, Brian. Although I ended up using an existing library, this is the answer to the original question, so this will be the correct answer.Sawicki
If "Just use X library" was the answer to every question, Stack Overflow wouldn't need to exist. There are thousands of coders out there that can't use libraries for legal and technical reasons. Thanks for your support.Fyke
S
3

Check this library: https://github.com/barnhill/barcodelib

On Nuget: https://github.com/barnhill/barcodelib

It will generate an image containing the barcode that reads as the text in input. Usage example:

BarcodeLib.Barcode b = new BarcodeLib.Barcode();
Image img = b.Encode(BarcodeLib.TYPE.CODE128, "038000356216", Color.Black, Color.White, 290, 120);
Scrivings answered 21/2, 2020 at 17:27 Comment(2)
Libraries like this are easily found by Google anyway. Can you provide any value in your answer beyond that?Horseweed
Updated the answer with basic usage example for Code 128 barcode generation.Scrivings

© 2022 - 2024 — McMap. All rights reserved.