条码(Code 128)字体无法扫描,可能存在问题。

7

使用Font()很容易生成一个3 of 9 条形码。

Font f = new Font("Free 3 of 9", 80);
this.Font = f;

Label l = new Label();
l.Text = "*STACKOVERFLOW*";
l.Size = new System.Drawing.Size(800, 600);
this.Controls.Add(l);

this.Size = new Size(800, 600);

现在它正在工作。我看到了条形码并能够扫描它。现在我想使用其他东西,比如Code 128。为此,我需要安装字体(已完成)并只需更改

Font f = new Font("Free 3 of 9", 80);Font f = new Font("Code 128", 80);

之后,我在窗口上看到了一个条形码。问题是我无法扫描它。我认为这是因为我没有使用正确的起始结束标签。据我所知,条形码必须始终具有起始/停止字符或其他类似的内容。对于3 of 9来说,是*,对于Code 128,我不确定。在维基百科上有Start Code A,所以我尝试了

Font f = new Font("<Start Code A>test<Stop>", 80);Font f = new Font("<Start Code A>test<Stop Code A>", 80);等等... 我无法扫描输出。因为扫描仪找不到起始和停止字符。有什么想法吗?谢谢


你是否正在创建正确的校验和字符?请查看此页面以了解如何计算校验和。另外,您还可以查看以下链接 - 这将允许您创建条形码位图:http://www.codeproject.com/KB/graphics/BarcodeLibrary.aspx?fid=470627&fr=26#xx0xx - Matt Wilko
我看到你的条形码有问题了,在我的答案底部看到修改。 - egerardus
3个回答

4

Code 128可以使用字体完美表示。但它比3 of 9更棘手,因为您必须在末尾包含一个校验字符,该字符需要根据条形码的内容动态计算。此外,还有3个不同版本,每个版本都有不同的起始字符。

换句话说,条形码需要按以下方式布局:

[start char][barcode][checksum][stop char]

code128的好处在于比3 of 9更为简洁。 这个页面帮助我解决了计算校验和算法的问题。
该算法的一般概述如下:
1. 条形码的每个字符都被分配一个特定的值,具体取决于字符是什么以及它在条形码中的位置。
2. 将以上所有值相加。
3. 获取以上总和的模103值。
4. 在大多数情况下,校验和字符将是ASCII码(模数值加32),如上所述。
有一些细微之处,最终我需要在javascript中创建此算法(不要问为什么)。为了我的未来参考和展示一些细节,这就是它的样子:
/*
 * This is the variable part of my barcode, I append this to a 
 * static prefix later, but I need to perform logic to compute the 
 * checksum for this variable. There is logic earlier that enforces 
 * this variable as a 9 character string containing only digits.   
 */ 
var formIncrement = // a 9 char "digit" string variable

/*
 * Dynamically compute the total checksum value (before modulus) 
 * for the variable part of my barcode, I will need to get a modulus 
 * from this total when I am done. If you need a variable number of 
 * characters in your barcodes or if they are not all digits 
 * obviously something different would have to be done here.  
 */ 
var incrementCS = ((parseInt(formIncrement.charAt(0)) + 16) * 7) +
                  ((parseInt(formIncrement.charAt(1)) + 16) * 8) +
                  ((parseInt(formIncrement.charAt(2)) + 16) * 9) +
                  ((parseInt(formIncrement.charAt(3)) + 16) * 10) +
                  ((parseInt(formIncrement.charAt(4)) + 16) * 11) +
                  ((parseInt(formIncrement.charAt(5)) + 16) * 12) +
                  ((parseInt(formIncrement.charAt(6)) + 16) * 13) +
                  ((parseInt(formIncrement.charAt(7)) + 16) * 14) + 
                  ((parseInt(formIncrement.charAt(8)) + 16) * 15);

/*
 * 452 is the total checksum for my barcodes static prefix (600001), 
 * so it doesn't need to be computed dynamically, I just add it to 
 * the variable checksum total determined above and then get the 
 * modulus of that sum:  
 */ 
var checksum = (452 + incrementCS) % 103


var barcode = "š600001" + formIncrement

/*
 * The 0 and the 95 - 102 cases had to be defined explicitly because 
 * their checksum figures do not line up with the javascript char 
 * codes for some reason (see the code 128 definition table in the 
 * linked page) otherwise we simply need to get the charCode of the 
 * checksum + 32. I also tack on the stop char here. 
 */ 
switch (checksum) {
    case 0 :
    barcode += "€œ";
    break;
    case 95 :
    barcode += "‘œ";
    break;
    case 96 :
    barcode += "’œ";
    break;
    case 97 :
    barcode += "“œ";
    break;
    case 98 :
    barcode += "”œ";
    break;
    case 99 :
    barcode += "•œ";
    break;
    case 100 :
    barcode += "–œ";
    break;
    case 101 :
    barcode += "—œ";
    break;
    case 102 :
    barcode += "˜œ";
    break;
    default :
    barcode += String.fromCharCode(checksum + 32) + "œ";
}

