41 return (
size_t)((box[3] - box[1]) * (box[2] - box[0]));
65 for(
size_t k = 0;
k < pixels;
k++)
67 const size_t offset = 4 *
k;
68 dt_Lab_2_LCH(input + offset, output + offset);
69 output[offset + 3] = input[offset + 3];
75 for(
size_t k = 0;
k < pixels;
k++)
77 const size_t offset = 4 *
k;
78 dt_RGB_2_HSL(input + offset, output + offset);
79 output[offset + 3] = input[offset + 3];
85 for(
size_t k = 0;
k < pixels;
k++)
87 const size_t offset = 4 *
k;
89 profile->
lut_out, profile->unbounded_coeffs_out,
91 output[offset + 3] = input[offset + 3];
97 for(
size_t k = 0;
k < pixels;
k++)
99 const size_t offset = 4 *
k;
101 profile->
lut_in, profile->unbounded_coeffs_in,
103 output[offset + 3] = input[offset + 3];
109 for(
size_t k = 0;
k < pixels;
k++)
111 const size_t offset = 4 *
k;
113 output[offset + 3] = input[offset + 3];
128 dt_ioppr_rgb_matrix_to_xyz(
rgb,
XYZ_D50, profile->matrix_in_transposed, profile->lut_in, profile->unbounded_coeffs_in,
129 profile->lutsize, profile->nonlinearlut);
139 dt_JzAzBz_2_JzCzhz(
JzAzBz, JzCzhz);
142 const float *
const pixels,
const float w,
const size_t width)
144 for(
size_t i = 0;
i <
width;
i += 4)
147 for(
size_t k = 0;
k < 4;
k++)
149 avg[
k] += w * pick[
k];
156 const float *
const pixels,
const float w,
const size_t width)
158 for(
size_t i = 0;
i <
width;
i += 4)
161 pick[3] = pick[0] < 0.5f ? pick[0] + 0.5f : pick[0] - 0.5f;
162 for(
size_t k = 0;
k < 4;
k++)
164 avg[
k] += w * pick[
k];
172 const float w,
const size_t width)
174 for(
size_t i = 0;
i <
width;
i += 4)
177 pick[3] = pick[2] < 0.5f ? pick[2] + 0.5f : pick[2] - 0.5f;
178 for(
size_t k = 0;
k < 4;
k++)
180 avg[
k] += w * pick[
k];
187 const float *
const pixels,
const float w,
const size_t width)
189 for(
size_t i = 0;
i <
width;
i += 4)
192 dt_Lab_2_LCH(pixels +
i, pick);
193 pick[3] = pick[2] < 0.5f ? pick[2] + 0.5f : pick[2] - 0.5f;
194 for(
size_t k = 0;
k < 4;
k++)
196 avg[
k] += w * pick[
k];
203 const float *
const pixels,
const float w,
const size_t width)
205 for(
size_t i = 0;
i <
width;
i += 4)
208 dt_RGB_2_HSL(pixels +
i, pick);
209 pick[3] = pick[0] < 0.5f ? pick[0] + 0.5f : pick[0] - 0.5f;
210 for(
size_t k = 0;
k < 4;
k++)
212 avg[
k] += w * pick[
k];
219 const float *
const pixels,
const float w,
const size_t width,
222 for(
size_t i = 0;
i <
width;
i += 4)
226 pick[3] = pick[2] < 0.5f ? pick[2] + 0.5f : pick[2] - 0.5f;
227 for(
size_t k = 0;
k < 4;
k++)
229 avg[
k] += w * pick[
k];
245 const size_t stride = 4 * (size_t)(box[2] - box[0]);
246 const size_t off_mul = 4 *
width;
247 const size_t off_add = 4 * box[0];
249 const float w = 1.0f / (float)
size;
254 for(
size_t j = box[1]; j < box[3]; j++)
256 const size_t offset = j * off_mul + off_add;
257 _color_picker_lch(picked_color, picked_color_min, picked_color_max, pixel + offset, w, stride);
262 for(
size_t j = box[1]; j < box[3]; j++)
264 const size_t offset = j * off_mul + off_add;
265 _color_picker_hsl(picked_color, picked_color_min, picked_color_max, pixel + offset, w, stride);
270 for(
size_t j = box[1]; j < box[3]; j++)
272 const size_t offset = j * off_mul + off_add;
273 _color_picker_jzczhz(picked_color, picked_color_min, picked_color_max, pixel + offset, w, stride, profile);
278 for(
size_t j = box[1]; j < box[3]; j++)
280 const size_t offset = j * off_mul + off_add;
295 const size_t stride = 4 * (size_t)(box[2] - box[0]);
296 const size_t off_mul = 4 *
width;
297 const size_t off_add = 4 * box[0];
299 const float w = 1.0f / (float)
size;
311 for(
int n = 0;
n < allocsize * numthreads;
n++)
326 for(
size_t j = box[1]; j < box[3]; j++)
328 const size_t offset = j * off_mul + off_add;
341 for(
size_t j = box[1]; j < box[3]; j++)
343 const size_t offset = j * off_mul + off_add;
356 for(
size_t j = box[1]; j < box[3]; j++)
358 const size_t offset = j * off_mul + off_add;
371 for(
size_t j = box[1]; j < box[3]; j++)
373 const size_t offset = j * off_mul + off_add;
379 for(
int n = 0;
n < numthreads;
n++)
381 for(
int k = 0;
k < 4;
k++)
383 picked_color[
k] += mean[allocsize *
n +
k];
384 picked_color_min[
k] = fminf(picked_color_min[
k], mmin[allocsize *
n +
k]);
385 picked_color_max[
k] = fmaxf(picked_color_max[
k], mmax[allocsize *
n +
k]);
405 picked_color_max, cst_to, profile);
419 const size_t stride = 4 * (size_t)(box[2] - box[0]);
420 const size_t off_mul = 4 *
width;
421 const size_t off_add = 4 * box[0];
422 const float w = 1.0f / (float)
size;
424 for(
size_t j = box[1]; j < box[3]; j++)
426 const size_t offset = j * off_mul + off_add;
444 const size_t stride = 4 * (size_t)(box[2] - box[0]);
445 const size_t off_mul = 4 *
width;
446 const size_t off_add = 4 * box[0];
447 const float w = 1.0f / (float)
size;
458 for(
int n = 0;
n < allocsize * numthreads;
n++)
470 for(
size_t j = box[1]; j < box[3]; j++)
472 const size_t offset = j * off_mul + off_add;
482 for(
int n = 0;
n < numthreads;
n++)
490 picked_color[
k] += tmean[
k];
491 picked_color_min[
k] = fminf(picked_color_min[
k], tmmin[
k]);
492 picked_color_max[
k] = fmaxf(picked_color_max[
k], tmmax[
k]);
510 picked_color_max, picker_cst);
513 picked_color_max, picker_cst);
522 const uint32_t filters = dsc->
filters;
524 uint32_t weights[4] = { 0u, 0u, 0u, 0u };
527 for(
size_t j = box[1]; j < box[3]; j++)
529 for(
size_t i = box[0];
i < box[2];
i++)
531 const int c =
FC(j + roi->
y,
i + roi->
x, filters);
532 const size_t k =
width * j +
i;
534 const float v = pixel[
k];
536 picked_color[c] +=
v;
537 picked_color_min[c] = fminf(picked_color_min[c],
v);
538 picked_color_max[c] = fmaxf(picked_color_max[c],
v);
544 for(
int c = 0; c < 4; c++)
546 picked_color[c] = weights[c] ? (picked_color[c] / (float)weights[c]) : 0.0f;
556 const uint32_t filters = dsc->
filters;
558 uint32_t weights[4] = { 0u, 0u, 0u, 0u };
563 float *
const msum = malloc(
sizeof(
float) * numthreads * 4);
564 float *
const mmin = malloc(
sizeof(
float) * numthreads * 4);
565 float *
const mmax = malloc(
sizeof(
float) * numthreads * 4);
566 uint32_t *
const cnt = malloc(
sizeof(uint32_t) * numthreads * 4);
571 for(
int n = 0;
n < 4 * numthreads;
n++)
582 float *
const tsum = msum + 4 * tnum;
583 float *
const tmmin = mmin + 4 * tnum;
584 float *
const tmmax = mmax + 4 * tnum;
585 uint32_t *
const tcnt = cnt + 4 * tnum;
587 for(
size_t j = box[1]; j < box[3]; j++)
589 for(
size_t i = box[0];
i < box[2];
i++)
591 const int c =
FC(j + roi->
y,
i + roi->
x, filters);
592 const size_t k =
width * j +
i;
594 const float v = pixel[
k];
597 tmmin[c] = fminf(tmmin[c],
v);
598 tmmax[c] = fmaxf(tmmax[c],
v);
604 for(
int n = 0;
n < numthreads;
n++)
606 for(
int c = 0; c < 4; c++)
608 picked_color[c] += msum[4 *
n + c];
609 picked_color_min[c] = fminf(picked_color_min[c], mmin[4 *
n + c]);
610 picked_color_max[c] = fmaxf(picked_color_max[c], mmax[4 *
n + c]);
611 weights[c] += cnt[4 *
n + c];
616 for(
int c = 0; c < 4; c++)
618 picked_color[c] = weights[c] ? (picked_color[c] / (float)weights[c]) : 0.0f;
647 const uint8_t(*
const xtrans)[6] = (
const uint8_t(*
const)[6])dsc->
xtrans;
649 uint32_t weights[3] = { 0u, 0u, 0u };
652 for(
size_t j = box[1]; j < box[3]; j++)
654 for(
size_t i = box[0];
i < box[2];
i++)
656 const int c =
FCxtrans(j,
i, roi, xtrans);
657 const size_t k =
width * j +
i;
659 const float v = pixel[
k];
661 picked_color[c] +=
v;
662 picked_color_min[c] = fminf(picked_color_min[c],
v);
663 picked_color_max[c] = fmaxf(picked_color_max[c],
v);
670 for(
int c = 0; c < 3; c++)
672 picked_color[c] /= (float)weights[c];
682 const uint8_t(*
const xtrans)[6] = (
const uint8_t(*
const)[6])dsc->
xtrans;
684 uint32_t weights[3] = { 0u, 0u, 0u };
689 float *
const mmin = malloc(
sizeof(
float) * numthreads * 3);
690 float *
const msum = malloc(
sizeof(
float) * numthreads * 3);
691 float *
const mmax = malloc(
sizeof(
float) * numthreads * 3);
692 uint32_t *
const cnt = malloc(
sizeof(uint32_t) * numthreads * 3);
698 for(
int n = 0;
n < 3 * numthreads;
n++)
709 float *
const tsum = msum + 3 * tnum;
710 float *
const tmmin = mmin + 3 * tnum;
711 float *
const tmmax = mmax + 3 * tnum;
712 uint32_t *
const tcnt = cnt + 3 * tnum;
714 for(
size_t j = box[1]; j < box[3]; j++)
716 for(
size_t i = box[0];
i < box[2];
i++)
718 const int c =
FCxtrans(j,
i, roi, xtrans);
719 const size_t k =
width * j +
i;
721 const float v = pixel[
k];
724 tmmin[c] = fminf(tmmin[c],
v);
725 tmmax[c] = fmaxf(tmmax[c],
v);
731 for(
int n = 0;
n < numthreads;
n++)
733 for(
int c = 0; c < 3; c++)
735 picked_color[c] += msum[3 *
n + c];
736 picked_color_min[c] = fminf(picked_color_min[c], mmin[3 *
n + c]);
737 picked_color_max[c] = fmaxf(picked_color_max[c], mmax[3 *
n + c]);
738 weights[c] += cnt[3 *
n + c];
744 for(
int c = 0; c < 3; c++)
746 picked_color[c] /= (float)weights[c];
776 dt_times_t start_time = { 0 }, end_time = { 0 };
784 float *converted = NULL;
792 if(((image_cst == picker_cst) || (picker_cst ==
IOP_CS_NONE)))
793 color_picker_helper_4ch(dsc, denoised, roi, box, picked_color, picked_color_min, picked_color_max, picker_cst, profile);
811 color_picker_helper_4ch(dsc, denoised, roi, box, picked_color, picked_color_min, picked_color_max, picker_cst, profile);
828 fprintf(stderr,
"colorpicker stats reading took %.3f secs (%.3f CPU)\n",
829 end_time.clock - start_time.
clock, end_time.user - start_time.
user);
static void error(char *msg)
static void blur_2D_Bspline(const float *const restrict in, float *const restrict out, float *const restrict tempbuf, const size_t width, const size_t height, const int mult, const gboolean clip_negatives)
static void _color_picker_convert_buffer(const float *const restrict input, float *const restrict output, const size_t pixels, const dt_iop_colorspace_type_t image_cst, const dt_iop_colorspace_type_t picker_cst, const dt_iop_order_iccprofile_info_t *const profile)
Convert a 4-channel sampling buffer into the picker colorspace.
static size_t _box_size(const int *const box)
static void color_picker_helper_4ch_converted_seq(const float *const pixel, const dt_iop_roi_t *const roi, const int *const box, dt_aligned_pixel_t picked_color, dt_aligned_pixel_t picked_color_min, dt_aligned_pixel_t picked_color_max, const dt_iop_colorspace_type_t picker_cst)
static void color_picker_helper_xtrans_parallel(const dt_iop_buffer_dsc_t *const dsc, const float *const pixel, const dt_iop_roi_t *const roi, const int *const box, dt_aligned_pixel_t picked_color, dt_aligned_pixel_t picked_color_min, dt_aligned_pixel_t picked_color_max)
static void color_picker_helper_4ch_converted(const float *const pixel, const dt_iop_roi_t *const roi, const int *const box, dt_aligned_pixel_t picked_color, dt_aligned_pixel_t picked_color_min, dt_aligned_pixel_t picked_color_max, const dt_iop_colorspace_type_t picker_cst)
static void rgb_to_JzCzhz(const dt_aligned_pixel_t rgb, dt_aligned_pixel_t JzCzhz, const dt_iop_order_iccprofile_info_t *const profile)
void dt_color_picker_helper(const dt_iop_buffer_dsc_t *dsc, const float *const pixel, const dt_iop_roi_t *roi, const int *const box, dt_aligned_pixel_t picked_color, dt_aligned_pixel_t picked_color_min, dt_aligned_pixel_t picked_color_max, const dt_iop_colorspace_type_t image_cst, const dt_iop_colorspace_type_t picker_cst, const dt_iop_order_iccprofile_info_t *const profile)
static void _color_picker_hsl(dt_aligned_pixel_t avg, dt_aligned_pixel_t min, dt_aligned_pixel_t max, const float *const pixels, const float w, const size_t width)
static void color_picker_helper_4ch_converted_parallel(const float *const pixel, const dt_iop_roi_t *const roi, const int *const box, dt_aligned_pixel_t picked_color, dt_aligned_pixel_t picked_color_min, dt_aligned_pixel_t picked_color_max, const dt_iop_colorspace_type_t picker_cst)
static void color_picker_helper_bayer(const dt_iop_buffer_dsc_t *dsc, const float *const pixel, const dt_iop_roi_t *roi, const int *const box, dt_aligned_pixel_t picked_color, dt_aligned_pixel_t picked_color_min, dt_aligned_pixel_t picked_color_max)
static void color_picker_helper_xtrans(const dt_iop_buffer_dsc_t *dsc, const float *const pixel, const dt_iop_roi_t *roi, const int *const box, dt_aligned_pixel_t picked_color, dt_aligned_pixel_t picked_color_min, dt_aligned_pixel_t picked_color_max)
static void _color_picker_jzczhz(dt_aligned_pixel_t avg, dt_aligned_pixel_t min, dt_aligned_pixel_t max, const float *const pixels, const float w, const size_t width, const dt_iop_order_iccprofile_info_t *const profile)
static void _color_picker_direct_lch_or_jzczhz(dt_aligned_pixel_t avg, dt_aligned_pixel_t min, dt_aligned_pixel_t max, const float *const pixels, const float w, const size_t width)
static void color_picker_helper_bayer_seq(const dt_iop_buffer_dsc_t *const dsc, const float *const pixel, const dt_iop_roi_t *const roi, const int *const box, dt_aligned_pixel_t picked_color, dt_aligned_pixel_t picked_color_min, dt_aligned_pixel_t picked_color_max)
static void _color_picker_direct_hsl(dt_aligned_pixel_t avg, dt_aligned_pixel_t min, dt_aligned_pixel_t max, const float *const pixels, const float w, const size_t width)
static void _color_picker_lch(dt_aligned_pixel_t avg, dt_aligned_pixel_t min, dt_aligned_pixel_t max, const float *const pixels, const float w, const size_t width)
static void color_picker_helper_4ch(const dt_iop_buffer_dsc_t *dsc, const float *const pixel, const dt_iop_roi_t *roi, const int *const box, dt_aligned_pixel_t picked_color, dt_aligned_pixel_t picked_color_min, dt_aligned_pixel_t picked_color_max, const dt_iop_colorspace_type_t cst_to, const dt_iop_order_iccprofile_info_t *const profile)
static void color_picker_helper_4ch_seq(const dt_iop_buffer_dsc_t *const dsc, const float *const pixel, const dt_iop_roi_t *const roi, const int *const box, dt_aligned_pixel_t picked_color, dt_aligned_pixel_t picked_color_min, dt_aligned_pixel_t picked_color_max, const dt_iop_colorspace_type_t cst_to, const dt_iop_order_iccprofile_info_t *const profile)
static void _color_picker_rgb_or_lab(dt_aligned_pixel_t avg, dt_aligned_pixel_t min, dt_aligned_pixel_t max, const float *const pixels, const float w, const size_t width)
static void color_picker_helper_bayer_parallel(const dt_iop_buffer_dsc_t *const dsc, const float *const pixel, const dt_iop_roi_t *const roi, const int *const box, dt_aligned_pixel_t picked_color, dt_aligned_pixel_t picked_color_min, dt_aligned_pixel_t picked_color_max)
static void color_picker_helper_4ch_parallel(const dt_iop_buffer_dsc_t *const dsc, const float *const pixel, const dt_iop_roi_t *const roi, const int *const box, dt_aligned_pixel_t picked_color, dt_aligned_pixel_t picked_color_min, dt_aligned_pixel_t picked_color_max, const dt_iop_colorspace_type_t cst_to, const dt_iop_order_iccprofile_info_t *const profile)
static void color_picker_helper_xtrans_seq(const dt_iop_buffer_dsc_t *const dsc, const float *const pixel, const dt_iop_roi_t *const roi, const int *const box, dt_aligned_pixel_t picked_color, dt_aligned_pixel_t picked_color_min, dt_aligned_pixel_t picked_color_max)
static dt_aligned_pixel_t rgb
static const float const float const float min
static dt_aligned_pixel_t XYZ_D65
static dt_aligned_pixel_t XYZ_D50
static dt_aligned_pixel_t JzAzBz
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
#define dt_get_bythread(buf, padsize, tnum)
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define omp_get_max_threads()
static int dt_get_thread_num()
static void dt_get_times(dt_times_t *t)
#define __OMP_DECLARE_SIMD__(...)
#define __OMP_PARALLEL__(...)
#define dt_pixelpipe_cache_free_align(mem)
#define dt_get_perthread(buf, padsize)
#define for_four_channels(_var,...)
#define __OMP_PARALLEL_FOR__(...)
#define dt_pixelpipe_cache_alloc_perthread_float(n, padded_size)
#define dt_unreachable_codepath()
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
static int FCxtrans(const int row, const int col, global const unsigned char(*const xtrans)[6])
static int FC(const int row, const int col, const unsigned int filters)
static gboolean dt_iop_colorspace_is_rgb(const dt_iop_colorspace_type_t cst)
float *const restrict const size_t k
float dt_aligned_pixel_t[4]
int32_t num_openmp_threads
dt_colormatrix_t matrix_out_transposed
dt_colormatrix_t matrix_in_transposed
Region of interest passed through the pixelpipe.