48#define DT_COMMON_BILATERAL_MAX_RES_S 3000
49#define DT_COMMON_BILATERAL_MAX_RES_R 50
69 b->sigma_r = L_range / _z;
71 b->size_x = (int)ceilf(
width / b->sigma_s) + 1;
72 b->size_y = (int)ceilf(
height / b->sigma_s) + 1;
73 b->size_z = (int)ceilf(L_range / b->sigma_r) + 1;
75 if (b->sigma_s !=
sigma_s) fprintf(stderr,
"[bilateral] clamped sigma_s (%g -> %g)!\n",
sigma_s,b->sigma_s);
76 if (b->sigma_r !=
sigma_r) fprintf(stderr,
"[bilateral] clamped sigma_r (%g -> %g)!\n",
sigma_r,b->sigma_r);
87 size_t grid_size = b.size_x * b.size_y * b.size_z;
90 return 2 * grid_size *
sizeof(float);
115 size_t grid_size = b.size_x * b.size_y * b.size_z;
132 float *xf,
float *yf,
float *zf)
134 float x =
CLAMPS(
i / b->sigma_s, 0, b->size_x - 1);
135 float y =
CLAMPS(j / b->sigma_s, 0, b->size_y - 1);
136 float z =
CLAMPS(
L / b->sigma_r, 0, b->size_z - 1);
137 const int xi =
MIN((
int)
x, b->size_x - 2);
138 const int yi =
MIN((
int)y, b->size_y - 2);
139 const int zi =
MIN((
int)z, b->size_z - 2);
143 return ((xi + yi * b->size_x) * b->size_z) + zi;
146static inline __attribute__((always_inline))
size_t image_to_relgrid(
const dt_bilateral_t *
const b,
const int i,
const float L,
float *xf,
float *zf)
148 float x =
CLAMPS(
i /
b->sigma_s, 0,
b->size_x - 1);
149 float z =
CLAMPS(
L /
b->sigma_r, 0,
b->size_z - 1);
150 const int xi =
MIN((
int)
x,
b->size_x - 2);
151 const int zi =
MIN((
int)z,
b->size_z - 2);
154 return (xi *
b->size_z) + zi;
168 b->sliceheight = (
height + b->numslices - 1) / b->numslices;
169 b->slicerows = (b->size_y + b->numslices - 1) / b->numslices + 2;
171 if(b->buf) memset(b->buf, 0,
sizeof(
float) * b->size_x * b->size_z * b->numslices * b->slicerows);
174 fprintf(stderr,
"[bilateral] unable to allocate buffer for %" G_GSIZE_FORMAT
"x%" G_GSIZE_FORMAT
"x%" G_GSIZE_FORMAT
" grid\n",b->size_x,b->size_y,b->size_z);
178 dt_print(
DT_DEBUG_DEV,
"[bilateral] created grid [%" G_GSIZE_FORMAT
" %" G_GSIZE_FORMAT
" %" G_GSIZE_FORMAT
"] with sigma (%f %f) (%f %f)\n",
179 b->size_x, b->size_y, b->size_z, b->sigma_s,
sigma_s, b->sigma_r,
sigma_r);
185 const int ox = b->size_z;
186 const int oy = b->size_x * b->size_z;
188 const float sigma_s = b->sigma_s * b->sigma_s;
189 float *
const buf = b->buf;
194 const size_t offsets[8] =
206 for(
int slice = 0; slice < b->numslices; slice++)
208 const int firstrow = slice * b->sliceheight;
209 const int lastrow =
MIN((slice+1)*b->sliceheight,b->height);
212 const int slice_offset = slice * b->slicerows - (int)(firstrow / b->sigma_s);
214 for(
int j = firstrow; j < lastrow; j++)
216 float y =
CLAMPS(j / b->sigma_s, 0, b->size_y - 1);
217 const int yi =
MIN((
int)y, b->size_y - 2);
218 const float yf = y - yi;
219 const size_t base = (size_t)(yi + slice_offset) * oy;
220 for(
int i = 0;
i < b->width;
i++)
222 size_t index = 4 * (j * b->width +
i);
224 const float L = in[index];
226 const size_t grid_index = base + image_to_relgrid(b,
i,
L, &xf, &zf);
230 (1.0f - xf) * (1.0f - yf) * 100.0f /
sigma_s,
231 xf * (1.0f - yf) * 100.0f /
sigma_s,
232 (1.0f - xf) * yf * 100.0f /
sigma_s,
236 for(
int k = 0;
k < 4;
k++)
238 buf[grid_index + offsets[
k]] += (contrib[
k] * (1.0f - zf));
239 buf[grid_index + offsets[
k+4]] += (contrib[
k] * zf);
246 for (
int slice = 1 ; slice < nthreads; slice++)
249 const int destrow = (int)(slice * b->sliceheight / b->sigma_s);
250 float *dest = buf + destrow * oy;
252 for(
int j = slice * b->slicerows; j < (slice+1)*b->slicerows; j++)
254 float *src = buf + j * oy;
255 for(
int i = 0;
i < oy;
i++)
263 memset(buf + j*oy,
'\0',
sizeof(
float) * oy);
268static void blur_line_z(
float *buf,
const int offset1,
const int offset2,
const int offset3,
const int size1,
269 const int size2,
const int size3)
271 const float w1 = 4.f / 16.f;
272 const float w2 = 2.f / 16.f;
274 for(
int k = 0;
k < size1;
k++)
276 size_t index = (size_t)
k * offset1;
277 for(
int j = 0; j < size2; j++)
279 float tmp1 = buf[index];
280 buf[index] =
w1 * buf[index + offset3] +
w2 * buf[index + 2 * offset3];
282 float tmp2 = buf[index];
283 buf[index] =
w1 * (buf[index + offset3] - tmp1) +
w2 * buf[index + 2 * offset3];
285 for(
int i = 2;
i < size3 - 2;
i++)
287 const float tmp3 = buf[index];
288 buf[index] = +
w1 * (buf[index + offset3] - tmp2) +
w2 * (buf[index + 2 * offset3] - tmp1);
293 const float tmp3 = buf[index];
294 buf[index] =
w1 * (buf[index + offset3] - tmp2) -
w2 * tmp1;
296 buf[index] = -
w1 * tmp3 -
w2 * tmp2;
298 index += offset2 - offset3 * size3;
303static void blur_line(
float *buf,
const int offset1,
const int offset2,
const int offset3,
const int size1,
304 const int size2,
const int size3)
306 const float w0 = 6.f / 16.f;
307 const float w1 = 4.f / 16.f;
308 const float w2 = 1.f / 16.f;
310 for(
int k = 0;
k < size1;
k++)
312 size_t index = (size_t)
k * offset1;
313 for(
int j = 0; j < size2; j++)
315 float tmp1 = buf[index];
316 buf[index] = buf[index] * w0 +
w1 * buf[index + offset3] +
w2 * buf[index + 2 * offset3];
318 float tmp2 = buf[index];
319 buf[index] = buf[index] * w0 +
w1 * (buf[index + offset3] + tmp1) +
w2 * buf[index + 2 * offset3];
321 for(
int i = 2;
i < size3 - 2;
i++)
323 const float tmp3 = buf[index];
325 = buf[index] * w0 +
w1 * (buf[index + offset3] + tmp2) +
w2 * (buf[index + 2 * offset3] + tmp1);
330 const float tmp3 = buf[index];
331 buf[index] = buf[index] * w0 +
w1 * (buf[index + offset3] + tmp2) +
w2 * tmp1;
333 buf[index] = buf[index] * w0 +
w1 * tmp3 +
w2 * tmp2;
335 index += offset2 - offset3 * size3;
345 const int ox = b->size_z;
346 const int oy = b->size_x * b->size_z;
349 blur_line(b->buf, oz, oy, ox, b->size_z, b->size_y, b->size_x);
351 blur_line(b->buf, oz, ox, oy, b->size_z, b->size_x, b->size_y);
353 blur_line_z(b->buf, ox, oy, oz, b->size_x, b->size_y, b->size_z);
359 const float norm = -detail * b->sigma_r * 0.04f;
360 const int ox = b->size_z;
361 const int oy = b->size_x * b->size_z;
363 float *
const buf = b->buf;
364 const int width = b->width;
365 const int height = b->height;
369 for(
int j = 0; j <
height; j++)
373 size_t index = 4 * (j *
width +
i);
375 const float L = in[index];
378 const float Lout = fmaxf( 0.0f,
L
379 + norm * (buf[gi] * (1.0f - xf) * (1.0f - yf) * (1.0f - zf)
380 + buf[gi + ox] * (xf) * (1.0f - yf) * (1.0f - zf)
381 + buf[gi + oy] * (1.0f - xf) * (yf) * (1.0f - zf)
382 + buf[gi + ox + oy] * (xf) * (yf) * (1.0f - zf)
383 + buf[gi + oz] * (1.0f - xf) * (1.0f - yf) * (zf)
384 + buf[gi + ox + oz] * (xf) * (1.0f - yf) * (zf)
385 + buf[gi + oy + oz] * (1.0f - xf) * (yf) * (zf)
386 + buf[gi + ox + oy + oz] * (xf) * (yf) * (zf)));
389 out[index + 1] = in[index + 1];
390 out[index + 2] = in[index + 2];
391 out[index + 3] = in[index + 3];
400 const float norm = -detail * b->sigma_r * 0.04f;
401 const int ox = b->size_z;
402 const int oy = b->size_x * b->size_z;
404 float *
const buf = b->buf;
405 const int width = b->width;
406 const int height = b->height;
410 for(
int j = 0; j <
height; j++)
414 size_t index = 4 * (j *
width +
i);
416 const float L = in[index];
419 const float Lout = norm * (buf[gi] * (1.0f - xf) * (1.0f - yf) * (1.0f - zf)
420 + buf[gi + ox] * (xf) * (1.0f - yf) * (1.0f - zf)
421 + buf[gi + oy] * (1.0f - xf) * (yf) * (1.0f - zf)
422 + buf[gi + ox + oy] * (xf) * (yf) * (1.0f - zf)
423 + buf[gi + oz] * (1.0f - xf) * (1.0f - yf) * (zf)
424 + buf[gi + ox + oz] * (xf) * (1.0f - yf) * (zf)
425 + buf[gi + oy + oz] * (1.0f - xf) * (yf) * (zf)
426 + buf[gi + ox + oy + oz] * (xf) * (yf) * (zf));
427 out[index] =
MAX(0.0f,
out[index] + Lout);
439#undef DT_COMMON_BILATERAL_MAX_RES_S
440#undef DT_COMMON_BILATERAL_MAX_RES_R
void dt_bilateral_free(dt_bilateral_t *b)
static __DT_CLONE_TARGETS__ void blur_line(float *buf, const int offset1, const int offset2, const int offset3, const int size1, const int size2, const int size3)
static __DT_CLONE_TARGETS__ void blur_line_z(float *buf, const int offset1, const int offset2, const int offset3, const int size1, const int size2, const int size3)
__DT_CLONE_TARGETS__ void dt_bilateral_splat(const dt_bilateral_t *b, const float *const in)
void dt_bilateral_grid_size(dt_bilateral_t *b, const int width, const int height, const float L_range, float sigma_s, const float sigma_r)
size_t dt_bilateral_memory_use(const int width, const int height, const float sigma_s, const float sigma_r)
#define DT_COMMON_BILATERAL_MAX_RES_S
dt_bilateral_t * dt_bilateral_init(const int width, const int height, const float sigma_s, const float sigma_r)
#define DT_COMMON_BILATERAL_MAX_RES_R
__DT_CLONE_TARGETS__ void dt_bilateral_slice_to_output(const dt_bilateral_t *const b, const float *const in, float *out, const float detail)
size_t dt_bilateral_singlebuffer_size(const int width, const int height, const float sigma_s, const float sigma_r)
__DT_CLONE_TARGETS__ void dt_bilateral_slice(const dt_bilateral_t *const b, const float *const in, float *out, const float detail)
void dt_bilateral_blur(const dt_bilateral_t *b)
size_t dt_bilateral_memory_use2(const int width, const int height, const float sigma_s, const float sigma_r)
size_t dt_bilateral_singlebuffer_size2(const int width, const int height, const float sigma_s, const float sigma_r)
static void image_to_grid(const dt_iop_colorreconstruct_bilateral_t *const b, const float i, const float j, const float L, float *x, float *y, float *z)
const dt_colormatrix_t dt_aligned_pixel_t out
int dt_get_num_openmp_threads(void)
Number of OpenMP threads the application decided to use.
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
float *const restrict const size_t k
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
#define __OMP_SIMD__(...)
#define __OMP_PARALLEL_FOR__(...)
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define dt_pixelpipe_cache_free_align(mem)
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Apply one channel's tone curve to each of the three colour channels, or pass the channel through unto...
#define __DT_CLONE_TARGETS__