IM: im_math.h Source File
From IM - An Imaging Tool
im_math.h
Go to the documentation of this file.00001 /** \file 00002 * \brief Math Utilities 00003 * 00004 * See Copyright Notice in im_lib.h 00005 */ 00006 00007 #ifndef __IM_MATH_H 00008 #define __IM_MATH_H 00009 00010 #include <math.h> 00011 #include "im_util.h" 00012 00013 #ifdef IM_DEFMATHFLOAT 00014 inline float acosf(float _X) {return ((float)acos((double)_X)); } 00015 inline float asinf(float _X) {return ((float)asin((double)_X)); } 00016 inline float atanf(float _X) {return ((float)atan((double)_X)); } 00017 inline float atan2f(float _X, float _Y) {return ((float)atan2((double)_X, (double)_Y)); } 00018 inline float ceilf(float _X) {return ((float)ceil((double)_X)); } 00019 inline float cosf(float _X) {return ((float)cos((double)_X)); } 00020 inline float coshf(float _X) {return ((float)cosh((double)_X)); } 00021 inline float expf(float _X) {return ((float)exp((double)_X)); } 00022 inline float fabsf(float _X) {return ((float)fabs((double)_X)); } 00023 inline float floorf(float _X) {return ((float)floor((double)_X)); } 00024 inline float fmodf(float _X, float _Y) {return ((float)fmod((double)_X, (double)_Y)); } 00025 inline float logf(float _X) {return ((float)log((double)_X)); } 00026 inline float log10f(float _X) {return ((float)log10((double)_X)); } 00027 inline float powf(float _X, float _Y) {return ((float)pow((double)_X, (double)_Y)); } 00028 inline float sinf(float _X) {return ((float)sin((double)_X)); } 00029 inline float sinhf(float _X) {return ((float)sinh((double)_X)); } 00030 inline float sqrtf(float _X) {return ((float)sqrt((double)_X)); } 00031 inline float tanf(float _X) {return ((float)tan((double)_X)); } 00032 inline float tanhf(float _X) {return ((float)tanh((double)_X)); } 00033 #endif 00034 00035 /** \defgroup math Math Utilities 00036 * \par 00037 * See \ref im_color.h 00038 * \ingroup util */ 00039 00040 00041 /** Does Zero Order Decimation (Mean). 00042 * \ingroup math */ 00043 template <class T, class TU> 00044 inline T imZeroOrderDecimation(int width, int height, T *map, float xl, float yl, float box_width, float box_height, TU Dummy) 00045 { 00046 int x0,x1,y0,y1; 00047 (void)Dummy; 00048 00049 x0 = (int)floor(xl - box_width/2.0 - 0.5) + 1; 00050 y0 = (int)floor(yl - box_height/2.0 - 0.5) + 1; 00051 x1 = (int)floor(xl + box_width/2.0 - 0.5); 00052 y1 = (int)floor(yl + box_height/2.0 - 0.5); 00053 00054 if (x0 == x1) x1++; 00055 if (y0 == y1) y1++; 00056 00057 x0 = x0<0? 0: x0>width-1? width-1: x0; 00058 y0 = y0<0? 0: y0>height-1? height-1: y0; 00059 x1 = x1<0? 0: x1>width-1? width-1: x1; 00060 y1 = y1<0? 0: y1>height-1? height-1: y1; 00061 00062 TU Value; 00063 int Count = 0; 00064 00065 Value = 0; 00066 00067 for (int y = y0; y <= y1; y++) 00068 { 00069 for (int x = x0; x <= x1; x++) 00070 { 00071 Value += map[y*width+x]; 00072 Count++; 00073 } 00074 } 00075 00076 if (Count == 0) 00077 { 00078 Value = 0; 00079 return (T)Value; 00080 } 00081 00082 return (T)(Value/(float)Count); 00083 } 00084 00085 /** Does Bilinear Decimation. 00086 * \ingroup math */ 00087 template <class T, class TU> 00088 inline T imBilinearDecimation(int width, int height, T *map, float xl, float yl, float box_width, float box_height, TU Dummy) 00089 { 00090 int x0,x1,y0,y1; 00091 (void)Dummy; 00092 00093 x0 = (int)floor(xl - box_width/2.0 - 0.5) + 1; 00094 y0 = (int)floor(yl - box_height/2.0 - 0.5) + 1; 00095 x1 = (int)floor(xl + box_width/2.0 - 0.5); 00096 y1 = (int)floor(yl + box_height/2.0 - 0.5); 00097 00098 if (x0 == x1) x1++; 00099 if (y0 == y1) y1++; 00100 00101 x0 = x0<0? 0: x0>width-1? width-1: x0; 00102 y0 = y0<0? 0: y0>height-1? height-1: y0; 00103 x1 = x1<0? 0: x1>width-1? width-1: x1; 00104 y1 = y1<0? 0: y1>height-1? height-1: y1; 00105 00106 TU Value, LineValue; 00107 float LineNorm, Norm, dxr, dyr; 00108 00109 Value = 0; 00110 Norm = 0; 00111 00112 for (int y = y0; y <= y1; y++) 00113 { 00114 dyr = yl - (y+0.5f); 00115 if (dyr < 0) dyr *= -1; 00116 00117 LineValue = 0; 00118 LineNorm = 0; 00119 00120 for (int x = x0; x <= x1; x++) 00121 { 00122 dxr = xl - (x+0.5f); 00123 if (dxr < 0) dxr *= -1; 00124 00125 LineValue += map[y*width+x] * dxr; 00126 LineNorm += dxr; 00127 } 00128 00129 Value += LineValue * dyr; 00130 Norm += dyr * LineNorm; 00131 } 00132 00133 if (Norm == 0) 00134 { 00135 Value = 0; 00136 return (T)Value; 00137 } 00138 00139 return (T)(Value/Norm); 00140 } 00141 00142 /** Does Zero Order Interpolation (Nearest Neighborhood). 00143 * \ingroup math */ 00144 template <class T> 00145 inline T imZeroOrderInterpolation(int width, int height, T *map, float xl, float yl) 00146 { 00147 int x0 = (int)(xl-0.5f); 00148 int y0 = (int)(yl-0.5f); 00149 x0 = x0<0? 0: x0>width-1? width-1: x0; 00150 y0 = y0<0? 0: y0>height-1? height-1: y0; 00151 return map[y0*width + x0]; 00152 } 00153 00154 /** Does Bilinear Interpolation. 00155 * \ingroup math */ 00156 template <class T> 00157 inline T imBilinearInterpolation(int width, int height, T *map, float xl, float yl) 00158 { 00159 int x0, y0, x1, y1; 00160 float t, u; 00161 00162 if (xl < 0.5) 00163 { 00164 x1 = x0 = 0; 00165 t = 0; 00166 } 00167 else if (xl > width-0.5) 00168 { 00169 x1 = x0 = width-1; 00170 t = 0; 00171 } 00172 else 00173 { 00174 x0 = (int)(xl-0.5f); 00175 x1 = x0+1; 00176 t = xl - (x0+0.5f); 00177 } 00178 00179 if (yl < 0.5) 00180 { 00181 y1 = y0 = 0; 00182 u = 0; 00183 } 00184 else if (yl > height-0.5) 00185 { 00186 y1 = y0 = height-1; 00187 u = 0; 00188 } 00189 else 00190 { 00191 y0 = (int)(yl-0.5f); 00192 y1 = y0+1; 00193 u = yl - (y0+0.5f); 00194 } 00195 00196 T fll = map[y0*width + x0]; 00197 T fhl = map[y0*width + x1]; 00198 T flh = map[y1*width + x0]; 00199 T fhh = map[y1*width + x1]; 00200 00201 return (T)((fhh - flh - fhl + fll) * u * t + 00202 (fhl - fll) * t + 00203 (flh - fll) * u + 00204 fll); 00205 } 00206 00207 /** Does Bicubic Interpolation. 00208 * \ingroup math */ 00209 template <class T, class TU> 00210 inline T imBicubicInterpolation(int width, int height, T *map, float xl, float yl, TU Dummy) 00211 { 00212 int x0, y0, x1, y1, x2, y2; 00213 float t, u; 00214 (void)Dummy; 00215 00216 if (xl < 0.5) 00217 { 00218 x2 = x1 = x0 = 0; 00219 t = 0; 00220 } 00221 else if (xl > width-0.5) 00222 { 00223 x2 = x1 = x0 = width-1; 00224 t = 0; 00225 } 00226 else 00227 { 00228 x0 = (int)(xl-0.5f); 00229 x1 = x0-1; 00230 if (x1 < 0) x1 = 0; 00231 x2 = x0+2; // 4 pixels (-1 0 +1 +2) 00232 if (x2 > width-1) x2 = width-1; 00233 t = xl - (x0+0.5f); 00234 } 00235 00236 if (yl < 0.5) 00237 { 00238 y2 = y1 = y0 = 0; 00239 u = 0; 00240 } 00241 else if (yl > height-0.5) 00242 { 00243 y2 = y1 = y0 = height-1; 00244 u = 0; 00245 } 00246 else 00247 { 00248 y0 = (int)(yl-0.5f); 00249 y1 = y0-1; 00250 if (y1 < 0) y1 = 0; 00251 y2 = y0+2; // 4 pixels (-1 0 +1 +2) 00252 if (y2 > height-1) y2 = height-1; 00253 u = yl - (y0+0.5f); 00254 } 00255 00256 float CX[4], CY[4]; 00257 00258 // Optimize calculations 00259 { 00260 float x, x2, x3; 00261 00262 #define C0 (-x3 + 2.0f*x2 - x) 00263 #define C1 ( x3 - 2.0f*x2 + 1.0f) 00264 #define C2 (-x3 + x2 + x) 00265 #define C3 ( x3 - x2) 00266 00267 x = t; 00268 x2 = x*x; x3 = x2*x; 00269 CX[0] = C0; CX[1] = C1; CX[2] = C2; CX[3] = C3; 00270 00271 x = u; 00272 x2 = x*x; x3 = x2*x; 00273 CY[0] = C0; CY[1] = C1; CY[2] = C2; CY[3] = C3; 00274 00275 #undef C0 00276 #undef C1 00277 #undef C2 00278 #undef C3 00279 } 00280 00281 TU LineValue, Value; 00282 float LineNorm, Norm; 00283 00284 Value = 0; 00285 Norm = 0; 00286 00287 for (int y = y1; y <= y2; y++) 00288 { 00289 LineValue = 0; 00290 LineNorm = 0; 00291 00292 for (int x = x1; x <= x2; x++) 00293 { 00294 LineValue += map[y*width+x] * CX[x-x1]; 00295 LineNorm += CX[x-x1]; 00296 } 00297 00298 Value += LineValue * CY[y-y1]; 00299 Norm += CY[y-y1] * LineNorm; 00300 } 00301 00302 if (Norm == 0) 00303 { 00304 Value = 0; 00305 return (T)Value; 00306 } 00307 00308 Value = (Value/Norm); 00309 00310 int size = sizeof(T); 00311 if (size == 1) 00312 return (T)(Value<=(TU)0? (TU)0: Value<=(TU)255? Value: (TU)255); 00313 else 00314 return (T)(Value); 00315 } 00316 00317 /** Calculates minimum and maximum values. 00318 * \ingroup math */ 00319 template <class T> 00320 inline void imMinMax(const T *map, int count, T& min, T& max) 00321 { 00322 min = *map++; 00323 max = min; 00324 for (int i = 1; i < count; i++) 00325 { 00326 T value = *map++; 00327 00328 if (value > max) 00329 max = value; 00330 else if (value < min) 00331 min = value; 00332 } 00333 } 00334 00335 #endif