private static void parseExpiryDate(String expiryDate, ref RecognitionResult result) { try { if ("<<<<<<".Equals(expiryDate)) { result.DoesNotExpire = true; } else { result.expiryYear = 2000 + int.Parse(expiryDate.Substr(0, 2)); result.expiryMonth = int.Parse(expiryDate.Substr(2, 4)); result.expiryDay = int.Parse(expiryDate.Substring(4)); } } catch (Exception ignore) { } }
private RecognitionResult ParseMrz(string mrz) { String[] mrzLines = mrz.Split('\n'); RecognitionResult result = new RecognitionResult(); if (mrzLines.Length >= 2 && mrzLines[0].Length >= 30 && mrzLines[1].Length == mrzLines[0].Length) { result.Raw = string.Join("\n", mrzLines); //Dictionary<String, String> countries = getCountriesMap(); char type = mrzLines[0][0]; if (type == 'P') { // passport result.Type = RecognitionResult.TYPE_PASSPORT; if (mrzLines[0].Length == 44) { result.IssuingCountry = mrzLines[0].Substr(2, 5); int lastNameEnd = mrzLines[0].IndexOf("<<", 6); if (lastNameEnd != -1) { result.LastName = mrzLines[0].Substr(5, lastNameEnd).Replace('<', ' ').Replace('0', 'O').Trim(); result.FirstName = mrzLines[0].Substring(lastNameEnd + 2).Replace('<', ' ').Replace('0', 'O').Trim(); if (result.FirstName.Contains(" ")) { result.FirstName = result.FirstName.Substr(0, result.FirstName.IndexOf(" ")); } } String number = mrzLines[1].Substr(0, 9).Replace('<', ' ').Replace('O', '0').Trim(); int numberChecksum = checksum(number); if (numberChecksum == getNumber(mrzLines[1][9])) { result.Number = number; } result.Nationality = mrzLines[1].Substr(10, 13); String birthDate = mrzLines[1].Substr(13, 19).Replace('O', '0').Replace('I', '1'); int birthDateChecksum = checksum(birthDate); if (birthDateChecksum == getNumber(mrzLines[1][19])) { parseBirthDate(birthDate, ref result); } result.Gender = parseGender(mrzLines[1][20]); String expiryDate = mrzLines[1].Substr(21, 27).Replace('O', '0').Replace('I', '1'); int expiryDateChecksum = checksum(expiryDate); if (expiryDateChecksum == getNumber(mrzLines[1][27]) || mrzLines[1][27] == '<') { parseExpiryDate(expiryDate, ref result); } // Russian internal passports use transliteration for the name and have a number one digit longer than fits into the standard MRZ format if ("RUS".Equals(result.IssuingCountry) && mrzLines[0][1] == 'N') { result.Type = RecognitionResult.TYPE_INTERNAL_PASSPORT; String[] names = result.FirstName.Split(' '); result.FirstName = cyrillicToLatin(russianPassportTranslit(names[0])); if (names.Length > 1) result.MiddleName = cyrillicToLatin(russianPassportTranslit(names[1])); result.LastName = cyrillicToLatin(russianPassportTranslit(result.LastName)); if (result.Number != null) result.Number = result.Number.Substr(0, 3) + mrzLines[1][28] + result.Number.Substring(3); } else { result.FirstName = result.FirstName.Replace('8', 'B'); result.LastName = result.LastName.Replace('8', 'B'); } result.LastName = capitalize(result.LastName); result.FirstName = capitalize(result.FirstName); result.MiddleName = capitalize(result.MiddleName); } } else if (type == 'I' || type == 'A' || type == 'C') { // id result.Type = RecognitionResult.TYPE_ID; if (mrzLines.Length == 3 && mrzLines[0].Length == 30 && mrzLines[2].Length == 30) { result.IssuingCountry = mrzLines[0].Substr(2, 5); String number = mrzLines[0].Substr(5, 14).Replace('<', ' ').Replace('O', '0').Trim(); int numberChecksum = checksum(number); if (numberChecksum == mrzLines[0][14] - '0') { result.Number = number; } String birthDate = mrzLines[1].Substr(0, 6).Replace('O', '0').Replace('I', '1'); int birthDateChecksum = checksum(birthDate); if (birthDateChecksum == getNumber(mrzLines[1][6])) { parseBirthDate(birthDate, ref result); } result.Gender = parseGender(mrzLines[1][7]); String expiryDate = mrzLines[1].Substr(8, 14).Replace('O', '0').Replace('I', '1'); int expiryDateChecksum = checksum(expiryDate); if (expiryDateChecksum == getNumber(mrzLines[1][14]) || mrzLines[1][14] == '<') { parseExpiryDate(expiryDate, ref result); } result.Nationality = mrzLines[1].Substr(15, 18); int lastNameEnd = mrzLines[2].IndexOf("<<"); if (lastNameEnd != -1) { result.LastName = mrzLines[2].Substr(0, lastNameEnd).Replace('<', ' ').Trim(); result.FirstName = mrzLines[2].Substring(lastNameEnd + 2).Replace('<', ' ').Trim(); } } else if (mrzLines.Length == 2 && mrzLines[0].Length == 36) { result.IssuingCountry = mrzLines[0].Substr(2, 5); if ("FRA".Equals(result.IssuingCountry) && type == 'I' && mrzLines[0][1] == 'D') { // French IDs use an entirely different format result.Nationality = "FRA"; result.LastName = mrzLines[0].Substr(5, 30).Replace('<', ' ').Trim(); result.FirstName = mrzLines[1].Substr(13, 27).Replace("<<", ", ").Replace('<', ' ').Trim(); String number = mrzLines[1].Substr(0, 12).Replace('O', '0'); if (checksum(number) == getNumber(mrzLines[1][12])) { result.Number = number; } String birthDate = mrzLines[1].Substr(27, 33).Replace('O', '0').Replace('I', '1'); if (checksum(birthDate) == getNumber(mrzLines[1][33])) { parseBirthDate(birthDate, ref result); } result.Gender = parseGender(mrzLines[1][34]); result.DoesNotExpire = true; } else { int lastNameEnd = mrzLines[0].IndexOf("<<"); if (lastNameEnd != -1) { result.LastName = mrzLines[0].Substr(5, lastNameEnd).Replace('<', ' ').Trim(); result.FirstName = mrzLines[0].Substring(lastNameEnd + 2).Replace('<', ' ').Trim(); } String number = mrzLines[1].Substr(0, 9).Replace('<', ' ').Replace('O', '0').Trim(); int numberChecksum = checksum(number); if (numberChecksum == getNumber(mrzLines[1][9])) { result.Number = number; } result.Nationality = mrzLines[1].Substr(10, 13); String birthDate = mrzLines[1].Substr(13, 19).Replace('O', '0').Replace('I', '1'); if (checksum(birthDate) == getNumber(mrzLines[1][19])) { parseBirthDate(birthDate, ref result); } result.Gender = parseGender(mrzLines[1][20]); String expiryDate = mrzLines[1].Substr(21, 27).Replace('O', '0').Replace('I', '1'); if (checksum(expiryDate) == getNumber(mrzLines[1][27]) || mrzLines[1][27] == '<') { parseExpiryDate(expiryDate, ref result); } } } result.FirstName = capitalize(result.FirstName.Replace('0', 'O').Replace('8', 'B')); result.LastName = capitalize(result.LastName.Replace('0', 'O').Replace('8', 'B')); } else { return null; } if (string.IsNullOrEmpty(result.FirstName) && string.IsNullOrEmpty(result.LastName)) return null; //result.IssuingCountry = countries.get(result.IssuingCountry); //result.Nationality = countries.get(result.Nationality); return result; } return null; }