如何读取NADRA身份证上的条形码?

7
我正在编写一个应用程序,从由巴基斯坦国家数据和登记局(NADRA)发行的身份证中读取条形码。NADRA向巴基斯坦公民发放CNIC。我想读取这些印在CNIC上的条形码。NADRA已经编码了诸如姓名、父亲姓名、地址、出生日期等信息,但这些信息使用乌尔都语存储。我成功地读取了这些条形码,但问题是我无法将它们的字符集转换成乌尔都语。我安装了乌尔都字体,如Noori Nistalique、Aswad等等,但是这些字符集只显示了一堆杂乱无章的字符,而不是有意义的信息。当我用简单的英语解码这些条形码时,数字信息正确,但不显示乌尔都语的信息。
是否有人尝试过读取这些条形码,并成功解码?请帮助我或指导我该做什么......
这里是我读取的样品,这是用简单的英语:
A0U1200708091232 13501722 T31 2602 -E'/
这里是我读取的样品,这是用乌尔都语:
آڑم٠٢٨٧٨٧٠١٨٠ء١٢٠٠٧٠٨٠٩١٢٣٢ ١٣٥٠١٧٢٢ ٹ٣١ص ٢٦٠٢ -فؓف ؐف-فڈف┴ف ‌،ف٩ف┴ف ‌١ف-فؐف"ففف ‌ ‌ ‌ ‌ ‌ ‌ ‌
如您所见,数字信息相同,但使用乌尔都语编码的信息是混乱的......
有什么帮助吗?

你找到解决问题的方法了吗?如果有,请分享。 - Khaled Javeed
@KhaledJaveed 请检查我的答案。 - moonzai
moonzai,能否帮个忙?我找不到任何可读取PDF417码的库,现在正在使用zxing...请指点一下... - Junaid
zxing是一个很好的库,它支持PDF417。你需要更好的相机,至少8MP,才能在手机上读取PDF417。还有另一个库,ZBar,它是用C/C++编写的。你也可以使用这个库。但这两个库都依赖于良好的相机分辨率。 - moonzai
1
@moonzai,@KhaledJaveed - CNIC的二维码只提供CNIC号码。你们是如何提取其他详细信息的? - Syed Asad Ali
2个回答

