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;
        }