127 return _(
"haze removal");
133 return _(
"dehaze|defog|smoke|smog");
140 _(
"linear, RGB, scene-referred"),
141 _(
"frequential, RGB"),
142 _(
"linear, RGB, scene-referred"));
180 const int program = 27;
209 g->distance_max = NAN;
238 g->expected_preview_hash = preview_hash;
247 g->distance_max = NAN;
255 gtk_widget_set_tooltip_text(
g->strength, _(
"amount of haze reduction"));
259 gtk_widget_set_tooltip_text(
g->distance, _(
"limit haze removal up to a specific spatial depth"));
313 for(
size_t i = 0;
i <
size;
i++)
317 m = fminf(pixel[1],
m);
318 m = fminf(pixel[2],
m);
336 for(
size_t i = 0;
i <
size;
i++)
339 float m = pixel[0] / A0[0];
340 m = fminf(pixel[1] / A0[1],
m);
341 m = fminf(pixel[2] / A0[2],
m);
356static float *
partition(
float *first,
float *last,
float val)
358 for(; first != last; ++first)
360 if(!((*first) < val))
break;
362 if(first == last)
return first;
363 for(
float *
i = first + 1;
i != last; ++
i)
383 if(first == last)
return;
388 float *pivot = first + (last - first) / 2;
389 float *p3 = last - 1;
413 const float dark_channel_quantil = 0.95f;
414 const float bright_quantil = 0.95f;
427 size_t p = (size_t)(
size * dark_channel_quantil);
429 const float crit_haze_level = bright_hazy.
data[
p];
430 size_t N_most_hazy = 0;
431 for(
size_t i = 0;
i <
size;
i++)
432 if(dark_ch.
data[
i] >= crit_haze_level)
436 bright_hazy.
data[N_most_hazy] = pixel_in[0] + pixel_in[1] + pixel_in[2];
439 p = (size_t)(N_most_hazy * bright_quantil);
441 const float crit_brightness = bright_hazy.
data[
p];
445 float A0_r = 0, A0_g = 0, A0_b = 0;
446 size_t N_bright_hazy = 0;
447 const float *
const data = dark_ch.
data;
449 for(
size_t i = 0;
i <
size;
i++)
452 if((data[
i] >= crit_haze_level) && (pixel_in[0] + pixel_in[1] + pixel_in[2] >= crit_brightness))
460 if(N_bright_hazy > 0)
462 A0_r /= N_bright_hazy;
463 A0_g /= N_bright_hazy;
464 A0_b /= N_bright_hazy;
477 *max_depth_out = crit_haze_level > 0 ? -1.125f * logf(crit_haze_level) : logf(FLT_MAX) / 2;
508 const float distance =
d->distance;
509 const float eps = sqrtf(0.025f);
519 float distance_max = NAN;
531 const uint64_t expected_preview_hash =
g->expected_preview_hash;
539 && hash == expected_preview_hash)
545 distance_max =
g->distance_max;
550 if(isnan(distance_max))
566 g->distance_max = distance_max;
567 g->expected_preview_hash = hash;
596 if(
guided_filter(img_in.
data, trans_map.
data, trans_map_filtered.
data,
width,
height,
ch,
w2,
eps, 1.f, -FLT_MAX,
605 = fminf(fmaxf(expf(-distance * distance_max), 1.f / 1024), 1.f);
606 const float *
const c_A0 = A0;
607 const gray_image c_trans_map_filtered = trans_map_filtered;
609 for(
size_t i = 0;
i <
size;
i++)
611 float t = fmaxf(c_trans_map_filtered.
data[
i], t_min);
612 const float *pixel_in = img_in.
data +
i * img_in.
stride;
613 float *pixel_out = img_out.
data +
i * img_out.
stride;
614 pixel_out[0] = (pixel_in[0] - c_A0[0]) /
t + c_A0[0];
615 pixel_out[1] = (pixel_in[1] - c_A0[1]) /
t + c_A0[1];
616 pixel_out[2] = (pixel_in[2] - c_A0[2]) /
t + c_A0[2];
641 float *max_depth_out)
652 if(err != CL_SUCCESS)
goto error;
656 err = CL_MEM_OBJECT_ALLOCATION_FAILURE;
683 if(err != CL_SUCCESS)
goto error;
716 if(err != CL_SUCCESS)
goto error;
735 const float strength,
const float *
const A0)
752 if(err != CL_SUCCESS)
764 const float t_min,
const float *
const A0)
806 const int devid = pipe->
devid;
814 const float distance =
d->distance;
815 const float eps = sqrtf(0.025f);
822 float distance_max = NAN;
834 const uint64_t expected_preview_hash =
g->expected_preview_hash;
837 && hash == expected_preview_hash)
843 distance_max =
g->distance_max;
848 if(isnan(distance_max))
850 float max_depth = 0.f;
852 distance_max = max_depth;
862 g->distance_max = distance_max;
863 g->expected_preview_hash = hash;
875 if(
guided_filter_cl(devid, img_in, trans_map, trans_map_filtered,
width,
height,
ch,
w2,
eps, 1.f, -CL_FLT_MAX,
885 = fminf(fmaxf(expf(-distance * distance_max), 1.f / 1024), 1.f);
886 dehaze_cl(self, devid, img_in, trans_map_filtered, img_out, t_min, A0);
static void error(char *msg)
void dt_bauhaus_slider_set_digits(GtkWidget *widget, int val)
int dt_box_max(float *const buf, const size_t height, const size_t width, const int ch, const int radius)
int dt_box_min(float *const buf, const size_t height, const size_t width, const int ch, const int radius)
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
const dt_colormatrix_t dt_aligned_pixel_t out
static float strength(float value, float strength)
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
void dt_print(dt_debug_thread_t thread, const char *msg,...)
#define dt_free_align(ptr)
static void * dt_calloc_align(size_t size)
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
#define dt_pixelpipe_cache_free_align(mem)
#define __DT_CLONE_TARGETS__
#define __OMP_PARALLEL_FOR__(...)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
dt_dev_pixelpipe_iop_t * dt_dev_distort_get_iop_pipe(struct dt_dev_pixelpipe_t *pipe, struct dt_iop_module_t *module)
gboolean dt_dev_pixelpipe_has_preview_output(const dt_develop_t *dev, const dt_dev_pixelpipe_t *pipe, const dt_iop_roi_t *roi)
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
int guided_filter_cl(int devid, cl_mem guide, cl_mem in, cl_mem out, const int width, const int height, const int ch, const int w, const float sqrt_eps, const float guide_weight, const float min, const float max)
__DT_CLONE_TARGETS__ int guided_filter(const float *const guide, const float *const in, float *const out, const int width, const int height, const int ch, const int w, const float sqrt_eps, const float guide_weight, const float min, const float max)
static void copy_gray_image(gray_image img1, gray_image img2)
static int new_gray_image(gray_image *img, int width, int height)
static void free_gray_image(gray_image *img_p)
int process_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, cl_mem img_in, cl_mem img_out)
static __DT_CLONE_TARGETS__ int ambient_light(const const_rgb_image img, int w1, rgb_pixel *pA0, float *max_depth_out)
const char ** description(struct dt_iop_module_t *self)
__DT_CLONE_TARGETS__ int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid)
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *params, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static int dehaze_cl(struct dt_iop_module_t *self, int devid, cl_mem img_in, cl_mem trans_map, cl_mem img_out, const float t_min, const float *const A0)
static int box_max_cl(struct dt_iop_module_t *self, int devid, cl_mem in, cl_mem out, const int w)
static uint64_t _current_preview_hash(dt_iop_module_t *self)
static float * partition(float *first, float *last, float val)
static __DT_CLONE_TARGETS__ int transition_map(const const_rgb_image img1, const gray_image img2, const int w, const float *const A0, const float strength)
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static int box_min_cl(struct dt_iop_module_t *self, int devid, cl_mem in, cl_mem out, const int w)
void gui_update(struct dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
void cleanup_global(dt_iop_module_so_t *self)
void gui_init(dt_iop_module_t *self)
static __DT_CLONE_TARGETS__ int dark_channel(const const_rgb_image img1, const gray_image img2, const int w)
void tiling_callback(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, struct dt_develop_tiling_t *tiling)
void gui_cleanup(dt_iop_module_t *self)
static int transition_map_cl(struct dt_iop_module_t *self, int devid, cl_mem img1, cl_mem img2, const int w1, const float strength, const float *const A0)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
static void pointer_swap_f(float *a, float *b)
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static int ambient_light_cl(struct dt_iop_module_t *self, int devid, cl_mem img, int w1, rgb_pixel *pA0, float *max_depth_out)
static void _history_resync_callback(gpointer instance, gpointer user_data)
void init_global(dt_iop_module_so_t *self)
dt_iop_hazeremoval_params_t dt_iop_hazeremoval_data_t
__DT_CLONE_TARGETS__ void quick_select(float *first, float *nth, float *last)
const char ** dt_iop_set_description(dt_iop_module_t *module, const char *main_text, const char *purpose, const char *input, const char *process, const char *output)
static void dt_iop_gui_enter_critical_section(dt_iop_module_t *const module) ACQUIRE(&module -> gui_lock)
@ IOP_FLAGS_INCLUDE_IN_STYLES
@ IOP_FLAGS_SUPPORTS_BLENDING
static void dt_iop_gui_leave_critical_section(dt_iop_module_t *const module) RELEASE(&module -> gui_lock)
#define IOP_GUI_ALLOC(module)
GtkWidget * dt_bauhaus_slider_from_params(dt_iop_module_t *self, const char *param)
static float kernel(const float *x, const float *y)
float *const restrict const size_t const size_t ch
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
void * dt_opencl_alloc_device(const int devid, const int width, const int height, const int bpp)
int dt_opencl_create_kernel(const int prog, const char *name)
int dt_opencl_get_image_height(cl_mem mem)
void dt_opencl_free_kernel(const int kernel)
int dt_opencl_get_image_width(cl_mem mem)
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_read_host_from_device(const int devid, void *host, void *device, const int width, const int height, const int bpp)
void dt_opencl_release_mem_object(cl_mem mem)
int dt_opencl_get_image_element_size(cl_mem mem)
#define DT_PIXELPIPE_CACHE_HASH_INVALID
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
@ DT_SIGNAL_HISTORY_RESYNC
This signal is raised once darkroom history has been resynchronized into all live pipelines....
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
struct _GtkWidget GtkWidget
unsigned __int64 uint64_t
struct dt_control_signal_t * signals
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
gboolean cache_output_on_ram
struct dt_dev_pixelpipe_t * preview_pipe
int kernel_hazeremoval_transision_map
int kernel_hazeremoval_dehaze
int kernel_hazeremoval_box_min_x
int kernel_hazeremoval_box_max_y
int kernel_hazeremoval_box_max_x
int kernel_hazeremoval_box_min_y
uint64_t expected_preview_hash
dt_iop_global_data_t * data
struct dt_develop_t * dev
dt_iop_gui_data_t * gui_data
dt_iop_global_data_t * global_data
Region of interest passed through the pixelpipe.