Extracting Data from pdf417 such as Drivers License

Please see below link and generate the parser to extract the information of driver License.

http://www.dol.wa.gov/external/docs/barcodeCalibration-EDLEID.pdf

I have make this decoder for ios app

here the code :

NSString *message=barcode.barcodeString;

    NSMutableArray *arrFixedData=[[NSMutableArray alloc]initWithObjects:@"DCS",@"DCT",@"DCU",@"DAG",@"DAI",@"DAJ",@"DAK",@"DCG",@"DAQ",@"DCA",@"DCB",@"DCD",@"DCF",@"DCH",@"DBA",@"DBB",@"DBC",@"DBD",@"DAU",@"DCE",@"DAY",@"ZWA",@"ZWB",@"ZWC",@"ZWD",@"ZWE",@"ZWF", nil];
    NSMutableArray *arrDriverData=[[NSMutableArray alloc]initWithObjects:@"Customer Family Name",@"Customer Given Name",@"Name Suffix",@"Street Address 1",@"City",@"Jurisdction Code",@"Postal Code",@"Country Identification",@"Customer Id Number",@"Class",@"Restrictions",@"Endorsements",@"Document Discriminator",@"Vehicle Code",@"Expiration Date",@"Date Of Birth",@"Sex",@"Issue Date",@"Height",@"Weight",@"Eye Color",@"Control Number",@"Endorsements",@"Transaction Types",@"Under 18 Until",@"Under 21 Until",@"Revision Date", nil];


    NSMutableDictionary *dict=[[NSMutableDictionary alloc]init];
    for (int i=0; i<[arrFixedData count]; i++)
    {
        NSRange range = [message  rangeOfString: [arrFixedData objectAtIndex:i] options: NSCaseInsensitiveSearch];
        NSLog(@"found: %@", (range.location != NSNotFound) ? @"Yes" : @"No");
        if (range.location != NSNotFound)
        {
            NSString *temp=[message substringFromIndex:range.location+range.length];

            NSRange end = [temp rangeOfString:@"\n"];
            if (end.location != NSNotFound)
            {
                temp = [temp substringToIndex:end.location];
                temp =[temp stringByReplacingOccurrencesOfString:@"\n" withString:@""];
                temp=[temp stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

            }
            NSLog(@"temp data : %@",temp);
            [dict setObject:temp forKey:[arrDriverData objectAtIndex:i]];
        }
    }

    NSLog(@"Dictionary : %@",dict);

The barcodestring contains the data which are scanned from pdf 417.

Thanks


Here's the Decoder for Android

Here, The Parameter "data" contains the string which you have to scanned pdf417.

==========Properties=============
HashMap<String, String> myData = new HashMap<String, String>();

public final String Customer_Family_Name = "DCS", Customer_Given_Name = "DCT", Name_Suffix = "DCU",
        Street_Address_1 = "DAG", City = "DAI", Jurisdction_Code = "DAJ", Postal_Code = "DAK",
        Country_Identification = "DCG", Customer_Id_Number = "DAQ", Class = "DCA", Restrictions = "DCB",
        Endorsements = "DCD", Document_Discriminator = "DCF", Vehicle_Code = "DCH", Expiration_Date = "DBA",
        Date_Of_Birth = "DBB", Sex = "DBC", Issue_Date = "DBD", Height = "DAU", Weight = "DCE", Eye_Color = "DAY",
        Control_Number = "ZWA", WA_SPECIFIC_ENDORSMENT = "ZWB", Transaction_Types = "ZWC", Under_18_Until = "ZWD",
        Under_21_Until = "ZWE", Revision_Date = "ZWF", Customer_Full_Name = "DAA", Customer_First_Name = "DAC",
        Customer_Middle_Name = "DAD", Street_Address_2 = "DAH", Street_Address_1_optional = "DAL",
        Street_Address_2_optional = "DAM";

ArrayList<String> allKeys = new ArrayList<String>();

============Methods after Scaning================

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
    if (requestCode == SCAN_REQUEST_CODE && resultCode == Activity.RESULT_OK)
    {
        ArrayList<BarcodeResult> barcodes = data.getParcelableArrayListExtra(BarcodeScanActivity.RESULT_EXTRA);
        Log.e("BARCODE RESULT ", "<<<>>" + barcodes.toString());
        String barcodeResult = barcodes.get(0).barcodeString;
        String lines[] = barcodeResult.split("\\r?\\n");
        for (int i = 0; i < lines.length; i++)
        {
            String str = lines[i];
            if (str.contains("ANSI"))
            {
                str = str.substring(str.indexOf("DL"));
                String str1[] = str.split("DL");
                if (str1.length > 1)
                {
                    str = str1[str1.length - 1];
                }
            }
            if (str.length() > 3)
            {
                String key = str.substring(0, 3);
                String value = str.substring(3);
                if (allKeys.contains(key))
                {
                    if (!value.equalsIgnoreCase("None"))
                    {
                        myData.put(allKeys.get(allKeys.indexOf(key)), value);
                    }
                }
            }
            Log.e("RESULT ", "<<>>" + lines[i]);
        }
        Log.e("TAG", "SO MAY BE FINAL RESULT");
        if (myData.containsKey(Customer_Family_Name))
        {
            Log.v("TAG", "users family name:" + myData.get(Customer_Family_Name));
            lname = myData.get(Customer_Family_Name).trim();
        }
        if (myData.containsKey(Customer_Given_Name))
        {
            Log.v("TAG", "users Given name:" + myData.get(Customer_Given_Name));
            try
            {
                String CustomerName[] = myData.get(Customer_Given_Name).split(" ");
                fname = CustomerName[0].trim();
                mname = CustomerName[1].substring(0, 1).trim();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
        if (myData.containsKey(Name_Suffix))
        {
            Log.v("TAG", "Surname name:" + myData.get(Name_Suffix));
        }
        if (myData.containsKey(Street_Address_1))
        {
            Log.v("TAG", "Address line 1 :" + myData.get(Street_Address_1));
            try
            {
                address = myData.get(Street_Address_1).trim();
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
        if (TextUtils.isEmpty(address))
        {
            if (myData.containsKey(Street_Address_2))
            {
                address = myData.get(Street_Address_2).trim();
            }
            if (TextUtils.isEmpty(address))
            {
                if (myData.containsKey(Street_Address_1_optional))
                {
                    address = myData.get(Street_Address_1_optional).trim();
                }
            }
            if (TextUtils.isEmpty(address))
            {
                if (myData.containsKey(Street_Address_2_optional))
                {
                    address = myData.get(Street_Address_2_optional).trim();
                }
            }
        }
        if (myData.containsKey(City))
        {
            Log.v("TAG", "City:" + myData.get(City));
            city = myData.get(City).trim();
        }
        if (myData.containsKey(Jurisdction_Code))
        {
            Log.v("TAG", "State:" + myData.get(Jurisdction_Code));
            State = myData.get(Jurisdction_Code).trim();
        }
        if (myData.containsKey(Postal_Code))
        {
            Log.v("TAG", "Pin Code:" + myData.get(Postal_Code));
            zipcode = myData.get(Postal_Code).substring(0, 5).trim();
        }
        if (myData.containsKey(Date_Of_Birth))
        {
            Log.v("TAG", "Birth Date    :" + myData.get(Date_Of_Birth));
            birthday = myData.get(Date_Of_Birth).substring(0, 2) + "/" + myData.get(Date_Of_Birth).substring(2, 4)
                    + "/" + myData.get(Date_Of_Birth).substring(4);
            if (isThisDateValid(birthday, "MM/dd/yyyy", myData.get(Date_Of_Birth)))
                Log.e("TAG", "IS VALID");
            else
                Log.e("TAG", "IS NOT VALID");
        }
        if (myData.containsKey(Sex))
        {
            Log.v("TAG", "Sex:" + (myData.get(Sex).toString().trim().equals("1") ? "Male" : "Female"));
        }
        if (myData.containsKey(Customer_Full_Name))
        {
            String cName = myData.get(Customer_Full_Name);
            int startIndexOfComma = 0;
            int endIndexOfComma = 0;
            startIndexOfComma = cName.indexOf(",");
            endIndexOfComma = cName.lastIndexOf(",");
            if (startIndexOfComma != endIndexOfComma)
            {
                String CustomerName[] = myData.get(Customer_Full_Name).split(",");
                lname = CustomerName[0].replace(",", "").trim();
                fname = CustomerName[1].trim();
                mname = CustomerName[2].substring(0, 1).trim();
            }
            else
            {
                String CustomerName[] = myData.get(Customer_Full_Name).split(" ");
                lname = CustomerName[0].replace(",", "").trim();
                fname = CustomerName[1].trim();
                mname = CustomerName[2].substring(0, 1).trim();
            }
        }
        if (myData.containsKey(Customer_First_Name))
        {
            fname = myData.get(Customer_First_Name).trim();
        }
        if (myData.containsKey(Customer_Middle_Name))
        {
            mname = myData.get(Customer_Middle_Name).substring(0, 1).trim();
        }
        // TODO edit here at 7/3/2014
        if (myData.containsKey(Customer_Id_Number))
        {
            licence_number = myData.get(Customer_Id_Number).trim();
            Log.e("TAG", "Licence Number is :" + licence_number);
        }
        if (myData.containsKey(Expiration_Date))
        {
            licence_expire_date = myData.get(Expiration_Date).trim();
            licence_expire_date = myData.get(Expiration_Date).substring(0, 2) + "/"
                    + myData.get(Expiration_Date).substring(2, 4) + "/" + myData.get(Expiration_Date).substring(4);
            licence_expire_date = makeDateValid(licence_expire_date, "MM/dd/yyyy", myData.get(Expiration_Date));
            Log.e("TAG", "expire date is :" + licence_expire_date);
        }
        etFirstName.setText(fname.trim());
        etMiddleName.setText(mname.trim());
        etLastName.setText(lname.trim());
        etAddress.setText(address.trim());
        etZipCode.setText(zipcode.trim());
        etCity.setText(city.trim());
        etState.setText(State.trim());
        etDLNumber.setText(licence_number);
        etDLExpirationDate.setText(licence_expire_date);
        etBirthDay.setText(birthday.trim());
    }
}

Here's the code I use to decode the PDF417 data in Swift.

private let pdf417Map: [String: String] = [
    "DAA":"Full Name",
    "DAB":"Family Name",
    "DAC":"Given Name",
    "DAD":"Middle Name",
    "DAE":"Name Suffix",
    "DAF":"Name Prefix",
    "DAG":"Mailing Street Address1",
    "DAH":"Mailing Street Address2",
    "DAI":"Mailing City",
    "DAJ":"Mailing Jurisdiction Code",
    "DAK":"Mailing Postal Code",
    "DAL":"Residence Street Address1",
    "DAM":"Residence Street Address2",
    "DAN":"Residence City",
    "DAO":"Residence Jurisdiction Code",
    "DAP":"Residence Postal Code",
    "DAQ":"License or ID Number",
    "DAR":"License Classification Code",
    "DAS":"License Restriction Code",
    "DAT":"License Endorsements Code",
    "DAU":"Height in FT_IN",
    "DAV":"Height in CM",
    "DAW":"Weight in LBS",
    "DAX":"Weight in KG",
    "DAY":"Eye Color",
    "DAZ":"Hair Color",
    "DBA":"License Expiration Date",
    "DBB":"Date of Birth",
    "DBC":"Sex",
    "DBD":"License or ID Document Issue Date",
    "DBE":"Issue Timestamp",
    "DBF":"Number of Duplicates",
    "DBG":"Medical Indicator Codes",
    "DBH":"Organ Donor",
    "DBI":"Non-Resident Indicator",
    "DBJ":"Unique Customer Identifier",
    "DBK":"Social Security Number",
    "DBL":"Date Of Birth",
    "DBM":"Social Security Number",
    "DBN":"Full Name",
    "DBO":"Family Name",
    "DBP":"Given Name",
    "DBQ":"Middle Name or Initial",
    "DBR":"Suffix",
    "DBS":"Prefix",
    "DCA":"Virginia Specific Class",
    "DCB":"Virginia Specific Restrictions",
    "DCD":"Virginia Specific Endorsements",
    "DCE":"Physical Description Weight Range",
    "DCF":"Document Discriminator",
    "DCG":"Country territory of issuance",
    "DCH":"Federal Commercial Vehicle Codes",
    "DCI":"Place of birth",
    "DCJ":"Audit information",
    "DCK":"Inventory Control Number",
    "DCL":"Race Ethnicity",
    "DCM":"Standard vehicle classification",
    "DCN":"Standard endorsement code",
    "DCO":"Standard restriction code",
    "DCP":"Jurisdiction specific vehicle classification description",
    "DCQ":"Jurisdiction-specific",
    "DCR":"Jurisdiction specific restriction code description",
    "DCS":"Last Name",
    "DCT":"First Name",
    "DCU":"Suffix",
    "DDA":"Compliance Type",
    "DDB":"Card Revision Date",
    "DDC":"HazMat Endorsement Expiry Date",
    "DDD":"Limited Duration Document Indicator",
    "DDE":"Family Name Truncation",
    "DDF":"First Names Truncation",
    "DDG":"Middle Names Truncation",
    "DDH":"Under 18 Until",
    "DDI":"Under 19 Until",
    "DDJ":"Under 21 Until",
    "DDK":"Organ Donor Indicator",
    "DDL":"Veteran Indicator",
    "PAA":"Permit Classification Code",
    "PAB":"Permit Expiration Date",
    "PAC":"Permit Identifier",
    "PAD":"Permit IssueDate",
    "PAE":"Permit Restriction Code",
    "PAF":"Permit Endorsement Code",
    "ZVA":"Court Restriction Code"
]
// metadataObj = @ ANSI 63601404....

if metadataObj.stringValue != nil {
    let licenseData = metadataObj.stringValue!.components(separatedBy: "\n")

    var customerProfile: [[String: String]] = []
    for item in licenseData {
        var metaDataItem = item
        if metaDataItem.count > 3 {
            if let dlCodeRange = metaDataItem.range(of: "DAQ") {
                let dlStart = dlCodeRange.lowerBound
                let dlEnd = metaDataItem.index(metaDataItem.endIndex, offsetBy: 0)
                let dlNoRange = dlStart..<dlEnd
                metaDataItem = String(metaDataItem[dlNoRange])
            }
            // Get the 3 letter code
            let pdf417Code = String(metaDataItem.prefix(3))
            // See if the code exists in the map
            if pdf417Map[pdf417Code] != nil {
                // Code exists in map, save to profile
                let start = metaDataItem.index(metaDataItem.startIndex, offsetBy: 3)
                let end = metaDataItem.index(metaDataItem.endIndex, offsetBy: 0)
                let range = start..<end

                let extractedData = metaDataItem[range]
                customerProfile.append([pdf417Map[pdf417Code]!: String(extractedData)])
            }
        }
    }
    print("customerProfile: \(customerProfile)")
}