条形码(代码 128)字体未扫描有问题

本文关键字:扫描 有问题 字体 代码 条形码 | 更新日期: 2023-09-27 18:36:42

使用 Font() 很容易生成 3/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);

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

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

之后,我在窗户上看到一个条形码。问题是我无法扫描它。我认为这是因为我没有为条形码使用正确的开始停止标签。据我了解,必须始终有一个开始/停止字符或其他什么。对于 3 个中的 9 个,代码 128 的 * 我不确定。在维基上有开始代码A,所以我尝试了

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

条形码(代码 128)字体未扫描有问题

代码 128 可以用完全精细的字体表示。不过,这比 9 个中的 3 个更棘手,因为您必须在末尾包含一个校验和字符,该字符需要根据条形码的内容动态计算。还有 3 个不同的版本,每个版本都有不同的起始字符。

换句话说,条形码需要像这样布局:

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

code128 的好处是它比 9 中的 3 要简洁得多。

这个页面帮助我计算出计算校验和的算法。

该算法的一个非常一般的概述是:

  1. 条形码的每个字符都会获得分配给它的特定值取决于字符是什么以及它在条形码。

  2. 上面 1) 中的所有值加在一起。

  3. 获取上面 2) 中总计的模数 103 值。

  4. 在大多数情况下,校验和字符将是以下的 ASCII 代码:(模值加 32) 如上述 3) 中确定。

有一些细微差别,我最终需要在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 字体,并且这些字符翻译成正确的字符。

编辑

我重新检查了我的文档。看起来我从这里得到了字体。专门使用该字体并使用上面的算法,我刚刚为test制作了一个code128b条形码,该条形码出来štestwœ,扫描正常。您的校验和算法似乎工作正常,因为我们都有w但是如果您得到:ÌtestwÎ,则看起来您的开始和停止代码已关闭。

特意寻找我正在使用的相同条形码字体,因为我有一种感觉,不同品牌的 code128 字体可能会实现不同的字符来表示开始和停止条形码。

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

规格

维基百科的Code 128页面对规范的解释如下:

Code 128 条形码有七个部分:

  1. 安静区
  2. 开始符号
  3. 编码数据
  4. 复选符号(必填)
  5. 停止符号
  6. 最终柱线(通常被视为止损符号的一部分)
  7. 安静区

复选符号是根据所有符号的加权和(模 103)计算得出的。

数据编码

该字体将处理所需的区域和线条,以及我们需要提供开始和停止符号以及复选符号的数据。

校验

位计算部分解释了校验和的计算方法是将起始代码"值"与每个符号的"值"的乘积乘以其在条形码字符串中的位置。然后将乘积的总和减少模103。由于本例中的起始代码值为 103,其中模数 103 为 0,因此可以忽略它,我们只需要计算数据符号即可。

使用免费条形码字体@ dobsonsw(代码 128B)或代码集 B,支持 95 个字符,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);
}

嘟嘟!