34 static_assert(
N % 2 == 1,
"KernelSpec length must be odd");
35 static_assert(
N >= 1,
"KernelSpec length must be >= 1");
38 static constexpr size_t half =
N / 2;
40 std::array<float, N>
taps {};
48 template <
typename... Ts>
49 requires(
sizeof...(Ts) ==
N) && (std::is_convertible_v<Ts, float> && ...)
51 :
taps {
static_cast<float>(values)... }
73 for (
size_t i = 0; i <
N; ++i)
89 for (
size_t i = 0; i <
N; ++i)
104 for (
size_t i = 0; i <
N; ++i)
115 for (
size_t i = 0; i <
N; ++i)
129 for (
size_t i = 0; i <
N; ++i)
148 for (
size_t i = 0; i <
N; ++i)
149 for (
size_t j = 0; j < M; ++j)
150 out.taps[i + j] +=
taps[i] * other.taps[j];
158 [[nodiscard]]
constexpr std::span<const float>
span() const noexcept
160 return {
taps.data(),
N };
163 constexpr operator std::span<const float>() const noexcept
168 [[nodiscard]]
constexpr const float*
data() const noexcept {
return taps.data(); }
169 [[nodiscard]]
constexpr size_t size() const noexcept {
return N; }
#define N(method_name, full_type_name)
constexpr auto sobel_smooth
constexpr auto prewitt_smooth
constexpr auto prewitt_kx
constexpr auto prewitt_ky
constexpr auto log_coarse
constexpr KernelSpec shift(float s) const noexcept
Add a scalar to all taps.
constexpr KernelSpec reflect() const noexcept
Reverse tap order.
constexpr KernelSpec scale(float s) const noexcept
Multiply all taps by a scalar.
constexpr KernelSpec< N+M - 1 > convolve(const KernelSpec< M > &other) const noexcept
Convolve this kernel with another of the same length.
constexpr size_t size() const noexcept
constexpr KernelSpec normalize() const noexcept
Divide all taps by their sum.
std::array< float, N > taps
static constexpr size_t half
static constexpr size_t length
constexpr std::span< const float > span() const noexcept
constexpr KernelSpec()=default
constexpr KernelSpec negate() const noexcept
Negate all taps.
constexpr KernelSpec(Ts... values) noexcept
constexpr const float * data() const noexcept
Compile-time 1D separable filter kernel.