SkGaussFilterTest.cpp 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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. #include "src/core/SkGaussFilter.h"
  8. #include <cmath>
  9. #include <tuple>
  10. #include <vector>
  11. #include "tests/Test.h"
  12. // one part in a million
  13. static constexpr double kEpsilon = 0.000001;
  14. static double careful_add(int n, double* gauss) {
  15. // Sum smallest to largest to retain precision.
  16. double sum = 0;
  17. for (int i = n - 1; i >= 1; i--) {
  18. sum += 2.0 * gauss[i];
  19. }
  20. sum += gauss[0];
  21. return sum;
  22. }
  23. DEF_TEST(SkGaussFilterCommon, r) {
  24. using Test = std::tuple<double, std::vector<double>>;
  25. auto golden_check = [&](const Test& test) {
  26. double sigma; std::vector<double> golden;
  27. std::tie(sigma, golden) = test;
  28. SkGaussFilter filter{sigma};
  29. double result[SkGaussFilter::kGaussArrayMax];
  30. int n = 0;
  31. for (auto d : filter) {
  32. result[n++] = d;
  33. }
  34. REPORTER_ASSERT(r, static_cast<size_t>(n) == golden.size());
  35. double sum = careful_add(n, result);
  36. REPORTER_ASSERT(r, sum == 1.0);
  37. for (size_t i = 0; i < golden.size(); i++) {
  38. REPORTER_ASSERT(r, std::abs(golden[i] - result[i]) < kEpsilon);
  39. }
  40. };
  41. // The following two sigmas account for about 85% of all sigmas used for masks.
  42. // Golden values generated using Mathematica.
  43. auto tests = {
  44. // GaussianMatrix[{{Automatic}, {.788675}}]
  45. Test{0.788675, {0.593605, 0.176225, 0.0269721}},
  46. // GaussianMatrix[{{4}, {1.07735}}, Method -> "Bessel"]
  47. Test{1.07735, {0.429537, 0.214955, 0.059143, 0.0111337}},
  48. };
  49. for (auto& test : tests) {
  50. golden_check(test);
  51. }
  52. }
  53. DEF_TEST(SkGaussFilterSweep, r) {
  54. // The double just before 2.0.
  55. const double maxSigma = nextafter(2.0, 0.0);
  56. auto check = [&](double sigma) {
  57. SkGaussFilter filter{sigma};
  58. double result[SkGaussFilter::kGaussArrayMax];
  59. int n = 0;
  60. for (auto d : filter) {
  61. result[n++] = d;
  62. }
  63. REPORTER_ASSERT(r, n <= SkGaussFilter::kGaussArrayMax);
  64. double sum = careful_add(n, result);
  65. REPORTER_ASSERT(r, sum == 1.0);
  66. };
  67. for (double sigma = 0.0; sigma < 2.0; sigma += 0.1) {
  68. check(sigma);
  69. }
  70. check(maxSigma);
  71. }