186 return _(
"graduated density");
192 _(
"corrective and creative"),
193 _(
"linear or non-linear, RGB, scene-referred"),
194 _(
"non-linear, RGB"),
195 _(
"non-linear, RGB, display-referred"));
214static inline float f(
const float t,
const float c,
const float x)
216 return (
t / (1.0f + powf(c, -
x * 6.0f)) + (1.0f -
t) * (
x * .5f + .5f));
230 const float sn2 = s.
x * s.
x + s.
y * s.
y;
231 if(sn2 <= 0.0f)
return u.
x * u.
x + u.
y * u.
y;
233 const float t = CLAMP((s.
x * u.
x + s.
y * u.
y) / sn2, 0.0f, 1.0f);
234 const float dx = u.
x -
t * s.
x;
235 const float dy = u.
y -
t * s.
y;
236 return dx * dx + dy * dy;
246 const float normal_sign,
const gboolean active)
250 const float dx = opposite.
x - endpoint.
x;
251 const float dy = opposite.
y - endpoint.
y;
252 const float length = dt_fast_hypotf(dx, dy);
254 const float inv_len = 1.0f / length;
255 const float ux = dx * inv_len;
256 const float uy = dy * inv_len;
257 const float px = -uy;
261 e_1.
x = endpoint.
x + ux *
x;
262 e_1.
y = endpoint.
y + uy *
x;
264 const float mx = (endpoint.
x + e_1.
x) * 0.5f;
265 const float my = (endpoint.
y + e_1.
y) * 0.5f;
266 e_2.
x = mx + px * (
x * normal_sign);
267 e_2.
y = my + py * (
x * normal_sign);
269 cairo_move_to(cr, endpoint.
x, endpoint.
y);
270 cairo_line_to(cr, e_1.
x, e_1.
y);
271 cairo_line_to(cr, e_2.
x, e_2.
y);
272 cairo_close_path(cr);
276 cairo_fill_preserve(cr);
284 float *rotation,
float *offset)
287 float pts[4] = { a->
x, a->
y, b->x, b->y };
297 const float eps = .0001f;
298 const float diff_x = pts[2] - pts[0];
299 const float diff_y = pts[3] - pts[1];
300 if(fabsf(diff_x) <=
eps && fabsf(diff_y) <=
eps)
return 9;
301 float v = atan2f(diff_y, diff_x);
302 *rotation = -
v * 180.0f /
M_PI;
305 const float sinv = sinf(
v);
306 const float cosv = cosf(
v);
307 const float ofs = (-2.0f * sinv * pts[0]) + sinv - cosv + 1.0f + (2.0f * cosv * pts[1]);
309 *offset = ofs * 50.0f;
315 const float rotation,
const float offset)
318 const float v = (-rotation / 180) *
M_PI;
319 const float sinv = sinf(
v);
320 const float cosv = cosf(
v);
321 const float eps = 1e-6f;
328 const float off = offset / 100.0f;
330 if(fabsf(sinv) <=
eps)
332 const int fwd = (cosv > 0.0f);
333 pts[0] = wp * (fwd ? 0.1f : 0.9f);
334 pts[2] = wp * (fwd ? 0.9f : 0.1f);
335 pts[1] = pts[3] = hp * (fwd ? off : (1.0f - off));
337 else if(fabsf(fabsf(sinv) - 1.0f) <=
eps)
339 const int fwd = (sinv < 0.0f);
340 pts[0] = pts[2] = wp * (fwd ? off : (1.0f - off));
341 pts[1] = hp * (fwd ? 0.9f : 0.1f);
342 pts[3] = hp * (fwd ? 0.1f : 0.9f);
347 float xx1 = (sinv - cosv + 1.0f - offset / 50.0f) * wp * 0.5f / sinv;
348 float xx2 = (sinv + cosv + 1.0f - offset / 50.0f) * wp * 0.5f / sinv;
351 const float aa = hp / (xx2 - xx1);
352 const float bb = -xx1 * aa;
355 xx1 = CLAMP(xx1, 0.0f, wp);
357 xx2 = CLAMP(xx2, 0.0f, wp);
361 const float dx = xx2 - xx1;
362 const float dy = yy2 - yy1;
369 const int first_is_xx1 = (rotation < 90.0f && rotation > -90.0f) ? (xx1 < xx2) : (xx1 > xx2);
410 float H = .0f,
S = .0f,
L = .0f;
413 if(fabsf(
p->hue -
H) < 0.0001f && fabsf(
p->saturation -
S) < 0.0001f)
437 int32_t pointerx, int32_t pointery)
455 float line[4] = {
g->a.x,
g->a.y,
g->b.x,
g->b.y };
461 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
462 if(
g->selected == 3 ||
g->dragging == 3)
468 cairo_move_to(cr, a.
x, a.
y);
469 cairo_line_to(cr, b.x, b.y);
472 if(
g->selected == 3 ||
g->dragging == 3)
477 cairo_move_to(cr, a.
x, a.
y);
478 cairo_line_to(cr, b.x, b.y);
489 float pzxpy[2] = { (float)
x, (
float)y };
491 float pzx = pzxpy[0];
492 float pzy = pzxpy[1];
503 else if(
g->dragging == 2)
509 else if(
g->dragging == 3)
512 g->a.x += pzx -
g->oldx;
513 g->b.x += pzx -
g->oldx;
514 g->a.y += pzy -
g->oldy;
515 g->b.y += pzy -
g->oldy;
526 const float ext2 = ext[0] * ext[0];
529 const float da_x = pz.
x -
g->a.x;
530 const float da_y = pz.
y -
g->a.y;
531 const float db_x = pz.
x -
g->b.x;
532 const float db_y = pz.
y -
g->b.y;
535 if(da_x * da_x + da_y * da_y < ext2)
539 else if(db_x * db_x + db_y * db_y < ext2)
547 if(
g->selected > 0 ||
g->dragging > 0)
557 float pzxpy[2] = { (float)
x, (
float)y };
559 float pzx = pzxpy[0];
560 float pzy = pzxpy[1];
574 else if(
g->selected > 0 && which == 1)
576 g->dragging =
g->selected;
591 float rotation = 0.0;
601 rotation =
p->rotation;
607 p->rotation = rotation;
625 dens = fminf(8.0,
p->density + 0.1);
627 dens = fmaxf(-8.0,
p->density - 0.1);
628 if(dens !=
p->density)
638 comp = fminf(100.0,
p->hardness + 1.0);
640 comp = fmaxf(0.0,
p->hardness - 1.0);
641 if(comp !=
p->hardness)
654 return (dens * CLAMP(0.5f + length, 0.0f, 1.0f) / 8.0f);
666 const float d1 =
t *
t * 0.5f;
667 const float d2 = d1 *
t * 0.333333333f;
668 const float d3 = d2 *
t * 0.25f;
669 const float d = 1 +
t + d1 + d2 + d3;
671 float density =
d *
d;
672 density = density * density;
673 density = density * density;
676 const float density = exp2f(dens *
CLIP(0.5f + length));
690 const int ix = (roi_in->
x);
691 const int iy = (roi_in->
y);
694 const float hw = iw / 2.0f;
695 const float hh = ih / 2.0f;
696 const float hw_inv = 1.0f / hw;
697 const float hh_inv = 1.0f / hh;
699 const float sinv = sinf(
v);
700 const float cosv = cosf(
v);
701 const float filter_radie = sqrtf((hh * hh) + (hw * hw)) / hh;
702 const float offset = data->
offset / 100.0f * 2;
704 const float filter_hardness = 1.0 / filter_radie / (1.0 - (0.5 + (data->
hardness / 100.0) * 0.9 / 2.0)) * 0.5;
711 for(
int y = 0; y <
height; y++)
713 const size_t k = (size_t)
width * y *
ch;
714 const float *
const restrict in = (
float *)ivoid +
k;
715 float *
const restrict
out = (
float *)
ovoid +
k;
717 float length = (sinv * (-1.0 + ix * hw_inv) - cosv * (-1.0 + (iy + y) * hh_inv) - 1.0 + offset)
719 const float length_inc = sinv * hw_inv * filter_hardness;
725 for(
int l = 0; l < 4; l++)
729 length += length_inc;
736 for(
int y = 0; y <
height; y++)
738 const size_t k = (size_t)
width * y *
ch;
739 const float *
const restrict in = (
float *)ivoid +
k;
740 float *
const restrict
out = (
float *)
ovoid +
k;
742 float length = (sinv * (-1.0f + ix * hw_inv) - cosv * (-1.0f + (iy + y) * hh_inv) - 1.0f + offset)
744 const float length_inc = sinv * hw_inv * filter_hardness;
750 for(
int l = 0; l < 4; l++)
754 length += length_inc;
773 const int devid = pipe->
devid;
777 const int ix = (roi_in->
x);
778 const int iy = (roi_in->
y);
781 const float hw = iw / 2.0f;
782 const float hh = ih / 2.0f;
783 const float hw_inv = 1.0f / hw;
784 const float hh_inv = 1.0f / hh;
786 const float sinv = sinf(
v);
787 const float cosv = cosf(
v);
788 const float filter_radie = sqrtf((hh * hh) + (hw * hw)) / hh;
789 const float offset = data->
offset / 100.0f * 2;
790 const float density = data->
density;
793 const float filter_hardness = 1.0 / filter_radie
794 / (1.0 - (0.5 + (data->
hardness / 100.0) * 0.9 / 2.0)) * 0.5;
796 const float hardness = data->
hardness / 100.0f;
797 const float t = 1.0f - .8f / (.8f + hardness);
798 const float c = 1.0f + 1000.0f * powf(4.0, hardness);
801 const float length_base = (sinv * (-1.0 + ix * hw_inv) - cosv * (-1.0 + iy * hh_inv) - 1.0 + offset)
803 const float length_inc_y = -cosv * hh_inv * filter_hardness;
804 const float length_inc_x = sinv * hw_inv * filter_hardness;
820 if(err != CL_SUCCESS)
goto error;
831 const int program = 8;
858 gtk_widget_queue_draw(
g->saturation);
868 d->density =
p->density;
869 d->hardness =
p->hardness;
870 d->rotation =
p->rotation;
871 d->offset =
p->offset;
873 hsl2rgb(
d->color,
p->hue,
p->saturation, 0.5);
877 for(
int l = 0; l < 4; l++)
d->color[l] = 1.0 -
d->color[l];
879 for(
int l = 0; l < 4; l++)
d->color1[l] = 1.0 -
d->color[l];
911 gtk_widget_set_tooltip_text(
g->density, _(
"the density in EV for the filter"));
916 gtk_widget_set_tooltip_text(
g->hardness, _(
"hardness of graduation:\n0% = soft, 100% = hard"));
920 gtk_widget_set_tooltip_text(
g->rotation, _(
"rotation of filter -180 to 180 degrees"));
933 gtk_widget_set_tooltip_text(
g->hue, _(
"select the hue tone of filter"));
939 gtk_widget_set_tooltip_text(
g->saturation, _(
"select the saturation of filter"));
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)
@ DEVELOP_BLEND_CS_RGB_DISPLAY
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
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)
void hsl2rgb(dt_aligned_pixel_t rgb, float h, float s, float l)
static dt_aligned_pixel_t rgb
const dt_aligned_pixel_t f
const dt_colormatrix_t dt_aligned_pixel_t out
void dt_control_queue_redraw_center()
request redraw of center window. This redraws the center view within a gdk critical section to preven...
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 __OMP_SIMD__(...)
float dt_boundingbox_t[4]
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
#define __OMP_DECLARE_SIMD__(...)
#define __DT_CLONE_TARGETS__
#define __OMP_PARALLEL_FOR__(...)
static gboolean dt_modifier_is(const GdkModifierType state, const GdkModifierType desired_modifier_mask)
#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_database_start_transaction(db)
#define dt_database_release_transaction(db)
#define dt_dev_add_history_item(dev, module, enable, redraw)
void dt_dev_coordinates_image_abs_to_image_norm(dt_develop_t *dev, float *points, size_t num_points)
dt_dev_pixelpipe_iop_t * dt_dev_distort_get_iop_pipe(struct dt_dev_pixelpipe_t *pipe, struct dt_iop_module_t *module)
int dt_dev_distort_transform_plus(const dt_dev_pixelpipe_t *pipe, const double iop_order, const int transf_direction, float *points, size_t points_count)
void dt_dev_coordinates_image_norm_to_preview_abs(dt_develop_t *dev, float *points, size_t num_points)
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.
int dt_dev_distort_backtransform_plus(const dt_dev_pixelpipe_t *pipe, const double iop_order, const int transf_direction, float *points, size_t points_count)
@ 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)
#define DT_GUI_MOUSE_EFFECT_RADIUS
#define DT_PIXEL_APPLY_DPI_DPP(value)
#define DT_PIXEL_APPLY_DPI(value)
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, const dt_develop_blend_colorspace_t blend_cst)
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
#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 k
float *const restrict const size_t const size_t ch
float dt_aligned_pixel_t[4]
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)
struct _GtkWidget GtkWidget
const float uint32_t state[4]
struct dt_gui_gtk_t * gui
const struct dt_database_t * db
struct dt_develop_t * develop
dt_iop_buffer_dsc_t dsc_in
struct dt_iop_module_t *void * data
struct dt_dev_pixelpipe_t * virtual_pipe
struct dt_develop_t::@17 roi
GModule *dt_dev_operation_t op
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
dt_aligned_pixel_t picked_color
Region of interest passed through the pixelpipe.