Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
coordinates.c
Go to the documentation of this file.
1/*
2 This file is part of the Ansel project.
3 Copyright (C) 2026 Aurélien PIERRE.
4
5 Ansel is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 Ansel is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Ansel. If not, see <http://www.gnu.org/licenses/>.
17*/
18
20
21static void _virtual_piece_input_offset(dt_iop_module_t *self, int *x, int *y)
22{
23 int ox = 0;
24 int oy = 0;
25
26 if(self && self->dev && self->dev->virtual_pipe)
27 {
29 if(piece)
30 dt_drawlayer_cache_resolve_piece_input_origin(piece, piece->pipe->iwidth, piece->pipe->iheight, &ox, &oy);
31 }
32
33 if(x) *x = ox;
34 if(y) *y = oy;
35}
36
37gboolean dt_drawlayer_widget_points_to_layer_coords(dt_iop_module_t *self, float *pts, const int count)
38{
39 if(!self || !self->dev || !self->dev->virtual_pipe || !pts || count <= 0) return FALSE;
40
43
46 return FALSE;
47
48 int offset_x = 0;
49 int offset_y = 0;
50 _virtual_piece_input_offset(self, &offset_x, &offset_y);
51 for(int i = 0; i < count; i++)
52 {
53 pts[2 * i] += offset_x;
54 pts[2 * i + 1] += offset_y;
55 }
56
57 return TRUE;
58}
59
60gboolean dt_drawlayer_layer_points_to_widget_coords(dt_iop_module_t *self, float *pts, const int count)
61{
62 if(!self || !self->dev || !self->dev->virtual_pipe || !pts || count <= 0) return FALSE;
63
64 int offset_x = 0;
65 int offset_y = 0;
66 _virtual_piece_input_offset(self, &offset_x, &offset_y);
67 for(int i = 0; i < count; i++)
68 {
69 pts[2 * i] -= offset_x;
70 pts[2 * i + 1] -= offset_y;
71 }
72
75 return FALSE;
76
79 return TRUE;
80}
81
82gboolean dt_drawlayer_widget_to_layer_coords(dt_iop_module_t *self, const double wx, const double wy,
83 float *lx, float *ly)
84{
85 if(!self || !self->dev || !self->dev->virtual_pipe || !lx || !ly) return FALSE;
86
87 float pt[2] = { (float)wx, (float)wy };
89
90 *lx = pt[0];
91 *ly = pt[1];
92 return TRUE;
93}
94
95gboolean dt_drawlayer_layer_to_widget_coords(dt_iop_module_t *self, const float x, const float y,
96 float *wx, float *wy)
97{
98 if(!self || !self->dev || !self->dev->virtual_pipe || !wx || !wy) return FALSE;
99
100 float pt[2] = { x, y };
101 if(!dt_drawlayer_layer_points_to_widget_coords(self, pt, 1)) return FALSE;
102 *wx = pt[0];
103 *wy = pt[1];
104 return TRUE;
105}
106
107gboolean dt_drawlayer_layer_bounds_to_widget_bounds(dt_iop_module_t *self, const float x0, const float y0,
108 const float x1, const float y1,
109 float *left, float *top,
110 float *right, float *bottom)
111{
112 if(!self || !self->dev || !self->dev->virtual_pipe) return FALSE;
113
114 float pts[8] = {
115 x0, y0, x1, y0, x0, y1, x1, y1,
116 };
117
118 if(!dt_drawlayer_layer_points_to_widget_coords(self, pts, 4)) return FALSE;
119
120 float min_x = pts[0];
121 float max_x = pts[0];
122 float min_y = pts[1];
123 float max_y = pts[1];
124 for(int i = 1; i < 4; i++)
125 {
126 min_x = fminf(min_x, pts[2 * i]);
127 max_x = fmaxf(max_x, pts[2 * i]);
128 min_y = fminf(min_y, pts[2 * i + 1]);
129 max_y = fmaxf(max_y, pts[2 * i + 1]);
130 }
131
132 if(left) *left = min_x;
133 if(top) *top = min_y;
134 if(right) *right = max_x;
135 if(bottom) *bottom = max_y;
136 return TRUE;
137}
138
140 const float fallback)
141{
142 if(!self || !self->dev || !self->dev->virtual_pipe || !dab) return fallback;
143
144 float pts[6] = {
145 dab->x, dab->y, dab->x + dab->radius, dab->y, dab->x, dab->y + dab->radius,
146 };
147
148 if(!dt_drawlayer_layer_points_to_widget_coords(self, pts, 3)) return fallback;
149
150 const float rx = hypotf(pts[2] - pts[0], pts[3] - pts[1]);
151 const float ry = hypotf(pts[4] - pts[0], pts[5] - pts[1]);
152 const float radius = 0.5f * (rx + ry);
153 return fmaxf(0.5f, isfinite(radius) ? radius : fallback);
154}
155
157{
159 .radius = fmaxf(_conf_size(), 0.5f),
160 .hardness = _conf_hardness(),
161 .shape = _conf_brush_shape(),
162 };
163 return ceilf(dab.radius + 1.0f);
164}
165
167{
168 if(!self || !self->dev || !view) return FALSE;
169
170 const int raw_width = self->dev->roi.raw_width;
171 const int raw_height = self->dev->roi.raw_height;
172 if(raw_width <= 0 || raw_height <= 0) return FALSE;
173
174 const float widget_w = (float)self->dev->roi.orig_width;
175 const float widget_h = (float)self->dev->roi.orig_height;
176 const float preview_w = self->dev->roi.preview_width;
177 const float preview_h = self->dev->roi.preview_height;
178 if(widget_w <= 0.0f || widget_h <= 0.0f || preview_w <= 0.0f || preview_h <= 0.0f) return FALSE;
179
180 const float zoom_scale = dt_dev_get_overlay_scale(self->dev);
181 const float border = (float)self->dev->roi.border_size;
182 const float roi_w = fminf(widget_w, preview_w * zoom_scale);
183 const float roi_h = fminf(widget_h, preview_h * zoom_scale);
184 const float rec_x = fmaxf(border, 0.5f * (widget_w - roi_w));
185 const float rec_y = fmaxf(border, 0.5f * (widget_h - roi_h));
186 const float rec_w = fminf(widget_w - 2.0f * border, roi_w);
187 const float rec_h = fminf(widget_h - 2.0f * border, roi_h);
188 if(rec_w <= 0.0f || rec_h <= 0.0f) return FALSE;
189
190 float pts[8] = {
191 rec_x, rec_y, rec_x + rec_w, rec_y, rec_x, rec_y + rec_h, rec_x + rec_w, rec_y + rec_h,
192 };
193 if(!dt_drawlayer_widget_points_to_layer_coords(self, pts, 4)) return FALSE;
194
195 float min_x = pts[0];
196 float max_x = pts[0];
197 float min_y = pts[1];
198 float max_y = pts[1];
199 for(int i = 1; i < 4; i++)
200 {
201 min_x = fminf(min_x, pts[2 * i]);
202 max_x = fmaxf(max_x, pts[2 * i]);
203 min_y = fminf(min_y, pts[2 * i + 1]);
204 max_y = fmaxf(max_y, pts[2 * i + 1]);
205 }
206
207 view->layer_x0 = min_x;
208 view->layer_y0 = min_y;
209 view->layer_x1 = max_x;
210 view->layer_y1 = max_y;
211
212 view->patch.x = MAX(0, (int)floorf(min_x - padding));
213 view->patch.y = MAX(0, (int)floorf(min_y - padding));
214 const int right = MIN(raw_width, (int)ceilf(max_x + padding));
215 const int bottom = MIN(raw_height, (int)ceilf(max_y + padding));
216 view->patch.width = MAX(0, right - view->patch.x);
217 view->patch.height = MAX(0, bottom - view->patch.y);
218 return view->patch.width > 0 && view->patch.height > 0;
219}
220
222 const dt_iop_roi_t *roi_in,
223 const dt_iop_roi_t *roi_out,
224 const int base_width,
225 const int base_height,
226 const float brush_radius,
228{
229 if(geometry) *geometry = (dt_drawlayer_process_patch_geometry_t){ 0 };
230 if(!piece || !piece->pipe || !roi_out || !geometry || base_width <= 0 || base_height <= 0) return FALSE;
231
232 geometry->process_roi = roi_in ? *roi_in : *roi_out;
234 piece->pipe->iwidth, piece->pipe->iheight,
235 base_width, base_height, &geometry->combined_roi);
236 if(geometry->combined_roi.scale <= 1e-6f || roi_out->width <= 0 || roi_out->height <= 0) return FALSE;
237
238 geometry->process_pad = MAX(0, (int)ceilf(fmaxf(brush_radius, 0.5f) * geometry->combined_roi.scale));
239 geometry->padded_roi = geometry->combined_roi;
240 geometry->padded_roi.x -= geometry->process_pad;
241 geometry->padded_roi.y -= geometry->process_pad;
242 geometry->padded_roi.width += 2 * geometry->process_pad;
243 geometry->padded_roi.height += 2 * geometry->process_pad;
244 geometry->patch_width = roi_out->width + 2 * geometry->process_pad;
245 geometry->patch_height = roi_out->height + 2 * geometry->process_pad;
246 return geometry->patch_width > 0 && geometry->patch_height > 0;
247}
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
const float i
Definition colorspaces_inline_conversions.h:669
const float top
Definition colorspaces_inline_conversions.h:672
gboolean dt_drawlayer_compute_view_patch(dt_iop_module_t *self, const float padding, drawlayer_view_patch_info_t *view)
Definition coordinates.c:166
gboolean dt_drawlayer_widget_points_to_layer_coords(dt_iop_module_t *self, float *pts, const int count)
Definition coordinates.c:37
static void _virtual_piece_input_offset(dt_iop_module_t *self, int *x, int *y)
Definition coordinates.c:21
gboolean dt_drawlayer_compute_process_patch_geometry(const dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out, const int base_width, const int base_height, const float brush_radius, dt_drawlayer_process_patch_geometry_t *geometry)
Definition coordinates.c:221
float dt_drawlayer_widget_brush_radius(dt_iop_module_t *self, const dt_drawlayer_brush_dab_t *dab, const float fallback)
Definition coordinates.c:139
gboolean dt_drawlayer_layer_points_to_widget_coords(dt_iop_module_t *self, float *pts, const int count)
Definition coordinates.c:60
gboolean dt_drawlayer_layer_bounds_to_widget_bounds(dt_iop_module_t *self, const float x0, const float y0, const float x1, const float y1, float *left, float *top, float *right, float *bottom)
Definition coordinates.c:107
float dt_drawlayer_current_live_padding(dt_iop_module_t *self)
Definition coordinates.c:156
gboolean dt_drawlayer_widget_to_layer_coords(dt_iop_module_t *self, const double wx, const double wy, float *lx, float *ly)
Definition coordinates.c:82
gboolean dt_drawlayer_layer_to_widget_coords(dt_iop_module_t *self, const float x, const float y, float *wx, float *wy)
Definition coordinates.c:95
Shared coordinate transforms and geometry computations for drawlayer.
uint32_t view(const dt_view_t *self)
Definition darkroom.c:214
void dt_dev_coordinates_image_abs_to_image_norm(dt_develop_t *dev, float *points, size_t num_points)
Definition develop.c:879
int dt_dev_distort_backtransform_plus(dt_develop_t *dev, dt_dev_pixelpipe_t *pipe, const double iop_order, const int transf_direction, float *points, size_t points_count)
Definition develop.c:1366
float dt_dev_get_overlay_scale(dt_develop_t *dev)
Get the overlay scale factor (scaling * natural_scale_on_processed_size * ppd)
Definition develop.c:1505
void dt_dev_coordinates_image_norm_to_widget(dt_develop_t *dev, float *points, size_t num_points)
Definition develop.c:837
int dt_dev_distort_transform_plus(dt_develop_t *dev, dt_dev_pixelpipe_t *pipe, const double iop_order, const int transf_direction, float *points, size_t points_count)
Definition develop.c:1337
void dt_dev_coordinates_image_norm_to_image_abs(dt_develop_t *dev, float *points, size_t num_points)
Definition develop.c:864
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.
Definition develop.c:812
dt_dev_pixelpipe_iop_t * dt_dev_distort_get_iop_pipe(dt_develop_t *dev, struct dt_dev_pixelpipe_t *pipe, struct dt_iop_module_t *module)
Definition develop.c:1373
@ DT_DEV_TRANSFORM_DIR_FORW_EXCL
Definition develop.h:100
void dt_drawlayer_cache_build_combined_process_roi_for_piece(const dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *process_roi, const int current_full_w, const int current_full_h, const int src_w, const int src_h, dt_iop_roi_t *combined_roi)
Build combined ROI using module origin heuristics from piece buffers.
Definition iop/drawlayer/cache.c:291
void dt_drawlayer_cache_resolve_piece_input_origin(const dt_dev_pixelpipe_iop_t *piece, const int current_full_w, const int current_full_h, int *module_origin_x, int *module_origin_y)
Build combined ROI using module origin heuristics from piece buffers.
Definition iop/drawlayer/cache.c:268
static float _conf_hardness(void)
Derive hardness as complementary value of softness.
Definition iop/drawlayer/conf.c:191
static float _conf_size(void)
Read and clamp configured brush size (px).
Definition iop/drawlayer/conf.c:137
static dt_iop_drawlayer_brush_shape_t _conf_brush_shape(void)
Read and clamp configured brush shape.
Definition iop/drawlayer/conf.c:123
static const float x
Definition iop_profile.h:239
Definition coordinates.h:19
Definition pixelpipe_hb.h:58
struct dt_iop_module_t *struct dt_dev_pixelpipe_t * pipe
Definition pixelpipe_hb.h:60
int32_t orig_height
Definition develop.h:185
struct dt_develop_t::@16 roi
int32_t border_size
Definition develop.h:180
int32_t raw_height
Definition develop.h:208
int32_t preview_height
Definition develop.h:193
int32_t orig_width
Definition develop.h:185
int32_t raw_width
Definition develop.h:208
struct dt_dev_pixelpipe_t * virtual_pipe
Definition develop.h:231
int32_t preview_width
Definition develop.h:193
Fully resolved input dab descriptor.
Definition brush.h:66
float x
Definition brush.h:67
float radius
Definition brush.h:71
float y
Definition brush.h:68
Definition coordinates.h:28
dt_iop_roi_t process_roi
Definition coordinates.h:29
int patch_height
Definition coordinates.h:34
dt_iop_roi_t combined_roi
Definition coordinates.h:30
dt_iop_roi_t padded_roi
Definition coordinates.h:31
int patch_width
Definition coordinates.h:33
int process_pad
Definition coordinates.h:32
Definition imageop.h:217
struct dt_develop_t * dev
Definition imageop.h:262
int iop_order
Definition imageop.h:231
Definition imageop.h:67
int x
Definition imageop.h:68
double scale
Definition imageop.h:69
int width
Definition imageop.h:68
int height
Definition imageop.h:68
int y
Definition imageop.h:68
#define MIN(a, b)
Definition thinplate.c:32
#define MAX(a, b)
Definition thinplate.c:29