00001 /* 00002 Copyright (c) 2010, The Barbarian Group 00003 All rights reserved. 00004 00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that 00006 the following conditions are met: 00007 00008 * Redistributions of source code must retain the above copyright notice, this list of conditions and 00009 the following disclaimer. 00010 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 00011 the following disclaimer in the documentation and/or other materials provided with the distribution. 00012 00013 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 00014 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00015 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00016 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00017 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00018 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00019 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00020 POSSIBILITY OF SUCH DAMAGE. 00021 */ 00022 00023 #pragma once 00024 00025 #include "cinder/CinderMath.h" 00026 00027 namespace cinder { 00028 00029 class FilterBase { 00030 public: 00031 FilterBase( float aSupport ) : mSupport( aSupport ) {} 00032 virtual ~FilterBase() {}; 00033 00034 float getSupport() const { return mSupport; } 00035 void setSupport( float aSupport ) { mSupport = aSupport; } 00036 00037 virtual float operator()( float x ) const = 0; 00038 protected: 00039 float mSupport; 00040 }; 00041 00042 // box, pulse, nearest-neighbor, Fourier window, 1st order (constant) b-spline 00043 class FilterBox : public FilterBase { 00044 public: 00045 FilterBox( float aSupport = 0.5f ) : FilterBase( aSupport ) {} 00046 00047 virtual float operator()( float x ) const { 00048 if ( x < -0.5f ) return 0.0f; 00049 else if ( x < 0.5f ) return 1.0f; 00050 return 0.0f; 00051 } 00052 }; 00053 00054 // triangle, Bartlett window, 2nd order (linear) b-spline 00055 class FilterTriangle : public FilterBase { 00056 public: 00057 FilterTriangle( float aSupport = 1.0f ) : FilterBase( aSupport ) {} 00058 00059 virtual float operator()( float x ) const { 00060 if ( x < -1.0f ) return 0.0f; 00061 else if ( x < 0.0f ) return 1.0f + x; 00062 else if ( x < 1.0f ) return 1.0f - x; 00063 return 0.0f; 00064 } 00065 }; 00066 00067 // 3rd order (quadratic) b-spline 00068 class FilterQuadratic : public FilterBase { 00069 public: 00070 FilterQuadratic( float aSupport = 1.5f ) : FilterBase( aSupport ) {} 00071 00072 virtual float operator()( float x ) const { 00073 float t; 00074 00075 if ( x < -1.5f ) return 0.0f; 00076 else if ( x < -0.5f ) { t = x + 1.5f; return 0.5f * t * t; } 00077 else if ( x < 0.5f ) return 0.75f - x * x; 00078 else if ( x < 1.5f ) { t = x - 1.5f; return 0.5f * t * t; } 00079 return 0.0f; 00080 } 00081 }; 00082 00083 // 4th order (cubic) b-spline 00084 class FilterCubic : public FilterBase { 00085 public: 00086 FilterCubic( float aSupport = 2.0f ) : FilterBase( aSupport ) {} 00087 00088 virtual float operator()( float x ) const { 00089 float t; 00090 00091 if ( x < -2.0f ) return 0.0f; 00092 else if ( x < -1.0f ) { t = 2.0f + x; return t * t * t / 6.0f; } 00093 else if ( x < 0.0f ) return ( 4.0f + x * x * ( -6.0f + x * -3.0f ) ) / 6.0f; 00094 else if ( x < 1.0f ) return ( 4.0f + x * x * ( -6.0f + x * 3.0f ) ) / 6.0f; 00095 else if ( x < 2.0f ) { t = 2.0f - x; return t * t * t / 6.0f; } 00096 return 0.0f; 00097 } 00098 }; 00099 00100 // Catmull-Rom spline, Overhauser spline 00101 class FilterCatmullRom : public FilterBase { 00102 public: 00103 FilterCatmullRom( float aSupport = 2.0f ) : FilterBase( aSupport ) {} 00104 00105 virtual float operator()( float x ) const { 00106 if ( x < -2.0f ) return 0.0f; 00107 else if ( x < -1.0f ) return 0.5f * ( 4.0f + x * ( 8.0f + x * ( 5.0f + x ) ) ); 00108 else if ( x < 0.0f ) return 0.5f * ( 2.0f + x * x * ( -5.0f + x * -3.0f ) ); 00109 else if ( x < 1.0f ) return 0.5f * ( 2.0f + x * x * ( -5.0f + x * 3.0f ) ); 00110 else if ( x < 2.0f ) return 0.5f * ( 4.0f + x * ( -8.0f + x * ( 5.0f - x ) ) ); 00111 return 0.0f; 00112 } 00113 }; 00114 00115 // Mitchell & Netravali's two-parameter cubic 00116 // see Mitchell&Netravali, "Reconstruction Filters in Computer Graphics", SIGGRAPH 88 00117 class FilterMitchell : public FilterBase { 00118 public: 00119 FilterMitchell( float aSupport = 2.0f, float b = 0.3333333333f, float c = 0.3333333333f ) : FilterBase( aSupport ) { 00120 mP0 = ( 6.0f - 2.0f * b ) / 6.0f; 00121 mP2 = ( -18.0f + 12.0f * b + 6.0f * c ) / 6.0f; 00122 mP3 = ( 12.0f - 9.0f * b - 6.0f * c ) / 6.0f; 00123 mQ0 = ( 8.0f * b + 24.0f * c ) / 6.0f; 00124 mQ1 = ( - 12.0f * b - 48.0f * c ) / 6.0f; 00125 mQ2 = ( 6.0f * b + 30.0f * c ) / 6.0f; 00126 mQ3 = ( -b - 6.0f * c ) / 6.0f; 00127 } 00128 00129 virtual float operator()( float x ) const { 00130 if ( x < -2.0f ) return 0.; 00131 else if ( x < -1.0f ) return mQ0 - x * ( mQ1 - x * ( mQ2 - x * mQ3 ) ); 00132 else if ( x < 0.0f ) return mP0 + x * x * ( mP2 - x * mP3 ); 00133 else if ( x < 1.0f ) return mP0 + x * x * ( mP2 + x * mP3 ); 00134 else if ( x < 2.0f ) return mQ0 + x * ( mQ1 + x * ( mQ2 + x * mQ3 ) ); 00135 return 0.0f; 00136 } 00137 00138 private: 00139 float mQ0, mQ1, mQ2, mQ3; 00140 float mP0, mP2, mP3; 00141 }; 00142 00143 // sinc filter, windowed by blackman 00144 class FilterSincBlackman : public FilterBase { 00145 public: 00146 FilterSincBlackman( float aSupport = 4.0f ) : FilterBase( aSupport ) {} 00147 00148 virtual float operator()( float x ) const { 00149 float v( ( x == 0.0f ) ? 1.0f : math<float>::sin( 3.14159265358979323846f * x ) / ( 3.14159265358979323846f * x ) ); 00150 // blackman 00151 x /= mSupport; 00152 return v * ( 0.42f + 0.50f * math<float>::cos( 3.14159265358979323846f * x ) + 0.08f * math<float>::cos( 6.2831853071795862f * x ) ); 00153 } 00154 }; 00155 00156 // sinc filter, windowed by blackman 00157 class FilterGaussian : public FilterBase { 00158 public: 00159 FilterGaussian( float aSupport = 1.25f ) : FilterBase( aSupport ) {} 00160 00161 virtual float operator()( float x ) const { 00162 return ( math<float>::exp( -2.0f * x * x ) * math<float>::sqrt( 2.0f / 3.14159265358979323846f ) ); 00163 } 00164 }; 00165 00166 #if ! defined( CINDER_COCOA_TOUCH ) 00167 class FilterBesselBlackman : public FilterBase { 00168 public: 00169 FilterBesselBlackman( float aSupport = 3.2383f ) : FilterBase( aSupport ) {} 00170 00171 virtual float operator()( float x ) const { 00172 #if defined (CINDER_MSW) 00173 // According to VS.Net 2K5, j1 was depcreated, use _j1 instead. 00174 float v( ( x == 0.0f ) ? ( 3.14159265358979323846f / 4.0f ) : static_cast<float>( _j1( 3.14159265358979323846f * x ) ) / ( 2.0f * x ) ); 00175 #else 00176 float v( ( x == 0.0f ) ? ( 3.14159265358979323846f / 4.0f ) : static_cast<float>( j1( 3.14159265358979323846f * x ) ) / ( 2.0f * x ) ); 00177 #endif 00178 // always bet on blackman 00179 x /= mSupport; 00180 return v * ( 0.42f + 0.50f * math<float>::cos( 3.14159265358979323846f * x ) + 0.08f * math<float>::cos( 6.2831853071795862f * x ) ); 00181 } 00182 }; 00183 #endif 00184 00185 } // namespace cinder