8
NADRA使用了一个诀窍,实际上是使用一个单词的十六进制值的最后两个字符,例如,如果 \u0622 是 Alif(假设),则 NADRA仅使用最后两个字符进行编码,即22,这就是这个技巧。我附上一些代码来将十六进制转换为乌尔都语,读取条形码数据,将其转换为十六进制字符串,然后将此字符串传递给此功能,您将获得所有乌尔都语信息,只需将此字符串放入某些支持乌尔都语或阿拉伯语的视图(Android),组件(Java)或如果您使用C#,则将其放入标签中。
public class ConvertToUrdu {

public static String convertToUrdu(String text)
{
    StringBuilder sb = new StringBuilder();

    String[] characters = text.split(",");

    for(String character : characters)
    {


        //if (ListDigits.Contains(ch))
        //{
        //    continue;
        //}
        switch (character)
        {
            case "20":
                sb.append(" ");
                break;

            case "22":
                sb.append("\u0622");
                break;

            case "27":
                sb.append("\u0627");
                break;

            case "13":
                sb.append("\u0613");
                break;

            case "28":
                sb.append("\u0628");
                break;

            case "2B":
                sb.append("\u062b");
                break;

            case "86":
                sb.append("\u0686");
                break;

            case "88":
                sb.append("\u0688");
                break;

            case "2F":
                sb.append("\u062f");
                break;

            case "10":
                sb.append("\u0610");
                break;

            case "39":
                sb.append("\u0639");
                break;

            case "41":
                sb.append("\u0641");
                break;

            case "3A":
                sb.append("\u063a");
                break;

            case "AF":
                sb.append("\u06af");
                break;

            case "2D":
                sb.append("\u062d");
                break;

            case "BE":
                sb.append("\u06be");
                break;

            case "CC":
                sb.append("\u06cc");
                break;

            case "36":
                sb.append("\u0636");
                break;

            case "2C":
                sb.append("\u062c");
                break;

            case "2E":
                sb.append("\u062e");
                break;

            case "43":
                sb.append("\u0643");
                break;

            case "12":
                sb.append("\u0612");
                break;

            case "44":
                sb.append("\u0644");
                break;

            case "45":
                sb.append("\u0645");
                break;

            case "BA":
                sb.append("\u06ba");
                break;

            case "46":
                sb.append("\u0646");
                break;

            case "29":
                sb.append("\u0629");
                break;

            case "A9":
                sb.append("\u06a9");
                break;

            case "C1":
                sb.append("\u06c1");
                break;

            //case "45":
            //    sb.Append("\u0645");
            //    break;

            case "7E":
                sb.append("\u067e");
                break;

            case "42":
                sb.append("\u0642");
                break;

            case "91":
                sb.append("\u0691");
                break;

            case "31":
                sb.append("\u0631");
                break;

            case "35":
                sb.append("\u0635");
                break;

            case "33":
                sb.append("\u0633");
                break;

            case "79":
                sb.append("\u0679");
                break;

            case "2A":
                sb.append("\u062a");
                break;

            case "21":
                sb.append("\u0621");
                break;

            case "38":
                sb.append("\u0638");
                break;

            case "37":
                sb.append("\u0637");
                break;

            //case "48":
            //    sb.Append("\\u0635\u0644\u0649\u0020\u0627\u0644\u0644\u0647\u0020\u0639\u0644\u064a\u0647\u0020\u0648\u0633\u0644\u0645");
            //    break;

            case "48":
                sb.append("\u0648");
                break;

            case "98":
                sb.append("\u0698");
                break;

            case "34":
                sb.append("\u0634");
                break;

            case "D2":
                sb.append("\u06d2");
                break;

            case "30":
                sb.append("\u0630");
                break;

            case "32":
                sb.append("\u0632");
                break;

            case "60":
                sb.append("\u0660");
                break;

            case "61":
                sb.append("\u0661");
                break;

            case "62":
                sb.append("\u0662");
                break;

            case "63":
                sb.append("\u0663");
                break;

            case "64":
                sb.append("\u0664");
                break;

            case "65":
                sb.append("\u0665");
                break;

            case "66":
                sb.append("\u0666");
                break;

            case "67":
                sb.append("\u0667");
                break;

            case "68":
                sb.append("\u0668");
                break;

            case "69":
                sb.append("\u0669");
                break;

            case "0C":
                sb.append(" \u200c");
                break;

            case "D4":
                sb.append("\u06d4");
                break;

            //case "0C":
            //    sb.Append("\u060c");
            //    break;

            case "1F":
                sb.append("\u061f");
                break;

            case "02":
                sb.append("\u0602");
                break;

            case "1B":
                sb.append("\u061b");
                break;

            case "7b":
                sb.append("\u007b");
                break;

            case "7D":
                sb.append("\u007d");
                break;
            //default:
            //    sb.Append(ch);
            //    break;
        }
    }

    return sb.toString();
}
}

我写了这段Java代码,你可以将其转换为任何其他语言。
祝一切顺利:-)
注意: 为了方便起见,在原始字符串中的两个字符后面添加了“,”,例如A0U1200708091232 -> A0,U1,20,07,08,09,12,32。只是为了调试,因此此函数实际上将第二个字符串转换为乌尔都语。
编辑: 根据评论,这是我的函数,它将字符串转换为十六进制,我用C#编写了它。
private string convertToHex(string text)
    {
        StringBuilder sb = new StringBuilder();
        foreach (char c in text)
        {
            if (c == '\n')
            {
                sb.Append('\n');
                sb.Append(',');
            }
            else
            {
                sb.Append(String.Format("{0:X}", (int)c));
                sb.Append(',');
                //sb.Append((int)c + " ");
            }
        }

        return sb.ToString();
    }

在JAVA中,您可以通过编写String hex = String.format("%04x", (int) c);来进行转换。

