backend: give backends more flexibility regarding shadow creation

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui
2022-08-25 05:21:19 +01:00
parent e942f253f7
commit 84407099a9
13 changed files with 100 additions and 32 deletions

View File

@@ -90,15 +90,20 @@ conv *gaussian_kernel(double r, int size) {
/// Estimate the element of the sum of the first row in a gaussian kernel with standard
/// deviation `r` and size `size`,
static inline double estimate_first_row_sum(double size, double r) {
// `factor` is integral of gaussian from -size to size
double factor = erf(size / r / sqrt(2));
// `a` is gaussian at (size, 0)
double a = exp(-0.5 * size * size / (r * r)) / sqrt(2 * M_PI) / r;
// The sum of the whole kernel is normalized to 1, i.e. each element is divided by
// factor sqaured. So the sum of the first row is a * factor / factor^2 = a /
// factor
return a / factor;
}
/// Pick a suitable gaussian kernel radius for a given kernel size. The returned radius
/// is the maximum possible radius (<= size*2) that satisfies no sum of the rows in
/// the kernel are less than `row_limit` (up to certain precision).
static inline double gaussian_kernel_std_for_size(int size, double row_limit) {
/// Pick a suitable gaussian kernel standard deviation for a given kernel size. The
/// returned radius is the maximum possible radius (<= size*2) that satisfies no sum of
/// the rows in the kernel are less than `row_limit` (up to certain precision).
static inline double gaussian_kernel_std_for_size(double size, double row_limit) {
assert(size > 0);
if (row_limit >= 1.0 / 2.0 / size) {
return size * 2;
@@ -121,9 +126,9 @@ static inline double gaussian_kernel_std_for_size(int size, double row_limit) {
/// transparent, so the transition from shadow to the background is smooth.
///
/// @param[in] shadow_radius the radius of the shadow
conv *gaussian_kernel_autodetect_deviation(int shadow_radius) {
conv *gaussian_kernel_autodetect_deviation(double shadow_radius) {
assert(shadow_radius >= 0);
int size = shadow_radius * 2 + 1;
int size = (int)(shadow_radius * 2 + 1);
if (shadow_radius == 0) {
return gaussian_kernel(0, size);