Extract Driver's License AAMVA Barcode - Windows C DLL

This tutorial shows how to extract information from a PDF417 barcode that follows the AAMVA specification using the LEADTOOLS SDK in a Windows C/C++ API Application.

Overview  
Summary This tutorial covers how to perform data extraction from a PDF417 that follows the AAMVA specification in a Windows C DLL Application.
Completion Time 30 minutes
Visual Studio Project Download tutorial project (19 KB)
Platform Windows C DLL Application
IDE Visual Studio 2017, 2019, 2022
Development License Download LEADTOOLS
Try it in another language

Required Knowledge

Before working on the Extract Driver's License AAMVA Barcode - Windows C DLL tutorial, get familiar with the basic steps of creating a project and loading/displaying an image by reviewing the Add References and Set a License and Load, Display and Save Images tutorials.

Create the Project and Add LEADTOOLS References

Start with a copy of the 64-bit Windows API project created in the Load, Display and Save Images tutorial. If the project is not available, create it by following the steps in that tutorial.

To read barcodes and extract AAMVA data using LEADTOOLS, add the required header and DLL files. Open the pre-compiled header file (either pch.h or stdafx.h, depending on the version of Visual Studio used) and add the following lines:

#include "C:\LEADTOOLS23\Include\Ltbar.h" 
#pragma comment (lib, "C:\\LEADTOOLS23\\Lib\\CDLL\\x64\\Ltbar_x.lib") // barcode and AAMVA support 

Note: For a full list of which DLLs are required for specific toolkit features or file formats, refer to Files to be Included With Your Application.

For details on needed Barcode DLLs, see the help topic Barcode Files to be Included With Your Application.

Set the License File

The License unlocks the features needed for the project. It must be set before any toolkit functionality is called. For details, including tutorials for different platforms, refer to Setting a Runtime License.

There are two types of runtime licenses:

Note: Adding LEADTOOLS references and setting a license are covered in more detail in the Add References and Set a License tutorial.

Add the AAMVA PDF417 Extraction Code

With the project created, the references added, the license set, and the load and display image code added, coding can begin.

The steps below are for Visual Studio 2019; they could be different for other versions of Visual Studio.

Go to the Solution Explorer and double-click the resources file (.rc).

Add a new &Barcode drop down menu next to the File menu. In the newly added &Barcode menu, add a &Extract PDF417 Data menu item. The new item's ID should be ID_BARCODE_EXTRACTPDF417DATA.

Go to the WndProc function and under the switch (wmId) statement that is below the WM_COMMAND case, add a new case:

