31#ifndef DT_GUI_DTGTK_FOCUS_H
32#define DT_GUI_DTGTK_FOCUS_H
45#define gbuf(BUF, A, B) ((BUF)[4 * (width * ((B)) + ((A))) + ch])
51 return (uint8_t)CLAMP(
i + 127, 0, 255);
61 const int step = 1 << l;
62 const int st = step / 2;
64 for(
int j = 0; j <
height; j++)
69 for(;
i <
width - st;
i += step)
76 for(
i = step;
i <
width - st;
i += step)
87 for(; j <
height - st; j += step)
94 for(j = step; j <
height - st; j += step)
107 int fx =
i / (float)wd * fcols;
108 int fy = j / (float)ht * frows;
109 int fi = fcols * fy +
fx;
121 f[fi].x2 += (float)
i *
i;
125 f[fi].y2 += (float)j * j;
140 int buffer_width,
int buffer_height)
143 const int wd = buffer_width;
144 const int ht = buffer_height;
145 const int fs = frows * fcols;
153#pragma omp parallel for default(shared)
155 for(
int j = 0; j < ht - 1; j += 4)
156 for(
int i = 0;
i < wd - 1;
i += 4)
165 int num_clusters = 0;
166 for(
int k = 0;
k < fs;
k++)
167 if(focus[
k].
n * 4 > wd * ht / (
float)fs * 0.01f) num_clusters++;
173#pragma omp parallel for default(shared)
175 for(
int j = 0; j < ht - 1; j += 8)
177 for(
int i = 0;
i < wd - 1;
i += 8)
186 for(
int k = 0;
k < fs;
k++)
188 if(focus[
k].
n * 6.0f > wd * ht / (
float)fs * 0.01f)
201#pragma omp parallel for default(shared)
203 for(
int j=1;j<ht-1;j++)
205 int index = 4*j*wd+4;
206 for(
int i=1;
i<wd-1;
i++)
208 int32_t diff = 4*buffer[index+1]
211 - buffer[index-4*wd+1]
212 - buffer[index+4*wd+1];
219 for(
int k = 0;
k < fs;
k++)
221 focus[
k].
thrs /= fabsf((
float)focus[
k].
n);
222 focus[
k].
x /= fabsf((
float)focus[
k].
n);
223 focus[
k].
x2 /= fabsf((
float)focus[
k].
n);
224 focus[
k].
y /= fabsf((
float)focus[
k].
n);
225 focus[
k].
y2 /= fabsf((
float)focus[
k].
n);
231 float full_zoom,
float full_x,
float full_y)
238 const int fs = frows * fcols;
243 int wd = buffer_width + image.
crop_x;
244 int ht = buffer_height + image.
crop_y;
247 float *pos = malloc(fs * 6 *
sizeof(
float));
248 float *offx = pos + fs * 2, *offy = pos + fs * 4;
250 for(
int k = 0;
k < fs;
k++)
252 const float stddevx = sqrtf(focus[
k].x2 - focus[
k].
x * focus[
k].
x);
253 const float stddevy = sqrtf(focus[
k].y2 - focus[
k].y * focus[
k].y);
256 const float x = focus[
k].
x + image.
crop_x;
257 const float y = focus[
k].
y + image.
crop_y;
261 offx[2 *
k + 0] =
x + stddevx;
264 offy[2 *
k + 1] = y + stddevy;
296 const float scale = fminf((
width - 2 * tb) / (
float)wd, (
height - 2 * tb) / (
float)ht) * full_zoom;
297 cairo_scale(cr, scale, scale);
303 fx = fminf((wd * scale -
width) / 2, fabsf(full_x));
304 if(full_x < 0)
fx = -
fx;
305 if(wd * scale <=
width)
fx = 0;
306 fy = fminf((ht * scale -
height) / 2, fabsf(full_y));
307 if(full_y < 0) fy = -fy;
308 if(ht * scale <=
height) fy = 0;
313 cairo_rectangle(cr, 0, 0, wd, ht);
317 const int ndash =
sizeof(dashes) /
sizeof(dashes[0]);
318 double offset = 0.0f;
319 cairo_set_dash(cr, dashes, ndash, offset);
322 for(
int k = 0;
k < fs;
k++)
325 const float col = fminf(1.0f, intens);
327 if(focus[
k].
n * 4.0f > buffer_width * buffer_height / (
float)fs * 0.01f)
329 else if(-focus[
k].
n * 6.0f > buffer_width * buffer_height / (
float)fs * 0.01f)
333 for(
int i = 0;
i < 2;
i++)
338 cairo_set_source_rgb(cr, .1f, .1f, col);
340 cairo_set_source_rgb(cr, col, .1f, .1f);
341 cairo_set_dash(cr, dashes, ndash, dashes[0]);
345 cairo_set_source_rgb(cr, .1f, .1f, .1f);
346 cairo_set_dash(cr, dashes, ndash, 0);
348 cairo_move_to(cr, offx[2 *
k + 0], offx[2 *
k + 1]);
349 cairo_curve_to(cr, -pos[2 *
k + 0] + offx[2 *
k + 0] + offy[2 *
k + 0],
350 -pos[2 *
k + 1] + offx[2 *
k + 1] + offy[2 *
k + 1],
351 -pos[2 *
k + 0] + offx[2 *
k + 0] + offy[2 *
k + 0],
352 -pos[2 *
k + 1] + offx[2 *
k + 1] + offy[2 *
k + 1], offy[2 *
k + 0], offy[2 *
k + 1]);
353 cairo_curve_to(cr, pos[2 *
k + 0] - offx[2 *
k + 0] + offy[2 *
k + 0],
354 pos[2 *
k + 1] - offx[2 *
k + 1] + offy[2 *
k + 1],
355 pos[2 *
k + 0] - offx[2 *
k + 0] + offy[2 *
k + 0],
356 pos[2 *
k + 1] - offx[2 *
k + 1] + offy[2 *
k + 1],
357 2 * pos[2 *
k + 0] - offx[2 *
k + 0], 2 * pos[2 *
k + 1] - offx[2 *
k + 1]);
358 cairo_curve_to(cr, 3 * pos[2 *
k + 0] - offx[2 *
k + 0] - offy[2 *
k + 0],
359 3 * pos[2 *
k + 1] - offx[2 *
k + 1] - offy[2 *
k + 1],
360 3 * pos[2 *
k + 0] - offx[2 *
k + 0] - offy[2 *
k + 0],
361 3 * pos[2 *
k + 1] - offx[2 *
k + 1] - offy[2 *
k + 1],
362 2 * pos[2 *
k + 0] - offy[2 *
k + 0], 2 * pos[2 *
k + 1] - offy[2 *
k + 1]);
363 cairo_curve_to(cr, pos[2 *
k + 0] + offx[2 *
k + 0] - offy[2 *
k + 0],
364 pos[2 *
k + 1] + offx[2 *
k + 1] - offy[2 *
k + 1],
365 pos[2 *
k + 0] + offx[2 *
k + 0] - offy[2 *
k + 0],
366 pos[2 *
k + 1] + offx[2 *
k + 1] - offy[2 *
k + 1], offx[2 *
k + 0], offx[2 *
k + 1]);
369 cairo_scale(cr, 1. / scale, 1. / scale);
struct dt_develop_t * dt_dev_get_global(void)
struct dt_gui_gtk_t * dt_gui_get_global(void)
void dt_dev_pixelpipe_get_roi_out(dt_dev_pixelpipe_t *pipe, const int width_in, const int height_in, int *width, int *height)
int32_t dt_dev_viewport_border_size(const dt_develop_t *dev)
void dt_dev_cleanup(dt_develop_t *dev)
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)
dt_dev_image_storage_t dt_dev_load_image(dt_develop_t *dev, const int32_t imgid)
void dt_dev_init(dt_develop_t *dev, int32_t gui_attached)
@ DT_DEV_TRANSFORM_DIR_ALL
static void dt_focus_draw_clusters(cairo_t *cr, int width, int height, int32_t imgid, int buffer_width, int buffer_height, dt_focus_cluster_t *focus, int frows, int fcols, float full_zoom, float full_x, float full_y)
static void dt_focus_create_clusters(dt_focus_cluster_t *focus, int frows, int fcols, uint8_t *buffer, int buffer_width, int buffer_height)
static void _dt_focus_cdf22_wtf(uint8_t *buf, const int l, const int width, const int height)
static void _dt_focus_update(dt_focus_cluster_t *f, int frows, int fcols, int i, int j, int wd, int ht, int diff)
static int _from_uint8(uint8_t i)
static uint8_t _to_uint8(int i)
dt_image_t * dt_image_cache_get(const int32_t imgid, char mode)
void dt_image_cache_read_release(const dt_image_t *img)
static const dt_dev_pixelpipe_t * pipe
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(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
#define __OMP_PARALLEL_FOR__(...)
void dt_dev_pixelpipe_set_input(dt_dev_pixelpipe_t *pipe, int32_t imgid, int width, int height, float iscale, dt_mipmap_size_t size)
int dt_dev_pixelpipe_init_dummy(dt_dev_pixelpipe_t *pipe, dt_develop_t *dev)
void dt_dev_pixelpipe_create_nodes(dt_dev_pixelpipe_t *pipe)
void dt_dev_pixelpipe_cleanup(dt_dev_pixelpipe_t *pipe)
#define dt_dev_pixelpipe_synch_all(pipe)