blob: 109e79c0903d48bd8b08721154e9252baa45be83 [file] [log] [blame]
// Copyright 2006 Google Inc.
// All Rights Reserved.
// Author: <renn@google.com> (Marius Renn)
// Local includes
#include "color.h"
#include "debugging.h"
#include "gaussiansmooth.h"
#include "point.h"
#include "mathfunctions.h"
using namespace helium;
GaussianSmooth::GaussianSmooth(unsigned size) :
kernel_size_(size + 1),
gauss_sum_(0),
kernel_(new int[size + 1]) {
// Create gaussian mask by calculating the binomial coefficients. We will
// later divide by the sum of these coefficients to obtain the output value.
for (unsigned i = 0; i < kernel_size_; i ++) {
int coeff = Binomi(size + 1, i + 1);
kernel_[i] = coeff;
gauss_sum_ += coeff;
}
}
GaussianSmooth::~GaussianSmooth() {
delete[] kernel_;
}
Image GaussianSmooth::Smooth(const Image& image) {
ASSERT(kernel_);
// Create intermediate and destination images
Image temp(image.width(), image.height());
Image dest(image.width(), image.height());
ASSERT(temp.Valid() && dest.Valid());
int s = kernel_size_ / 2;
Color pixel;
Point p;
int r, g, b;
int row = image.width();
// Setup data pointers
Color* src_ptr = image.Access(s, s);
Color* temp_ptr = temp.Access(s, s);
Color* dest_ptr = dest.Access(s, s);
// First pass (horizontal smoothing)
for (p.y = s; p.y < image.height() - s; p.y++) {
for (p.x = s; p.x < image.width() - s; p.x++) {
int r_gauss = 0;
int g_gauss = 0;
int b_gauss = 0;
for (int i = 0; i < kernel_size_; i++) {
pixel = *(src_ptr + i - s);
ColorSeparate(pixel, r, g, b);
r_gauss += r * kernel_[i];
g_gauss += g * kernel_[i];
b_gauss += b * kernel_[i];
}
r_gauss /= gauss_sum_;
g_gauss /= gauss_sum_;
b_gauss /= gauss_sum_;
*(temp_ptr++) = MakeColor(r_gauss, g_gauss, b_gauss);
src_ptr++;
}
src_ptr += s*2;
temp_ptr += s*2;
}
// Second pass (vertical smoothing)
temp_ptr = temp.Access(s, s);
for (p.y = s; p.y < image.height() - s; p.y++) {
for (p.x = s; p.x < image.width() - s; p.x++) {
int r_gauss = 0;
int g_gauss = 0;
int b_gauss = 0;
for (int i = 0; i < kernel_size_; i++) {
pixel = *(temp_ptr + (i - s) * row);
ColorSeparate(pixel, r, g, b);
r_gauss += r * kernel_[i];
g_gauss += g * kernel_[i];
b_gauss += b * kernel_[i];
}
r_gauss /= gauss_sum_;
g_gauss /= gauss_sum_;
b_gauss /= gauss_sum_;
*(dest_ptr++) = MakeColor(r_gauss, g_gauss, b_gauss);
temp_ptr++;
}
dest_ptr += s*2;
temp_ptr += s*2;
}
return dest;
}