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/ScanFilterCustom.h>
00032 #include <cfl/FilterDlg_Custom.h>
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
00042 LPCTSTR CScanFilterCustom::m_lpcsFilterName = _T("Custom");
00043
00044 LPCTSTR CScanFilterCustom::m_lpcsShortFilterName = CScanFilterCustom::m_lpcsFilterName;
00045
00046 IMPLEMENT_SERIAL( CScanFilterCustom, CScanFilter, CFL_SCHEMAVERSION_FILTERCUSTOM )
00047
00048
00049
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
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
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
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
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
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
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
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
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
00158
00159 CScanFilterCustom::CScanFilterCustom() :
00160 m_currentFilterType( ftBlur )
00161 {
00162
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
00177
00178 CScanFilterCustom::~CScanFilterCustom()
00179 {
00180
00181
00182 ;
00183 }
00184
00185
00186
00187
00188
00189 void CScanFilterCustom::Serialize(CArchive& ar)
00190 {
00191
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
00219
00220
00221 void CScanFilterCustom::ReadFilterSettings()
00222 {
00223
00224
00225 CWinApp* pApp = AfxGetApp();
00226
00227 if ( Q_INVALID( NULL == pApp ) )
00228 return ;
00229
00230
00231
00232
00233 SetParameters( pApp->GetProfileString( gCflRegistrySubkey, m_lpcsFilterName, _T( "" ) ) );
00234 }
00235
00236
00237
00238
00239
00240 void CScanFilterCustom::WriteFilterSettings() const
00241 {
00242
00243
00244 CWinApp* pApp = AfxGetApp();
00245
00246 if ( Q_INVALID( NULL == pApp ) )
00247 return ;
00248
00249
00250
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
00263
00264
00265
00266 LPCTSTR CScanFilterCustom::GetParameters() const
00267 {
00268
00269
00270
00271
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
00291
00292
00293 BOOL CScanFilterCustom::SetParameters( LPCTSTR lpParameters )
00294 {
00295
00296
00297 if ( Q_INVALID( NULL == lpParameters && "CScanFilterShift (SetParameters): parameters expected, none provided (NULL)." ) )
00298 {
00299 return FALSE;
00300 }
00301
00302
00303
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
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
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
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
00409
00410
00411 BOOL CScanFilterCustom::RunModeless( CWnd* pParentWnd, CDocument* pDoc )
00412 {
00413
00414
00415 CFilterDlg_CustomPtr pDlg = new CFilterDlg_Custom();
00416
00417 if ( Q_INVALID( NULL == pDlg ) )
00418 return FALSE;
00419
00420 pDlg->SetParameters( this, pDoc );
00421
00422
00423
00424
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
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
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
00467
00468 Convolve( FALSE );
00469
00470
00471
00472
00473 if ( m_lpsbIn->IsBidirectionalScan() && m_lpsbOut->IsBidirectionalScan() )
00474 {
00475 Convolve( TRUE );
00476 }
00477
00478
00479
00480
00481 m_lpsbOut->m_dwParameterMask = 0;
00482
00483 return TRUE;
00484 }
00485
00486
00487
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
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
00526
00527