Performs automatic bitmap processing clean up on the image to enhance the quality of the page before beginning recognition.
#include "ltocr.h"
L_LTOCR_API L_INT EXT_FUNCTION L_OcrPage_AutoPreprocess(page, commands, callback, userData)
Handle to the OCR page.
The preprocessing command to perform.
Optional callback to show operation progress.
Optional user data to pass to the callback function.
Value | Meaning |
---|---|
SUCCESS | The function was successful. |
< 1 | An error occurred. Refer to Return Codes. |
Performs automatic bitmap processing clean up on the image to enhance the quality of the page before beginning recognition.
Use this method to deskew, rotate or invert the bitmap according to command. By performing auto pre-processing on a page, you can improve the image quality of draft mode faxes.
Use the L_OcrProgressCallback to show the operation progress or to abort it. For more information and an example, refer to L_OcrProgressCallback.
Call this method prior to calling L_OcrPage_Recognize.
This method will call L_OcrPage_GetDeskewAngle, L_OcrPage_GetRotateAngle and L_OcrPage_IsInverted to determine whether the page needs processing, if the page does, this method will internally deskews, rotates or inverts the image accordingly.
If the image is skewed, L_OcrPage_GetDeskewAngle will return the angle needed to deskew the page bitmap, if you call L_OcrPage_AutoPreprocess on the page, all subsequent calls to L_OcrPage_GetDeskewAngle will return 0 since the bitmap is no longer skewed. Same with L_OcrPage_GetRotateAngle and L_OcrPage_IsInverted.
Use L_OcrPage_GetAutoPreprocessValues to obtain the accumulative pre-processing values applied to this L_OcrPage.
This method works on both the original and processing version of the image. For example, if you add a page that is skewed and call L_OcrPage_AutoPreprocess width L_OcrAutoPreprocessPageCommand_Deskew, then obtain either the original or processing bitmaps with L_OcrPage_GetBitmap, you will get two bitmap handles that are both rotated and deskewed.
static L_INT CreateSampleImage(pBITMAPHANDLE bitmapHandle)
{
L_INT retVal = -1;
//Make it white on black
L_UINT reserved = 0;
retVal = L_InvertBitmap(bitmapHandle, reserved);
if(retVal != SUCCESS)
return retVal;
//Rotate 185 degrees to simulate upside-down skewed image
L_UINT ROTATE_CROP = 0;
L_COLORREF fillColor = NULL;
retVal = L_RotateBitmap(bitmapHandle, 18500, ROTATE_CROP, fillColor);
if(retVal != SUCCESS)
return retVal;
return SUCCESS;
}
static L_VOID EXT_CALLBACK bitmapChangedCB(L_OcrPage /*page*/, L_OcrAutoPreprocessPageCommands commands, L_VOID* /*userData*/)
{
std::cout << "L_OcrPageBitmapChangedCallback fired with the following command flag:\n";
switch(commands)
{
case L_OcrAutoPreprocessPageCommands_None:
std::cout << "L_OcrAutoPreprocessPageCommands_None\n";
break;
case L_OcrAutoPreprocessPageCommands_All:
std::cout << "L_OcrAutoPreprocessPageCommands_All\n";
break;
case L_OcrAutoPreprocessPageCommands_Deskew:
std::cout << "L_OcrAutoPreprocessPageCommands_Deskew\n";
break;
case L_OcrAutoPreprocessPageCommands_Rotate:
std::cout << "L_OcrAutoPreprocessPageCommands_Rotate\n";
break;
case L_OcrAutoPreprocessPageCommands_Invert:
std::cout << "L_OcrAutoPreprocessPageCommands_Invert\n";
break;
}
}
L_INT L_OcrPage_AutoPreprocessExample()
{
BITMAPHANDLE bitmap = { 0 };
L_OcrEngine ocrEngine = NULL;
L_OcrPage ocrPage = NULL;
L_OcrDocumentManager ocrDocumentManager = NULL;
L_OcrDocument ocrDocument = NULL;
// Create an instance of the engine
L_INT retCode = L_OcrEngineManager_CreateEngine(L_OcrEngineType_LEAD, &ocrEngine);
if(retCode != SUCCESS)
return retCode;
// Load a page to process
retCode = L_LoadBitmap(MAKE_IMAGE_PATH(L_TEXT("Ocr1.tif")), &bitmap, sizeof(BITMAPHANDLE), 0, ORDER_RGB, NULL, NULL);
if(retCode != SUCCESS)
return retCode;
// Create a sample image to test with
retCode = CreateSampleImage(&bitmap);
if(retCode != SUCCESS)
goto CLEANUP;
// Start the engine using default parameters
std::cout << "Starting up the engine...\n";
retCode = L_OcrEngine_Startup(ocrEngine, NULL, OCR_LEAD_RUNTIME_DIR);
if(retCode == SUCCESS)
{
// Add this image to the document
retCode = L_OcrPage_FromBitmap(ocrEngine, &ocrPage, &bitmap, L_OcrBitmapSharingMode_AutoFree, NULL, NULL);
if(retCode != SUCCESS)
return retCode;
// We have a valid page and bitmap ownership has transfered. So, we do not need to free the bitmap anymore.
// Bitmap will be freed when ocrPage is destroyed.
bitmap.Flags.Allocated = 0;
L_OcrPage_SetBitmapChangedCallback(ocrPage, &bitmapChangedCB, NULL);
// show that the original page is inverted
L_BOOL isInverted = L_FALSE;
L_OcrPage_IsInverted(ocrPage, &isInverted);
if(isInverted)
std::cout << "Before AutoPreprocess: OCR page is inverted";
else
std::cout << "Before AutoPreprocess: OCR page is not inverted";
// Auto-preprocess it
std::cout << "Preprocessing the page...\n";
// Note: The following can be condensed into a single call using the flag
// L_OcrAutoPreprocessPageCommands_All. They have been listed out here for illustration.
L_OcrPage_AutoPreprocess(ocrPage, L_OcrAutoPreprocessPageCommands_Invert, NULL, NULL);
L_OcrPage_AutoPreprocess(ocrPage, L_OcrAutoPreprocessPageCommands_Rotate, NULL, NULL);
L_OcrPage_AutoPreprocess(ocrPage, L_OcrAutoPreprocessPageCommands_Deskew, NULL, NULL);
// check for image inversion again and show result
L_OcrPage_IsInverted(ocrPage, &isInverted);
if(isInverted)
std::cout << "After AutoPreprocess: OCR page is inverted";
else
std::cout << "After AutoPreprocess: OCR page is not inverted";
// Get bitmap and save it out to show preprocessing
BITMAPHANDLE exportPage = { 0 };
L_OcrPage_GetBitmap(ocrPage, L_OcrPageBitmapType_Original, &exportPage, sizeof(BITMAPHANDLE));
if(exportPage.Flags.Allocated != 0)
retCode = L_SaveBitmap(MAKE_IMAGE_PATH(L_TEXT("Ocr1_Preproccessed.tif")), &exportPage, FILE_CCITT_GROUP4, 1, 0, NULL);
// Recognize it and save it as PDF
std::cout << "Recognizing...\n";
retCode = L_OcrPage_Recognize(ocrPage, NULL, NULL);
if(retCode != SUCCESS)
goto CLEANUP;
// Get the document manager
retCode = L_OcrEngine_GetDocumentManager(ocrEngine, &ocrDocumentManager);
if(retCode != SUCCESS)
goto CLEANUP;
// Create an OCR document
retCode = L_OcrDocumentManager_CreateDocument(ocrDocumentManager, &ocrDocument, L_OcrCreateDocumentOptions_AutoDeleteFile, NULL);
if(retCode != SUCCESS)
goto CLEANUP;
// In Document File Mode, add OcrPage to OcrDocument after recognition
retCode = L_OcrDocument_AddPage(ocrDocument, ocrPage);
if(retCode != SUCCESS)
goto CLEANUP;
// Adding the page to a file based document will take a snap shot of the recognition data and store it in the document.
// At this point, the page is no longer needed. So destroy it to free up memory not used anymore
L_OcrPage_Destroy(ocrPage);
// Set the handle to NULL so we do not free it in our clean-up code
ocrPage = NULL;
std::wcout << "Saving the output file...\"" << MAKE_IMAGE_PATH(L_TEXT("Clean.pdf")) << "\"\n";
retCode = L_OcrDocument_Save(ocrDocument, MAKE_IMAGE_PATH(L_TEXT("Clean.pdf")), DOCUMENTFORMAT_PDF, NULL, NULL);
}
CLEANUP:
if(bitmap.Flags.Allocated)
L_FreeBitmap(&bitmap);
if(ocrPage != NULL)
L_OcrPage_Destroy(ocrPage);
if(ocrDocument != NULL)
L_OcrDocument_Destroy(ocrDocument);
if(ocrEngine != NULL)
L_OcrEngine_Destroy(ocrEngine);
return retCode;
}