Read Driver License barcode and decode data
Reading the Driver License barcode data provides properly spelled driver identification data in a reliable and consistent manner. The success rate approaches 100%. Barcode reading is faster and more accurate than trying to read the text on the front of the license
C#
1234567891011121314151617181920212223242526272829303132333435363738394041424344
using Inlite.ClearImageNet;// . . .void DecodeDrvLic(string text) { Inlite.Data.DLDecoder decoder = new Inlite.Data.DLDecoder(); if (decoder.Decode(text) != "") { Console.WriteLine("last: " + decoder.last); Console.WriteLine("first: " + decoder.first); Console.WriteLine("middle: " + decoder.middle); Console.WriteLine("dob: " + decoder.dob); Console.WriteLine("eyes: " + decoder.eyes); Console.WriteLine("hair: " + decoder.hair); Console.WriteLine("sex: " + decoder.sex); Console.WriteLine("height: " + decoder.height); Console.WriteLine("street: " + decoder.street); Console.WriteLine("city: " + decoder.city); Console.WriteLine("state: " + decoder.state); Console.WriteLine("postal: " + decoder.postal); Console.WriteLine("country: " + decoder.country); Console.WriteLine("id: " + decoder.id); Console.WriteLine("issued: " + decoder.issued); Console.WriteLine("expires: " + decoder.expires); } else { Console.WriteLine("Unknown Format"); } } void ReadDrvLic(string fileName, int page){ try { BarcodeReader reader = new BarcodeReader(); // Select barcode type(s) to read reader.DrvLicID = true; Barcode[] barcodes = reader.Read(fileName, page); // Process results if (barcodes.Length > 0) DecodeDrvLic(barcodes[0].Text); } catch (Exception ex) { ProcessException(ex); }}
VB
123456789101112131415161718192021222324252627282930313233343536373839404142
Imports Inlite.ClearImageNet' . . .Private Sub DecodeDrvLic(text As String) Dim decoder As New Inlite.Data.DLDecoder() If decoder.Decode(text) <> "" Then Console.WriteLine("last: " + decoder.last) Console.WriteLine("first: " + decoder.first) Console.WriteLine("middle: " + decoder.middle) Console.WriteLine("dob: " + decoder.dob) Console.WriteLine("eyes: " + decoder.eyes) Console.WriteLine("hair: " + decoder.hair) Console.WriteLine("sex: " + decoder.sex) Console.WriteLine("height: " + decoder.height) Console.WriteLine("street: " + decoder.street) Console.WriteLine("city: " + decoder.city) Console.WriteLine("state: " + decoder.state) Console.WriteLine("postal: " + decoder.postal) Console.WriteLine("country: " + decoder.country) Console.WriteLine("id: " + decoder.id) Console.WriteLine("issued: " + decoder.issued) Console.WriteLine("expires: " + decoder.expires) Else Console.WriteLine("Unknown Format") End IfEnd Sub Private Sub ReadDrvLic(fileName As String, page As Integer) Try Dim reader As New BarcodeReader() ' Select barcode type(s) to read reader.DrvLicID = True Dim barcodes As Barcode() = reader.Read(fileName, page) ' Process results If barcodes.Length > 0 Then DecodeDrvLic(barcodes(0).Text) End If Catch ex As Exception ProcessException(ex) End TryEnd Sub
C++
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
#import "progid:ClearImage.ClearImage" no_namespace named_guids#import "progid:ClearImageDLID.DLDecoder" no_namespace named_guids #include <iostream>using namespace std; void decodeDrvLicFields (_bstr_t txt) { // Create Decoder IDLDecoderPtr decoder; HRESULT hr = decoder.CreateInstance(__uuidof(DLDecoder)); // Decode decoder->Decode(txt); // Process results if (decoder->last.length() > 0) { cout << "last: " << decoder->last << endl; cout << "first: " << decoder->first << endl; cout << "middle: " << decoder->middle << endl; cout << "suffix: " << decoder->suffix << endl; cout << "dob: " << decoder->dob << endl; cout << "eyes: " << decoder->eyes << endl; cout << "hair: " << decoder->hair << endl; cout << "sex: " << decoder->sex << endl; cout << "height: " << decoder->height << endl; cout << "weight: " << decoder->weight << endl; cout << "street: " << decoder->street << endl; cout << "city: " << decoder->city << endl; cout << "state: " << decoder->state << endl; cout << "postal: " << decoder->postal << endl; cout << "country: " << decoder->country << endl; cout << "id: " << decoder->id << endl; cout << "issued: " << decoder->issued << endl; cout << "expires: " << decoder->expires << endl; } // cout << endl << "XML Data:" << endl << decoder->xml << endl; } void ReadDrvLic (const char *fileName, const long page) { try { // Create reader ICiServerPtr Ci; HRESULT hr = Ci.CreateInstance(__uuidof(CiServer)); ICiPdf417Ptr reader = Ci->CreatePdf417(); reader->Encodings = (EBarcodeEncoding)102; // Activate DLID reading mode reader->Image->Open(_bstr_t(fileName), page); // Read barcode ICiBarcodePtr bc = reader->FirstBarcode(); // Process results if (bc != 0) decodeDrvLicFields (bc->Text); else cout << "PDF417 barcode not found" << endl; } catch (_com_error &ex) {ProcessException(ex);} }
PHP
123456789101112131415161718192021222324252627282930313233343536373839404142434445
function DecodeDrvLic($text) { // Create decoder $decoder = new COM("ClearImageDLID.DLDecoder"); // Decode text $decoder->Decode($text); if ($decoder->last != "") { print "last: $decoder->last \n"; print "first: $decoder->first \n"; print "middle: $decoder->middle \n"; print "suffix: $decoder->suffix \n"; print "dob: $decoder->dob \n"; print "eyes: $decoder->eyes \n"; print "hair: $decoder->hair \n"; print "sex: $decoder->sex \n"; print "height: $decoder->height \n"; print "weight: $decoder->weight \n"; print "street: $decoder->street \n"; print "city: $decoder->city \n"; print "state: $decoder->state \n"; print "postal: $decoder->postal \n"; print "country: $decoder->country \n"; print "id: $decoder->id \n"; print "issued: $decoder->issued \n"; print "expires: $decoder->expires \n"; } print "XML Data: \n $decoder->xml \n";} function ReadDrvLic($fileName, $page) { // Create ClearImage Reader $ciServer = new COM("ClearImage.ClearImage"); $reader = $ciServer->CreatePdf417(); // Open image $reader->Image->Open($fileName, $page); // Read Barcode $bc = $reader->FirstBarcode(); // Process results if ($bc != NULL) {DecodeDrvLic ($bc->Text);} else {print "Driver License barcode not found \n";} }
Delphi
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
// Import Type Library for:// ClearImage DLID Reader// ClearImage Driver License Decoderuses ...,ClearImage_TLB, DriverLicenseDecoder_TLB; procedure DecodeDrvLic(const text: string); var decoder: IDLDecoder; s: string; CR, LF, CRLF: string; begin try try begin //Create decoder decoder:=CoDLDecoder.Create; // Decode decoder.Decode(text); // Process results if (decoder.last <> '') then begin CR := #13; LF := #10; CRLF := CR + LF; s := s + 'last: ' + decoder.last + CRLF; s := s + 'first: ' + decoder.first + CRLF; s := s + 'middle: ' + decoder.middle + CRLF; s := s + 'suffix: ' + decoder.suffix + CRLF; s := s + 'dob: ' + decoder.dob + CRLF; s := s + 'eyes: ' + decoder.eyes + CRLF; s := s + 'hair: ' + decoder.hair + CRLF; s := s + 'sex: ' + decoder.sex + CRLF; s := s + 'height: ' + decoder.height + CRLF; s := s + 'weight: ' + decoder.weight + CRLF; s := s + 'street: ' + decoder.street + CRLF; s := s + 'city: ' + decoder.city + CRLF; s := s + 'state: ' + decoder.state + CRLF; s := s + 'postal: ' + decoder.postal + CRLF; s := s + 'country: ' + decoder.country + CRLF; s := s + 'id: ' + decoder.id + CRLF; s := s + 'issued: ' + decoder.issued + CRLF; s := s + 'expires: ' + decoder.expires + CRLF; s := s + CRLF; ShowMessage (s) end; end except on E:Exception do //Process errors ShowMessage(Format('Error:%s', [E.Message])); end finally end end; procedure ReadDrvLic(const fileName: string; const page: integer); var Ci: ICiServer; reader: ICiPdf417; bc: ICiBarcode; begin try try begin //Create reader Ci:=CoCiServer.Create; reader:=Ci.CreatePdf417; // Open image reader.Image.Open(fileName, page); // Read barcodes bc := reader.FirstBarcode(); // Process results if (bc <> nil) then DecodeDrvLic (bc.Text) else ShowMessage ('No Driver License Barcode found') end except on E:Exception do //Process errors ShowMessage(Format('Error:%s.File:%s', [E.Message,FileName])); end finally end end;
VBScript/ASP
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
Sub DecodeDrvLic(text) On Error Resume Next 'Create decoder Dim decoder Set decoder = CreateObject("ClearImageDLID.DLDecoder") If Err.Number <> 0 Then WScript.Echo Err.Description : Exit Sub 'Decode text decoder.Decode text If Err.Number <> 0 Then WScript.Echo Err.Description : Exit Sub Dim s: s = "" If (decoder.last <> "") Then s = s + "last: " + decoder.last + vbCrLf s = s + "first: " + decoder.first + vbCrLf s = s + "middle: " + decoder.middle + Vbcrlf s = s + "suffix: " + decoder.suffix + vbCrLf s = s + "dob: " + decoder.dob + vbCrLf s = s + "eyes: " + decoder.eyes + vbCrLf s = s + "hair: " + decoder.hair + vbCrLf s = s + "sex: " + decoder.sex + vbCrLf s = s + "height: " + decoder.height + vbCrLf s = s + "weight: " + decoder.weight + vbCrLf s = s + "street: " + decoder.street + vbCrLf s = s + "city: " + decoder.city + vbCrLf s = s + "state: " + decoder.state + vbCrLf s = s + "postal: " + decoder.postal + vbCrLf s = s + "country: " + decoder.country + vbCrLf s = s + "id: " + decoder.id + vbCrLf s = s + "issued: " + decoder.issued + vbCrLf s = s + "expires: " + decoder.expires + vbCrLf End If WScript.Echo s ' WScript.Echo "XML Data: " + vbCrLf + decoder.xml + vbCrLfEnd Sub Sub ReadDrvLic(fileName, page) On Error Resume Next Dim ci, reader, bc 'Create reader Set ci = CreateObject("ClearImage.ClearImage") If Err.Number <> 0 Then WScript.Echo Err.Description : Exit Sub Set reader = ci.CreatePdf417() If Err.Number <> 0 Then WScript.Echo Err.Description : Exit Sub ' Open image reader.Image.Open fileName, page If Err.Number <> 0 Then WScript.Echo Err.Description : Exit Sub ' Read Barcode Set bc = reader.FirstBarcode If Err.Number <> 0 Then WScript.Echo Err.Description : Exit Sub ' Process results If Not bc Is Nothing Then DecodeDrvLic bc.Text Else WScript.Echo "Driver License barcode not found" End ifEnd Sub
Recommended best practices
The image quality of the barcode on the back of the driver license image is lower quality than for scanned document. Licenses are covered by a relatively thick laminated coating that diffuses the images and may be scratched or smudged..
The ClearImage DL/ID Reader employs multiple image processing techniques to deal with the most difficult images attuned to read the specific barcode found on the back of the licenses. Inlite recommends the following best practices to achieve the highest recognition rate and recognition speed:
- Scan driver license as grayscale at a resolution of 300dpi. If needed image can be saved for archival purposes at different resolution and color using the ClearImage API.
- If using a camera, then
- Use 3-5 Mega Pixel setting
- Take the picture head on to keep the barcode rectangular
- Avoid flash or shadows. Even illumination is best
- Avoid using low-quality JPEG compression when saving images. Set the highest JPEG quality possible. Use these recommendations to mitigate effects of JPEG blocking.
Example of Driver License reader XML output
The following example shows the typical (California) barcode contents as provided by the DL/ID reader. The available contents varies from state to state, and between generations of licenses.