/** \file * \brief Math Utilities * * See Copyright Notice in im_lib.h * $Id: Exp $ */ #ifndef __IM_MATH_H #define __IM_MATH_H #include #include "im_util.h" #ifdef IM_DEFMATHFLOAT inline float acosf(float _X) {return ((float)acos((double)_X)); } inline float asinf(float _X) {return ((float)asin((double)_X)); } inline float atanf(float _X) {return ((float)atan((double)_X)); } inline float atan2f(float _X, float _Y) {return ((float)atan2((double)_X, (double)_Y)); } inline float ceilf(float _X) {return ((float)ceil((double)_X)); } inline float cosf(float _X) {return ((float)cos((double)_X)); } inline float coshf(float _X) {return ((float)cosh((double)_X)); } inline float expf(float _X) {return ((float)exp((double)_X)); } inline float fabsf(float _X) {return ((float)fabs((double)_X)); } inline float floorf(float _X) {return ((float)floor((double)_X)); } inline float fmodf(float _X, float _Y) {return ((float)fmod((double)_X, (double)_Y)); } inline float logf(float _X) {return ((float)log((double)_X)); } inline float log10f(float _X) {return ((float)log10((double)_X)); } inline float powf(float _X, float _Y) {return ((float)pow((double)_X, (double)_Y)); } inline float sinf(float _X) {return ((float)sin((double)_X)); } inline float sinhf(float _X) {return ((float)sinh((double)_X)); } inline float sqrtf(float _X) {return ((float)sqrt((double)_X)); } inline float tanf(float _X) {return ((float)tan((double)_X)); } inline float tanhf(float _X) {return ((float)tanh((double)_X)); } #endif /** \defgroup math Math Utilities * \par * See \ref im_color.h * \ingroup util */ /** Does Zero Order Decimation (Mean). * \ingroup math */ template inline T imZeroOrderDecimation(int width, int height, T *map, float xl, float yl, float box_width, float box_height, TU Dummy) { int x0,x1,y0,y1; (void)Dummy; x0 = (int)floor(xl - box_width/2.0 - 0.5) + 1; y0 = (int)floor(yl - box_height/2.0 - 0.5) + 1; x1 = (int)floor(xl + box_width/2.0 - 0.5); y1 = (int)floor(yl + box_height/2.0 - 0.5); if (x0 == x1) x1++; if (y0 == y1) y1++; x0 = x0<0? 0: x0>width-1? width-1: x0; y0 = y0<0? 0: y0>height-1? height-1: y0; x1 = x1<0? 0: x1>width-1? width-1: x1; y1 = y1<0? 0: y1>height-1? height-1: y1; TU Value; int Count = 0; Value = 0; for (int y = y0; y <= y1; y++) { for (int x = x0; x <= x1; x++) { Value += map[y*width+x]; Count++; } } if (Count == 0) { Value = 0; return (T)Value; } return (T)(Value/(float)Count); } /** Does Bilinear Decimation. * \ingroup math */ template inline T imBilinearDecimation(int width, int height, T *map, float xl, float yl, float box_width, float box_height, TU Dummy) { int x0,x1,y0,y1; (void)Dummy; x0 = (int)floor(xl - box_width/2.0 - 0.5) + 1; y0 = (int)floor(yl - box_height/2.0 - 0.5) + 1; x1 = (int)floor(xl + box_width/2.0 - 0.5); y1 = (int)floor(yl + box_height/2.0 - 0.5); if (x0 == x1) x1++; if (y0 == y1) y1++; x0 = x0<0? 0: x0>width-1? width-1: x0; y0 = y0<0? 0: y0>height-1? height-1: y0; x1 = x1<0? 0: x1>width-1? width-1: x1; y1 = y1<0? 0: y1>height-1? height-1: y1; TU Value, LineValue; float LineNorm, Norm, dxr, dyr; Value = 0; Norm = 0; for (int y = y0; y <= y1; y++) { dyr = yl - (y+0.5f); if (dyr < 0) dyr *= -1; LineValue = 0; LineNorm = 0; for (int x = x0; x <= x1; x++) { dxr = xl - (x+0.5f); if (dxr < 0) dxr *= -1; LineValue += map[y*width+x] * dxr; LineNorm += dxr; } Value += LineValue * dyr; Norm += dyr * LineNorm; } if (Norm == 0) { Value = 0; return (T)Value; } return (T)(Value/Norm); } /** Does Zero Order Interpolation (Nearest Neighborhood). * \ingroup math */ template inline T imZeroOrderInterpolation(int width, int height, T *map, float xl, float yl) { int x0 = (int)(xl-0.5f); int y0 = (int)(yl-0.5f); x0 = x0<0? 0: x0>width-1? width-1: x0; y0 = y0<0? 0: y0>height-1? height-1: y0; return map[y0*width + x0]; } /** Does Bilinear Interpolation. * \ingroup math */ template inline T imBilinearInterpolation(int width, int height, T *map, float xl, float yl) { int x0 = (int)(xl-0.5f); int y0 = (int)(yl-0.5f); int x1 = x0+1; int y1 = y0+1; float t = xl - (x0+0.5f); float u = yl - (y0+0.5f); x0 = x0<0? 0: x0>width-1? width-1: x0; y0 = y0<0? 0: y0>height-1? height-1: y0; x1 = x1<0? 0: x1>width-1? width-1: x1; y1 = y1<0? 0: y1>height-1? height-1: y1; T fll = map[y0*width + x0]; T fhl = map[y0*width + x1]; T flh = map[y1*width + x0]; T fhh = map[y1*width + x1]; return (T)((fhh - flh - fhl + fll) * u * t + (fhl - fll) * t + (flh - fll) * u + fll); } /** Does Bicubic Interpolation. * \ingroup math */ template inline T imBicubicInterpolation(int width, int height, T *map, float xl, float yl, TU Dummy) { (void)Dummy; int x0 = (int)(xl-0.5f); int y0 = (int)(yl-0.5f); int x1 = x0-1; int x2 = x0+2; int y1 = y0-1; int y2 = y0+2; float t = xl - (x0+0.5f); float u = yl - (y0+0.5f); x1 = x1<0? 0: x1>width-1? width-1: x1; y1 = y1<0? 0: y1>height-1? height-1: y1; x2 = x2<0? 0: x2>width-1? width-1: x2; y2 = y2<0? 0: y2>height-1? height-1: y2; float CX[4], CY[4]; // Optimize calculations { float x, x2, x3; #define C0 (-x3 + 2.0f*x2 - x) #define C1 ( x3 - 2.0f*x2 + 1.0f) #define C2 (-x3 + x2 + x) #define C3 ( x3 - x2) x = t; x2 = x*x; x3 = x2*x; CX[0] = C0; CX[1] = C1; CX[2] = C2; CX[3] = C3; x = u; x2 = x*x; x3 = x2*x; CY[0] = C0; CY[1] = C1; CY[2] = C2; CY[3] = C3; } #undef C0 #undef C1 #undef C2 #undef C3 TU LineValue, Value; float LineNorm, Norm; Value = 0; Norm = 0; for (int y = y1; y <= y2; y++) { LineValue = 0; LineNorm = 0; for (int x = x1; x <= x2; x++) { LineValue += map[y*width+x] * CX[x-x1]; LineNorm += CX[x-x1]; } Value += LineValue * CY[y-y1]; Norm += CY[y-y1] * LineNorm; } if (Norm == 0) { Value = 0; return (T)Value; } Value = (Value/Norm); int size = sizeof(T); if (size == 1) return (T)(Value<=0? 0: Value<=255? Value: 255); else return (T)(Value); } /** Calculates minimum and maximum values. * \ingroup math */ template inline void imMinMax(const T *map, int count, T& min, T& max) { min = *map++; max = min; for (int i = 1; i < count; i++) { T value = *map++; if (value > max) max = value; else if (value < min) min = value; } if (min == max) { max = min + 1; if (min != 0) min = min - 1; } } #endif