44 uint8_t *
const restrict image,
45 const int buf_width,
const int buf_height,
49 float *
const restrict luma =
dt_alloc_align(
sizeof(
float) * (
size_t)buf_width * buf_height);
50 float *
const restrict luma_ds =
dt_alloc_align(
sizeof(
float) * (
size_t)buf_width * buf_height);
51 uint8_t *restrict focus_peaking = NULL;
59 const size_t npixels = (size_t)buf_height * buf_width;
62 for(
size_t index = 0; index < npixels; index++)
64 const size_t index_RGB = index * 4;
75 if(
fast_eigf_surface_blur(luma, buf_width, buf_height, 12, 0.00005f, 4,
DT_GF_BLENDING_LINEAR, 1, 0.0f, exp2f(-8.0f), 1.0f) != 0)
83 float x_integral = 0.f;
84 float y_integral = 0.f;
86 for(
size_t i = 0;
i < buf_height; ++
i)
87 for(
size_t j = 0; j < buf_width; ++j)
89 size_t index =
i * buf_width + j;
90 if(i < 8 || i >= buf_height - 8 || j < 8 || j > buf_width - 8)
93 luma_ds[index] = 0.0f;
98 static const float kernel[7][7]
99 = { { 0.00053449f, 0.00352729f, 0.00992912f, 0.01362207f, 0.00992912f, 0.00352729f, 0.00053449f },
100 { 0.00352729f, 0.01828379f, 0.03437727f, 0.03474665f, 0.03437727f, 0.01828379f, 0.00352729f },
101 { 0.00992912f, 0.03437727f, -0.00982925f, -0.09093110f, -0.00982925f, 0.03437727f, 0.00992912f },
102 { 0.01362207f, 0.03474665f, -0.09093110f, -0.26187433f, -0.09093110f, 0.03474665f, 0.01362207f },
103 { 0.00992912f, 0.03437727f, -0.00982925f, -0.09093110f, -0.00982925f, 0.03437727f, 0.00992912f },
104 { 0.00352729f, 0.01828379f, 0.03437727f, 0.03474665f, 0.03437727f, 0.01828379f, 0.00352729f },
105 { 0.00053449f, 0.00352729f, 0.00992912f, 0.01362207f, 0.00992912f, 0.00352729f, 0.00053449f } };
110 float laplacian_close = 0.f;
111 float laplacian_far = 0.f;
113 for(
int ii = 0; ii < 7; ii++)
114 for(
int jj = 0; jj < 7; jj++)
116 laplacian_close += luma[(
i - 3 + ii) * buf_width + (j - 3 + jj)] *
kernel[ii][jj];
117 laplacian_far += luma[(
i + (-3 + ii) * 2) * buf_width + (j + (-3 + jj) * 2)] *
kernel[ii][jj];
121 const float gradient_1_y = (luma[(
i - 2) * buf_width + (j)] - luma[(
i + 2) * buf_width + (j)]) / 4.f;
122 const float gradient_1_x = (luma[(
i) * buf_width + (j - 2)] - luma[(
i) * buf_width + (j + 2)]) / 4.f;
123 const float TV_1 = dt_fast_hypotf(gradient_1_x, gradient_1_y);
126 const float gradient_2_y = (luma[(
i - 2) * buf_width + (j - 2)] - luma[(
i + 2) * buf_width + (j + 2)]) / (2.f * sqrtf(2.f));
127 const float gradient_2_x = (luma[(
i - 2) * buf_width + (j + 2)] - luma[(
i + 2) * buf_width + (j - 2)]) / (2.f * sqrtf(2.f));
128 const float TV_2 = dt_fast_hypotf(gradient_2_x, gradient_2_y);
131 const float gradient_3_y = (luma[(
i - 1) * buf_width + (j)] - luma[(
i + 1) * buf_width + (j)]) / 2.f;
132 const float gradient_3_x = (luma[(
i) * buf_width + (j - 1)] - luma[(
i) * buf_width + (j + 1)]) / 2.f;
133 const float TV_3 = dt_fast_hypotf(gradient_3_x, gradient_3_y);
136 const float gradient_4_y = (luma[(
i - 1) * buf_width + (j - 1)] - luma[(
i + 1) * buf_width + (j + 1)]) / (sqrtf(2.f));
137 const float gradient_4_x = (luma[(
i - 1) * buf_width + (j + 1)] - luma[(
i + 1) * buf_width + (j - 1)]) / (sqrtf(2.f));
138 const float TV_4 = dt_fast_hypotf(gradient_4_x, gradient_4_y);
144 const float TV = 100.f * (TV_1 + TV_2 + TV_3 + TV_4) / 4.f;
145 luma_ds[index] = (laplacian_close > 1e-15f) ? fmaxf(fabsf(laplacian_close) - 0.5f * fabsf(laplacian_far), 0.f) / (TV + 1.f) : 0.f;
148 mass += luma_ds[index];
149 x_integral += ((float)j) * luma_ds[index];
150 y_integral += ((float)
i) * luma_ds[index];
155 if(
x) *
x = CLAMP(x_integral / mass, 0, buf_height);
156 if(y) *y = CLAMP(y_integral / mass, 0, buf_height);
168 focus_peaking =
dt_alloc_align(
sizeof(uint8_t) * buf_width * buf_height * 4);
177 for(
size_t i = 0;
i < buf_height; ++
i)
178 for(
size_t j = 0; j < buf_width; ++j)
180 size_t index =
i * buf_width + j;
181 if(i < 8 || i >= buf_height - 8 || j < 8 || j > buf_width - 8)
189 static const float kernel[3][3] = { { 1.f } };
191 for(
int ii = 0; ii < 3; ii++)
192 for(
int jj = 0; jj < 3; jj++)
193 luma[index] += luma_ds[(
i - 1 + ii) * buf_width + (j - 1 + jj)] *
kernel[ii][jj];
198 if(
dt_box_mean(luma, buf_height, buf_width, 1, 3, 1) != 0)
205 if(
fast_eigf_surface_blur(luma, buf_width, buf_height, 12, 0.000005f, 1,
DT_GF_BLENDING_LINEAR, 1, 0.0f, exp2f(-8.0f), 1.0f) != 0)
214 for(
size_t i = 8;
i < buf_height - 8; ++
i)
215 for(
size_t j = 8; j < buf_width - 8; ++j)
216 TV_sum += luma[
i * buf_width + j] / ((
float)(buf_height - 16) * (
float)(buf_width - 16));
221 for(
size_t i = 8;
i < buf_height - 8; ++
i)
222 for(
size_t j = 8; j < buf_width - 8; ++j)
223 sigma += sqf(luma[
i * buf_width + j] - TV_sum) / ((float)(buf_height - 16) * (float)(buf_width - 16));
228 const float six_sigma = TV_sum + 4.f *
sigma;
229 const float four_sigma = TV_sum + 3.f *
sigma;
230 const float two_sigma = TV_sum + 2.f *
sigma;
234 for(
size_t i = 0;
i < buf_height; ++
i)
235 for(
size_t j = 0; j < buf_width; ++j)
237 static const uint8_t yellow[4] = { 0, 255, 255, 255 };
238 static const uint8_t green[4] = { 0, 255, 0, 255 };
239 static const uint8_t blue[4] = { 255, 0, 0, 255 };
241 const size_t index = (
i * buf_width + j) * 4;
242 const float TV = luma[(
i * buf_width + j)];
249 else if(TV > four_sigma)
254 else if(TV > two_sigma)
268 cairo_rectangle(cr, 0, 0, buf_width, buf_height);
269 cairo_surface_t *surface = cairo_image_surface_create_for_data((
unsigned char *)focus_peaking,
271 buf_width, buf_height,
272 cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, buf_width));
273 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
274 cairo_set_source_surface(cr, surface, 0.0, 0.0);
280 cairo_surface_destroy(surface);