Provides information about the cardholder's name and how it was determined.
public class AAMVANameResult
Card issuing authorities are using older AAMVA CDS versions that is using the DAA data element to encode full names.
The CDS, at the time, did not clearly define a formatting standard for this data element. Therefore, state DMVs improvised and ended up using varying formatting. Examples:
AAMVAID.FirstName and AAMVAID.LastName will retrieve the cardholder's name from the DAA data element's value, only if a DAA data element is available in all of the AAMVAID's subfiles. The value of AAMVANameResult.InferredFromFullName property will be true in these cases.
Due to uncertainty in DMV formatting along with individuals with mononyms, multiple surnames (Spanish naming customs), and multiple given names, the resulting name is not guaranteed to be accurate in all cases, but only when inferring from the full name, the resulting name is only a best guess.
For IDs conforming to newer versions of the AAMVA CDS, this class will provide preference to the newer and more reliable first or last name data elements, and AAMVANameResult.InferredFromFullName will be set to false. In these cases, the resulting name is guaranteed to be accurate.
using Leadtools;
using Leadtools.Barcode;
using Leadtools.Codecs;
/* This example defines an instance of AAMVAID, sets and reads the data, and finally saves a PDF17 barcode.
* The code is outlined in sections as follows:
*
* 1. Set the members to simulate reading AAMVAID and extract it at a later point
* 2. Build the AAMVAID instance
* 3. Define a hash set and parse to a specific element
* 4. Process AAMAValidCharacters
* 5. Extract AAMVAID properties
* 6. Extract data and write as PDF417 barcode
*/
public void AAMVA_Example()
{
//1. Set the members to simulate reading AAMVAID and extract it at a later point
const string JURISDICTION_VERSION = "00";
const string SUBFILE_TYPE_CODE = "DL";
const int SUBFILES_COUNT = 1;
const int BITS_PER_PIXEL = 24;
const int IMAGE_DPI = 300;
AAMVAID driversLicenseID = null;
AAMVANameResult nameResult = null;
DateTime birthday = new DateTime(DateTime.Now.Year - 16, DateTime.Now.Month, DateTime.Now.Day);
string[,] driversLicenseData = new string[,] {{"DDF", "N"}, // First name truction (N = not truncated)
{"DDE", "N"}, // Last name truction (N = not truncated)
{"DCG", "USA"}, // Country identification
{"DCF", "NONE"}, // Document discriminator
{"DAQ", "1234567890"}, // ID Number
{"DAK", "123456 "}, // Postal code
{"DAJ", "PA"}, // Address Jurisdiction Code
{"DAI", "Any Town"}, // Address City
{"DAG", "123 Main Street"}, // Address Street 1
{"DAU", "072 in"}, // Height (inches or centimeters)
{"DAY", "BRO"}, // Eye color
{"DBC", "1"}, // Sex (Male = 1, Female = 2, 9 = Not specified)
{"DBB", birthday.ToString("MMddyyyy")}, // Date of Birth
{"DBD", DateTime.Now.ToString("MMddyyyy")}, // Document Issue Date
{"DAD", "NONE"}, // Middle Name
{"DAC", "John"}, // First name
{"DCS", "Doe"}, // Last name
{"DBA", DateTime.Now.AddYears(6).ToString("MMddyyyy")},// Expiration date
{"DCD", "M"}, // Jurisdiction-specific endorsement codes
{"DCB", "NONE"}, // Jurisdiction-specific restriction codes
{"DCA", "C"}, // Jurisdiction-specific vehicle class
{"DDJ", birthday.AddYears(21).ToString("MMddyyyy")}, // Under 21 until
{"DDI", birthday.AddYears(19).ToString("MMddyyyy")}, // Under 19 until
{"DDH", birthday.AddYears(18).ToString("MMddyyyy")}, // Under 18 until
{"DAZ", "BRO"}}; // Hair color
// 2. Build the AAMVAID instance
using (AAMVAIDBuilder builder = new AAMVAIDBuilder())
{
builder.SetJurisdiction(AAMVAJurisdiction.Pennsylvania, AAMVAID.LookupIssuerIdentificationNumber(AAMVAJurisdiction.Pennsylvania))
.SetVersion(AAMVAVersion.Version2016)
.SetJurisdictionVersion(JURISDICTION_VERSION)
.SetNumberOfEntries(SUBFILES_COUNT);
builder.SetSubfileType(SUBFILES_COUNT - 1, AAMVASubfileType.DL, SUBFILE_TYPE_CODE);
for (int i = 0; i < driversLicenseData.GetLength(0); i++)
builder.AddDataElementToSubfile(0, driversLicenseData[i, 0], driversLicenseData[i, 1]);
Console.WriteLine($"Is AAMVAIDBuilder disposed: {builder.IsDisposed} \n");
Console.WriteLine("===================================================================");
Console.WriteLine("\n");
driversLicenseID = builder.Build();
builder.Reset();
}
foreach (KeyValuePair<string, AAMVADataElement> element in driversLicenseID.Subfiles[0].DataElements)
{
Console.WriteLine($"ElementID: {element.Value.ElementID} Element value:{element.Value.Value}");
}
// 3. Define a hash set and parse to a specific element
IDictionary<string, AAMVADataElementInfo> _dataElementInfo;
_dataElementInfo = AAMVADataElementInfo.RetrieveAll(AAMVAVersion.Version2016);
HashSet<string> DataElements = new HashSet<string>()
{
"DCA", "DCB", "DCD", "DBA", "DCS", "DAC", "DAD", "DBD", "DBB", "DBC", "DAY", "DAZ", "DCL",
"DAU", "DAG", "DAI", "DAJ", "DAH", "DAK", "DAQ", "DCF", "DCG", "DDE", "DDF", "DDG", "DCU"
};
foreach (string elementID in DataElements)
{
AAMVADataElementInfo info = _dataElementInfo[elementID];
info.LengthType = AAMVALengthType.Fixed;
Console.WriteLine($"ElementID: {info.ElementID}");
switch (elementID)
{
case "DAY": // Eye color
AAMVAEyeColor eyeColor = driversLicenseID.EyeColor;
Console.WriteLine($"Eye Color: {eyeColor}");
break;
case "DAZ": // Hair color
AAMVAHairColor hairColor = driversLicenseID.HairColor;
Console.WriteLine($"Eye Color: {hairColor}");
break;
case "DAI": // City
Console.WriteLine($"City Name: {driversLicenseID.AddressCity}");
break;
case "DAK": // Jurisdiction
AAMVARegion rgn = AAMVAID.LookupRegion(driversLicenseID.Jurisdiction);
Console.WriteLine($"Postal Code: {driversLicenseID.AddressPostalCode} {rgn}");
break;
case "DCG": // Address region (country)
Console.WriteLine($"Address Region: {driversLicenseID.AddressRegion}");
break;
case "DAJ": // State abbreviation
AAMVAJurisdiction[] jurisdictions = (AAMVAJurisdiction[])Enum.GetValues(typeof(AAMVAJurisdiction));
for (int i = 0; i < jurisdictions.Length; i++)
{
string abbr = AAMVAID.LookupStateAbbreviation(jurisdictions[i]);
Console.WriteLine($"State abbreviations: {abbr}");
}
Console.WriteLine($"Address State Abbreviation: {driversLicenseID.AddressStateAbbreviation}");
break;
case "DBC": // Sex
AAMVASex[] sex = (AAMVASex[])Enum.GetValues(typeof(AAMVASex));
for (int i = 0; i < sex.Length; i++)
{
Console.WriteLine($"Sex codes: {sex[i]}");
}
break;
case "DAG": // Street address 1
Console.WriteLine($"Street Address1: {driversLicenseID.AddressStreet1}");
break;
case "DAH": // Street address 2
Console.WriteLine($"Street Address2: {driversLicenseID.AddressStreet2}" +
$"- Can be null if address street line 2 is not encoded in the barcode data");
break;
case "DBB": // Date of Birth
Console.WriteLine($"Date of Birth: {driversLicenseID.DateOfBirth}");
break;
case "DBA": // Expiration date
Console.WriteLine($"Expiration Available: {driversLicenseID.ExpirationAvailable} | Is Expired: {driversLicenseID.Expired} | Expiration Date: {driversLicenseID.ExpirationDate}");
break;
case "DBD": // Issue date
Console.WriteLine($"Issue Date: {driversLicenseID.IssueDate}");
break;
case "DCS": // Last name
Console.WriteLine($"Last Name: {driversLicenseID.LastName.Value}");
break;
case "DAD": // Middle name
Console.WriteLine($"Middle Name: {driversLicenseID.MiddleName.Value}");
break;
case "DAC": // First name
Console.WriteLine($"Middle Name: {driversLicenseID.FirstName.Value}");
break;
case "DCU": // Suffix
AAMVANameSuffix[] enums = (AAMVANameSuffix[])Enum.GetValues(typeof(AAMVANameSuffix));
for (int i = 2; i < enums.Length; i++)
{
AAMVANameSuffix enumValue = enums[i];
string codeArabic = AAMVAID.LookupNameSuffixCodeArabic(enumValue);
Console.WriteLine("Arabic suffix: " + enumValue.ToString() + " - \"" + codeArabic + "\"");
string codeRoman = AAMVAID.LookupNameSuffixCodeRoman(enumValue);
Console.WriteLine("Roman suffix: " + enumValue.ToString() + " - \"" + codeRoman + "\"");
}
break;
case "DCL": // Suffix
AAMVARaceEthnicity[] races = (AAMVARaceEthnicity[])Enum.GetValues(typeof(AAMVARaceEthnicity));
for (int i = 0; i < races.Length; i++)
{
AAMVARaceEthnicity race = races[i];
string code = AAMVAID.LookupRaceEthnicityCode(race);
Console.WriteLine("Race: " + race + " - \"" + code + "\"");
}
break;
}
Console.WriteLine($"Definition: {info.Definition}");
Console.WriteLine($"Friendly Name: {info.FriendlyName}");
Console.WriteLine($"Length Type: {info.LengthType}");
Console.WriteLine($"Valid Characters: {info.ValidCharacters}");
Console.WriteLine($"Valid Subfile Types: {info.ValidSubfileTypes}");
Console.WriteLine($"Value Max Length: {info.ValueMaxLength}");
Console.WriteLine("\n");
Console.WriteLine("===================================================================");
Console.WriteLine("\n");
}
// 4. Process AAMAValidCharacters
AAMVAValidCharacters[] characters = (AAMVAValidCharacters[])Enum.GetValues(typeof(AAMVAValidCharacters));
for (int i = 0; i < characters.Length; i++)
{
Console.WriteLine($"Valid characters: {characters[i]}");
}
// 5. Extract AAMVAID properties
Console.WriteLine($"Is over 18: {driversLicenseID.Over18}"); //Is over 18
Console.WriteLine($"Is over 18: {driversLicenseID.Over18Available}"); //Over 18 available
Console.WriteLine($"Is over 19: {driversLicenseID.Over19}"); //Is over 19
Console.WriteLine($"Is over 19: {driversLicenseID.Over19Available}"); //Over 19 available
Console.WriteLine($"Is over 21: {driversLicenseID.Over21}"); //Is over 21
Console.WriteLine($"Is over 21: {driversLicenseID.Over21Available}"); //Over 21 available
Console.WriteLine($"Version: {driversLicenseID.Version}"); //Version
Console.WriteLine($"Number of entries: {driversLicenseID.NumberOfEntries}"); //Number of entries
Console.WriteLine($"Is AMMVAID Disposed: {driversLicenseID.IsDisposed}"); //Is Disposed
Console.WriteLine($"Issuer Identification Number: {driversLicenseID.IssuerIdentificationNumber}"); //Issuer Identification Number
Console.WriteLine($"Jurisdiction Version Number: {driversLicenseID.JurisdictionVersion}"); // Jurisdiction Version Number
var jurisdiction = AAMVAID.LookupJurisdiction(driversLicenseID.IssuerIdentificationNumber); // Returns state
var suffix = AAMVAID.LookupNameSuffix("JR"); // Returns name suffix
var raceEthnicity = AAMVAID.LookupRaceEthnicity("BK"); // Returns race/ethnicity
Console.WriteLine($"{jurisdiction} \n {suffix} \n {raceEthnicity}");
nameResult = driversLicenseID.FirstName;
nameResult.InferredFromFullName = true;
Console.WriteLine($"Name result: {nameResult.Value}");
var subfilesList = driversLicenseID.Subfiles;
foreach (AAMVASubfile subfile in subfilesList)
{
Console.WriteLine($"{subfile.Offset} \n {subfile.SubfileType} \n {subfile.SubfileTypeCode}");
}
// 6. Extract data and write as PDF417 barcode
PDF417BarcodeData data = new PDF417BarcodeData();
data.Symbology = BarcodeSymbology.PDF417;
data.SetData(driversLicenseID.GetBytes());
Console.WriteLine($"=======================================");
AAMVAID parsedAAMVAData = BarcodeData.ParseAAMVAData(driversLicenseID.GetBytes(), true);
Console.WriteLine($"Parsed AAMVAData First Name: {parsedAAMVAData.FirstName.Value}");
Console.WriteLine($"Parsed AAMVAData Last Name: {parsedAAMVAData.LastName.Value}");
Console.WriteLine($"Parsed AAMVAData Issue Date: {parsedAAMVAData.IssueDate}");
BarcodeEngine barcodeEngine = new BarcodeEngine();
PDF417BarcodeWriteOptions pdf417WriteOptions = (PDF417BarcodeWriteOptions)barcodeEngine.Writer.GetDefaultOptions(BarcodeSymbology.PDF417);
//Refer to AAMVA CDS 2016 Section D.3 thru D.11.2
//Must range from 0.0066 to 0.015 inches
pdf417WriteOptions.XModule = 15; //0.015
//Must >= 3
pdf417WriteOptions.XModuleAspectRatio = 3;
//Error level must be at least 3, 5 is recommended
pdf417WriteOptions.ECCLevel = PDF417BarcodeECCLevel.Level5;
//Default WidthAspectRatio is 2:1. 4:1 looks similar to ID barcodes in the wild
pdf417WriteOptions.SymbolWidthAspectRatio = 4;
//Default quiet zone for PDF417 is 2 * XModule
RasterCodecs codecs = new RasterCodecs();
barcodeEngine.Writer.CalculateBarcodeDataBounds(LeadRect.Empty, IMAGE_DPI, IMAGE_DPI, data, pdf417WriteOptions);
using (RasterImage image = RasterImage.Create(data.Bounds.Width, data.Bounds.Height, BITS_PER_PIXEL, IMAGE_DPI, new RasterColor(255, 255, 255)))
{
barcodeEngine.Writer.WriteBarcode(image, data, pdf417WriteOptions); // Write the barcode
codecs.Save(image, Path.Combine(LEAD_VARS.ImagesDir, "MyDriversLicense.png"), RasterImageFormat.Png, 1); // write the output to file
}
codecs.Dispose();
}
static class LEAD_VARS
{
public const string ImagesDir = @"C:\LEADTOOLS23\Resources\Images";
}