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