90#define INSET DT_PIXEL_APPLY_DPI(5)
97#define MAX_NUM_SCALES 8
100#define dt_atrous_show_upper_label(cr, text, layout, ink) \
101 pango_layout_set_text(layout, text, -1); \
102 pango_layout_get_pixel_extents(layout, &ink, NULL); \
103 cairo_move_to(cr, .5 * (width - ink.width), (.08 * height) - ink.height); \
104 pango_cairo_show_layout(cr, layout);
107#define dt_atrous_show_lower_label(cr, text, layout, ink) \
108 pango_layout_set_text(layout, text, -1); \
109 pango_layout_get_pixel_extents(layout, &ink, NULL); \
110 cairo_move_to(cr, .5 * (width - ink.width), (.98 * height) - ink.height); \
111 pango_cairo_show_layout(cr, layout);
172 return _(
"contrast equalizer");
177 return _(
"sharpness|acutance|local contrast");
183 _(
"corrective and creative"),
184 _(
"linear, Lab, scene-referred"),
185 _(
"frequential, RGB"),
186 _(
"linear, Lab, scene-referred"));
234 const float scale = roi_in->
scale;
242 const float supp = 2 * (2 <<
i) + 1;
247 if(
t[
i] < 0.0f)
break;
266 const float scale = roi_in->
scale;
276 const float supp = 2 * (2 <<
i) + 1;
281 const float t = 1.0f - (
i_in + .5f) /
i0;
356 float *
buf1 = (
float *)
i;
364 for(
int scale = 0; scale <
max_scale; scale++)
368 if(scale == 0)
buf1 = (
float *)
tmp2;
428 float m[] = { 0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f };
430 for(
int j = 0;
j < 5;
j++)
447 const int width = roi_out->width;
448 const int height = roi_out->height;
556 float m[] = { 0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f };
558 for(
int j = 0;
j < 5;
j++)
559 for(
int i = 0;
i < 5;
i++)
581 size_t origin[] = { 0, 0, 0 };
615 for(
int scale =
max_scale - 1; scale >= 0; scale--)
701 const int program = 1;
726 const int ch,
const int k,
728 const float px,
const float py,
float *
x,
float *y)
742 printf(
"---------- atrous preset begin\n");
743 printf(
"p.octaves = %d; p.mix = %.2f\n",
p->octaves,
p->mix);
749 printf(
"---------- atrous preset end\n");
751 d->octaves =
p->octaves;
810#define GAUSS(x, sigma) expf( -(1.0f - x) * (1.0f - x) / (sigma * sigma)) / (2.0 * sigma * powf(M_PI, 0.5f))
833 self->version(), &
p,
sizeof(
p), 1);
848 self->version(), &
p,
sizeof(
p), 1);
863 self->version(), &
p,
sizeof(
p), 1);
878 self->version(), &
p,
sizeof(
p), 1);
893 self->version(), &
p,
sizeof(
p), 1);
909 self->version(), &
p,
sizeof(
p), 1);
924 self->version(), &
p,
sizeof(
p), 1);
930 const float x =
k / (float)(
BANDS - 1);
934 const float coeff = 0.5f + (coarse + medium + fine) / 16.0f;
935 const float noise = (coarse + medium + fine) / 128.f;
944 self->version(), &
p,
sizeof(
p), 1);
948 const float x =
k / (float)(
BANDS - 1);
951 const float coeff = 0.5f + (medium + fine) / 16.0f;
952 const float noise = (medium + fine) / 128.f;
961 self->version(), &
p,
sizeof(
p), 1);
965 const float x =
k / (float)(
BANDS - 1);
967 const float coeff = 0.5f + fine / 16.f;
968 const float noise = fine / 128.f;
977 self->version(), &
p,
sizeof(
p), 1);
981 const float x =
k / (float)(
BANDS - 1);
985 const float coeff = 0.5f + (coarse + medium + fine) / 24.0f;
986 const float noise = (coarse + medium + fine) / 192.f;
995 self->version(), &
p,
sizeof(
p), 1);
999 const float x =
k / (float)(
BANDS - 1);
1002 const float coeff = 0.5f + (medium + fine) / 24.0f;
1003 const float noise = (medium + fine) / 192.f;
1012 self->version(), &
p,
sizeof(
p), 1);
1016 const float x =
k / (float)(
BANDS - 1);
1018 const float coeff = 0.5f + fine / 24.0f;
1019 const float noise = fine / 192.f;
1028 self->version(), &
p,
sizeof(
p), 1);
1032 const float x =
k / (float)(
BANDS - 1);
1036 const float coeff = 0.5f + (coarse + medium + fine) / 32.0f;
1037 const float noise = (coarse + medium + fine) / 128.f;
1046 self->version(), &
p,
sizeof(
p), 1);
1050 const float x =
k / (float)(
BANDS - 1);
1053 const float coeff = 0.5f + (medium + fine) / 32.0f;
1054 const float noise = (medium + fine) / 128.f;
1063 self->version(), &
p,
sizeof(
p), 1);
1067 const float x =
k / (float)(
BANDS - 1);
1069 const float coeff = 0.5f + fine / 32.f;
1070 const float noise = fine / 128.f;
1079 self->version(), &
p,
sizeof(
p), 1);
1088 c->drag_params = *
p;
1107 if(!c->dragging) c->mouse_y =
fabs(c->mouse_y);
1117 if(!c->dragging) c->mouse_y = -
fabs(c->mouse_y);
1118 c->in_curve =
FALSE;
1140 const float mix = c->in_curve ? 1.0f :
p.mix;
1144 const int ch2 = (int)c->channel2;
1150 const int inset =
INSET;
1151 GtkAllocation allocation;
1153 int width = allocation.width,
height = allocation.height;
1172 graph_bg.green = 0.0;
1173 graph_bg.blue = 0.0;
1174 graph_bg.alpha = 1.0;
1193 if(c->mouse_y > 0 || c->dragging)
1195 const int ch2 = (int)c->channel2;
1223 if(c->num_samples > 0)
1226 for(
int k = 1;
k < c->num_samples;
k += 2)
1235 if(c->num_samples & 1)
1265 int ch = ((int)c->channel +
i + 1) % (
atrous_s + 1);
1285 if(c->channel2 ==
ch2)
1301 for(
int k =
RES - 2;
k >= 0;
k--)
1313 for(
int k = 0;
k <
RES;
k++)
1322 if(c->mouse_y > 0 || c->dragging)
1324 const int ch = (int)c->channel;
1325 const int ch2 = (int)c->channel2;
1347 if(c->mouse_y > 0 || c->dragging)
1352 for(
int k = 1;
k <
RES;
k++)
1354 for(
int k =
RES - 1;
k >= 0;
k--)
1360 const float pos =
RES * c->mouse_x;
1362 const float f =
k - pos;
1364 const float ht = -
height * (
f * c->draw_ys[
k] + (1 -
f) * c->draw_ys[
k + 1]);
1390 if(c->mouse_y > 0 || c->dragging)
1451 const int inset =
INSET;
1452 GtkAllocation allocation;
1454 const int height = allocation.height - 2 * inset;
1455 const int width = allocation.width - 2 * inset;
1456 if(!c->dragging) c->mouse_x =
CLAMP(event->x - inset, 0,
width) / (float)
width;
1459 int ch2 = c->channel;
1466 *
p = c->drag_params;
1470 if(c->x_move > 0 && c->x_move <
BANDS - 1)
1472 const float minx =
p->x[c->channel][c->x_move - 1] + 0.001f;
1473 const float maxx =
p->x[c->channel][c->x_move + 1] - 0.001f;
1474 p->x[
ch2][c->x_move] =
p->x[c->channel][c->x_move] =
fminf(maxx,
fmaxf(minx,
mx));
1479 get_params(
p, c->channel2, c->mouse_x, c->mouse_y + c->mouse_pick, c->mouse_radius);
1484 else if(event->y >
height)
1488 float dist =
fabs(
p->x[c->channel][0] - c->mouse_x);
1491 const float d2 =
fabs(
p->x[c->channel][
k] - c->mouse_x);
1503 const int ch = c->channel;
1504 float dist = 1000000.0f;
1507 float d2 =
fabs(
p->x[c->channel][
k] - c->mouse_x);
1536 p->x[c->channel2][
k] =
d->x[c->channel2][
k];
1537 p->y[c->channel2][
k] =
d->y[c->channel2][
k];
1542 else if(event->button == 1)
1547 const int inset =
INSET;
1548 GtkAllocation allocation;
1550 const int height = allocation.height - 2 * inset;
1551 const int width = allocation.width - 2 * inset;
1563 if(event->button == 1)
1582 c->mouse_radius =
CLAMP(c->mouse_radius * (1.0 + 0.1 *
delta_y), 0.25 /
BANDS, 1.0);
1614 c->channel = c->channel2 =
dt_conf_get_int(
"plugins/darkroom/atrous/gui_channel");
1615 int ch = (int)c->channel;
1619 c->mouse_x = c->mouse_y = c->mouse_pick = -1.0;
1623 c->mouse_radius = 1.0 /
BANDS;
1624 c->in_curve =
FALSE;
1631 dt_ui_notebook_page(c->channel_tabs,
N_(
"edges"),
_(
"change edge halos at each feature size\nonly changes results of luma and chroma tabs"));
1642 "plugins/darkroom/atrous/graphheight", 280, 100),
static double dist(double x1, double y1, double x2, double y2)
static void error(char *msg)
void init(dt_iop_module_t *module)
static gboolean area_button_press(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
const char ** description(struct dt_iop_module_t *self)
static __DT_CLONE_TARGETS__ int get_scales(float(*thrs)[4], float(*boost)[4], float *sharp, const dt_iop_atrous_data_t *const d, const dt_iop_roi_t *roi_in, const dt_dev_pixelpipe_iop_t *const piece)
static gboolean area_leave_notify(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
static void reset_mix(dt_iop_module_t *self)
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)
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
void gui_update(struct dt_iop_module_t *self)
void gui_init(struct dt_iop_module_t *self)
static void mix_callback(GtkWidget *slider, gpointer user_data)
static void _apply_mix(dt_iop_module_t *self, const int ch, const int k, const float mix, const float px, const float py, float *x, float *y)
#define dt_atrous_show_lower_label(cr, text, layout, ink)
static __DT_CLONE_TARGETS__ int process_wavelets(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, const void *const i, void *const o, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out, const eaw_decompose_t decompose, const eaw_synthesize_t synthesize)
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 cleanup_global(dt_iop_module_so_t *module)
static void get_params(dt_iop_atrous_params_t *p, const int ch, const double mouse_x, const double mouse_y, const float rad)
static gboolean area_enter_notify(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
static gboolean area_button_release(GtkWidget *widget, GdkEventButton *event, gpointer user_data)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
static gboolean area_motion_notify(GtkWidget *widget, GdkEventMotion *event, gpointer user_data)
static gboolean area_draw(GtkWidget *widget, cairo_t *crf, gpointer user_data)
void gui_cleanup(struct dt_iop_module_t *self)
void init_presets(dt_iop_module_so_t *self)
static __DT_CLONE_TARGETS__ int get_samples(float *t, const dt_iop_atrous_data_t *const d, const dt_iop_roi_t *roi_in, const dt_dev_pixelpipe_iop_t *const piece)
static gboolean area_scrolled(GtkWidget *widget, GdkEventScroll *event, gpointer user_data)
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
int process(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, const struct dt_dev_pixelpipe_iop_t *piece, const void *const i, void *const o)
void init_global(dt_iop_module_so_t *module)
#define dt_atrous_show_upper_label(cr, text, layout, ink)
int process_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out)
static void tab_switch(GtkNotebook *notebook, GtkWidget *page, guint page_num, gpointer user_data)
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
float dt_bauhaus_slider_get(GtkWidget *widget)
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
const float *const const float coeff[3]
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
const dt_colormatrix_t dt_aligned_pixel_t out
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
Integer for name, clamped to the bounds declared in the XML.
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
#define dt_database_start_transaction()
#define dt_database_release_transaction()
#define dt_dev_add_history_item(dev, module, enable, redraw)
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
static void dt_draw_curve_calc_values(dt_draw_curve_t *c, const float min, const float max, const int res, float *x, float *y)
static void dt_draw_grid(cairo_t *cr, const int num, const int left, const int top, const int right, const int bottom)
static float dt_draw_curve_calc_value(dt_draw_curve_t *c, const float x)
static void dt_draw_curve_destroy(dt_draw_curve_t *c)
static void dt_draw_curve_set_point(dt_draw_curve_t *c, const int num, const float x, const float y)
static int dt_draw_curve_add_point(dt_draw_curve_t *c, const float x, const float y)
static dt_draw_curve_t * dt_draw_curve_new(const float min, const float max, unsigned int type)
void eaw_decompose(float *const restrict out, const float *const restrict in, float *const restrict detail, const int scale, const float sharpen, const int32_t width, const int32_t height)
void eaw_synthesize(float *const out, const float *const in, const float *const restrict detail, const float *const restrict threshold, const float *const restrict boost, const int32_t width, const int32_t height)
void dt_gui_presets_add_generic(const char *name, dt_dev_operation_t op, const int32_t version, const void *params, const int32_t params_size, const int32_t enabled)
int dt_iop_alloc_image_buffers(struct dt_iop_module_t *const module, const struct dt_iop_roi_t *const roi_in, const struct dt_iop_roi_t *const roi_out,...)
static void dt_iop_image_copy_by_size(float *const __restrict__ out, const float *const __restrict__ in, const size_t width, const size_t height, const size_t ch)
void dt_iop_default_init(dt_iop_module_t *module)
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)
@ IOP_FLAGS_SUPPORTS_BLENDING
GtkWidget * dt_bauhaus_slider_from_params(dt_iop_module_t *self, const char *param)
static dt_iop_gui_data_t * dt_iop_gui_data(const struct dt_iop_module_t *m)
The module's GUI data blob, NULL-safe for headless callers: IOP process() implementations read it for...
#define IOP_GUI_ALLOC(module)
static const dt_dev_pixelpipe_t * pipe
static const dt_dev_pixelpipe_t const dt_dev_pixelpipe_iop_t * piece
static const dt_iop_drawlayer_params_t * params
static float mix(const float a, const float b, const float t)
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
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_align(ptr)
Release memory from dt_alloc_align() and set ptr to NULL.
static void * dt_calloc_align(size_t size)
dt_alloc_align() followed by a zero fill.
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
DT_MODULE() for a module whose params struct is introspected.
GtkWidget * dt_ui_notebook_page(GtkNotebook *notebook, const char *text, const char *tooltip)
GtkNotebook * dt_ui_notebook_new()
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)
void * dt_opencl_copy_host_to_device_constant(const int devid, const size_t size, void *host)
int dt_opencl_enqueue_copy_image(const int devid, cl_mem src, cl_mem dst, size_t *orig_src, size_t *orig_dst, size_t *region)
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)
void dt_opencl_release_mem_object(cl_mem mem)
#define __OMP_SIMD__(...)
#define dt_pixelpipe_cache_free_align(mem)
static cairo_surface_t * dt_cairo_image_surface_create(cairo_format_t format, int width, int height)
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
dt_draw_curve_t * curve[atrous_none]
atrous_channel_t channel2
dt_iop_atrous_params_t drag_params
GtkNotebook * channel_tabs
dt_draw_curve_t * minmax_curve
dt_iop_params_t * default_params
struct dt_iop_module_gui_t * gui
struct dt_develop_t * dev
dt_iop_global_data_t * global_data
Region of interest passed through the pixelpipe.
#define __DT_CLONE_TARGETS__