我收到了这个字符串AE71145350170U1200108031246 611011805606102 X41G61 23111977 (D 'DE - EH / (Y 0 H' DAB '1 E - EH / (Y E ©' فلمیں ایف ایف ای (1 351-C ¯ D I / E - ڈی Á 483 I © Y 1 G-6 / 1-4 '3 D' E '(' / '3 D' E '(' / 我可以将其转换为十六进制值,但不能用乌尔都语。有什么帮助吗? - Nauman Khalid
1
@moonzai,我有一个关于地址的问题,因为地址包含英文、乌尔都语和数字,你是如何区分它们的?因为当我转换它时,姓名和父亲姓名没问题,但地址会改变,其中使用了英文或数字字符。 - Umair Anwaar
@moonzai,可以来聊聊吗?我有两种不同的格式,一种是2010年之前的NIC,另一种是2014年之后的,两者略有不同。我会分享给你,我们可以在聊天中讨论吗? - Umair Anwaar
AF20715300060U1200111211952 103731043808002 4210116286091 O3F7S1 1983-02-25 E-E/9D .'F F,E 'D-3F .'F '1HF 1'&D 3y A2 3ADy FE(1 P-301E-D D3*'F ,H1 (D' 171' 41B此NIC生成于2014年,行3中的NIC号码。 - Umair Anwaar
1
我在这里简化了你的代码 https://dotnetfiddle.net/ZxcmC2 - 我认为NADRA无法解密同时包含英文和乌尔都语字符的地址。该算法无法区分E或م(meem)例如:مکان نمبر E-111。还有另一个问题是NADRA省略了逗号,因此您无法区分空格,例如:کراجی،سندھ将变成کراچیسندھ... - Waqar
显示剩余11条评论

3
除了@moonzai的回答之外,我想补充一些细节,这些细节我目前已经能够实现(在@moonzai的帮助下,当然)。
到目前为止,有三种类型的CNIC:
1. 常规CNIC [条形码编码:PDF417] 2. NICOP卡 [条形码编码:Code 128] 3. 带DIP芯片的卡 [条形码编码:QR Code]
后两者(2和3)只有身份证号码和一些附加的数字信息(在情况(2)中可能是发行数量,在情况(3)中可能是Nadra_DB_#)。
以下是PDF417格式条形码(1)编码的信息:
- 收据号码(Parchi Number),包括您访问NADRA办事处的时间戳 - CNIC号码 - 家庭号码(Khandan Number) - 出生日期 - 全名[乌尔都语] - 父亲的姓名[乌尔都语] - 包括地区和Tehsil信息的完整地址[乌尔都语+英语+Eng-Numeric]
乌尔都语是通过省略HEX代码的常见部分来编码的,即在Java / C / C ++ / ...的情况下是\u06,在Web的情况下是"&#x6",或者简单地是0x06。例如,“alif”的HEX代码为\u0627或ا,他们只加入了27并省略了&#x6。对于单词“جاوید”,实际字符应该如下所示:&#x62C&#x627&#x648&#x6CC&#x62F,但NADRA仅添加了2C2748CC2F(省略所有&#x6)。
以下是可帮助生成CNIC卡扫描输出的WEB字符串的VBA代码。我将不断添加精细的代码,以及其他语言的代码,特别是JS / Jquery和PHP。
公共函数Convert2Urdu(vString As String)作用是将输入的字符串转换成乌尔都语字符。具体实现过程如下:
1. 遍历输入字符串中的每一个字符vChar。 2. 将vChar转化为Unicode码,然后再将Unicode码转化为16进制字符串vHex。 3. 根据vHex的值返回对应的乌尔都语字符,并将这些字符拼接到一起形成新的字符串vCharArray。 4. 返回最终的字符串vCharArray。
私有函数GetUrduChar(vHex)作用是根据16进制字符串vHex返回对应的乌尔都语字符。具体实现过程如下:
1. 根据vHex的值判断其类型(字母、数字、符号等),并返回对应的乌尔都语字符。 2. 如果vHex的值没有对应的字符,则将其转化为10进制整数,并使用Chr函数返回对应的ASCII码字符。

我收到了这个字符串AE71145350170U1200108031246 611011805606102 X41G61 23111977 (D 'DE - EH / (Y 0 H' DAB '1 E - EH / (Y E ©' فلمیں ایف ایف ای (1 351-C ¯ D I / E - ڈی Á 483 I © Y 1 G-6 / 1-4 '3 D' E '(' / '3 D' E '(' / 我可以将其转换为十六进制值,但不能用乌尔都语。有什么帮助吗? - Nauman Khalid
你们能指导我一下吗,你们在使用哪个库来处理PDF417呢...我卡住了,请帮帮我!!!我会非常感激的! - Junaid
使用哪个PHP库? - Rameez Iqbal

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