00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "stdafx.h"
00026
00027 #include <cfl/resource.h>
00028
00029 #include <Camera/InterfaceDll.h>
00030
00031 #include <cfl/ScanFilterLowPass.h>
00032 #include <cfl/FilterDlg_LowPass.h>
00033
00034 #pragma warning( disable: 4018 4100 4116 4146 4244 4663)
00035 #include <cil/Math.h>
00036 #pragma warning( default: 4018 4100 4116 4146 4244 4663)
00037
00038 #undef min // use lpm::min instead of macro
00039 #undef max // use lpm::max instead of macro
00040
00041 #ifdef _DEBUG
00042 #undef THIS_FILE
00043 static char THIS_FILE[]=__FILE__;
00044 #define new DEBUG_NEW
00045 #endif
00046
00047 #define CFL_SCHEMAVERSION_FILTERLOWPASS 0 // permanent storage schema version
00048
00049 LPCTSTR CScanFilterLowPass::m_lpcsFilterName = _T("Low-Pass");
00050
00051 LPCTSTR CScanFilterLowPass::m_lpcsShortFilterName = _T( "LP" );
00052
00053 IMPLEMENT_SERIAL( CScanFilterLowPass, CScanFilterFourierBase, CFL_SCHEMAVERSION_FILTERLOWPASS )
00054
00055
00056
00057
00058 const CScanFilterLowPass::RealType CScanFilterLowPass::def_dCutOff = 0.75;
00059
00060
00061
00062
00063 const CScanFilterLowPass::RealType CScanFilterLowPass::def_dSoftEdge = 0.05;
00064
00065
00066
00067
00068 CScanFilterLowPass::CScanFilterLowPass() :
00069 m_dCutOff ( def_dCutOff ),
00070 m_dSoftEdge ( def_dSoftEdge )
00071 {
00072
00073
00074 m_csFilterName = m_lpcsFilterName;
00075
00076 ReadFilterSettings();
00077 }
00078
00079
00080
00081
00082 CScanFilterLowPass::~CScanFilterLowPass()
00083 {
00084
00085 }
00086
00087
00088
00089
00090
00091 void CScanFilterLowPass::Serialize(CArchive& ar)
00092 {
00093
00094
00095 CScanFilterFourierBase::Serialize( ar );
00096
00097 if ( ar.IsStoring() )
00098 {
00099 ar << m_dCutOff << m_dSoftEdge;
00100 }
00101 else
00102 {
00103 ar >> m_dCutOff >> m_dSoftEdge;
00104 }
00105 }
00106
00107
00108
00109
00110
00111 void CScanFilterLowPass::ReadFilterSettings( )
00112 {
00113
00114
00115 CWinApp* pApp = AfxGetApp();
00116
00117 if ( Q_INVALID( NULL == pApp ) )
00118 return ;
00119
00120
00121
00122
00123 SetParameters( pApp->GetProfileString( gCflRegistrySubkey, m_lpcsFilterName, _T( "0.75,0.05" ) ) );
00124 }
00125
00126
00127
00128
00129
00130 void CScanFilterLowPass::WriteFilterSettings() const
00131 {
00132
00133
00134 CWinApp* pApp = AfxGetApp();
00135
00136 if ( Q_INVALID( NULL == pApp ) )
00137 return ;
00138
00139
00140
00141
00142 LPCTSTR pStr = GetParameters();
00143
00144 if ( pStr )
00145 {
00146 pApp->WriteProfileString( gCflRegistrySubkey, m_lpcsFilterName, pStr );
00147 delete const_cast<LPTSTR>( pStr );
00148 }
00149 }
00150
00151
00152
00153
00154
00155
00156 LPCTSTR CScanFilterLowPass::GetParameters( ) const
00157 {
00158
00159
00160
00161
00162
00163 CString csParameters;
00164
00165 csParameters.Format( _T("%.2lf,%.2lf"), m_dCutOff, m_dSoftEdge );
00166
00167 return strcpy( new TCHAR[ csParameters.GetLength() + 1 ], csParameters );
00168 }
00169
00170
00171
00172
00173 BOOL CScanFilterLowPass::SetParameters( LPCTSTR lpParameters )
00174 {
00175
00176
00177 if ( Q_INVALID( NULL == lpParameters && "CScanFilterLowPass (SetParameters): parameters expected, none provided (NULL)." ) )
00178 {
00179 return FALSE;
00180 }
00181
00182
00183
00184
00185 m_dCutOff = 0.0;
00186 m_dSoftEdge = 0.0;
00187
00188 int nfields = _stscanf( lpParameters, _T( "%lf,%lf" ), &m_dCutOff, &m_dSoftEdge );
00189
00190 if ( Q_INVALID( 2 > nfields && "CScanFilterLowPass (SetParameters): cutoff and softedge expected, got fewer." ) )
00191 {
00192 return FALSE;
00193 }
00194
00195 if ( Q_INVALID( ( m_dCutOff < 0.0 || m_dCutOff > 10.0 ) && "CScanFilterLowPass: invalid cutoff value." ) )
00196 {
00197 return FALSE;
00198 }
00199
00200 if ( Q_INVALID( ( m_dSoftEdge < 0.0 || m_dSoftEdge > 10.0 ) && "CScanFilterLowPass: invalid softedge value." ) )
00201 {
00202 return FALSE;
00203 }
00204
00205 return TRUE;
00206 }
00207
00208
00209
00210
00211
00212 BOOL CScanFilterLowPass::RunModeless( CWnd* pParentWnd, CDocument* pDoc )
00213 {
00214
00215
00216 CFilterDlg_LowPassPtr pDlg = new CFilterDlg_LowPass();
00217
00218 if ( Q_INVALID( NULL == pDlg ) )
00219 return FALSE;
00220
00221 pDlg->SetParameters( this, pDoc );
00222
00223
00224
00225
00226
00227 pDlg->Create( IDD_FILTERDLG_LOWPASS, pParentWnd );
00228
00229 m_pDlg = pDlg;
00230
00231
00232
00233
00234 BOOL bRet = Apply();
00235
00236 if ( bRet )
00237 {
00238 pDlg->UpdateView();
00239 }
00240
00241 return bRet;
00242 }
00243
00244
00245
00246
00247
00248
00249 BOOL CScanFilterLowPass::Apply()
00250 {
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261 if ( Q_INVALID( NULL == m_lpsbIn && "ensure input buffer") )
00262 return FALSE;
00263
00264 if ( Q_INVALID( NULL == m_lpsbOut && "ensure output buffer" ) )
00265 return FALSE;
00266
00267 if ( Q_INVALID( !m_lpsbIn->IsCompleteFrame() && "ensure complete frame" ) )
00268 return FALSE;
00269
00270
00271
00272
00273 Q_RETURN( m_lpsbOut->CreateOutputBufferFor( *m_lpsbIn ) );
00274
00275 m_lpsbOut->m_csBufferName = m_lpsbIn->m_csBufferName + _T(" - ") + m_lpcsShortFilterName;
00276
00277 if ( IsInteractive() )
00278 {
00279 m_pDlg->SetDlgItemText( IDC_BUFFEROUTNAME, m_lpsbOut->m_csBufferName );
00280 }
00281
00282
00283
00284
00285
00286 CProgressDlg dlg( IsInteractive() ? m_pDlg : AfxGetMainWnd() );
00287
00288 ThreadArgs threadArgs( &dlg, this );
00289
00290 CWinThread *hThread = AfxBeginThread(
00291 ComputationThreadFunction,
00292 &threadArgs,
00293 THREAD_PRIORITY_BELOW_NORMAL,
00294 0,
00295
00296 CREATE_SUSPENDED,
00297 NULL
00298 );
00299
00300
00301
00302
00303 if ( dlg.DoModal( hThread ) <= 0 )
00304 {
00305 return FALSE;
00306 };
00307
00308
00309
00310
00311 return threadArgs.bReturn;
00312 }
00313
00314
00315
00316
00317 UINT CScanFilterLowPass::ComputationThreadFunction(LPVOID lpContext)
00318 {
00319
00320
00321 CScanFilterLowPass::ThreadArgs *lpTreadArgs = static_cast< CScanFilterLowPass::ThreadArgs* >( lpContext );
00322
00323 lpTreadArgs->bReturn = lpTreadArgs->pThis->Compute( lpTreadArgs->pDlg );
00324
00325 lpTreadArgs->pDlg->Terminate();
00326
00327 return lpTreadArgs->bReturn;
00328 }
00329
00330
00331
00332
00333 BOOL CScanFilterLowPass::Compute( CProgressDlg *pDlg )
00334 {
00335
00336
00337
00338
00339
00340 BOOL bL2R = m_lpsbIn->HasLeftToRightScan();
00341 BOOL bR2L = m_lpsbIn->HasRightToLeftScan();
00342
00343
00344
00345
00346 pDlg->SetText(_T("Computing 2D low-pass"));
00347 pDlg->SetRange( 0, bR2L && bL2R ? 4 : 3 );
00348
00349
00350
00351
00352 if ( bL2R && 0 == m_lpsbIn->m_pdFourierL2R ||
00353 bR2L && 0 == m_lpsbIn->m_pdFourierR2L )
00354 {
00355 MessageBox(
00356 IsInteractive() ? m_pDlg->m_hWnd : AfxGetMainWnd()->m_hWnd,
00357 _T( "This scanbuffer does not contain a fourier spectrum." ),
00358 _T( "Cannot transform" ),
00359 MB_ICONEXCLAMATION | MB_OK
00360 );
00361
00362 return FALSE;
00363 }
00364
00365
00366
00367
00368
00369
00370
00371
00372 Q_RETURN( m_lpsbOut->CreateFourierBuffer() );
00373
00374
00375
00376
00377 int progress = 0;
00378
00379
00380
00381
00382 if ( bL2R )
00383 {
00384 ComputePart( m_lpsbIn->FourierDataL2R(), m_lpsbOut->FourierDataL2R() );
00385
00386 pDlg->SetPos( ++progress );
00387 }
00388
00389
00390
00391
00392 if ( bR2L )
00393 {
00394 ComputePart( m_lpsbIn->FourierDataR2L(), m_lpsbOut->FourierDataR2L() );
00395
00396 pDlg->SetPos( ++progress );
00397 }
00398
00399
00400
00401
00402 const int& nrow = m_lpsbOut->Rows();
00403 const int& ncol = m_lpsbOut->Columns();
00404
00405 RealType *dAmpBuffer = new RealType[ nrow * ncol * 2 ];
00406
00407 RealType dMax = CScanFilterFourierBase::BuildTmpAmpBuffer(
00408 nrow, ncol, bL2R, bR2L, m_lpsbOut->FourierDataL2R(), m_lpsbOut->FourierDataR2L(), dAmpBuffer );
00409
00410 pDlg->SetPos( ++progress );
00411
00412 CScanFilterFourierBase::CopyAmpBufferToScanBuffer( nrow, ncol, bL2R, bR2L, dAmpBuffer, dMax );
00413
00414 pDlg->SetPos( ++progress );
00415
00416 delete dAmpBuffer;
00417
00418
00419
00420
00421 if ( pDlg->StopRequested() )
00422 {
00423 return FALSE;
00424 }
00425 else
00426 {
00427 return TRUE;
00428 }
00429 }
00430
00431
00432
00433
00434 void CScanFilterLowPass::ComputePart( FourierElementType** in, FourierElementType** out )
00435 {
00436
00437
00438
00439 SizeType nrow = m_lpsbOut->GetRowsForFFT();
00440 SizeType ncol = m_lpsbOut->GetColumnsForFFT();
00441
00442 for ( SizeType y = 0; y < nrow / 2; ++y )
00443 {
00444 for ( SizeType x = 0; x < ncol / 2; ++x )
00445 {
00446 SizeType xi = 2 * x;
00447
00448
00449
00450
00451
00452
00453
00454 RealType dDistance = lpm::sqrt( lpm::sqr( 2.0 * x / ncol ) + lpm::sqr( 2.0 * y / nrow ) );
00455
00456 RealType dScale = ( dDistance < ( m_dCutOff - m_dSoftEdge ) ? 1.0 :
00457 ( dDistance > ( m_dCutOff + m_dSoftEdge ) ? 0.0 :
00458 0.5 * ( 1.0 - lpm::sin( lpm::Pi * ( dDistance - m_dCutOff ) / ( 2.0 * m_dSoftEdge ) ) ) ) );
00459
00460 out[ y ][ xi ] = dScale * in[ y ][ xi ];
00461 out[ y ][ xi + 1] = dScale * in[ y ][ xi + 1];
00462 out[nrow - y - 1][ xi ] = dScale * in[nrow - y - 1][ xi ];
00463 out[nrow - y - 1][ xi + 1] = dScale * in[nrow - y - 1][ xi + 1];
00464 out[ y ][2 * ncol - xi - 2] = dScale * in[ y ][2 * ncol - xi - 2];
00465 out[ y ][2 * ncol - xi - 1] = dScale * in[ y ][2 * ncol - xi - 1];
00466 out[nrow - y - 1][2 * ncol - xi - 2] = dScale * in[nrow - y - 1][2 * ncol - xi - 2];
00467 out[nrow - y - 1][2 * ncol - xi - 1] = dScale * in[nrow - y - 1][2 * ncol - xi - 1];
00468 }
00469 }
00470 }
00471
00472
00473
00474
00475