L_ExtractObjectsBitmap (original) (raw)

Summary

Extracts the connected groups of pixels from a bitmap using various options.

Syntax

#include "l_bitmap.h"

L_LTIMGCOR_API L_INT L_ExtractObjectsBitmap(pBitmap, pOptions, pData)

Parameters

pBITMAPHANDLE pBitmap

Pointer to the bitmap handle that references the bitmap to be processed.

pEXOBJ_OPTIONS pOptions

Extraction options. This value cannot be null.

pEXOBJ_DATA *pData

Pointer to be updated with the extracted objects.

Returns

Value Meaning
SUCCESS The function was successful.
< 1 An error occurred. Refer to Return Codes.

Required DLLs and Libraries

Platforms

Win32, x64, Linux.

Example

This example shows how to use the various object extraction functions.

L_INT ExtractObjectsBitmapExample(L_VOID) { L_INT nRet = SUCCESS; BITMAPHANDLE InputBitmap = { 0 }; BITMAPHANDLE OutputBitmap = { 0 }; pEXOBJ_DATA pData = NULL; EXOBJ_OPTIONS ExtractOptions = { 0 }; EXOBJ_FILTER_OPTIONS FilterOptions = { 0 }; EXOBJ_CONTENTBOUND ContentBound = { 0 }; EXOBJ_CONTENTBOUND_OPTIONS ContentBoundOptions = { 0 }; EXOBJ_REGION_OPTIONS RegionOptions = { 0 }; pEXOBJ_OBJECT* pObjectArray = NULL; // Temporary array for L_ExtractObjects_CalcRegion pEXOBJ_OBJECTLIST pObjectList = NULL; // Temporary variable for iterating // Load the original image nRet = L_LoadBitmap(MAKE_IMAGE_PATH(TEXT("demoicr2.tif")), &InputBitmap, sizeof(BITMAPHANDLE), 0, ORDER_BGRORGRAY, NULL, NULL); if (nRet != SUCCESS) goto cleanup; // Setup the extraction options ExtractOptions.uStructSize = sizeof(EXOBJ_OPTIONS); ExtractOptions.uFlags = EXOBJ_8_CONNECTIVITY | EXOBJ_DETECT_CHILDREN | EXOBJ_OUTLINE; // Extract the objects nRet = L_ExtractObjectsBitmap(&InputBitmap, &ExtractOptions, &pData); if (nRet != SUCCESS) goto cleanup; // Log the number of objects from the first list pObjectList = pData->pHead->pObjects; printf(TEXT("Number of objects (before filtering): %u\n"), pObjectList->uCount); // Log the number of points around the first object (braces for scope) { pEXOBJ_OUTLINE_POINT pIter; L_INT iCount; for (pIter = pObjectList->pHead->pOutline->pHead, iCount = 0; pIter != NULL; pIter = pIter->pNext, iCount++) { // Nothing to do, just incrementing iCount } printf(TEXT("First object's outline length: %d\n"), iCount); } // Setup the filter options FilterOptions.uStructSize = sizeof(EXOBJ_FILTER_OPTIONS); FilterOptions.nLargeObjectThreshold = -1; // No upper limit on size. FilterOptions.nSmallObjectThreshold = 10; // Remove objects smaller than 10x10 pixels // Filter the objects nRet = L_ExtractObjects_FilterList(pData, pObjectList, &FilterOptions); if (nRet != SUCCESS) goto cleanup; // Log the number of objects again printf(TEXT("Number of objects (after filtering): %u\n"), pObjectList->uCount); // Setup the content bound options ContentBound.uStructSize = sizeof(EXOBJ_CONTENTBOUND); L_Rect_Make(&ContentBound.rcInput, 192, 260, 323, 146); ContentBoundOptions.uStructSize = sizeof(EXOBJ_CONTENTBOUND_OPTIONS); ContentBoundOptions.pObjectsOfInterest = NULL; // Passing NULL to use every object in pData ContentBoundOptions.uObjectsOfInterestCount = 0; // Passing 0 to use every object in pData // Calculate the content bounds nRet = L_ExtractObjects_CalcContentBound(pData, &ContentBound, 1, &ContentBoundOptions); if (nRet != SUCCESS) goto cleanup; // Allocate a new array to hold the objects pObjectArray = (pEXOBJ_OBJECT*)malloc(pObjectList->uCount * sizeof(pEXOBJ_OBJECT)); if (pObjectArray == NULL) { nRet = ERROR_NO_MEMORY; goto cleanup; } // Convert the linked list to an array (braces for scope) { pEXOBJ_OBJECT pIter; L_INT iIndex; for (pIter = pObjectList->pHead, iIndex = 0; pIter != NULL; pIter = pIter->pNext, iIndex++) pObjectArray[iIndex] = pIter; } // Setup the region options RegionOptions.uStructSize = sizeof(EXOBJ_REGION_OPTIONS); RegionOptions.uFlags = EXOBJ_REGION_HORIZONTAL; // Calculate each object's region nRet = L_ExtractObjects_CalcRegion(pData, pObjectArray, pObjectList->uCount, &RegionOptions); if (nRet != SUCCESS) goto cleanup; // Create an output image nRet = L_CreateBitmap(&OutputBitmap, sizeof(BITMAPHANDLE), TYPE_CONV, InputBitmap.Width, InputBitmap.Height, 24, ORDER_BGR, NULL, TOP_LEFT, NULL, 0); if (nRet != SUCCESS) goto cleanup; // Fill the output image with white nRet = L_FillBitmap(&OutputBitmap, RGB(255, 255, 255)); if (nRet != SUCCESS) goto cleanup; // Draw the content bound rects for the first word. Red for the input, green for the output. nRet = L_SetBitmapRgnRect(&OutputBitmap, NULL, &ContentBound.rcInput, L_RGN_SET); if (nRet != SUCCESS) goto cleanup; nRet = L_FillBitmap(&OutputBitmap, RGB(255, 0, 0)); if (nRet != SUCCESS) goto cleanup; nRet = L_SetBitmapRgnRect(&OutputBitmap, NULL, &ContentBound.rcContent, L_RGN_SET); if (nRet != SUCCESS) goto cleanup; nRet = L_FillBitmap(&OutputBitmap, RGB(0, 255, 0)); if (nRet != SUCCESS) goto cleanup; // Populate the output image with each object's region (braces for scope) { pEXOBJ_OBJECT pObjectIter; for (pObjectIter = pObjectList->pHead; pObjectIter != NULL; pObjectIter = pObjectIter->pNext) { pEXOBJ_SEGMENT pSegmentIter; for (pSegmentIter = pObjectIter->pRegionHorizontal->pHead; pSegmentIter != NULL; pSegmentIter = pSegmentIter->pNext) { // Update the region to the current segment nRet = L_SetBitmapRgnRect(&OutputBitmap, NULL, &pSegmentIter->rcBounds, L_RGN_SET); if (nRet != SUCCESS) goto cleanup; // Fill the region with black nRet = L_FillBitmap(&OutputBitmap, RGB(0, 0, 0)); if (nRet != SUCCESS) goto cleanup; } } } // Clear the output image's region nRet = L_FreeBitmapRgn(&OutputBitmap); if (nRet != SUCCESS) goto cleanup; // Save the output image nRet = L_SaveBitmap(MAKE_IMAGE_PATH(TEXT("ExtractObjects.png")), &OutputBitmap, FILE_PNG, 0, 0, NULL); if (nRet != SUCCESS) goto cleanup; cleanup: // Free the loaded images if (InputBitmap.Flags.Allocated) L_FreeBitmap(&InputBitmap); if (OutputBitmap.Flags.Allocated) L_FreeBitmap(&OutputBitmap); // Free the results if (pData != NULL) L_ExtractObjects_FreeData(&pData); // Free the array if (pObjectArray != NULL) free(pObjectArray); return nRet; }