Split Document with Patch Codes - Windows C DLL

This tutorial shows how to use the LEADTOOLS SDK in a C/C++ Windows API Application to search for patch code barcodes in a document and use the codes to split the pages into separate files.

Note

When scanning a document with many pages, it is often best for organizational purposes to split the document into smaller sets of pages.

Overview  
Summary This tutorial covers how to use the LEADTOOLS Barcode SDK technology to process patch codes in a Windows C DLL Application.
Completion Time 30 minutes
Visual Studio Project Download tutorial project (18 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 Split Document with Patch Codes - Windows C DLL tutorial, get familiar with the basic steps of creating a project by reviewing the Add References and Set a License tutorial.

Create the Project and Add LEADTOOLS References

Start with a copy of the 64-bit Windows API project created in the Add References and Set a License tutorial. If the project is not available, create it by following the steps in that tutorial.

In order to load and save images and to detect patch codes, LEADTOOLS requires additional DLLs. Add the required libraries by opening the pre-compiled header file, either pch.h or stdafx.h depending on the Visual Studio version used, and add the following lines:

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

Note

For a complete list of which DLL files are required for your application, refer to 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 function 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 Split Document Code

Now that the LEADTOOLS references have been added and the license has been set, 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).

Expand the menu in the resources tree and double-click the menu resource to open it in the designer interface.

In the empty item below the Exit item, click and type Split &Patch Document. Drag the new item above Exit. This should cause the item's ID to become ID_FILE_SPLITPATCHDOCUMENT.

Go to the main CPP file of the project and navigate to the WndProc function of the main window. Under the switch (wmId) statement, that is below the WM_COMMAND case, add a new case:

switch (wmId) 
{ 
   case ID_FILE_SPLITPATCHDOCUMENT: 
   { 
      TCHAR szFileName[500] = TEXT(""); // File name 
      if (SUCCESS != GetDocmentFileName(hWnd, szFileName, ARRAYSIZE(szFileName))) 
         break; 
      SplitPatchDocument(szFileName); 
   } 
   break; 
 
// Keep rest of the code as is 

The GetDocmentFileName() function can be any function that fills the szFileName variable with a valid multipage image file name (including full path, if needed). To display a File Open dialog to obtain the file name, add the following code:

L_INT GetDocmentFileName(HWND hwnd, TCHAR* pszFileName, DWORD nLen) 
{ 
   OPENFILENAME OpenFileName = { 0 }; 
   OpenFileName.lStructSize = sizeof(OpenFileName); 
   OpenFileName.hwndOwner = hwnd; 
   OpenFileName.lpstrFile = pszFileName; 
   OpenFileName.nMaxFile = nLen; 
   OpenFileName.lpstrFilter = TEXT("TIFF\0*.tif\0All\0*.*\0"); 
   OpenFileName.nFilterIndex = 1; 
   OpenFileName.lpstrFileTitle = NULL; 
   OpenFileName.nMaxFileTitle = 0; 
   OpenFileName.lpstrInitialDir = NULL; 
   OpenFileName.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; 
 
   // Show the File Open dialog box 
   if (!GetOpenFileName(&OpenFileName)) 
      return FAILURE; 
   return SUCCESS; 
} 

Add a SplitPatchDocument function above the WndProc function and add the following code to it:

void SplitPatchDocument(L_TCHAR* pszInputFile) 
{ 
   BITMAPHANDLE bmp = { 0 }; 
   FILEINFO FileInfo = { 0 }; 
   L_TCHAR szOutputFile[500]; 
   int fromPage = 1; 
   TCHAR drive[_MAX_DRIVE], dir[_MAX_DIR], fname[_MAX_FNAME]; 
   _tsplitpath_s(pszInputFile, drive, ARRAYSIZE(drive), dir, ARRAYSIZE(dir), fname, ARRAYSIZE(fname), NULL, 0); 
   wsprintf(szOutputFile, TEXT("%s%s%s_fromPage%d.tif"), drive, dir, fname, fromPage); 
   L_FileInfo(pszInputFile, &FileInfo, sizeof FileInfo, FILEINFO_TOTALPAGES, NULL); 
   LOADFILEOPTION LoadOption = { 0 }; 
   L_GetDefaultLoadFileOption(&LoadOption, sizeof LoadOption); 
   SAVEFILEOPTION SaveOption = { 0 }; 
   L_GetDefaultSaveFileOption(&SaveOption, sizeof SaveOption); 
   SaveOption.PageNumber = 1; //overwrite 
   for (int i = 1; i <= FileInfo.TotalPages; ++i) 
   { 
      LoadOption.PageNumber = i; 
      L_LoadBitmap(pszInputFile, &bmp, sizeof BITMAPHANDLE, 0, ORDER_BGRORGRAY, &LoadOption, 0); 
      if ((i > 1) && IsPatchCodePage(&bmp)) 
      { 
         fromPage = i; 
         SaveOption.PageNumber = 1; // overwrite, to create new file 
         wsprintf(szOutputFile, TEXT("%s%s%s_fromPage%d.tif"), drive, dir, fname, fromPage); 
 
      } 
      L_SaveBitmap(szOutputFile, &bmp, FILE_TIFLZW, bmp.BitsPerPixel, 0, &SaveOption); 
      SaveOption.PageNumber = 2; // append, to add subsequent pages to same file 
      L_FreeBitmap(&bmp); 
   } 
} 

Add a function named IsPatchCodePage() that detects whether an image contains patch codes and add the following code to it:

bool IsPatchCodePage(pBITMAPHANDLE pBmpPage) 
{ 
   bool bRet = false; 
   if (L_BarCodeInit(BARCODES_1D) != SUCCESS) 
      return bRet; 
   pBARCODEDATA pBarCodes = NULL; 
   BARCODE1D Bar1d = { 0 }; 
   Bar1d.uStructSize = sizeof BARCODE1D; 
   Bar1d.bErrorCheck = TRUE; 
   Bar1d.nGranularity = 9; 
   Bar1d.nDirection = BARCODE_DIR_HORIZONTAL | BARCODE_DIR_VERTICAL; 
   BARCODECOLOR BarColor = { 0 }; 
   BarColor.uStructSize = sizeof BARCODECOLOR; 
   BarColor.dwColorBar = RGB(0, 0, 0); 
   BarColor.dwColorSpace = RGB(255, 255, 255); 
   // Search for all 1D barcodes in the enite bitmap  
   L_INT nRet = L_BarCodeRead(pBmpPage, NULL, BARCODE_1D_PATCH_CODE, BARCODE_SCANLINES_PER_PIXELS, BARCODE_BLOCK_SEARCH, 0, &Bar1d, NULL, &BarColor, &pBarCodes, sizeof BARCODEDATA); 
   if (SUCCESS == nRet) 
      if (pBarCodes->nTotalCount > 0) 
         bRet = true; 
   if (pBarCodes) 
      L_BarCodeFree(&pBarCodes); 
   L_BarCodeExit(); 
   return bRet; 
} 

Note

Since Patch Codes are commonly used when scanning documents, it might be of interest to use the code for the IsPatchCodePage(pBITMAPHANDLE pBmpPage) function with the L_TwainAcquire function in a scanning session. For more details, see the Acquire an Image From a TWAIN Source tutorial.

Run the Project

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

If the steps are followed correctly, the application runs and enables the user to select a multipage file, then splits the input sample document according to the barcode detection results.

Wrap-up

This tutorial covered how to use the BARCODEDATA structure and the L_BarCodeRead function to detect patch codes using the LEADTOOLS SDK in a Windows API application.

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.