"L. Spiro Engine"
|
00001 00017 #ifndef __LSI_RESAMPLER_H__ 00018 #define __LSI_RESAMPLER_H__ 00019 00020 #include "../LSIImageLib.h" 00021 00022 namespace lsi { 00023 00031 class CResampler { 00032 public : 00033 // == Various constructors. 00034 LSE_CALLCTOR CResampler(); 00035 LSE_CALLCTOR ~CResampler(); 00036 00037 00038 // == Enumerations. 00042 enum { 00043 LSI_MAX_SCANLINE = 16384 00044 }; 00045 00046 00047 // == Types. 00051 typedef struct LSI_CONTRIB { 00055 LSFLOAT fWeight; 00056 00060 LSUINT16 ui16Value; 00061 } * LPLSI_CONTRIB, * const LPCLSI_CONTRIB; 00062 00066 typedef struct LSI_CONTRIB_EX { 00070 LSI_CONTRIB * pcValues; 00071 00075 LSUINT32 ui32N; 00076 } * LPLSI_CONTRIB_EX, * const LPCLSI_CONTRIB_EX; 00077 00081 typedef struct LSI_CONTRIB_LIST { 00085 CVectorPoD<LSI_CONTRIB, LSUINT32> vPool; 00086 00090 CVectorPoD<LSI_CONTRIB_EX, LSUINT32> vList; 00091 } * LPLSI_CONTRIB_LIST, * const LPCLSI_CONTRIB_LIST; 00092 00096 typedef struct LSI_SCANLINE { 00100 LSFLOAT * pfScanBufL[LSI_MAX_SCANLINE]; 00101 00105 LSINT32 i32ScanBufY[LSI_MAX_SCANLINE]; 00106 } * LPLSI_SCANLINE, * const LPCLSI_SCANLINE; 00107 00114 typedef LSFLOAT (LSE_CALL * PfFilterFunc)( LSFLOAT _fT ); 00115 00119 typedef struct LSI_FILTER { 00123 const LSCHAR * pcName; 00124 00128 PfFilterFunc pfFunc; 00129 00133 LSFLOAT pfSupport; 00134 } * LPLSI_FILTER, * const LPCLSI_FILTER; 00135 00136 00137 // == Functions. 00155 LSSTD_ERRORS LSE_CALL InitResampler( LSUINT32 _ui32SrcWidth, LSUINT32 _ui32SrcHeight, 00156 LSUINT32 _ui32DstWidth, LSUINT32 _ui32DstHeight, 00157 LSFLOAT _fSampleLow = 0.0f, LSFLOAT _fSampleHi = 1.0f, 00158 const LSCHAR * _pcFilter = "lanczos4", 00159 LSI_CONTRIB_LIST * _pclContX = NULL, 00160 LSI_CONTRIB_LIST * _pclContY = NULL, 00161 LSFLOAT _fFilterScaleX = 1.0f, 00162 LSFLOAT _fFilterScaleY = 1.0f, 00163 CVectorPoD<LSFLOAT, LSUINT32> * _pvDstBuffer = NULL ); 00164 00170 LSI_CONTRIB_LIST * LSE_CALL GetContribX(); 00171 00177 LSI_CONTRIB_LIST * LSE_CALL GetContribY(); 00178 00185 LSBOOL LSE_CALL AddScanLine( const LSFLOAT * _pfScanline ); 00186 00192 const CVectorPoD<LSFLOAT, LSUINT32> * LSE_CALL 00193 GetScanLine(); 00194 00195 00196 protected : 00197 // == Types. 00201 typedef struct LSI_CONTRIB_BOUNDS { 00205 LSFLOAT fCenter; 00206 00210 LSINT32 i32Left; 00211 00215 LSINT32 i32Right; 00216 } * LPLSI_CONTRIB_BOUNDS, * const LPCLSI_CONTRIB_BOUNDS; 00217 00218 // == Members. 00222 LSI_CONTRIB_LIST * m_pclContribsX; 00223 00227 LSI_CONTRIB_LIST * m_pclContribsY; 00228 00232 LSI_FILTER * m_pfFilter; 00233 00237 LSBOOL m_bBorrowedX; 00238 00242 LSBOOL m_bBorrowedY; 00243 00247 LSFLOAT m_fLow; 00248 00252 LSFLOAT m_fHi; 00253 00257 LSUINT32 m_ui32SrcWidth; 00258 00262 LSUINT32 m_ui32SrcHeight; 00263 00267 LSUINT32 m_ui32DstWidth; 00268 00272 LSUINT32 m_ui32DstHeight; 00273 00277 LSUINT32 m_ui32CurSrcY; 00278 00282 LSUINT32 m_ui32CurDstY; 00283 00287 LSUINT32 m_ui32IntermX; 00288 00292 LSBOOL m_bDelayX; 00293 00297 mutable CVectorPoD<LSINT32, LSUINT32> m_vSrcCountY; 00298 00302 mutable CVectorPoD<LSUINT8, LSUINT32> m_vSrcFlagsY; 00303 00307 CVectorPoD<LSFLOAT, LSUINT32> * m_pvDstBuffer; 00308 00312 mutable CVectorPoD<LSFLOAT, LSUINT32> m_vTempBuffer; 00313 00317 LSI_SCANLINE * m_psScanBuffer; 00318 00322 CVectorPoD<LSFLOAT, LSUINT32> m_vScanBufferChunk; 00323 00327 LSUINT32 m_ui32ScanChunkPos; 00328 00332 LSUINT32 m_ui32LastSearchPos; 00333 00337 static LSI_FILTER m_fFilters[]; 00338 00339 00340 // == Functions. 00347 LSVOID LSE_CALL ResampleX( LSFLOAT * _pfDst, const LSFLOAT * _pfSrc ) const; 00348 00354 LSVOID LSE_CALL ResampleY( CVectorPoD<LSFLOAT, LSUINT32> &_vDst ) const; 00355 00364 static LSVOID LSE_CALL ScaleY( CVectorPoD<LSFLOAT, LSUINT32> &_pfDst, const LSFLOAT * _pfSrc, LSFLOAT _fScale, LSUINT32 _ui32Total ); 00365 00374 static LSVOID LSE_CALL ScaleYAdd( CVectorPoD<LSFLOAT, LSUINT32> &_pfDst, const LSFLOAT * _pfSrc, LSFLOAT _fScale, LSUINT32 _ui32Total ); 00375 00384 static LSVOID LSE_CALL ClampSamples( LSFLOAT * _pfSamples, LSUINT32 _ui32Total, LSFLOAT _fLo, LSFLOAT _fHi ); 00385 00396 static LSI_CONTRIB_LIST * CreateContribList( LSUINT32 _ui32SrcSize, LSUINT32 _ui32DstSize, 00397 PfFilterFunc _pfFilter, LSFLOAT _fFilterSupport, LSFLOAT _fFilterScale ); 00398 00406 static LSINT32 LSE_CALL ClampTexel( LSINT32 _i32TexelPos, LSUINT32 _ui32Size ); 00407 00414 static LSUINT32 LSE_CALL CountOps( const LSI_CONTRIB_LIST &_clList ); 00415 00422 static LSE_INLINE LSFLOAT LSE_CALL Clean( LSDOUBLE _dVal ); 00423 00432 static LSE_INLINE LSDOUBLE LSE_CALL KaiserHelper( LSDOUBLE _dAlpha, LSDOUBLE _dHalfWidth, LSDOUBLE _dX ); 00433 00442 static LSE_INLINE LSFLOAT LSE_CALL MitchellFilterHelper( LSFLOAT _fT, LSFLOAT _fB, LSFLOAT _fC ); 00443 00450 static LSE_INLINE LSDOUBLE LSE_CALL Bessel0( LSDOUBLE _dX ); 00451 00458 static LSE_INLINE LSDOUBLE LSE_CALL SinC( LSDOUBLE _dX ); 00459 00466 static LSFLOAT LSE_CALL BoxFilterFunc( LSFLOAT _fT ); 00467 00474 static LSFLOAT LSE_CALL BilinearFilterFunc( LSFLOAT _fT ); 00475 00482 static LSFLOAT LSE_CALL KaiserFilterFunc( LSFLOAT _fT ); 00483 00490 static LSFLOAT LSE_CALL Lanczos3FilterFunc( LSFLOAT _fT ); 00491 00498 static LSFLOAT LSE_CALL Lanczos4FilterFunc( LSFLOAT _fT ); 00499 00506 static LSFLOAT LSE_CALL Lanczos6FilterFunc( LSFLOAT _fT ); 00507 00514 static LSFLOAT LSE_CALL Lanczos8FilterFunc( LSFLOAT _fT ); 00515 00522 static LSFLOAT LSE_CALL Lanczos12FilterFunc( LSFLOAT _fT ); 00523 00530 static LSFLOAT LSE_CALL Lanczos64FilterFunc( LSFLOAT _fT ); 00531 00538 static LSFLOAT LSE_CALL MitchellFilterFunc( LSFLOAT _fT ); 00539 00546 static LSFLOAT LSE_CALL CatmullRomFilterFunc( LSFLOAT _fT ); 00547 }; 00548 00549 00550 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00551 // DEFINITIONS 00552 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00553 // == Functions. 00560 LSE_INLINE LSFLOAT LSE_CALL CResampler::Clean( LSDOUBLE _dVal ) { 00561 static const LSDOUBLE dEps = 0.0000125; 00562 return ::fabs( _dVal ) >= dEps ? static_cast<LSFLOAT>(_dVal) : 0.0f; 00563 } 00564 00573 LSE_INLINE LSDOUBLE LSE_CALL CResampler::KaiserHelper( LSDOUBLE _dAlpha, LSDOUBLE _dHalfWidth, LSDOUBLE _dX ) { 00574 const LSDOUBLE dRatio = _dX / _dHalfWidth; 00575 return Bessel0( _dAlpha * ::sqrt( 1.0 - dRatio * dRatio ) ) / Bessel0( _dAlpha ); 00576 } 00577 00586 LSE_INLINE LSFLOAT LSE_CALL CResampler::MitchellFilterHelper( LSFLOAT _fT, LSFLOAT _fB, LSFLOAT _fC ) { 00587 00588 LSFLOAT fTt = _fT * _fT; 00589 _fT = ::fabsf( _fT ); 00590 if ( _fT < 1.0f ) { 00591 _fT = (((12.0f - 9.0f * _fB - 6.0f * _fC) * (_fT * fTt)) 00592 + ((-18.0f + 12.0f * _fB + 6.0f * _fC) * fTt) 00593 + (6.0f - 2.0f * _fB)); 00594 return _fT / 6.0f; 00595 } 00596 else if ( _fT < 2.0f ) { 00597 _fT = (((-1.0f * _fB - 6.0f * _fC) * (_fT * fTt)) 00598 + ((6.0f * _fB + 30.0f * _fC) * fTt) 00599 + ((-12.0f * _fB - 48.0f * _fC) * _fT) 00600 + (8.0f * _fB + 24.0f * _fC)); 00601 00602 return (_fT / 6.0f); 00603 } 00604 00605 return 0.0f; 00606 } 00607 00614 LSE_INLINE LSDOUBLE LSE_CALL CResampler::Bessel0( LSDOUBLE _dX ) { 00615 static const LSDOUBLE dEspiRatio = 1.0e-16; 00616 LSDOUBLE dSum = 1.0, dPow = 1.0, dDs = 1.0, dXh = _dX * 0.5; 00617 LSUINT32 ui32K = 0; 00618 00619 while ( dDs > dSum * dEspiRatio ) { 00620 ++ui32K; 00621 dPow *= (dXh / ui32K); 00622 dDs = dPow * dPow; 00623 dSum += dDs; 00624 } 00625 00626 return dSum; 00627 } 00628 00635 LSE_INLINE LSDOUBLE LSE_CALL CResampler::SinC( LSDOUBLE _dX ) { 00636 _dX *= LSM_PI_DOUBLE; 00637 if ( _dX < 0.01 && _dX > -0.01 ) { 00638 return 1.0 + _dX * _dX * (-1.0 / 6.0 + _dX * _dX * 1.0 / 120.0); 00639 } 00640 00641 return ::sin( _dX ) / _dX; 00642 } 00643 00644 } // namespace lsi 00645 00646 #endif // __LSI_RESAMPLER_H__