1 /* 2 * Copyright 2017 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkGaussFilter.h" 9 10 #include <cmath> 11 #include <tuple> 12 #include <vector> 13 #include "Test.h" 14 15 // one part in a million 16 static constexpr double kEpsilon = 0.000001; 17 18 static double careful_add(int n, double* gauss) { 19 // Sum smallest to largest to retain precision. 20 double sum = 0; 21 for (int i = n - 1; i >= 1; i--) { 22 sum += 2.0 * gauss[i]; 23 } 24 sum += gauss[0]; 25 return sum; 26 } 27 28 DEF_TEST(SkGaussFilterCommon, r) { 29 using Test = std::tuple<double, SkGaussFilter::Type, std::vector<double>>; 30 31 auto golden_check = [&](const Test& test) { 32 double sigma; SkGaussFilter::Type type; std::vector<double> golden; 33 std::tie(sigma, type, golden) = test; 34 SkGaussFilter filter{sigma, type}; 35 double result[SkGaussFilter::kGaussArrayMax]; 36 int n = 0; 37 for (auto d : filter) { 38 result[n++] = d; 39 } 40 REPORTER_ASSERT(r, static_cast<size_t>(n) == golden.size()); 41 double sum = careful_add(n, result); 42 REPORTER_ASSERT(r, sum == 1.0); 43 for (size_t i = 0; i < golden.size(); i++) { 44 REPORTER_ASSERT(r, std::abs(golden[i] - result[i]) < kEpsilon); 45 } 46 }; 47 48 // The following two sigmas account for about 85% of all sigmas used for masks. 49 // Golden values generated using Mathematica. 50 auto tests = { 51 // 0.788675 - most common mask sigma. 52 // GaussianMatrix[{{Automatic}, {.788675}}, Method -> "Gaussian"] 53 Test{0.788675, SkGaussFilter::Type::Gaussian, {0.506205, 0.226579, 0.0203189}}, 54 55 // GaussianMatrix[{{Automatic}, {.788675}}] 56 Test{0.788675, SkGaussFilter::Type::Bessel, {0.593605, 0.176225, 0.0269721}}, 57 58 // 1.07735 - second most common mask sigma. 59 // GaussianMatrix[{{Automatic}, {1.07735}}, Method -> "Gaussian"] 60 Test{1.07735, SkGaussFilter::Type::Gaussian, {0.376362, 0.244636, 0.0671835}}, 61 62 // GaussianMatrix[{{4}, {1.07735}}, Method -> "Bessel"] 63 Test{1.07735, SkGaussFilter::Type::Bessel, {0.429537, 0.214955, 0.059143, 0.0111337}}, 64 }; 65 66 for (auto& test : tests) { 67 golden_check(test); 68 } 69 } 70 71 DEF_TEST(SkGaussFilterSweep, r) { 72 // The double just before 2.0. 73 const double maxSigma = nextafter(2.0, 0.0); 74 auto check = [&](double sigma, SkGaussFilter::Type type) { 75 SkGaussFilter filter{sigma, type}; 76 double result[SkGaussFilter::kGaussArrayMax]; 77 int n = 0; 78 for (auto d : filter) { 79 result[n++] = d; 80 } 81 REPORTER_ASSERT(r, n <= SkGaussFilter::kGaussArrayMax); 82 double sum = careful_add(n, result); 83 REPORTER_ASSERT(r, sum == 1.0); 84 }; 85 86 { 87 88 for (double sigma = 0.0; sigma < 2.0; sigma += 0.1) { 89 check(sigma, SkGaussFilter::Type::Gaussian); 90 } 91 92 check(maxSigma, SkGaussFilter::Type::Gaussian); 93 } 94 95 { 96 97 for (double sigma = 0.0; sigma < 2.0; sigma += 0.1) { 98 check(sigma, SkGaussFilter::Type::Bessel); 99 } 100 101 check(maxSigma, SkGaussFilter::Type::Bessel); 102 } 103 } 104