00001 #ifndef vipl_gaussian_convolution_txx_
00002 #define vipl_gaussian_convolution_txx_
00003
00004 #include "vipl_gaussian_convolution.h"
00005 #include <vcl_cmath.h>
00006
00007 template <class ImgIn,class ImgOut,class DataIn,class DataOut,class PixelItr>
00008 bool vipl_gaussian_convolution <ImgIn,ImgOut,DataIn,DataOut,PixelItr> :: section_applyop()
00009 {
00010 const ImgIn &in = this->in_data(0);
00011 ImgOut &out = *this->out_data_ptr();
00012 int size = masksize();
00013
00014
00015 int width = stop(this->X_Axis()) - start(this->X_Axis());
00016 int height = stop(this->Y_Axis()) - start(this->Y_Axis());
00017 double* buf = new double[width*height];
00018 if (!buf) return false;
00019
00020
00021
00022
00023 int starty = start(this->Y_Axis());
00024 int stopy = stop(this->Y_Axis());
00025 for (int j = starty; j < stopy; ++j)
00026 {
00027 int buf_j = j - starty;
00028 int startx = start(this->X_Axis(),j);
00029 int stopx = stop(this->X_Axis(),j);
00030 for (int i = startx; i < stopx; ++i) {
00031 int buf_i = i - startx;
00032 double result = mask()[0] * fgetpixel(in, i, j, DataIn(0));
00033 for (int x=1; x<size; ++x)
00034 result += mask()[x] * (getpixel(in, i+x, j, DataIn(0)) + getpixel(in, i-x, j, DataIn(0)));
00035 buf[buf_i+width*buf_j] = result;
00036 }
00037 }
00038
00039 for (int j = starty; j < stopy; ++j)
00040 {
00041 int buf_j = j - starty;
00042 int startx = start(this->X_Axis(),j);
00043 int stopx = stop(this->X_Axis(),j);
00044 for (int i = startx; i < stopx; ++i) {
00045 int buf_i = i - startx;
00046 double result = mask()[0] * buf[buf_i+width*buf_j];
00047 for (int y=1; y<size; ++y) {
00048 if (buf_j+y < height) result += mask()[y] * buf[buf_i+width*(buf_j+y)];
00049 if (buf_j >= y) result += mask()[y] * buf[buf_i+width*(buf_j-y)];
00050 }
00051 fsetpixel(out, i, j, DataOut(result));
00052 }
00053 }
00054 delete[] buf;
00055 return true;
00056 }
00057
00058
00059
00060 template <class ImgIn,class ImgOut,class DataIn,class DataOut,class PixelItr>
00061 bool vipl_gaussian_convolution <ImgIn,ImgOut,DataIn,DataOut,PixelItr> :: preop()
00062 {
00063
00064 double lc = -2 * vcl_log(cutoff());
00065 int radius = (lc<=0) ? 0 : 1 + int(vcl_sqrt(lc)*sigma());
00066 int size = radius + 1;
00067 ref_masksize() = size;
00068 delete[] ref_mask(); ref_mask() = new double[size];
00069 double s = -0.5/sigma()/sigma();
00070 double halfnorm = vcl_exp(0.25*s) + 1.0;
00071 for (int y=1; y<8; ++y) halfnorm += 2*vcl_exp(y*y*0.0625*0.0625*s);
00072 ref_mask()[0] = 2*halfnorm;
00073 for (int x=1; x<size; ++x)
00074 {
00075 ref_mask()[x] = vcl_exp((x-0.5)*(x-0.5)*s) + vcl_exp((x+0.5)*(x+0.5)*s);
00076 for (int y=-7; y<8; ++y) ref_mask()[x] += 2*vcl_exp((x+y*0.0625)*(x+y*0.0625)*s);
00077 halfnorm += mask()[x];
00078 }
00079 for (int x=0; x<size; ++x) ref_mask()[x] /= 2*halfnorm;
00080 return true;
00081 }
00082
00083
00084 template <class ImgIn,class ImgOut,class DataIn,class DataOut,class PixelItr>
00085 bool vipl_gaussian_convolution <ImgIn,ImgOut,DataIn,DataOut,PixelItr> :: postop()
00086 {
00087 delete[] ref_mask(); ref_mask()=0;
00088 return true;
00089 }
00090
00091 #endif // vipl_gaussian_convolution_txx_