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 |
Development License | Download LEADTOOLS |
Try it in another language |
|
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.
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:\\LEADTOOLS22\\Lib\\CDLL\\x64\\Ltfil_x.lib") // file loading and saving
#include "C:\LEADTOOLS22\Include\Ltbar.h"
#pragma comment (lib, "C:\\LEADTOOLS22\\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.
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.
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 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.
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.