192 return _(
"graduated density");
198 _(
"corrective and creative"),
199 _(
"linear or non-linear, RGB, scene-referred"),
200 _(
"non-linear, RGB"),
201 _(
"non-linear, RGB, display-referred"));
220static inline float f(
const float t,
const float c,
const float x)
222 return (
t / (1.0f + powf(c, -
x * 6.0f)) + (1.0f -
t) * (
x * .5f + .5f));
236 const float sn2 = s.
x * s.
x + s.
y * s.
y;
237 if(sn2 <= 0.0f)
return u.
x * u.
x + u.
y * u.
y;
239 const float t = CLAMP((s.
x * u.
x + s.
y * u.
y) / sn2, 0.0f, 1.0f);
240 const float dx = u.
x -
t * s.
x;
241 const float dy = u.
y -
t * s.
y;
242 return dx * dx + dy * dy;
252 const float normal_sign,
const gboolean active)
256 const float dx = opposite.
x - endpoint.
x;
257 const float dy = opposite.
y - endpoint.
y;
258 const float length = dt_fast_hypotf(dx, dy);
260 const float inv_len = 1.0f / length;
261 const float ux = dx * inv_len;
262 const float uy = dy * inv_len;
263 const float px = -uy;
267 e_1.
x = endpoint.
x + ux *
x;
268 e_1.
y = endpoint.
y + uy *
x;
270 const float mx = (endpoint.
x + e_1.
x) * 0.5f;
271 const float my = (endpoint.
y + e_1.
y) * 0.5f;
272 e_2.
x = mx + px * (
x * normal_sign);
273 e_2.
y = my + py * (
x * normal_sign);
275 cairo_move_to(cr, endpoint.
x, endpoint.
y);
276 cairo_line_to(cr, e_1.
x, e_1.
y);
277 cairo_line_to(cr, e_2.
x, e_2.
y);
278 cairo_close_path(cr);
282 cairo_fill_preserve(cr);
290 float *rotation,
float *offset)
293 float pts[4] = { a->x, a->y, b->x, b->y };
298 pts[0] /= (float)mod_out.
width;
299 pts[2] /= (float)mod_out.
width;
300 pts[1] /= (float)mod_out.
height;
301 pts[3] /= (float)mod_out.
height;
304 const float eps = .0001f;
305 const float diff_x = pts[2] - pts[0];
306 const float diff_y = pts[3] - pts[1];
307 if(fabsf(diff_x) <=
eps && fabsf(diff_y) <=
eps)
return 9;
308 float v = atan2f(diff_y, diff_x);
309 *rotation = -
v * 180.0f /
M_PI;
312 const float sinv = sinf(
v);
313 const float cosv = cosf(
v);
314 const float ofs = (-2.0f * sinv * pts[0]) + sinv - cosv + 1.0f + (2.0f * cosv * pts[1]);
316 *offset = ofs * 50.0f;
322 const float rotation,
const float offset)
325 const float v = (-rotation / 180) *
M_PI;
326 const float sinv = sinf(
v);
327 const float cosv = cosf(
v);
328 const float eps = 1e-6f;
335 const float off = offset / 100.0f;
337 if(fabsf(sinv) <=
eps)
339 const int fwd = (cosv > 0.0f);
340 pts[0] = wp * (fwd ? 0.1f : 0.9f);
341 pts[2] = wp * (fwd ? 0.9f : 0.1f);
342 pts[1] = pts[3] = hp * (fwd ? off : (1.0f - off));
344 else if(fabsf(fabsf(sinv) - 1.0f) <=
eps)
346 const int fwd = (sinv < 0.0f);
347 pts[0] = pts[2] = wp * (fwd ? off : (1.0f - off));
348 pts[1] = hp * (fwd ? 0.9f : 0.1f);
349 pts[3] = hp * (fwd ? 0.1f : 0.9f);
354 float xx1 = (sinv - cosv + 1.0f - offset / 50.0f) * wp * 0.5f / sinv;
355 float xx2 = (sinv + cosv + 1.0f - offset / 50.0f) * wp * 0.5f / sinv;
358 const float aa = hp / (xx2 - xx1);
359 const float bb = -xx1 * aa;
362 xx1 = CLAMP(xx1, 0.0f, wp);
364 xx2 = CLAMP(xx2, 0.0f, wp);
368 const float dx = xx2 - xx1;
369 const float dy = yy2 - yy1;
376 const int first_is_xx1 = (rotation < 90.0f && rotation > -90.0f) ? (xx1 < xx2) : (xx1 > xx2);
417 float H = .0f,
S = .0f,
L = .0f;
420 if(fabsf(
p->hue -
H) < 0.0001f && fabsf(
p->saturation -
S) < 0.0001f)
444 int32_t pointerx, int32_t pointery)
462 float line[4] = {
g->a.x,
g->a.y,
g->b.x,
g->b.y };
468 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
469 if(
g->selected == 3 ||
g->dragging == 3)
475 cairo_move_to(cr, a.x, a.y);
476 cairo_line_to(cr, b.x, b.y);
479 if(
g->selected == 3 ||
g->dragging == 3)
484 cairo_move_to(cr, a.x, a.y);
485 cairo_line_to(cr, b.x, b.y);
496 float pzxpy[2] = { (float)
x, (
float)y };
498 float pzx = pzxpy[0];
499 float pzy = pzxpy[1];
510 else if(
g->dragging == 2)
516 else if(
g->dragging == 3)
519 g->a.x += pzx -
g->oldx;
520 g->b.x += pzx -
g->oldx;
521 g->a.y += pzy -
g->oldy;
522 g->b.y += pzy -
g->oldy;
533 const float ext2 = ext[0] * ext[0];
536 const float da_x = pz.
x -
g->a.x;
537 const float da_y = pz.
y -
g->a.y;
538 const float db_x = pz.
x -
g->b.x;
539 const float db_y = pz.
y -
g->b.y;
542 if(da_x * da_x + da_y * da_y < ext2)
546 else if(db_x * db_x + db_y * db_y < ext2)
554 if(
g->selected > 0 ||
g->dragging > 0)
564 float pzxpy[2] = { (float)
x, (
float)y };
566 float pzx = pzxpy[0];
567 float pzy = pzxpy[1];
581 else if(
g->selected > 0 && which == 1)
583 g->dragging =
g->selected;
598 float rotation = 0.0;
608 rotation =
p->rotation;
614 p->rotation = rotation;
638 dens = fminf(8.0,
p->density + 0.1);
640 dens = fmaxf(-8.0,
p->density - 0.1);
641 if(dens !=
p->density)
651 comp = fminf(100.0,
p->hardness + 1.0);
653 comp = fmaxf(0.0,
p->hardness - 1.0);
654 if(comp !=
p->hardness)
667 return (dens * CLAMP(0.5f + length, 0.0f, 1.0f) / 8.0f);
679 const float d1 =
t *
t * 0.5f;
680 const float d2 = d1 *
t * 0.333333333f;
681 const float d3 = d2 *
t * 0.25f;
682 const float d = 1 +
t + d1 + d2 + d3;
684 float density =
d *
d;
685 density = density * density;
686 density = density * density;
689 const float density = exp2f(dens *
CLIP(0.5f + length));
703 const int ix = (roi_in->
x);
704 const int iy = (roi_in->
y);
707 const float hw = iw / 2.0f;
708 const float hh = ih / 2.0f;
709 const float hw_inv = 1.0f / hw;
710 const float hh_inv = 1.0f / hh;
712 const float sinv = sinf(
v);
713 const float cosv = cosf(
v);
714 const float filter_radie = sqrtf((hh * hh) + (hw * hw)) / hh;
715 const float offset = data->
offset / 100.0f * 2;
717 const float filter_hardness = 1.0 / filter_radie / (1.0 - (0.5 + (data->
hardness / 100.0) * 0.9 / 2.0)) * 0.5;
724 for(
int y = 0; y <
height; y++)
726 const size_t k = (size_t)
width * y *
ch;
727 const float *
const restrict in = (
float *)ivoid +
k;
728 float *
const restrict
out = (
float *)
ovoid +
k;
730 float length = (sinv * (-1.0 + ix * hw_inv) - cosv * (-1.0 + (iy + y) * hh_inv) - 1.0 + offset)
732 const float length_inc = sinv * hw_inv * filter_hardness;
738 for(
int l = 0; l < 4; l++)
742 length += length_inc;
749 for(
int y = 0; y <
height; y++)
751 const size_t k = (size_t)
width * y *
ch;
752 const float *
const restrict in = (
float *)ivoid +
k;
753 float *
const restrict
out = (
float *)
ovoid +
k;
755 float length = (sinv * (-1.0f + ix * hw_inv) - cosv * (-1.0f + (iy + y) * hh_inv) - 1.0f + offset)
757 const float length_inc = sinv * hw_inv * filter_hardness;
763 for(
int l = 0; l < 4; l++)
767 length += length_inc;
786 const int devid = pipe->
devid;
790 const int ix = (roi_in->
x);
791 const int iy = (roi_in->
y);
794 const float hw = iw / 2.0f;
795 const float hh = ih / 2.0f;
796 const float hw_inv = 1.0f / hw;
797 const float hh_inv = 1.0f / hh;
799 const float sinv = sinf(
v);
800 const float cosv = cosf(
v);
801 const float filter_radie = sqrtf((hh * hh) + (hw * hw)) / hh;
802 const float offset = data->
offset / 100.0f * 2;
803 const float density = data->
density;
806 const float filter_hardness = 1.0 / filter_radie
807 / (1.0 - (0.5 + (data->
hardness / 100.0) * 0.9 / 2.0)) * 0.5;
809 const float hardness = data->
hardness / 100.0f;
810 const float t = 1.0f - .8f / (.8f + hardness);
811 const float c = 1.0f + 1000.0f * powf(4.0, hardness);
814 const float length_base = (sinv * (-1.0 + ix * hw_inv) - cosv * (-1.0 + iy * hh_inv) - 1.0 + offset)
816 const float length_inc_y = -cosv * hh_inv * filter_hardness;
817 const float length_inc_x = sinv * hw_inv * filter_hardness;
833 if(err != CL_SUCCESS)
goto error;
844 const int program = 8;
871 gtk_widget_queue_draw(
g->saturation);
881 d->density =
p->density;
882 d->hardness =
p->hardness;
883 d->rotation =
p->rotation;
884 d->offset =
p->offset;
886 hsl2rgb(
d->color,
p->hue,
p->saturation, 0.5);
890 for(
int l = 0; l < 4; l++)
d->color[l] = 1.0 -
d->color[l];
892 for(
int l = 0; l < 4; l++)
d->color1[l] = 1.0 -
d->color[l];
924 gtk_widget_set_tooltip_text(
g->density, _(
"the density in EV for the filter"));
929 gtk_widget_set_tooltip_text(
g->hardness, _(
"hardness of graduation:\n0% = soft, 100% = hard"));
933 gtk_widget_set_tooltip_text(
g->rotation, _(
"rotation of filter -180 to 180 degrees"));
946 gtk_widget_set_tooltip_text(
g->hue, _(
"select the hue tone of filter"));
952 gtk_widget_set_tooltip_text(
g->saturation, _(
"select the saturation of filter"));
Handle default and user-set shortcuts (accelerators)
static void error(char *msg)
void dt_bauhaus_slider_set_stop(GtkWidget *widget, float stop, float r, float g, float b)
void dt_bauhaus_slider_set_feedback(GtkWidget *widget, int feedback)
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
void dt_bauhaus_slider_set_factor(GtkWidget *widget, float factor)
void dt_iop_color_picker_reset(dt_iop_module_t *module, gboolean keep)
GtkWidget * dt_color_picker_new(dt_iop_module_t *module, dt_iop_color_picker_kind_t kind, GtkWidget *w)
void rgb2hsl(const dt_aligned_pixel_t rgb, float *h, float *s, float *l)
Convert RGB to HSL. Common helper used by iop modules.
void hsl2rgb(dt_aligned_pixel_t rgb, float h, float s, float l)
Convert HSL back to RGB. Common helper used by iop modules.
The colour-profile module's API: which profiles exist, and how to apply one.
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
static dt_aligned_pixel_t rgb
const dt_colormatrix_t dt_aligned_pixel_t out
void dt_control_queue_redraw_center()
Request a redraw of the centre view.
#define dt_database_start_transaction()
#define dt_database_release_transaction()
#define dt_dev_add_history_item(dev, module, enable, redraw)
float dt_dev_viewport_scaling(const dt_develop_t *dev)
void dt_dev_coordinates_image_abs_to_image_norm(dt_develop_t *dev, float *points, size_t num_points)
int dt_dev_distort_backtransform_gui(dt_develop_t *dev, const double iop_order, const int transf_direction, float *points, size_t points_count)
The inverse of dt_dev_distort_transform_gui(), same rules.
void dt_dev_coordinates_image_norm_to_preview_abs(dt_develop_t *dev, float *points, size_t num_points)
gboolean dt_dev_module_geometry_gui(dt_develop_t *dev, dt_iop_module_t *module, dt_iop_roi_t *in, dt_iop_roi_t *out)
One module's own input and output rectangles at full resolution, from the geometry service.
int dt_dev_distort_transform_gui(dt_develop_t *dev, const double iop_order, const int transf_direction, float *points, size_t points_count)
The GUI's bounded transform folds, composed by the geometry service.
gboolean dt_dev_rescale_roi(dt_develop_t *dev, cairo_t *cr, int32_t width, int32_t height)
Scale the ROI to fit within given width/height, centered.
void dt_dev_coordinates_image_norm_to_image_abs(dt_develop_t *dev, float *points, size_t num_points)
void dt_dev_coordinates_widget_to_image_norm(dt_develop_t *dev, float *points, size_t num_points)
Coordinate conversion helpers between widget, normalized image, and absolute image spaces.
@ DT_DEV_PIXELPIPE_DISPLAY_MASK
@ DT_DEV_TRANSFORM_DIR_FORW_EXCL
static void dt_draw_set_color_overlay(cairo_t *cr, gboolean bright, double alpha)
static void dt_draw_node(cairo_t *cr, const gboolean square, const gboolean point_action, const gboolean selected, const float zoom_scale, const float x, const float y)
Draw an node point of a mask.
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
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)
static float compute_density(const float dens, const float length)
static int set_grad_from_points(struct dt_iop_module_t *self, const grad_point_t *a, const grad_point_t *b, float *rotation, float *offset)
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
void gui_reset(struct dt_iop_module_t *self)
int scrolled(dt_iop_module_t *self, double x, double y, int up, uint32_t state)
void gui_update(struct dt_iop_module_t *self)
Refresh GUI controls from current params and configuration.
void gui_init(struct dt_iop_module_t *self)
int button_pressed(struct dt_iop_module_t *self, double x, double y, double pressure, int which, int type, uint32_t state)
static int set_points_from_grad(struct dt_iop_module_t *self, grad_point_t *a, grad_point_t *b, const float rotation, const float offset)
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
int button_released(struct dt_iop_module_t *self, double x, double y, int which, uint32_t state)
void cleanup_global(dt_iop_module_so_t *module)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
void gui_post_expose(struct dt_iop_module_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery)
void init_presets(dt_iop_module_so_t *self)
static float density_times_length(const float dens, const float length)
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static void _draw_end_marker(cairo_t *cr, const grad_point_t endpoint, const grad_point_t opposite, const float zoom_scale, const float normal_sign, const gboolean active)
Draw one triangular endpoint marker on the graduated line.
void init_global(dt_iop_module_so_t *module)
static void update_saturation_slider_end_color(GtkWidget *slider, float hue)
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)
int mouse_moved(struct dt_iop_module_t *self, double x, double y, double pressure, int which)
static float _dist_seg(grad_point_t a, grad_point_t b, grad_point_t c)
void color_picker_apply(dt_iop_module_t *self, GtkWidget *picker, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
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)
float dt_boundingbox_t[4]
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_INCLUDE_IN_STYLES
@ IOP_FLAGS_SUPPORTS_BLENDING
@ IOP_FLAGS_TILING_FULL_ROI
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 float kernel(const float *x, const float *y)
_lib_location_type_t type
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...
dt_masks_form_t * dt_masks_get_visible_form(const dt_develop_t *dev)
Return the currently visible form used by the masks GUI.
The interactive half of the masks subsystem: the editing state (dt_masks_form_gui_t),...
#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.
int dt_opencl_enqueue_kernel_2d(const int dev, const int kernel, const size_t *sizes)
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)
#define __OMP_SIMD__(...)
#define __OMP_DECLARE_SIMD__(...)
#define __OMP_PARALLEL_FOR__(...)
Asking the interface to repaint itself.
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
const float uint32_t state[4]
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
struct dt_masks_form_gui_t * form_gui
dt_iop_global_data_t * data
struct dt_develop_t * dev
dt_iop_global_data_t * global_data
dt_aligned_pixel_t picked_color
Region of interest passed through the pixelpipe.
#define __DT_CLONE_TARGETS__