40#define MIN_FLOAT exp2f(-16.0f)
86#pragma omp declare simd
89static inline float fast_clamp(
const float value,
const float bottom,
const float top)
92 return fmaxf(fminf(value, top), bottom);
89static inline float fast_clamp(
const float value,
const float bottom,
const float top) {
…}
97static inline void interpolate_bilinear(
const float *
const restrict in,
const size_t width_in,
const size_t height_in,
98 float *
const restrict out,
const size_t width_out,
const size_t height_out,
103#pragma omp parallel for collapse(2) default(none) \
104 dt_omp_firstprivate(in, out, width_out, height_out, width_in, height_in, ch) \
105 schedule(simd:static)
107 for(
size_t i = 0; i < height_out; i++)
109 for(
size_t j = 0; j < width_out; j++)
112 const float x_out = (float)j /(
float)width_out;
113 const float y_out = (float)i /(
float)height_out;
116 const float x_in = x_out * (float)width_in;
117 const float y_in = y_out * (float)height_in;
120 size_t x_prev = (size_t)floorf(x_in);
121 size_t x_next = x_prev + 1;
122 size_t y_prev = (size_t)floorf(y_in);
123 size_t y_next = y_prev + 1;
125 x_prev = (x_prev < width_in) ? x_prev : width_in - 1;
126 x_next = (x_next < width_in) ? x_next : width_in - 1;
127 y_prev = (y_prev < height_in) ? y_prev : height_in - 1;
128 y_next = (y_next < height_in) ? y_next : height_in - 1;
131 const size_t Y_prev = y_prev * width_in;
132 const size_t Y_next = y_next * width_in;
133 const float *
const Q_NW = (
float *)in + (Y_prev + x_prev) * ch;
134 const float *
const Q_NE = (
float *)in + (Y_prev + x_next) * ch;
135 const float *
const Q_SE = (
float *)in + (Y_next + x_next) * ch;
136 const float *
const Q_SW = (
float *)in + (Y_next + x_prev) * ch;
139 const float Dy_next = (float)y_next - y_in;
140 const float Dy_prev = 1.f - Dy_next;
141 const float Dx_next = (float)x_next - x_in;
142 const float Dx_prev = 1.f - Dx_next;
145 float *
const pixel_out = (
float *)out + (i * width_out + j) * ch;
148 for(
size_t c = 0; c < ch; c++)
150 pixel_out[c] = Dy_prev * (Q_SW[c] * Dx_next + Q_SE[c] * Dx_prev) +
151 Dy_next * (Q_NW[c] * Dx_next + Q_NE[c] * Dx_prev);
97static inline void interpolate_bilinear(
const float *
const restrict in,
const size_t width_in,
const size_t height_in, {
…}
160 const float *
const restrict mask,
161 float *
const restrict ab,
163 const int radius,
const float feathering)
171 const size_t Ndimch = Ndim * 4;
177 if(input == NULL)
goto error;
181#pragma omp parallel for default(none) \
182 dt_omp_firstprivate(guide, mask, Ndim, radius, input) \
183 schedule(simd:static)
185 for(
size_t k = 0; k < Ndim; k++)
187 const size_t index = k * 4;
188 input[index] = guide[k];
189 input[index + 1] = mask[k];
190 input[index + 2] = guide[k] * guide[k];
191 input[index + 3] = guide[k] * mask[k];
199#pragma omp parallel for default(none) \
200 dt_omp_firstprivate(ab, input, width, height, feathering) \
205 const float d = fmaxf((input[4*idx+2] - input[4*idx+0] * input[4*idx+0]) + feathering, 1e-15f);
206 const float a = (input[4*idx+3] - input[4*idx+0] * input[4*idx+1]) / d;
207 const float b = input[4*idx+1] - a * input[4*idx+0];
219 const float *
const restrict ab,
220 const size_t num_elem)
223#pragma omp parallel for simd default(none) \
224dt_omp_firstprivate(image, ab, num_elem) \
225schedule(simd:static) aligned(image, ab:64)
227 for(
size_t k = 0; k < num_elem; k++)
230 image[k] = fmaxf(image[k] * ab[k * 2] + ab[k * 2 + 1],
MIN_FLOAT);
237 const float *
const restrict ab,
238 const size_t num_elem)
241#pragma omp parallel for simd default(none) \
242dt_omp_firstprivate(image, ab, num_elem) \
243schedule(simd:static) aligned(image, ab:64)
245 for(
size_t k = 0; k < num_elem; k++)
248 image[k] = sqrtf(image[k] * fmaxf(image[k] * ab[k * 2] + ab[k * 2 + 1],
MIN_FLOAT));
254static inline void quantize(
const float *
const restrict image,
255 float *
const restrict out,
256 const size_t num_elem,
257 const float sampling,
const float clip_min,
const float clip_max)
266 else if(sampling == 1.0f)
270#pragma omp parallel for simd default(none) \
271dt_omp_firstprivate(image, out, num_elem, sampling, clip_min, clip_max) \
272schedule(simd:static) aligned(image, out:64)
274 for(
size_t k = 0; k < num_elem; k++)
275 out[k] =
fast_clamp(exp2f(floorf(log2f(image[k]))), clip_min, clip_max);
282#pragma omp parallel for simd default(none) \
283dt_omp_firstprivate(image, out, num_elem, sampling, clip_min, clip_max) \
284schedule(simd:static) aligned(image, out:64)
286 for(
size_t k = 0; k < num_elem; k++)
287 out[k] =
fast_clamp(exp2f(floorf(log2f(image[k]) / sampling) * sampling), clip_min, clip_max);
254static inline void quantize(
const float *
const restrict image, {
…}
295 const int radius,
float feathering,
const int iterations,
297 const float quantization,
const float quantize_min,
const float quantize_max)
303 const float scaling = 4.0f;
304 const int ds_radius = (radius < 4) ? 1 : radius / scaling;
306 const size_t ds_height =
height / scaling;
307 const size_t ds_width =
width / scaling;
309 const size_t num_elem_ds = ds_width * ds_height;
317 if(!ds_image || !ds_mask || !ds_ab || !ab)
319 dt_control_log(_(
"fast guided filter failed to allocate memory, check your RAM settings"));
327 for(
int i = 0; i < iterations; ++i)
330 quantize(ds_image, ds_mask, ds_width * ds_height, quantization, quantize_min, quantize_max);
334 variance_analyse(ds_mask, ds_image, ds_ab, ds_width, ds_height, ds_radius, feathering);
337 dt_box_mean(ds_ab, ds_height, ds_width, 2, ds_radius, 1);
339 if(i != iterations - 1)
static void error(char *msg)
Definition ashift_lsd.c:191
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
void dt_box_mean(float *const buf, const size_t height, const size_t width, const int ch, const int radius, const unsigned iterations)
Definition box_filters.c:1225
void dt_control_log(const char *msg,...)
Definition control.c:424
static float * dt_alloc_align_float(size_t pixels)
Definition darktable.h:345
static size_t dt_round_size_sse(const size_t size)
Definition darktable.h:285
#define __DT_CLONE_TARGETS__
Definition darktable.h:249
#define dt_free_align(A)
Definition darktable.h:334
static void * dt_alloc_sse_ps(size_t pixels)
Definition darktable.h:356
static __DT_CLONE_TARGETS__ void variance_analyse(const float *const restrict guide, const float *const restrict mask, float *const restrict ab, const size_t width, const size_t height, const int radius, const float feathering)
Definition fast_guided_filter.h:159
dt_iop_guided_filter_blending_t
Definition fast_guided_filter.h:44
@ DT_GF_BLENDING_LINEAR
Definition fast_guided_filter.h:45
@ DT_GF_BLENDING_GEOMEAN
Definition fast_guided_filter.h:46
static __DT_CLONE_TARGETS__ void quantize(const float *const restrict image, float *const restrict out, const size_t num_elem, const float sampling, const float clip_min, const float clip_max)
Definition fast_guided_filter.h:254
#define MIN_FLOAT
Definition fast_guided_filter.h:40
static __DT_CLONE_TARGETS__ void fast_surface_blur(float *const restrict image, const size_t width, const size_t height, const int radius, float feathering, const int iterations, const dt_iop_guided_filter_blending_t filter, const float scale, const float quantization, const float quantize_min, const float quantize_max)
Definition fast_guided_filter.h:293
static __DT_CLONE_TARGETS__ void apply_linear_blending_w_geomean(float *const restrict image, const float *const restrict ab, const size_t num_elem)
Definition fast_guided_filter.h:236
static __DT_CLONE_TARGETS__ void apply_linear_blending(float *const restrict image, const float *const restrict ab, const size_t num_elem)
Definition fast_guided_filter.h:218
static __DT_CLONE_TARGETS__ float fast_clamp(const float value, const float bottom, const float top)
Definition fast_guided_filter.h:89
static __DT_CLONE_TARGETS__ void interpolate_bilinear(const float *const restrict in, const size_t width_in, const size_t height_in, float *const restrict out, const size_t width_out, const size_t height_out, const size_t ch)
Definition fast_guided_filter.h:97
void dt_iop_image_copy(float *const __restrict__ out, const float *const __restrict__ in, const size_t nfloats)
Definition imagebuf.c:134