Skip to content

Commit

Permalink
remove Gauss option from SkGaussFilter
Browse files Browse the repository at this point in the history
Unused except in unit tests.

Change-Id: I07bb70515a383898ad59c0fa918461052b582e35
Reviewed-on: https://skia-review.googlesource.com/c/168860
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Mike Klein <mtklein@google.com>
  • Loading branch information
Mike Klein authored and Skia Commit-Bot committed Nov 6, 2018
1 parent 0e50a38 commit 630e7d6
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 84 deletions.
43 changes: 2 additions & 41 deletions src/core/SkGaussFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@
#include "SkTypes.h"
#include <cmath>

static constexpr double kPi = 3.14159265358979323846264338327950288;

// The value when we can stop expanding the filter. The spec implies that 3% is acceptable, but
// we just use 1%.
static constexpr double kGoodEnough = 1.0 / 100.0;
Expand Down Expand Up @@ -104,45 +102,8 @@ static int calculate_bessel_factors(double sigma, double *gauss) {
return n;
}

static int calculate_gauss_factors(double sigma, double* gauss) {
SkASSERT(0 <= sigma && sigma < 2);

// From the SVG blur spec: 8.13 Filter primitive <feGaussianBlur>.
// H(x) = exp(-x^2/ (2s^2)) / sqrt(2π * s^2)
auto var = sigma * sigma;
auto expGaussDenom = -2 * var;
auto normalizeDenom = std::sqrt(2 * kPi) * sigma;

// Use the recursion relation from "Incremental Computation of the Gaussian" by Ken
// Turkowski in GPUGems 3. Page 877.
double g0 = sk_ieee_double_divide_TODO_IS_DIVIDE_BY_ZERO_SAFE_HERE(1.0, normalizeDenom);
double g1 = std::exp(sk_ieee_double_divide_TODO_IS_DIVIDE_BY_ZERO_SAFE_HERE(1.0, expGaussDenom));
double g2 = g1 * g1;

gauss[0] = g0;
g0 *= g1;
g1 *= g2;
gauss[1] = g0;

int n = 1;
while (gauss[n] > kGoodEnough) {
g0 *= g1;
g1 *= g2;
gauss[n+1] = g0;
n += 1;
}

normalize(n, gauss);

return n;
}

SkGaussFilter::SkGaussFilter(double sigma, Type type) {
SkGaussFilter::SkGaussFilter(double sigma) {
SkASSERT(0 <= sigma && sigma < 2);

if (type == Type::Bessel) {
fN = calculate_bessel_factors(sigma, fBasis);
} else {
fN = calculate_gauss_factors(sigma, fBasis);
}
fN = calculate_bessel_factors(sigma, fBasis);
}
11 changes: 2 additions & 9 deletions src/core/SkGaussFilter.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,12 @@
#include <cstddef>

// Define gaussian filters for values of sigma < 2. Produce values good to 1 part in 1,000,000.
// Gaussian produces values as defined in the SVG 1.1 spec:
// https://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement
// Bessel produces values as defined in "Scale-Space for Discrete Signals" by Tony Lindeberg
// Produces values as defined in "Scale-Space for Discrete Signals" by Tony Lindeberg.
class SkGaussFilter {
public:
static constexpr int kGaussArrayMax = 6;
enum class Type : bool {
Gaussian,
Bessel
};

// Type selects which method is used to calculate the gaussian factors.
SkGaussFilter(double sigma, Type type);
explicit SkGaussFilter(double sigma);

size_t size() const { return fN; }
int radius() const { return fN - 1; }
Expand Down
4 changes: 2 additions & 2 deletions src/core/SkMaskBlurFilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -871,8 +871,8 @@ static SkIPoint small_blur(double sigmaX, double sigmaY, const SkMask& src, SkMa
SkASSERT(0.01 <= sigmaX && sigmaX < 2);
SkASSERT(0.01 <= sigmaY && sigmaY < 2);

SkGaussFilter filterX{sigmaX, SkGaussFilter::Type::Bessel},
filterY{sigmaY, SkGaussFilter::Type::Bessel};
SkGaussFilter filterX{sigmaX},
filterY{sigmaY};

int radiusX = filterX.radius(),
radiusY = filterY.radius();
Expand Down
43 changes: 11 additions & 32 deletions tests/SkGaussFilterTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ static double careful_add(int n, double* gauss) {
}

DEF_TEST(SkGaussFilterCommon, r) {
using Test = std::tuple<double, SkGaussFilter::Type, std::vector<double>>;
using Test = std::tuple<double, std::vector<double>>;

auto golden_check = [&](const Test& test) {
double sigma; SkGaussFilter::Type type; std::vector<double> golden;
std::tie(sigma, type, golden) = test;
SkGaussFilter filter{sigma, type};
double sigma; std::vector<double> golden;
std::tie(sigma, golden) = test;
SkGaussFilter filter{sigma};
double result[SkGaussFilter::kGaussArrayMax];
int n = 0;
for (auto d : filter) {
Expand All @@ -48,19 +48,11 @@ DEF_TEST(SkGaussFilterCommon, r) {
// The following two sigmas account for about 85% of all sigmas used for masks.
// Golden values generated using Mathematica.
auto tests = {
// 0.788675 - most common mask sigma.
// GaussianMatrix[{{Automatic}, {.788675}}, Method -> "Gaussian"]
Test{0.788675, SkGaussFilter::Type::Gaussian, {0.506205, 0.226579, 0.0203189}},

// GaussianMatrix[{{Automatic}, {.788675}}]
Test{0.788675, SkGaussFilter::Type::Bessel, {0.593605, 0.176225, 0.0269721}},

// 1.07735 - second most common mask sigma.
// GaussianMatrix[{{Automatic}, {1.07735}}, Method -> "Gaussian"]
Test{1.07735, SkGaussFilter::Type::Gaussian, {0.376362, 0.244636, 0.0671835}},
Test{0.788675, {0.593605, 0.176225, 0.0269721}},

// GaussianMatrix[{{4}, {1.07735}}, Method -> "Bessel"]
Test{1.07735, SkGaussFilter::Type::Bessel, {0.429537, 0.214955, 0.059143, 0.0111337}},
Test{1.07735, {0.429537, 0.214955, 0.059143, 0.0111337}},
};

for (auto& test : tests) {
Expand All @@ -71,8 +63,8 @@ DEF_TEST(SkGaussFilterCommon, r) {
DEF_TEST(SkGaussFilterSweep, r) {
// The double just before 2.0.
const double maxSigma = nextafter(2.0, 0.0);
auto check = [&](double sigma, SkGaussFilter::Type type) {
SkGaussFilter filter{sigma, type};
auto check = [&](double sigma) {
SkGaussFilter filter{sigma};
double result[SkGaussFilter::kGaussArrayMax];
int n = 0;
for (auto d : filter) {
Expand All @@ -83,21 +75,8 @@ DEF_TEST(SkGaussFilterSweep, r) {
REPORTER_ASSERT(r, sum == 1.0);
};

{

for (double sigma = 0.0; sigma < 2.0; sigma += 0.1) {
check(sigma, SkGaussFilter::Type::Gaussian);
}

check(maxSigma, SkGaussFilter::Type::Gaussian);
}

{

for (double sigma = 0.0; sigma < 2.0; sigma += 0.1) {
check(sigma, SkGaussFilter::Type::Bessel);
}

check(maxSigma, SkGaussFilter::Type::Bessel);
for (double sigma = 0.0; sigma < 2.0; sigma += 0.1) {
check(sigma);
}
check(maxSigma);
}

0 comments on commit 630e7d6

Please sign in to comment.