00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef KINO_PLUGIN_UTILITY_H
00021 #define KINO_PLUGIN_UTILITY_H
00022
00023 #include <cassert>
00024 #include <deque>
00025 #include <vector>
00026 #include <numeric>
00027
00028 namespace kino
00029 {
00030
00032 template<typename ArgType>
00033 ArgType clamp(const ArgType A, const ArgType MinVal, const ArgType MaxVal)
00034 {
00035 return std::min(std::max(A, MinVal), MaxVal);
00036 }
00037
00039 template<typename ArgType>
00040 inline ArgType lerp(const ArgType A, const ArgType B, const double Mix)
00041 {
00042 return static_cast<ArgType>(A * (1.0 - Mix) + B * Mix);
00043 }
00044
00045 inline double step(const double Edge, const double A)
00046 {
00047 return A < Edge ? 0.0 : 1.0;
00048 }
00049
00050 inline double linearstep(const double Edge1, const double Edge2, const double A)
00051 {
00052 if(A < Edge1)
00053 return 0.0;
00054
00055 if(A >= Edge2)
00056 return 1.0;
00057
00058 return (A - Edge1) / (Edge2 - Edge1);
00059 }
00060
00061 inline double smoothstep(const double Edge1, const double Edge2, const double A)
00062 {
00063 if(A < Edge1)
00064 return 0.0;
00065
00066 if(A >= Edge2)
00067 return 1.0;
00068
00069 double a = (A - Edge1) / (Edge2 - Edge1);
00070
00071 return (a * a * (3 - 2 * a));
00072 }
00073
00074 inline double pulse(const double Edge1, const double Edge2, const double A)
00075 {
00076 return step(Edge1, A) - step(Edge2, A);
00077 }
00078
00079 inline double factorial(const unsigned int X)
00080 {
00081 double result = 1;
00082
00083 for(unsigned int i = 2; i <= X; ++i)
00084 result *= i;
00085
00086 return result;
00087 }
00088
00090 template<typename PixelType>
00091 class convolve_filter
00092 {
00093 public:
00094 convolve_filter() :
00095 m_scale(0)
00096 {
00097 }
00098
00099 void push_weight(const double Weight)
00100 {
00101 m_weights.push_back(Weight);
00102 m_values.resize(m_weights.size());
00103
00104 m_scale = std::accumulate(m_weights.begin(), m_weights.end(), 0.0);
00105 if(m_scale)
00106 m_scale = 1.0 / m_scale;
00107 }
00108
00109 unsigned int width()
00110 {
00111 return m_weights.size();
00112 }
00113
00114 unsigned int neighbors()
00115 {
00116 return m_weights.size() / 2;
00117 }
00118
00119 unsigned int middle()
00120 {
00121 return m_weights.size() / 2;
00122 }
00123
00124 void push_value(const PixelType Value)
00125 {
00126
00127 assert(m_weights.size());
00128 assert(m_weights.size() == m_values.size());
00129
00130 m_values.push_back(Value);
00131 m_values.pop_front();
00132 }
00133
00134 PixelType get_value()
00135 {
00136 PixelType result;
00137
00138 weight_collection_type::const_iterator weight = m_weights.begin();
00139 for(typename value_collection_type::iterator value = m_values.begin(); value != m_values.end(); ++value, ++weight)
00140 {
00141 result.red += (value->red) * (*weight);
00142 result.green += (value->green) * (*weight);
00143 result.blue += (value->blue) * (*weight);
00144 }
00145
00146 result.red *= m_scale;
00147 result.green *= m_scale;
00148 result.blue *= m_scale;
00149
00150 return result;
00151 }
00152
00153 PixelType get_value(const unsigned int Start, const unsigned int End)
00154 {
00155 double scale = std::accumulate(m_weights.begin() + Start, m_weights.begin() + End, 0.0);
00156 if(scale)
00157 scale = 1.0 / scale;
00158
00159 PixelType result;
00160
00161 weight_collection_type::const_iterator weight = m_weights.begin() + Start;
00162 for(typename value_collection_type::iterator value = m_values.begin() + Start; value != m_values.begin() + End; ++value, ++weight)
00163 {
00164 result.red += (value->red) * (*weight);
00165 result.green += (value->green) * (*weight);
00166 result.blue += (value->blue) * (*weight);
00167 }
00168
00169 result.red *= scale;
00170 result.green *= scale;
00171 result.blue *= scale;
00172
00173 return result;
00174 }
00175
00176 private:
00177 typedef std::vector<double> weight_collection_type;
00178 weight_collection_type m_weights;
00179
00180 typedef std::deque<PixelType> value_collection_type;
00181 value_collection_type m_values;
00182
00183 double m_scale;
00184 };
00185
00187 template<typename ResourceType>
00188 class raii
00189 {
00190 public:
00191 raii(ResourceType* const Resource, void (*ReleaseMethod)(ResourceType*)) :
00192 m_resource(Resource),
00193 m_release_method(ReleaseMethod)
00194 {
00195
00196 assert(m_release_method);
00197 }
00198
00199 ~raii()
00200 {
00201 if(m_resource)
00202 (*m_release_method)(m_resource);
00203 }
00204
00205 ResourceType* get() const
00206 {
00207 return m_resource;
00208 }
00209
00210 ResourceType* operator->() const
00211 {
00212 return m_resource;
00213 }
00214
00215 ResourceType& operator*() const
00216 {
00217 return *m_resource;
00218 }
00219
00220 private:
00221 ResourceType* const m_resource;
00222 void (*m_release_method)(ResourceType*);
00223 };
00224
00225 }
00226
00227 #endif // !KINO_PLUGIN_UTILITY_H