return barcode;

您可能会注意到,在我的示例中,起始和停止字符(š,œ)似乎与链接页面上显示的不匹配。如果我没记错的话,这是因为我有一些非标准的code128字体,这些字符被翻译成了正确的字符。
编辑
我检查了我的文档。看起来我从right here得到了字体。使用特定的字体和上述算法,我刚刚制作了一个test的code128b条形码,结果为štestwœ,扫描正常。您的校验和算法似乎运行良好,因为我们都有w,但是如果您得到ÌtestwÎ,那么您的起始和停止代码可能有误。
我特意寻找了与我正在使用的相同的条形码字体,因为我有一种感觉,不同品牌的code128字体可能实现不同的字符来表示起始和停止条形码。

那很有趣,谢谢。如果我从页面下载源代码并启动它,我可以生成Code 128(或看起来像Code 128),但是我无法扫描它。嗯,有些不对劲。 - sabisabi
@sabisabi 如果您发布条形码包含的字符,我可能可以告诉您它有什么问题。 - egerardus
嗨,我的输入值是“test”,我的编码值是“ÌtestwΔ - 我得到了一个条形码,但我无法扫描它(http://www.jtbarton.com/Barcodes/BarcodeStringBuilderExample.aspx)。 - sabisabi
我可以正确生成条形码并读取它,但当校验和为32时(例如100004392),指定的字体无法显示字符。而且找不到一种能够同时显示这个32和前缀/后缀的字体。有什么想法吗? - Laurent Crivello
@LaurentCrivello 可能与代码128版本(A、B、C)有关 - 如果我记得正确,不同的版本具有略微不同的起始和停止字符以及略微不同的算法(例如使用模102而不是模103)。 - egerardus
显示剩余2条评论

1

查看维基百科页面上的Barcode128,我认为你应该使用ASCII码208-210来分隔块,根据条形码宽度段落和表格。


这就是我不理解的地方。208到210应该是起始“标签”,对吧?停止标记是211?然后我在字符串开头添加一个ASCII字符,如208,在结尾添加一个ASCII字符211 - 不确定如何在C#中实现。 - sabisabi
像这样:(char)(0208).ToString()。有不同的方法可以同时转换多个字节,但对于此操作,这应该足够了。https://dev59.com/-GYr5IYBdhLWcg3wXJAK或者只需搜索将char字节数组转换为字符串即可。 - Andreas Reiff

0

规格

维基百科的Code 128页面解释了以下规格:

Code 128条形码有七个部分:

  1. 空白区域
  2. 起始符号
  3. 编码数据
  4. 校验符号(必需)
  5. 停止符号
  6. 最后一根条(通常被认为是停止符号的一部分)
  7. 空白区域

校验符号是从所有符号的加权和(模103)计算出来的。

数据编码

字体将处理所需的区域和线条,除了我们需要提供起始和停止符号以及校验符号的数据。

章节校验位计算解释了校验和是通过将起始码“值”与每个符号的“值”乘以其在条形码字符串中的位置的积之和来计算的。然后,产品的总和被减少模103。由于此情况下的起始码值为103,其中模103为0,因此可以忽略它,我们只需要统计数据符号。

使用Free barcode fonts @ dobsonsw,这是一种支持95个字符的Code 128B或Code set B字体,ASCII字符32到127。为了显示检查符号,还有9个额外的溢出字符不按顺序排列,需要加以考虑。

正如@egerardus所解决的那样,这种特殊字体使用非标准的起始(353)和停止(339)符号以及不同范围的溢出字符(8216、8217、8220、8221、8226、8211、8212、0732、8364)。

实现

以下是条形码数据编码的C#实现示例。

private string BarcodeEncode(string value)
{
    int[] overChars = { 8216, 8217, 8220, 8221, 8226, 8211, 8212, 732, 8364 };
    char[] valueChars = value.ToCharArray();
    int[] checksumVals = new int[value.Length];

    for (int n = 0; n < valueChars.Length; n++)
    {
        checksumVals[n] = (((byte)valueChars[n]) - 32) * (n + 1);
    }

    int checksum = checksumVals.Sum() % 103;
    char check = (char)(checksum + 33);
    if (checksum > 93)
        check = (char)overChars[checksum - 94];

    string start = ((char)353).ToString();
    string stop = ((char)339).ToString();

    return start + value + check.ToString() + stop;
}

接下来是相应的 JavaScript 实现。

function barcodeEncode(value) {
    var overChars = [8216, 8217, 8220, 8221, 8226, 8211, 8212, 732, 8364];
    var checksum = [...value]
            .map((i, n) => (i.charCodeAt(0) - 32) * ++n)
            .reduce((a, b) => a + b, 0) % 103;
    return String.fromCharCode(353) + value
        + (checksum < 94
            ? String.fromCharCode(checksum + 33)
            : String.fromCharCode(overChars[checksum - 94]))
        + String.fromCharCode(339);
}

享受乐趣!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接