46 return (
size_t)((box[3] - box[1]) * (box[2] - box[0]));
77 const gboolean image_lab = (image_cst ==
IOP_CS_LAB);
81 for(
size_t k = 0;
k < pixels;
k++)
83 const size_t offset = 4 *
k;
84 dt_aligned_pixel_t base = { input[offset], input[offset + 1], input[offset + 2], 0.0f };
86 if(image_lab && !want_lab)
89 else if(!image_lab && want_lab)
96 dt_Lab_2_LCH(base, output + offset);
99 dt_RGB_2_HSL(base, output + offset);
105 for(
int c = 0; c < 3; c++) output[offset + c] = base[c];
108 output[offset + 3] = input[offset + 3];
122 dt_ioppr_rgb_matrix_to_xyz(
rgb,
XYZ_D50, profile->matrix_in_transposed, profile->lut_in, profile->unbounded_coeffs_in,
123 profile->lutsize, profile->nonlinearlut);
133 dt_JzAzBz_2_JzCzhz(
JzAzBz, JzCzhz);
136 const float *
const pixels,
const float w,
const size_t width)
138 for(
size_t i = 0;
i <
width;
i += 4)
141 for(
size_t k = 0;
k < 4;
k++)
143 avg[
k] += w * pick[
k];
150 const float *
const pixels,
const float w,
const size_t width)
152 for(
size_t i = 0;
i <
width;
i += 4)
155 pick[3] = pick[0] < 0.5f ? pick[0] + 0.5f : pick[0] - 0.5f;
156 for(
size_t k = 0;
k < 4;
k++)
158 avg[
k] += w * pick[
k];
166 const float w,
const size_t width)
168 for(
size_t i = 0;
i <
width;
i += 4)
171 pick[3] = pick[2] < 0.5f ? pick[2] + 0.5f : pick[2] - 0.5f;
172 for(
size_t k = 0;
k < 4;
k++)
174 avg[
k] += w * pick[
k];
181 const float *
const pixels,
const float w,
const size_t width)
183 for(
size_t i = 0;
i <
width;
i += 4)
186 dt_Lab_2_LCH(pixels +
i, pick);
187 pick[3] = pick[2] < 0.5f ? pick[2] + 0.5f : pick[2] - 0.5f;
188 for(
size_t k = 0;
k < 4;
k++)
190 avg[
k] += w * pick[
k];
197 const float *
const pixels,
const float w,
const size_t width)
199 for(
size_t i = 0;
i <
width;
i += 4)
202 dt_RGB_2_HSL(pixels +
i, pick);
203 pick[3] = pick[0] < 0.5f ? pick[0] + 0.5f : pick[0] - 0.5f;
204 for(
size_t k = 0;
k < 4;
k++)
206 avg[
k] += w * pick[
k];
213 const float *
const pixels,
const float w,
const size_t width,
216 for(
size_t i = 0;
i <
width;
i += 4)
220 pick[3] = pick[2] < 0.5f ? pick[2] + 0.5f : pick[2] - 0.5f;
221 for(
size_t k = 0;
k < 4;
k++)
223 avg[
k] += w * pick[
k];
239 const size_t stride = 4 * (size_t)(box[2] - box[0]);
240 const size_t off_mul = 4 *
width;
241 const size_t off_add = 4 * box[0];
243 const float w = 1.0f / (float)
size;
248 for(
size_t j = box[1]; j < box[3]; j++)
250 const size_t offset = j * off_mul + off_add;
251 _color_picker_lch(picked_color, picked_color_min, picked_color_max, pixel + offset, w, stride);
256 for(
size_t j = box[1]; j < box[3]; j++)
258 const size_t offset = j * off_mul + off_add;
259 _color_picker_hsl(picked_color, picked_color_min, picked_color_max, pixel + offset, w, stride);
264 for(
size_t j = box[1]; j < box[3]; j++)
266 const size_t offset = j * off_mul + off_add;
267 _color_picker_jzczhz(picked_color, picked_color_min, picked_color_max, pixel + offset, w, stride, profile);
272 for(
size_t j = box[1]; j < box[3]; j++)
274 const size_t offset = j * off_mul + off_add;
289 const size_t stride = 4 * (size_t)(box[2] - box[0]);
290 const size_t off_mul = 4 *
width;
291 const size_t off_add = 4 * box[0];
293 const float w = 1.0f / (float)
size;
305 for(
int n = 0;
n < allocsize * numthreads;
n++)
320 for(
size_t j = box[1]; j < box[3]; j++)
322 const size_t offset = j * off_mul + off_add;
335 for(
size_t j = box[1]; j < box[3]; j++)
337 const size_t offset = j * off_mul + off_add;
350 for(
size_t j = box[1]; j < box[3]; j++)
352 const size_t offset = j * off_mul + off_add;
365 for(
size_t j = box[1]; j < box[3]; j++)
367 const size_t offset = j * off_mul + off_add;
373 for(
int n = 0;
n < numthreads;
n++)
375 for(
int k = 0;
k < 4;
k++)
377 picked_color[
k] += mean[allocsize *
n +
k];
378 picked_color_min[
k] = fminf(picked_color_min[
k], mmin[allocsize *
n +
k]);
379 picked_color_max[
k] = fmaxf(picked_color_max[
k], mmax[allocsize *
n +
k]);
399 picked_color_max, cst_to, profile);
413 const size_t stride = 4 * (size_t)(box[2] - box[0]);
414 const size_t off_mul = 4 *
width;
415 const size_t off_add = 4 * box[0];
416 const float w = 1.0f / (float)
size;
418 for(
size_t j = box[1]; j < box[3]; j++)
420 const size_t offset = j * off_mul + off_add;
438 const size_t stride = 4 * (size_t)(box[2] - box[0]);
439 const size_t off_mul = 4 *
width;
440 const size_t off_add = 4 * box[0];
441 const float w = 1.0f / (float)
size;
452 for(
int n = 0;
n < allocsize * numthreads;
n++)
464 for(
size_t j = box[1]; j < box[3]; j++)
466 const size_t offset = j * off_mul + off_add;
476 for(
int n = 0;
n < numthreads;
n++)
484 picked_color[
k] += tmean[
k];
485 picked_color_min[
k] = fminf(picked_color_min[
k], tmmin[
k]);
486 picked_color_max[
k] = fmaxf(picked_color_max[
k], tmmax[
k]);
504 picked_color_max, picker_cst);
507 picked_color_max, picker_cst);
516 const uint32_t filters = dsc->
filters;
518 uint32_t weights[4] = { 0u, 0u, 0u, 0u };
521 for(
size_t j = box[1]; j < box[3]; j++)
523 for(
size_t i = box[0];
i < box[2];
i++)
525 const int c =
FC(j + roi->
y,
i + roi->
x, filters);
526 const size_t k =
width * j +
i;
528 const float v = pixel[
k];
530 picked_color[c] +=
v;
531 picked_color_min[c] = fminf(picked_color_min[c],
v);
532 picked_color_max[c] = fmaxf(picked_color_max[c],
v);
538 for(
int c = 0; c < 4; c++)
540 picked_color[c] = weights[c] ? (picked_color[c] / (float)weights[c]) : 0.0f;
550 const uint32_t filters = dsc->
filters;
552 uint32_t weights[4] = { 0u, 0u, 0u, 0u };
557 float *
const msum = malloc(
sizeof(
float) * numthreads * 4);
558 float *
const mmin = malloc(
sizeof(
float) * numthreads * 4);
559 float *
const mmax = malloc(
sizeof(
float) * numthreads * 4);
560 uint32_t *
const cnt = malloc(
sizeof(uint32_t) * numthreads * 4);
565 for(
int n = 0;
n < 4 * numthreads;
n++)
576 float *
const tsum = msum + 4 * tnum;
577 float *
const tmmin = mmin + 4 * tnum;
578 float *
const tmmax = mmax + 4 * tnum;
579 uint32_t *
const tcnt = cnt + 4 * tnum;
581 for(
size_t j = box[1]; j < box[3]; j++)
583 for(
size_t i = box[0];
i < box[2];
i++)
585 const int c =
FC(j + roi->
y,
i + roi->
x, filters);
586 const size_t k =
width * j +
i;
588 const float v = pixel[
k];
591 tmmin[c] = fminf(tmmin[c],
v);
592 tmmax[c] = fmaxf(tmmax[c],
v);
598 for(
int n = 0;
n < numthreads;
n++)
600 for(
int c = 0; c < 4; c++)
602 picked_color[c] += msum[4 *
n + c];
603 picked_color_min[c] = fminf(picked_color_min[c], mmin[4 *
n + c]);
604 picked_color_max[c] = fmaxf(picked_color_max[c], mmax[4 *
n + c]);
605 weights[c] += cnt[4 *
n + c];
610 for(
int c = 0; c < 4; c++)
612 picked_color[c] = weights[c] ? (picked_color[c] / (float)weights[c]) : 0.0f;
641 const uint8_t(*
const xtrans)[6] = (
const uint8_t(*
const)[6])dsc->
xtrans;
643 uint32_t weights[3] = { 0u, 0u, 0u };
646 for(
size_t j = box[1]; j < box[3]; j++)
648 for(
size_t i = box[0];
i < box[2];
i++)
650 const int c =
FCxtrans(j,
i, roi, xtrans);
651 const size_t k =
width * j +
i;
653 const float v = pixel[
k];
655 picked_color[c] +=
v;
656 picked_color_min[c] = fminf(picked_color_min[c],
v);
657 picked_color_max[c] = fmaxf(picked_color_max[c],
v);
664 for(
int c = 0; c < 3; c++)
666 picked_color[c] /= (float)weights[c];
676 const uint8_t(*
const xtrans)[6] = (
const uint8_t(*
const)[6])dsc->
xtrans;
678 uint32_t weights[3] = { 0u, 0u, 0u };
683 float *
const mmin = malloc(
sizeof(
float) * numthreads * 3);
684 float *
const msum = malloc(
sizeof(
float) * numthreads * 3);
685 float *
const mmax = malloc(
sizeof(
float) * numthreads * 3);
686 uint32_t *
const cnt = malloc(
sizeof(uint32_t) * numthreads * 3);
692 for(
int n = 0;
n < 3 * numthreads;
n++)
703 float *
const tsum = msum + 3 * tnum;
704 float *
const tmmin = mmin + 3 * tnum;
705 float *
const tmmax = mmax + 3 * tnum;
706 uint32_t *
const tcnt = cnt + 3 * tnum;
708 for(
size_t j = box[1]; j < box[3]; j++)
710 for(
size_t i = box[0];
i < box[2];
i++)
712 const int c =
FCxtrans(j,
i, roi, xtrans);
713 const size_t k =
width * j +
i;
715 const float v = pixel[
k];
718 tmmin[c] = fminf(tmmin[c],
v);
719 tmmax[c] = fmaxf(tmmax[c],
v);
725 for(
int n = 0;
n < numthreads;
n++)
727 for(
int c = 0; c < 3; c++)
729 picked_color[c] += msum[3 *
n + c];
730 picked_color_min[c] = fminf(picked_color_min[c], mmin[3 *
n + c]);
731 picked_color_max[c] = fmaxf(picked_color_max[c], mmax[3 *
n + c]);
732 weights[c] += cnt[3 *
n + c];
738 for(
int c = 0; c < 3; c++)
740 picked_color[c] /= (float)weights[c];
770 dt_times_t start_time = { 0 }, end_time = { 0 };
778 float *converted = NULL;
792 const gboolean convertible
793 = image_convertible && picker_convertible && (!crosses_family || !
IS_NULL_PTR(profile));
795 if(((image_cst == picker_cst) || (picker_cst ==
IOP_CS_NONE)))
796 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, const size_t width, const size_t height)
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
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 gboolean _picker_cst_wants_lab(const dt_iop_colorspace_type_t picker_cst)
Whether a picker colorspace derives from Lab (Lab, LCh) rather than from RGB (RGB,...
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)
The colour-profile struct and the maths over it: the derived matrix/LUT engine.
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
int dt_get_num_openmp_threads(void)
Number of OpenMP threads the application decided to use.
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)
int32_t dt_get_debug_flags(void)
float *const restrict const size_t k
#define dt_unreachable_codepath()
Mark a branch as impossible.
#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_get_max_threads()
static int dt_get_thread_num()
Index of the calling thread within its parallel region, 0 outside one.
#define __OMP_DECLARE_SIMD__(...)
#define __OMP_PARALLEL__(...)
#define __OMP_PARALLEL_FOR__(...)
#define dt_get_bythread(buf, padsize, tnum)
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define dt_pixelpipe_cache_free_align(mem)
#define dt_get_perthread(buf, padsize)
#define dt_pixelpipe_cache_alloc_perthread_float(n, padded_size)
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
#define for_four_channels(_var,...)
A profile reduced to the arithmetic the pixel loop can run: two matrices and six tone-curve LUTs,...
int nonlinearlut
Non-zero when the profile has tone curves at all; tested as a boolean everywhere, but it is really th...
int lutsize
Entry count of each of the six LUTs. Always 65536 in practice: both callers of dt_ioppr_init_profile_...
dt_colormatrix_t matrix_out_transposed
float * lut_out[3]
Per-channel linear -> encoded tone curve, same convention as lut_in.
float * lut_in[3]
Per-channel encoded -> linear tone curve, lutsize entries each, sampled over [0,1]....
dt_colormatrix_t matrix_in_transposed
Region of interest passed through the pixelpipe.
static void dt_get_times(dt_times_t *t)