Article 9 — Appendix A.2
Gaussian filter, or Gaussian blur source code
Download Gaussian filter, or Gaussian blur C++ source code (zip, 4 Kb)
gaussianblur.cpp
#ifndef _GAUSSIANBLUR_CPP_
#define _GAUSSIANBLUR_CPP_
#include "gaussianblur.h"
#include <math.h>
template <class T> bool TGaussianBlur<T>::Filter(T *pSignal, T *pResult,
unsigned int N, unsigned int W) const
{
if (!Consistent(pSignal, N, W))
return false;
CExtension Extension;
if (!Extension.Allocate(N, W))
return false;
const CArray Signal(pSignal, N);
Extension.Paste(Signal.Buffer);
Extension.Extend();
CWindow Window;
if (!Window.Create(W))
return false;
const T *ExtIter = Extension.Buffer;
const T *const ExtStop = Extension.Buffer + Extension.Size.x;
T *ResIter = pResult ? pResult : pSignal;
while (ExtIter < ExtStop)
*(ResIter++) = Window.Apply(ExtIter++);
return true;
}
template <class T> bool TGaussianBlur<T>::Filter(T *pImage, T *pResult,
unsigned int N, unsigned int M, unsigned int W) const
{
if (!Consistent(pImage, CSize(N, M), W))
return false;
CExtension Extension;
if (!Extension.Allocate(CSize(N, M), W))
return false;
CArray Image(pImage, CSize(N, M));
CWindow Window;
if (!Window.Create(W))
return false;
const T * ExtStop = Extension.Buffer + Extension.Size.x;
T *ResIter = pResult ? pResult : pImage;
const T *ImIter = Image.Buffer;
const T * ImStop = Image.Buffer + Image.Size.Area();
while (ImIter < ImStop)
{
Extension.Paste(ImIter);
Extension.Extend();
const T *ExtIter = Extension.Buffer;
while (ExtIter < ExtStop)
*(ResIter++) = Window.Apply(ExtIter++);
ImIter += Image.Size.x;
}
Image.Buffer = pResult ? pResult : pImage;
Extension.SetMode(CExtension::ModeVertical);
ExtStop = Extension.Buffer + Extension.Size.y;
T *ResColumnIter = pResult ? pResult : pImage;
ImIter = Image.Buffer;
ImStop = Image.Buffer + Image.Size.x;
while (ImIter < ImStop)
{
Extension.Paste(ImIter++);
Extension.Extend();
const T *ExtIter = Extension.Buffer;
ResIter = ResColumnIter;
while (ExtIter < ExtStop)
{
*ResIter = Window.Apply(ExtIter++);
ResIter += Image.Size.x;
}
++ResColumnIter;
}
return true;
}
template <class T> bool TGaussianBlur<T>::CExtension::_Allocate(
const CSize &_Size, unsigned int _Margin)
{
Buffer = new T[(_Size.x > _Size.y ? _Size.x : _Size.y) + (_Margin << 1)];
if (!Buffer)
return false;
Size = _Size;
Margin = _Margin;
return true;
}
template <class T> void TGaussianBlur<T>::CExtension::Paste(const T *const _Start)
{
if (Mode == ModeHorizontal)
{
memcpy(Buffer + Margin, _Start, Size.x * sizeof(T));
}
else
{
const T *const Stop = _Start + Size.Area();
const T *ArrIter = _Start;
T *ExtIter = Buffer + Margin;
while (ArrIter < Stop)
{
*(ExtIter++) = *ArrIter;
ArrIter += Size.x;
}
}
}
template <class T> void TGaussianBlur<T>::CExtension::Extend()
{
const unsigned int Line = Mode == ModeHorizontal ? Size.x : Size.y;
const T *const Stop = Buffer - 1;
T *ExtLeft = Buffer + Margin - 1;
const T *ArrLeft = ExtLeft + 2;
T *ExtRight = ExtLeft + Line + 1;
const T *ArrRight = ExtRight - 2;
while (ExtLeft > Stop)
{
*(ExtLeft--) = *(ArrLeft++);
*(ExtRight++) = *(ArrRight--);
}
}
template <class T> bool TGaussianBlur<T>::CWindow::Create(unsigned int _Size)
{
Weights = new double[_Size];
if (!Weights)
return false;
Size = _Size;
const unsigned int Half = Size >> 1;
Weights[Half] = 1.;
for (unsigned int Weight = 1; Weight < Half + 1; ++Weight)
{
const double x = 3.* double(Weight) / double(Half);
Weights[Half - Weight] = Weights[Half + Weight] = exp(-x * x / 2.);
}
double k = 0.;
for (unsigned int Weight = 0; Weight < Size; ++Weight)
k += Weights[Weight];
for (unsigned int Weight = 0; Weight < Size; ++Weight)
Weights[Weight] /= k;
return true;
}
#endif
|