switch (wmId) 
{ 
case ID_BARCODE_EXTRACTPDF417DATA: 
   if (LEADBmp.Flags.Allocated) 
      ExtractPDF417Data(hWnd); 
   else 
      MessageBox(hWnd, TEXT("Cannot search for AAMVA data. No image loaded"), TEXT("Barcode Demo"), MB_ICONERROR); 
   break; 
// keep rest of the code as is 

Add a new ExtractPDF417Data function. You can place this function above the WndProc function, and add the following code:

void ExtractPDF417Data(HWND hwnd) 
{ 
   if (L_BarCodeInit(BARCODES_PDF_READ) != SUCCESS) 
      return; 
   pBARCODEDATA pBarCodes = NULL; 
   BARCODEREADPDF BarPdf = { 0 }; 
   BarPdf.uStructSize = sizeof BARCODEREADPDF; 
   BarPdf.nDirection = BARCODE_DIR_HORIZONTAL; 
   BARCODECOLOR BarColor = { 0 }; 
   BarColor.uStructSize = sizeof BARCODECOLOR; 
   BarColor.dwColorBar = RGB(0, 0, 0); 
   BarColor.dwColorSpace = RGB(255, 255, 255); 
   // Search for PDF417 barcodes in the entire bitmap 
   L_INT nRet = L_BarCodeRead(&LEADBmp, NULL, BARCODE_PDF417, BARCODE_SCANLINES_PER_PIXELS, BARCODE_BLOCK_SEARCH, 0, NULL, &BarPdf, &BarColor, &pBarCodes, sizeof BARCODEDATA); 
   if (SUCCESS == nRet) 
   { 
      if(ParseAAMVAData(hwnd, pBarCodes) != SUCCESS) 
         MessageBox(hwnd, TEXT("ParseAAMVAData returned an error"), TEXT("Barcode Demo"), MB_ICONERROR); 
   } 
   else 
      MessageBox(hwnd, TEXT("Could not read PDF 417 Barcodes"), TEXT("Barcode Demo"), MB_ICONERROR); 
 
   if (pBarCodes) 
      L_BarCodeFree(&pBarCodes); 
   L_BarCodeExit(); 
} 

Add a new ParseAAMVAData function that is called from within ExtractPDF417Data(). Add the below code to parse the AAMVA data from the PDF417 barcode:

L_INT ParseAAMVAData(HWND hwnd, pBARCODEDATA pBarCodeData) 
{ 
   if (!pBarCodeData) 
      return FAILURE; 
 
   AAMVAID id = { 0 }; 
 
   // Parse Barcode AAMVA data 
   L_INT nRet = L_BarCodeParseAAMVAData(pBarCodeData->pszBarCodeData, pBarCodeData->nSizeofBarCodeData, &id, L_FALSE); 
   if (nRet != SUCCESS) 
      return nRet; 
 
   L_CHAR szResultString[1024] = "Issuer Identification Number: "; 
   strcat_s(szResultString, id.IssuerIdentificationNumber); 
 
   //First Name 
   L_BOOL bInferredFromFullName; 
   L_CHAR* pszFirstName = NULL; 
   nRet = L_BarCodeAAMVAIDFirstName(&id, &pszFirstName, &bInferredFromFullName); 
   if (nRet != SUCCESS) 
      return nRet; 
   strcat_s(szResultString, "\nFirst Name: "); 
   strcat_s(szResultString, pszFirstName); 
   //Must free result 
   L_BarCodeAAMVAMemoryFree(pszFirstName); 
 
   //Last Name 
   L_CHAR* pszLastName = NULL; 
   nRet = L_BarCodeAAMVAIDLastName(&id, &pszLastName, &bInferredFromFullName); 
   if (nRet != SUCCESS) 
      return nRet; 
   strcat_s(szResultString, "\nLast Name: "); 
   strcat_s(szResultString, pszLastName); 
   //Must free result 
   L_BarCodeAAMVAMemoryFree(pszLastName); 
 
   L_BOOL bRes; 
   //Check if we can determine if ID holder is Over 21 
   nRet = L_BarCodeAAMVAIDOver21Available(&id, &bRes); 
   if (nRet != SUCCESS) 
      return nRet; 
   strcat_s(szResultString, "\nOver 21?: "); 
   if (bRes) 
   { 
      //Over21 is available. Let's check if ID hold is 21+ 
      L_CHAR* pszCurrentDate = GetCurrentDate(); 
      nRet = L_BarCodeAAMVAIDOver21(&id, pszCurrentDate, &bRes); 
      if (nRet != SUCCESS) 
         return nRet; 
      if (bRes) 
         strcat_s(szResultString, "True"); 
      else 
         strcat_s(szResultString, "False"); 
   } 
   else //Over21 is NOT available. 
      strcat_s(szResultString, "Not Available"); 
 
   MessageBoxA(hwnd, szResultString, "AAMVA data", MB_OK); 
 
   //Free the AAMVAID structure 
   nRet = L_BarCodeFreeAAMVAID(&id); 
   return nRet; 
} 

Add a new helper function namedGetCurrentDate. Any function that returns the date in yyyymmdd format can be used instead of it.

#include <time.h> 
L_CHAR* GetCurrentDate() 
{ 
   static char currentDate[9]; 
   time_t t = time(NULL); 
   struct tm local_t = { 0 }; 
   localtime_s(&local_t, &t); 
   wsprintfA(currentDate, "%4.4d%2.2d%2.2d", local_t.tm_year + 1900, local_t.tm_mon + 1, local_t.tm_mday); 
   return currentDate; 
} 

Note: There are more AAMVAID functions in the toolkit; the snippet above showcases a few commonly used values.

Run the Project

Run the project by pressing F5, or by selecting Debug -> Start Debugging.

If the steps were followed correctly, the application should run and enable the user to select File -> Open to load the image containing the barcode data. Select Barcode -> Extract PDF417 Data, to have the application run barcode recognition and parse the AAMVA data and display it in a message box.

Extracted PDF417 barcode data displayed to user.

Note: If there's no image with driver license barcode available for testing, it is possible to use the image at this file path: C:\LEADTOOLS23\Resources\Images\license_sample_rear_aamva.png

Wrap-Up

This tutorial showed how to use the AAMVAID function.

See Also

Help Version 23.0.2024.5.22
Products | Support | Contact Us | Intellectual Property Notices
© 1991-2024 LEAD Technologies, Inc. All Rights Reserved.

Products | Support | Contact Us | Intellectual Property Notices
© 1991-2023 LEAD Technologies, Inc. All Rights Reserved.