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