This example demonstrates how to use frame filters to perform basic image processing.
It shows, how to:
The example is located in the %TOPLEVEL%\Samples\VC\Filter Inspector directory of the IC Imaging Control installation.
In the OnInitDialog method, the Grabber is initialized. The most important part here is to disable graphic overlay completely, by calling Grabber::setOverlayBitmapPathPosition, thus avoiding interference with the possible color formats of the frame filters. After that, the device selection dialog is displayed and live mode is started.
// Set the live video output window to the static IDC_DISPLAY. m_Grabber.setHWND( GetDlgItem( IDC_DISPLAY )->GetSafeHwnd() ); // Disable all overlay bitmaps. m_Grabber.setOverlayBitmapPathPosition( ePP_NONE ); // Show the device page to let the user select a video capture device. m_Grabber.showDevicePage( m_hWnd ); // When a video capture device was selected, start live mode. if( m_Grabber.isDevValid() ) { Startlive(); }
To obtain a list of available frame filters, call FilterLoader::getAvailableFrameFilters, which returns a vector of FilterInfo structures. The parameter of this static method checks which kind of filters should be loaded. You have the choice between generic filters ( eFC_GENERIC ) that should work in all environments and filters that were designed to work only in certain programs ( eFC_INTERNAL ). The latter kind of filter may not work properly, if not initialized correctly. In this example, we use eFC_ALL to load all available filters:
// Get a list with all available frame filters. std::vector<FilterInfo> filterInfos = FilterLoader::getAvailableFrameFilters( eFC_ALL );
Now we want to fill a list box with the names of the files in which the filters have been found. To do that, we look at each filter and add its module name to the list box, while filling FilterFileList with the module paths of the filters. The module names are not added when the module path is already in the vector:
CListBox* pFilesList = (CListBox*)GetDlgItem( IDC_FILES ); // In this loop, we create a list with all files that contain filters. for( size_t i = 0; i < filterInfos.size(); ++i ) { // For each filter, see if its module was already added to the list. // If not, add it, otherwise skip it. bool bFound = false; for( size_t j = 0; j < m_FilterFileList.size(); ++j ) { if( m_FilterFileList[j] == filterInfos[i].getModulePath() ) { bFound = true; break; } } if( !bFound ) { // Save the filter module path in a list to access it when the // user selects the list entry. m_FilterFileList.push_back( filterInfos[i].getModulePath() ); // Add the filter file name to the list. pFilesList->AddString( filterInfos[i].getModuleNameW().c_str() ); } }
In the event handler that is called when the user selects a filter module name from the list box, a second list box is filled with the names of the filters in that module:
void CFilterInspectorDlg::OnLbnSelchangeFiles() { CListBox* pFilesList = (CListBox*)GetDlgItem( IDC_FILES ); CListBox* pFilterList = (CListBox*)GetDlgItem( IDC_FILTERS ); // Get a list with all available frame filters. std::vector<FilterInfo> filterInfos = FilterLoader::getAvailableFrameFilters( eFC_ALL ); // Get the index of the currently selected filter file. int sel = pFilesList->GetCurSel(); if( sel != -1 ) { // If a filter file was selected, fill the filter list with the filter of that file. // First, clear the list. pFilterList->ResetContent(); // Add all filters of the selected file to the list. int n = 0; for( int i = 0; i < int(filterInfos.size()); ++i ) { FilterInfo& fi = filterInfos[i]; // Check whether the filter's module matches the selected file. if( m_FilterFileList[sel] == fi.getModulePath() ) { pFilterList->AddString( fi.getFilterNameW().c_str() ); // Save the index of the filter in the list of the // available filters in the list item's item data. pFilterList->SetItemData( n++, i ); } } } }
In a loop, the filter module paths of all filters are compared to the path of the selected file. If the filter comes from the selected file, its name is added to the filter list box. The index of the filter in the original filter list that was retrieved from FilterLoader::getAvailableFrameFilters is stored in the list box item data by calling CListBox::SetItemData, thus allowing to find the filter when the user clicks the item.
When the user selects a filter from the filter list, the item data of the selected item is read using CListBox::GetItemData. Because we previously stored the filter's index in the list of available filters in the item data, we can use this number now to select the FilterInfo in the filterInfos list:
// We previously stored the index of the filter in the list of available // filters in the item data of the list item. Read it back. int filterIndex = (int)pFilterList->GetItemData( sel ); // Filters can only be set when live mode is stopped. bool bIsLive = m_Grabber.isLive(); Stoplive(); // Create the new filter instance. m_pFilter = FilterLoader::createFilter( filterInfos[filterIndex] );
The frame filter instance is created by calling FilterLoader::createFilter with the FilterInfo structure as parameter.
To activate the frame filter, it has to be registered at the grabber object. Use Grabber::setDeviceFrameFilters to set the frame filter to transform the image data coming from the video capture device.
// Set the filter as device frame filter. m_Grabber.setDeviceFrameFilters( m_pFilter.get() ); // Restart live mode, if possible. if( m_Grabber.isDevValid() && bIsLive ) { Startlive(); } // Enable the "Dialog..."-Button if the filter has a built-in dialog. GetDlgItem( IDC_DIALOG )->EnableWindow( m_pFilter->hasDialog() );
Live mode has to be stopped to set a frame filter.
The pointer to the frame filter instance is stored in a member variable of the dialog class, so that the filter instance exists after the event handler has been executed. As the pointer to the frame filter instance is a smart_com, the instance would be destroyed once a local pointer variable runs out of scope.
Live mode has to be stopped before the new filter instance is assigned to the member variable m_pFilter, because the assignment destroys the filter instance it previously pointed to.