Creating a Filter Module

This example demonstrates how to create a filter module, containing frame filter implementations.

This article shows you how to:

You can find a Visual Studio project with a working filter module in the Samples\VC\DemoFilters directory of the IC Imaging Control installation.

In this article, the filter that was created in Writing a Frame Filter: Binarization will be used. For information on how a frame filter is implemented, please take a look at this article.

Implement the Frame Filter Class

We will now extend the binarization filter from Writing a Frame Filter: Binarization to work inside a filter module.

A generic application that loads a filter does now know the filter's interface (like the CBinarizationFilter::enable or CBinarizationFilter::setThreshold methods). To be able to set filter parameters from that program, there is a generic filter interface implemented in IFrameFilter and FrameFilterImpl. The application can use IFrameFilter::getAvailableParameters to find out which parameters a filter supports and then call IFrameFilter::setParameter to alter parameter values.

To make the binarization filter support such parameters, it has to use FrameFilterImpl::addBoolParam or one of the other parameter registration methods. Extend the constructor of CBinarizationFilter to register two parameters:

CBinarizationFilter::CBinarizationFilter()
    :    m_bEnabled( false ),
        m_threshold( 127 )
{
    // Add 'enable' parameter to enable or disable the binarization
    addBoolParam( "enable", &CBinarizationFilter::getEnable, &CBinarizationFilter::setEnable );
    // Add 'threshold' parameter to set the binarization threshold
    addLongParam( "threshold", &CBinarizationFilter::getThreshold, &CBinarizationFilter::setThreshold );
}

The first parameter of the registration functions is the name by which an application can access the parameter. The second and third parameter are names of member functions of CBinarizationFilter. Replace the old enable and setThreshold methods by the following code:

public:
    // Enables or disables binarizarion
    DShowLib::tFilterError getEnable( bool& bEnable );
    DShowLib::tFilterError setEnable( bool bEnable );
    // Sets the threshold for the binarization
    DShowLib::tFilterError getThreshold( long& threshold );
    DShowLib::tFilterError setThreshold( long threshold );
private:
    bool    m_bEnabled;
    int        m_threshold;
};

These methods will be called when a program that loaded the filter calls setParameter( "enable", true ) or setParameter( "threshold", 100 ).

Their implementation is very simple:

/*
 *    Returns the 'enabled' state of the binarization
 */
tFilterError CBinarizationFilter::getEnable( bool& bEnable )
{
    bEnable = m_bEnabled;
    return eNO_ERROR;
}
/*
 *    Sets the 'enabled' state of the binarization
 */
tFilterError CBinarizationFilter::setEnable( bool bEnable )
{
    m_bEnabled = bEnable;
    return eNO_ERROR;
}
/*
 *    Returns the binarization threshold
 */
tFilterError CBinarizationFilter::getThreshold( long& threshold )
{
    threshold = m_threshold;
    return eNO_ERROR;
}
/*
 *    Sets the binarization threshold
 */
tFilterError CBinarizationFilter::setThreshold( long threshold )
{
    m_threshold = threshold;
    return eNO_ERROR;
}

We now created a filter that should work with generic applications. Change the getStaticFilterInfo method to flag the filter as eFC_GENERIC:

FilterInfo CBinarizationFilter::getStaticFilterInfo()
{
    // Return a filter name and declare the filter as eFC_GENERIC.
    FilterInfo fi = { L"Demo_Binarization", L"", eFC_GENERIC };
    return fi;
}

Registering the Frame Filter Class

Go to the main file of your filter module and add a FILTERDLL_REGISTER_FILTER-line for the name of your filter class inside the FILTERDLL_BEGIN_EXPORT- FILTERDLL_END_EXPORT-section.

FILTERDLL_BEGIN_EXPORT()
    FILTERDLL_REGISTER_FILTER(CRotateTransform)
    FILTERDLL_REGISTER_FILTER(CDeNoiseTransform)
    FILTERDLL_REGISTER_FILTER(CSnapFilter)
    FILTERDLL_REGISTER_FILTER(CBinarizationFilter)
FILTERDLL_END_EXPORT()

Adding a dialog to the frame filter

To add a user interface to your filter, you can override the IFrameFilter::hasDialog and IFrameFilter::callDialog methods.

The default implementation of hasDialog returns false, so we need to change it to true:

bool    CBinarizationFilter::hasDialog() const
{
    return true;
}

In the callDialog implementation, we save the current settings of the filter, using IFrameFilter::getSettings and display a dialog box allowing the user to change the filter's parameters. If the user exists the dialog by clicking the cancel button, the filter setting are restored to the saved values.

bool    CBinarizationFilter::callDialog( HWND hParent )
{
    // Save settings
    std::string data = getSettings();
    // Display modal dialog.
    // Pass the pointer to this instance to WM_INITDIALOG.
    INT_PTR result = DialogBoxParam( g_hInst,
                                    MAKEINTRESOURCE(IDD_BINARIZATION_CONFIG),
                                    hParent,
                                    BinarizationConfigDlgProc,
                                    (LPARAM)this );
    // When the user clicked 'cancel' restore settings
    if( result == IDCANCEL )
    {
        setSettings( data );
    }
    // Return true when the dialog was displayed.
    return result >= 1;
}

<< Programmer's Guide