Filter Library Camera Interface Physics

ScanFilterCustom.cpp

00001 /*
00002  * ScanFilterCustom.cpp - custom filter.
00003  *
00004  * This file is part of the Camera Filter Library.
00005  * Computer Aided Measurement Environment for Realtime Atomic imaging (Camera)
00006  *
00007  * Copyright (C) 2004-2005, Leiden Probe Microscopy.
00008  * Copyright (C) 2004-2005, Universiteit Leiden.
00009  *
00010  * Authors: M. Seynen (original), Martin J. Moene
00011  *
00012  * $Id: ScanFilterCustom.cpp 358 2006-03-06 14:49:02Z moene $
00013  */
00014 
00015 /*
00016  * configuration defines:
00017  */
00018 
00019 // currently nothing
00020 
00021 /*
00022  * end of configuration defines.
00023  */
00024 
00025 #include "stdafx.h"                     // for common (pre-compiled) headers
00026 //#include <cfl/stdafx.h>                 // for common (pre-compiled) headers
00027 #include <cfl/resource.h>               // for messages and other resources
00028 
00029 #include <Camera/InterfaceDll.h>        // Camera--Filter Library interface
00030 
00031 #include <cfl/ScanFilterCustom.h>       // this filter's header
00032 #include <cfl/FilterDlg_Custom.h>       // this filter's dialog
00033 
00034 #ifdef _DEBUG
00035 #undef THIS_FILE
00036 static char THIS_FILE[]=__FILE__;
00037 #define new DEBUG_NEW
00038 #endif
00039 
00040 #define CFL_SCHEMAVERSION_FILTERCUSTOM 0 // permanent storage schema version
00041                                         // this filter's name
00042 LPCTSTR CScanFilterCustom::m_lpcsFilterName = _T("Custom");
00043                                         // this filter's short name
00044 LPCTSTR CScanFilterCustom::m_lpcsShortFilterName = CScanFilterCustom::m_lpcsFilterName;
00045                                         // serialization
00046 IMPLEMENT_SERIAL( CScanFilterCustom, CScanFilter, CFL_SCHEMAVERSION_FILTERCUSTOM )
00047 
00048 /**
00049  * the blur filter-weights (5x5).
00050  */
00051 const CScanFilterCustom::WeightType CScanFilterCustom::m_blurWeights[ KernelSize ] =
00052 {
00053    1, 1, 1, 1, 1,
00054    1, 1, 1, 1, 1,
00055    1, 1, 1, 1, 1,
00056    1, 1, 1, 1, 1,
00057    1, 1, 1, 1, 1,
00058 };
00059 
00060 /**
00061  * the low-pass filter-weights (5x5).
00062  */
00063 const CScanFilterCustom::WeightType CScanFilterCustom::m_lowpassWeights[ KernelSize ] =
00064 {
00065    0, 0, 0, 0, 0,
00066    0, 1, 1, 1, 0,
00067    0, 1, 2, 1, 0,
00068    0, 1, 1, 1, 0,
00069    0, 0, 0, 0, 0,
00070 };
00071 
00072 /**
00073  * the high-pass filter-weights (5x5).
00074  */
00075 const CScanFilterCustom::WeightType CScanFilterCustom::m_highpassWeights[ KernelSize ] =
00076 {
00077    -1, 1,-1,-1,-1,
00078    -1,-1,-1,-1,-1,
00079    -1,-1,25,-1,-1,
00080    -1,-1,-1,-1,-1,
00081    -1,-1,-1,-1,-1,
00082 };
00083 
00084 /**
00085  * the edge filter-weights (5x5).
00086  */
00087 const CScanFilterCustom::WeightType CScanFilterCustom::m_edgeWeights[ KernelSize ] =
00088 {
00089    -1, 0, 0, 0, 0,
00090     0,-1, 0, 0, 0,
00091     0, 0, 1, 0, 0,
00092     0, 0, 0, 1, 0,
00093     0, 0, 0, 0, 0,
00094 };
00095 
00096 /**
00097  * the pyramidal filter-weights (5x5).
00098  */
00099 const CScanFilterCustom::WeightType CScanFilterCustom::m_pyramidalWeights[ KernelSize ] =
00100 {
00101    1, 2, 3, 2, 1,
00102    2, 4, 6, 4, 2,
00103    3, 6, 9, 6, 3,
00104    2, 4, 6, 4, 2,
00105    1, 2, 3, 2, 1,
00106 };
00107 
00108 /**
00109  * the cone filter-weights (5x5).
00110  */
00111 const CScanFilterCustom::WeightType CScanFilterCustom::m_coneWeights[ KernelSize ] =
00112 {
00113    0, 0, 1, 0, 0,
00114    0, 2, 2, 2, 0,
00115    1, 2, 5, 2, 1,
00116    0, 2, 2, 2, 0,
00117    0, 0, 1, 0, 0,
00118 };
00119 
00120 /**
00121  * the edge filter-weights (5x5).
00122  */
00123 const CScanFilterCustom::WeightType CScanFilterCustom::m_gaussianWeights[ KernelSize ] =
00124 {
00125    1, 4, 7, 4, 1,
00126    4,16,26,16, 4,
00127    7,26,41,26, 7,
00128    4,16,26,16, 4,
00129    1, 4, 7, 4, 1,
00130 };
00131 
00132 /**
00133  * the edge filter-weights (5x5).
00134  */
00135 const CScanFilterCustom::WeightType CScanFilterCustom::m_laplacianWeights[ KernelSize ] =
00136 {
00137    0, 0, 0, 0, 0,
00138    0,+1,+1,+1, 0,
00139    0,+1,-8,+1, 0,
00140    0,+1,+1,+1, 0,
00141    0, 0, 0, 0, 0,
00142 };
00143 
00144 /**
00145  * the edge filter-weights (5x5).
00146  */
00147 const CScanFilterCustom::WeightType CScanFilterCustom::m_sharpeningWeights[ KernelSize ] =
00148 {
00149    0, 0, 0, 0, 0,
00150    0,+1,+1,+1, 0,
00151    0,+1,-7,+1, 0,
00152    0,+1,+1,+1, 0,
00153    0, 0, 0, 0, 0,
00154 };
00155 
00156 /*
00157  * constructor.
00158  */
00159 CScanFilterCustom::CScanFilterCustom() :
00160    m_currentFilterType( ftBlur )
00161 {
00162 //   Q_LOG( _T("CScanFilterCustom::CScanFilterCustom()") );
00163 
00164    m_csFilterName = m_lpcsFilterName;
00165 
00166    for ( int i = 0; i < KernelSize; i++ )
00167    {
00168       m_userWeights[i] = 1.0;
00169    }
00170 
00171    SetFilterType( ftBlur );
00172    ReadFilterSettings();
00173 }
00174 
00175 /*
00176  * destructor.
00177  */
00178 CScanFilterCustom::~CScanFilterCustom()
00179 {
00180 //   Q_LOG( _T("CScanFilterCustom::~CScanFilterCustom()") );
00181 
00182    ; // do nothing
00183 }
00184 
00185 /*
00186  * store or retrieve the object's settings;
00187  * see also CScanFilterNull::Serialize().
00188  */
00189 void CScanFilterCustom::Serialize(CArchive& ar)
00190 {
00191 //   Q_LOG( _T("CScanFilterCustom::CScanFilterCustom()") );
00192 
00193    CScanFilter::Serialize( ar );
00194 
00195    if ( ar.IsStoring() )
00196    {
00197       for ( int i = 0; i < KernelSize; ++i )
00198       {
00199          ar << m_userWeights[i];
00200       }
00201 
00202       ar << static_cast< int >( m_currentFilterType );
00203    }
00204    else
00205    {
00206       for ( int i = 0; i < KernelSize; ++i )
00207       {
00208          ar >> m_userWeights[i];
00209       }
00210 
00211       int type;
00212       ar >> type;
00213       m_currentFilterType = static_cast< FilterType >( type );
00214    }
00215 }
00216 
00217 /*
00218  * \brief configure filter with settings as provided by the application on the
00219  * filterlist window (e.g. via registry); see also CScanFilterNull::ReadFilterSettings().
00220  */
00221 void CScanFilterCustom::ReadFilterSettings()
00222 {
00223 //   Q_LOG( _T("CScanFilterCustom::ReadFilterSettings()") );
00224 
00225    CWinApp* pApp = AfxGetApp();
00226 
00227    if ( Q_INVALID( NULL == pApp ) )
00228       return ;
00229 
00230    /*
00231     * parameter string:
00232     */
00233    SetParameters( pApp->GetProfileString( gCflRegistrySubkey, m_lpcsFilterName, _T( "" ) ) );
00234 }
00235 
00236 /*
00237  * \brief save filter settings e.g. for use with the filterlist window (e.g. via registry);
00238  * see also ReadFilterSettings().
00239  */
00240 void CScanFilterCustom::WriteFilterSettings() const
00241 {
00242 //   Q_LOG( _T("CScanFilterCustom::WriteFilterSettings()") );
00243 
00244    CWinApp* pApp = AfxGetApp();
00245 
00246    if ( Q_INVALID( NULL == pApp ) )
00247       return ;
00248 
00249    /*
00250     * parameter string:
00251     */
00252    LPCTSTR pStr = GetParameters();
00253 
00254    if ( pStr )
00255    {
00256       pApp->WriteProfileString( gCflRegistrySubkey, m_lpcsFilterName, pStr );
00257       delete const_cast<LPTSTR>( pStr );
00258    }
00259 }
00260 
00261 /*
00262  * provide current filter parameter(s) for filter-scripting capture
00263  * in the main application;
00264  * see also CScanFilterNull::GetParameters().
00265  */
00266 LPCTSTR CScanFilterCustom::GetParameters() const
00267 {
00268 //   Q_LOG( _T("CScanFilterCustom::GetParameters()") );
00269 
00270    /*
00271     * format parameters and return a c-string on the heap:
00272     */
00273    CString csParameters;
00274    CString csWeight;
00275 
00276    for ( int i = 0; i < KernelSize; ++i )
00277    {
00278       csWeight.Format( _T( "%g," ), m_userWeights[i] );
00279 
00280       csParameters += csWeight;
00281    }
00282 
00283    CString csType; csType.Format( _T( "%d" ), m_currentFilterType );
00284    csParameters += csType;
00285 
00286    return strcpy( new TCHAR[ csParameters.GetLength() + 1 ], csParameters );
00287 }
00288 
00289 /*
00290  * set parameters for filter-script execution of filter;
00291  * see also CScanFilterNull::SetParameters().
00292  */
00293 BOOL CScanFilterCustom::SetParameters( LPCTSTR lpParameters )
00294 {
00295 //   Q_LOG( _T("CScanFilterCustom::SetParameters()") );
00296 
00297    if ( Q_INVALID( NULL == lpParameters && "CScanFilterShift (SetParameters): parameters expected, none provided (NULL)." ) )
00298    {
00299       return FALSE;
00300    }
00301 
00302    /*
00303     * set defaults, read parameter string:
00304     */
00305    int     nfields = 0;
00306    CString cs( lpParameters );
00307 
00308    for ( int i = 0; i < KernelSize; ++i )
00309    {
00310       double weight = 1.0;
00311 
00312       nfields += _stscanf( cs, _T( "%lg," ), &weight );
00313 
00314       m_userWeights[i] = weight;
00315 
00316       cs.Delete( 0, cs.Find( _T( ',' ) ) + 1 );
00317    }
00318 
00319    if ( Q_INVALID( KernelSize > nfields && "CScanFilterClad (SetParameters): more kernel weights expected." ) )
00320    {
00321       return FALSE;
00322    }
00323 
00324    /*
00325     * read filter type:
00326     */
00327    FilterType type = ftBlur;
00328    nfields = _stscanf( cs, _T( "%d" ), &type );
00329    SetFilterType( type );
00330 
00331    if ( Q_INVALID( 1 > nfields && "CScanFilterClad (SetParameters): filter type expected, got none." ) )
00332    {
00333       return FALSE;
00334    }
00335 
00336    return TRUE;
00337 }
00338 
00339 /**
00340  * set the given filter type.
00341  */
00342 void CScanFilterCustom::SetFilterType( FilterType type )
00343 {
00344    if ( Q_INVALID ( ( ftBlur > type || type > ftUser ) && "ensure valid filter type." ) )
00345    {
00346       return ;
00347    }
00348 
00349    m_currentFilterType = type;
00350 
00351    switch ( type )
00352    {
00353       case ftBlur:
00354          m_currentWeights = m_blurWeights;
00355          break;
00356       case ftLowPass:
00357          m_currentWeights = m_lowpassWeights;
00358          break;
00359       case ftHighPass:
00360          m_currentWeights = m_highpassWeights;
00361          break;
00362       case ftEdge:
00363          m_currentWeights = m_edgeWeights;
00364          break;
00365       case ftPyramidal:
00366          m_currentWeights = m_pyramidalWeights;
00367          break;
00368       case ftCone:
00369          m_currentWeights = m_coneWeights;
00370          break;
00371       case ftGaussian:
00372          m_currentWeights = m_gaussianWeights;
00373          break;
00374       case ftLaplacian:
00375          m_currentWeights = m_laplacianWeights;
00376          break;
00377       case ftSharpening:
00378          m_currentWeights = m_sharpeningWeights;
00379          break;
00380       case ftUser:
00381          m_currentWeights = m_userWeights;
00382          break;
00383    }
00384 }
00385 
00386 /*
00387  * the selected filter name (short).
00388  */
00389 LPCTSTR CScanFilterCustom::GetShortFilterName() const
00390 {
00391    switch( GetFilterType() )
00392    {
00393       case ftBlur: return "Custom-Blur";
00394       case ftLowPass: return "Custom-Low-Pass";
00395       case ftHighPass: return "Custom-High-Pass";
00396       case ftEdge: return "Custom-Edge";
00397       case ftPyramidal: return "Custom-Pyramidal";
00398       case ftCone: return "Custom-Cone";
00399       case ftGaussian: return "Custom-Gaussian";
00400       case ftLaplacian: return "Custom-Laplacian";
00401       case ftSharpening: return "Custom-Sharpening";
00402       case ftUser: return "Custom-User-Defined";
00403       default: return "[unrcognized]";
00404    }
00405 }
00406 
00407 /*
00408  * create filter dialog and pre Apply() filter to view result;
00409  * see also CScanFilterNull::RunModeless().
00410  */
00411 BOOL CScanFilterCustom::RunModeless( CWnd* pParentWnd, CDocument* pDoc )
00412 {
00413 //   Q_LOG( _T("CScanFilterCustom::RunModeless()") );
00414 
00415    CFilterDlg_CustomPtr pDlg = new CFilterDlg_Custom();
00416 
00417    if ( Q_INVALID( NULL == pDlg ) )
00418       return FALSE;
00419 
00420    pDlg->SetParameters( this, pDoc );   // (void) method
00421 
00422    /*
00423     * Create returns non-zero if dialog was created and initialized succesfully.
00424     * Note: no pDlg->DestroyWindow() must be done.
00425     */
00426    pDlg->Create( IDD_FILTERDLG_CUSTOM, pParentWnd );
00427 
00428    m_pDlg = pDlg;
00429 
00430    BOOL bRet = Apply();
00431 
00432    if ( bRet )
00433    {
00434       pDlg->UpdateView();
00435    }
00436 
00437    return bRet;
00438 }
00439 
00440 BOOL CScanFilterCustom::Apply()
00441 {
00442 //   Q_LOG( _T("CScanFilterShift::Apply()") );
00443 
00444    if ( Q_INVALID( NULL == m_lpsbIn && "ensure input buffer") )
00445       return FALSE;
00446 
00447    if ( Q_INVALID( NULL == m_lpsbOut && "ensure output buffer" ) )
00448       return FALSE;
00449 
00450    if ( Q_INVALID( !m_lpsbIn->IsCompleteFrame() && "ensure complete frame" ) )
00451       return FALSE;
00452 
00453    /*
00454     * create output buffer:
00455     */
00456    Q_RETURN( m_lpsbOut->CreateOutputBufferFor( *m_lpsbIn ) );
00457 
00458    m_lpsbOut->m_csBufferName.Format( _T("%s - %s" ), m_lpsbIn->m_csBufferName, GetShortFilterName() );
00459 
00460    if ( IsInteractive() )
00461    {
00462       m_pDlg->SetDlgItemText( IDC_BUFFEROUTNAME, m_lpsbOut->m_csBufferName );
00463    }
00464 
00465    /*
00466     * process first part (L2R):
00467     */
00468    Convolve( FALSE );
00469 
00470    /*
00471     * if we have a double buffer, L2R and R2L, process that part tooo.
00472     */
00473    if ( m_lpsbIn->IsBidirectionalScan() && m_lpsbOut->IsBidirectionalScan() )
00474    {
00475       Convolve( TRUE );
00476    }
00477 
00478    /*
00479     * recalculate all temporary variables:
00480     */
00481    m_lpsbOut->m_dwParameterMask  = 0;
00482 
00483    return TRUE;
00484 }
00485 
00486 /*
00487  * process the frame part at the given offset (L2R, R2L frame part).
00488  */
00489 void CScanFilterCustom::Convolve( BOOL bDoR2L )
00490 {
00491    DWORD dwOffset = bDoR2L ? m_lpsbIn->m_dwSizeX * m_lpsbIn->m_dwSizeY : 0;
00492    DWORD      ptr = dwOffset;
00493 
00494    for ( DWORD y = 0; y < m_lpsbIn->m_dwSizeY; y++ )
00495    {
00496       for ( DWORD x = 0; x < m_lpsbIn->m_dwSizeX; x++ )
00497       {
00498          // loop through 5x5 pixel area
00499          double dDummySum = 0;
00500          double dDummyCount = 0.0;
00501 
00502          for ( int yi = max( 0, (int) y - 2 ); yi < min( (int) m_lpsbIn->m_dwSizeY, (int) y + 3 ); yi++ )
00503          {
00504             for ( int xi = max( 0, (int) x - 2 ); xi < min( (int) m_lpsbIn->m_dwSizeX, (int) x + 3 ); xi++ )
00505             {
00506                int nWeight = (2 + yi - (int)y) * 5 + (2 + xi - (int)x);
00507 
00508                dDummySum += m_currentWeights[ nWeight ] * m_lpsbIn->m_pwData[ dwOffset + yi * m_lpsbIn->m_dwSizeX + xi ];
00509 
00510                dDummyCount += m_currentWeights[ nWeight ];
00511             }
00512          }
00513 
00514          if ( dDummyCount == 0.0 )
00515          {
00516             dDummyCount = 1.0;
00517          }
00518 
00519          m_lpsbOut->m_pwData[ ptr++ ] = (short)( dDummySum / dDummyCount );
00520       }
00521    }
00522 }
00523 
00524 /*
00525  * end of file
00526  */
00527 

Camera Filter Library documentation © 2004-2007 by Leiden Probe Microscopy