44 const int return_layer,
const int merge_from_scale,
void *user_data,
45 const float preview_scale,
const int use_sse)
55 p->return_layer = return_layer;
56 p->merge_from_scale = merge_from_scale;
57 p->user_data = user_data;
58 p->preview_scale = preview_scale;
78 float size_tmp = ((
size >>= 1) * preview_scale);
81 size_tmp = ((
size >>= 1) * preview_scale);
87 while((maxscale > 0) && ((1 << maxscale) * preview_scale >=
size)) maxscale--;
94 return _get_max_scale(
p->width /
p->preview_scale,
p->height /
p->preview_scale,
p->preview_scale);
102 for(
unsigned int lev = 0; lev < num_scales; lev++)
108 first_scale = lev + 1;
123 if(
p->image != layer) memcpy(
p->image, layer,
sizeof(
float) *
p->width *
p->height *
p->ch);
129 const size_t height,
const size_t width,
const size_t lev)
131 const size_t vscale =
MIN(1 << lev,
height-1);
133 for(
int rowid = 0; rowid <
height ; rowid++)
141 const size_t rowstart = (size_t)4 *
row *
width;
142 const size_t above_row = (
row > vscale) ?
row - vscale : vscale -
row;
144 const float*
const restrict center = in + rowstart;
145 const float*
const restrict above = in + 4 * above_row *
width;
146 const float*
const restrict below = in + 4 * below_row *
width;
147 float*
const restrict temprow =
out + rowstart;
148 for (
size_t col = 0; col < 4*
width; col += 4)
152 temprow[col + c] = 2.f * center[col+c] + above[col+c] + below[col+c];
162 const size_t height,
const size_t width,
const size_t lev)
164 const int hscale =
MIN(1 << lev,
width);
173 const size_t rowindex = (size_t)4 * (
row *
width);
175 float*
const restrict details = in + rowindex;
176 float*
const restrict coarse =
out + rowindex;
178 for (
int col = 0; col <
width - hscale; col++)
180 const size_t leftpos = (size_t)4*abs(col-hscale);
181 const size_t rightpos = (size_t)4*(col+hscale);
184 const float left = coarse[leftpos+c];
185 const float right = coarse[rightpos+c];
187 const float hat = (2.f * coarse[4*col+c] + left + right) / 16.f;
189 temprow[4*col+c] = hat;
190 details[4*col+c] -= hat;
194 for (
int col =
width - hscale; col <
width; col++)
196 const size_t leftpos = (size_t)4 * abs(col-hscale);
197 const size_t rightpos = (size_t)4 * (2*
width - 2 - (col+hscale));
200 const float left = coarse[leftpos+c];
201 const float right = coarse[rightpos+c];
203 const float hat = (2.f * coarse[4*col+c] + left + right) / 16.f;
205 temprow[4*col+c] = hat;
206 details[4*col+c] -= hat;
211 memcpy(coarse, temprow,
sizeof(
float) * 4 *
width);
216static inline __attribute__((always_inline))
void dwt_decompose_layer(
float *
const restrict
out,
float *
const restrict in,
float *
const temp,
const int lev,
229 float *layers = NULL;
230 float *merged_layers = NULL;
231 float *buffer[2] = { 0, 0 };
234 const size_t size = (size_t)
p->width *
p->height *
p->ch;
238 if(layer_func && layer_func(img,
p, 0) != 0)
return 1;
253 printf(
"not enough memory for wavelet decomposition");
259 if(
p->merge_from_scale > 0)
264 printf(
"not enough memory for wavelet decomposition");
272 unsigned int hpass = 0;
273 for(
unsigned int lev = 0; lev <
p->scales && bcontinue; lev++)
275 unsigned int lpass = (1 - (lev & 1));
277 dwt_decompose_layer(buffer[lpass], buffer[hpass], temp, lev,
p);
280 if(
p->merge_from_scale == 0 ||
p->merge_from_scale > lev + 1)
283 if(layer_func && layer_func(buffer[hpass],
p, lev + 1) != 0)
290 if(
p->return_layer == lev + 1)
293 dwt_get_image_layer(buffer[hpass],
p);
298 else if(
p->return_layer == 0)
311 if(layer_func && layer_func(merged_layers,
p, lev + 1) != 0)
318 if(
p->return_layer == lev + 1)
321 dwt_get_image_layer(merged_layers,
p);
334 if(layer_func && layer_func(buffer[hpass],
p,
p->scales + 1) != 0)
341 if(
p->return_layer ==
p->scales + 1)
344 dwt_get_image_layer(buffer[hpass],
p);
347 else if(
p->return_layer == 0)
350 if(
p->merge_from_scale > 0)
360 if(layer_func && layer_func(layers,
p,
p->scales + 2) != 0)
367 dwt_get_image_layer(layers,
p);
383 if(
p->preview_scale <= 0.f)
p->preview_scale = 1.f;
386 if(
p->return_layer >
p->scales + 1)
388 p->return_layer =
p->scales + 1;
394 if(
p->scales > max_scale)
397 if(
p->return_layer >
p->scales)
p->return_layer = max_scale + 1;
399 else if(
p->return_layer > max_scale)
400 p->return_layer = max_scale;
402 p->scales = max_scale;
412 const size_t height,
const size_t width,
const size_t lev)
414 const int vscale =
MIN(1 << lev,
height);
416 for(
int rowid = 0; rowid <
height ; rowid++)
424 const size_t rowstart = (size_t)
row *
width;
426 const float *
const restrict center = in + rowstart;
427 const float *
const restrict above = in + abs(
row - vscale) *
width;
428 const float *
const restrict below = in + below_row *
width;
429 float*
const restrict outrow =
out + rowstart;
431 for (
int col= 0; col <
width; col++)
433 outrow[col] = 2.f * center[col] + above[col] + below[col];
442 float *
const restrict accum,
const size_t height,
const size_t width,
443 const size_t lev,
const float thold,
const int last)
445 const int hscale =
MIN(1 << lev,
width);
454 const size_t rowindex = (size_t)
row *
width;
455 float *
const restrict details = in + rowindex;
456 float *
const restrict coarse =
out + rowindex;
457 float *
const restrict accum_row = accum + rowindex;
460 for (
int col = 0; col < hscale; col++)
463 const float hat = (2.f * coarse[col] + coarse[hscale-col] + coarse[col+hscale]) / 16.f;
466 const float diff = details[col] - hat;
471 accum_row[col] +=
MAX(diff - thold,0.0f) +
MIN(diff + thold, 0.0f);
474 for (
int col = hscale; col <
width - hscale; col++)
477 const float hat = (2.f * coarse[col] + coarse[col-hscale] + coarse[col+hscale]) / 16.f;
480 const float diff = details[col] - hat;
485 accum_row[col] +=
MAX(diff - thold,0.0f) +
MIN(diff + thold, 0.0f);
489 for (
int col =
width - hscale; col <
width; col++)
491 const float right = coarse[2*
width - 2 - (col+hscale)];
493 const float hat = (2.f * coarse[col] + coarse[col-hscale] + right) / 16.f;
496 const float diff = details[col] - hat;
498 accum_row[col] +=
MAX(diff - thold,0.0f) +
MIN(diff + thold, 0.0f);
503 for (
int col = 0; col <
width; col++)
505 details[col] += accum_row[col];
525 for(
int lev = 0; lev < bands; lev++)
527 const int last = (lev+1) == bands;
552 const int program = 20;
578 const int return_layer,
const int merge_from_scale,
void *user_data,
579 const float preview_scale)
591 p->return_layer = return_layer;
592 p->merge_from_scale = merge_from_scale;
593 p->user_data = user_data;
594 p->preview_scale = preview_scale;
607 return _get_max_scale(
p->width /
p->preview_scale,
p->height /
p->preview_scale,
p->preview_scale);
617 cl_int err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
619 const int devid =
p->devid;
620 const int kernel =
p->global->kernel_dwt_subtract_layer;
624 const float lpass_mult = (1.f / 16.f);
625 const int width =
p->width;
640 cl_int err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
642 const int devid =
p->devid;
643 const int kernel =
p->global->kernel_dwt_add_img_to_layer;
647 const int width =
p->width;
661 cl_int err = CL_SUCCESS;
663 if(
p->image != layer)
665 (
size_t)
p->width *
p->height *
p->ch *
sizeof(
float));
672 cl_int err = CL_SUCCESS;
674 const int devid =
p->devid;
677 cl_mem layers = NULL;
678 cl_mem merged_layers = NULL;
679 unsigned int lpass, hpass;
680 cl_mem buffer[2] = { 0, 0 };
685 err = layer_func(img,
p, 0);
686 if(err != CL_SUCCESS)
goto cleanup;
695 if(buffer[1] == NULL)
697 printf(
"not enough memory for wavelet decomposition");
698 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
706 printf(
"not enough memory for wavelet decomposition");
707 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
712 const int kernel =
p->global->kernel_dwt_init_buffer;
715 const int width =
p->width;
722 if(err != CL_SUCCESS)
goto cleanup;
725 if(
p->merge_from_scale > 0)
730 printf(
"not enough memory for wavelet decomposition");
731 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
736 const int kernel =
p->global->kernel_dwt_init_buffer;
739 const int width =
p->width;
746 if(err != CL_SUCCESS)
goto cleanup;
753 for(
unsigned int lev = 0; lev <
p->scales && bcontinue; lev++)
755 lpass = (1 - (lev & 1));
762 printf(
"not enough memory for wavelet decomposition");
763 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
769 const int kernel =
p->global->kernel_dwt_hat_transform_row;
772 sc = (int)(sc *
p->preview_scale);
773 if(sc >
p->width) sc =
p->width;
783 if(err != CL_SUCCESS)
goto cleanup;
788 const int kernel =
p->global->kernel_dwt_hat_transform_col;
791 sc = (int)(sc *
p->preview_scale);
792 if(sc >
p->height) sc =
p->height;
793 const float lpass_mult = (1.f / 16.f);
804 if(err != CL_SUCCESS)
goto cleanup;
814 if(err != CL_SUCCESS)
goto cleanup;
817 if(
p->merge_from_scale == 0 ||
p->merge_from_scale > lev + 1)
822 err = layer_func(buffer[hpass],
p, lev + 1);
823 if(err != CL_SUCCESS)
goto cleanup;
827 if(
p->return_layer == lev + 1)
831 if(err != CL_SUCCESS)
goto cleanup;
836 else if(
p->return_layer == 0)
840 if(err != CL_SUCCESS)
goto cleanup;
848 if(err != CL_SUCCESS)
goto cleanup;
853 err = layer_func(merged_layers,
p, lev + 1);
854 if(err != CL_SUCCESS)
goto cleanup;
858 if(
p->return_layer == lev + 1)
862 if(err != CL_SUCCESS)
goto cleanup;
877 err = layer_func(buffer[hpass],
p,
p->scales + 1);
878 if(err != CL_SUCCESS)
goto cleanup;
882 if(
p->return_layer ==
p->scales + 1)
886 if(err != CL_SUCCESS)
goto cleanup;
889 else if(
p->return_layer == 0)
892 if(
p->merge_from_scale > 0)
896 if(err != CL_SUCCESS)
goto cleanup;
901 if(err != CL_SUCCESS)
goto cleanup;
906 err = layer_func(layers,
p,
p->scales + 2);
907 if(err != CL_SUCCESS)
goto cleanup;
912 if(err != CL_SUCCESS)
goto cleanup;
927 cl_int err = CL_SUCCESS;
930 if(
p->preview_scale <= 0.f)
p->preview_scale = 1.f;
933 if(
p->return_layer >
p->scales + 1)
935 p->return_layer =
p->scales + 1;
941 if(
p->scales > max_scale)
944 if(
p->return_layer >
p->scales)
p->return_layer = max_scale + 1;
946 else if(
p->return_layer > max_scale)
947 p->return_layer = max_scale;
949 p->scales = max_scale;
void cleanup(dt_imageio_module_format_t *self)
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.
static __DT_CLONE_TARGETS__ void dwt_decompose_horiz(float *const restrict out, float *const restrict in, float *const temp, const size_t height, const size_t width, const size_t lev)
static __DT_CLONE_TARGETS__ int dwt_wavelet_decompose(float *img, dwt_params_t *const p, _dwt_layer_func layer_func)
__DT_CLONE_TARGETS__ int dwt_denoise(float *const img, const int width, const int height, const int bands, const float *const noise)
int dt_dwt_first_scale_visible_cl(dwt_params_cl_t *p)
static cl_int dwt_wavelet_decompose_cl(cl_mem img, dwt_params_cl_t *const p, _dwt_layer_func_cl layer_func)
int dwt_decompose(dwt_params_t *p, _dwt_layer_func layer_func)
int dwt_get_max_scale(dwt_params_t *p)
void dt_dwt_free(dwt_params_t *p)
dwt_params_cl_t * dt_dwt_init_cl(const int devid, cl_mem image, const int width, const int height, const int scales, const int return_layer, const int merge_from_scale, void *user_data, const float preview_scale)
static __DT_CLONE_TARGETS__ void dwt_denoise_horiz_1ch(float *const restrict out, float *const restrict in, float *const restrict accum, const size_t height, const size_t width, const size_t lev, const float thold, const int last)
static __DT_CLONE_TARGETS__ void dwt_decompose_vert(float *const restrict out, const float *const restrict in, const size_t height, const size_t width, const size_t lev)
static __DT_CLONE_TARGETS__ void dwt_denoise_vert_1ch(float *const restrict out, const float *const restrict in, const size_t height, const size_t width, const size_t lev)
static dt_dwt_cl_global_t * _dwt_cl_global
void dt_dwt_init_cl_global(void)
void dt_dwt_free_cl(dwt_params_cl_t *p)
dwt_params_t * dt_dwt_init(float *image, const int width, const int height, const int ch, const int scales, const int return_layer, const int merge_from_scale, void *user_data, const float preview_scale, const int use_sse)
void dt_dwt_free_cl_global(void)
static __DT_CLONE_TARGETS__ int _get_max_scale(const int width, const int height, const float preview_scale)
cl_int dwt_decompose_cl(dwt_params_cl_t *p, _dwt_layer_func_cl layer_func)
int dwt_get_max_scale_cl(dwt_params_cl_t *p)
static __DT_CLONE_TARGETS__ int _first_scale_visible(const int num_scales, const float preview_scale)
static cl_int dwt_get_image_layer_cl(cl_mem layer, dwt_params_cl_t *const p)
int dt_dwt_first_scale_visible(dwt_params_t *p)
static cl_int dwt_add_layer_cl(cl_mem img, cl_mem layers, dwt_params_cl_t *const p, const int n_scale)
static cl_int dwt_subtract_layer_cl(cl_mem bl, cl_mem bh, dwt_params_cl_t *const p)
int() _dwt_layer_func(float *layer, dwt_params_t *const p, const int scale)
static int dwt_interleave_rows(const int rowid, const int height, const int stride)
cl_int() _dwt_layer_func_cl(cl_mem layer, dwt_params_cl_t *const p, const int scale)
__DT_CLONE_TARGETS__ void dt_iop_image_add_image(float *const buf, const float *const other_image, const size_t width, const size_t height, const size_t ch)
__DT_CLONE_TARGETS__ void dt_iop_image_fill(float *const buf, const float fill_value, const size_t width, const size_t height, const size_t ch)
static float kernel(const float *x, const float *y)
float *const restrict const size_t const size_t ch
#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.
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
void * dt_opencl_alloc_device_buffer(const int devid, const size_t size)
int dt_opencl_create_kernel(const int prog, const char *name)
void dt_opencl_free_kernel(const int kernel)
int dt_opencl_set_kernel_arg(const int dev, const int kernel, const int num, const size_t size, const void *arg)
int dt_opencl_enqueue_copy_buffer_to_buffer(const int devid, cl_mem src_buffer, cl_mem dst_buffer, size_t srcoffset, size_t dstoffset, size_t size)
void dt_opencl_release_mem_object(cl_mem mem)
#define __OMP_SIMD__(...)
static int dt_get_thread_num()
Index of the calling thread within its parallel region, 0 outside one.
#define __OMP_PARALLEL_FOR__(...)
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define dt_pixelpipe_cache_free_align(mem)
#define for_each_channel(_var,...)
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...
int kernel_dwt_add_img_to_layer
dt_dwt_cl_global_t * global
#define __DT_CLONE_TARGETS__