Skip to content

Commit

Permalink
Deduplicate dt_UCS_22_build_gamut_LUT
Browse files Browse the repository at this point in the history
That code was copy&pasted from the original in colorbalancergb,
has been deduplicated.
  • Loading branch information
jenshannoschwalm committed Sep 12, 2024
1 parent bf10fc5 commit 0094614
Showing 1 changed file with 4 additions and 82 deletions.
86 changes: 4 additions & 82 deletions src/iop/colorbalancergb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1200,13 +1200,11 @@ void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pix
// instead of D50 pipeline to D50 XYZ (work_profile->matrix_in) and then D50 XYZ to D65 XYZ
dt_colormatrix_t input_matrix;
dt_colormatrix_mul(input_matrix, XYZ_D50_to_D65_CAT16, work_profile->matrix_in);
float *const restrict sampler = dt_calloc_align_float(LUT_ELEM);

float *gamut_LUT = d->gamut_LUT;
// make RGB values vary between [0; 1] in working space, convert to Ych and get the max(c(h)))
if(p->saturation_formula == DT_COLORBALANCE_SATURATION_JZAZBZ)
{

float *const restrict sampler = dt_calloc_align_float(LUT_ELEM);
DT_OMP_FOR(reduction(max: sampler[:LUT_ELEM]) collapse(3))
for(size_t r = 0; r < STEPS; r++)
for(size_t g = 0; g < STEPS; g++)
Expand Down Expand Up @@ -1245,88 +1243,12 @@ void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pix
d->gamut_LUT[1] = (sampler[LUT_ELEM - 1] + sampler[0] + sampler[1] + sampler[2] + sampler[3]) / 5.f;
d->gamut_LUT[LUT_ELEM - 1] = (sampler[LUT_ELEM - 3] + sampler[LUT_ELEM - 2] + sampler[LUT_ELEM - 1] + sampler[0] + sampler[1]) / 5.f;
d->gamut_LUT[LUT_ELEM - 2] = (sampler[LUT_ELEM - 4] + sampler[LUT_ELEM - 3] + sampler[LUT_ELEM - 2] + sampler[LUT_ELEM - 1] + sampler[0]) / 5.f;
dt_free_align(sampler);
}
else if(p->saturation_formula == DT_COLORBALANCE_SATURATION_DTUCS)
{
for(size_t k = 0; k < LUT_ELEM; k++) gamut_LUT[k] = 0.f;
const dt_aligned_pixel_t D65_xyY = { D65xyY.x, D65xyY.y, 1.f, 0.f };

// Compute the RGB space primaries in xyY
dt_aligned_pixel_t RGB_red = { 1.f, 0.f, 0.f, 0.f };
dt_aligned_pixel_t RGB_green = { 0.f, 1.f, 0.f, 0.f };
dt_aligned_pixel_t RGB_blue = { 0.f, 0.f, 1.f, 0.f };

dt_aligned_pixel_t XYZ_red, XYZ_green, XYZ_blue;
dot_product(RGB_red, input_matrix, XYZ_red);
dot_product(RGB_green, input_matrix, XYZ_green);
dot_product(RGB_blue, input_matrix, XYZ_blue);

dt_aligned_pixel_t xyY_red, xyY_green, xyY_blue;
dt_D65_XYZ_to_xyY(XYZ_red, xyY_red);
dt_D65_XYZ_to_xyY(XYZ_green, xyY_green);
dt_D65_XYZ_to_xyY(XYZ_blue, xyY_blue);

// Get the "hue" angles of the primaries in xy compared to D65
const float h_red = atan2f(xyY_red[1] - D65_xyY[1], xyY_red[0] - D65_xyY[0]);
const float h_green = atan2f(xyY_green[1] - D65_xyY[1], xyY_green[0] - D65_xyY[0]);
const float h_blue = atan2f(xyY_blue[1] - D65_xyY[1], xyY_blue[0] - D65_xyY[0]);

// March the gamut boundary in CIE xyY 1931 by angular steps of 0.02°
DT_OMP_FOR(reduction(+: gamut_LUT[:LUT_ELEM], sampler[:LUT_ELEM]))
for(int i = 0; i < 50 * LUT_ELEM; i++)
{
const float angle = -M_PI_F + ((float)i) / (float)(50 * LUT_ELEM) * 2.f * M_PI_F;
const float tan_angle = tanf(angle);

const float t_1 = Delta_H(angle, h_blue) / Delta_H(h_red, h_blue);
const float t_2 = Delta_H(angle, h_red) / Delta_H(h_green, h_red);
const float t_3 = Delta_H(angle, h_green) / Delta_H(h_blue, h_green);

float x_t = 0;
float y_t = 0;

if(t_1 == CLAMP(t_1, 0, 1))
{
const float t = (D65_xyY[1] - xyY_blue[1] + tan_angle * (xyY_blue[0] - D65_xyY[0]))
/ (xyY_red[1] - xyY_blue[1] + tan_angle * (xyY_blue[0] - xyY_red[0]));
x_t = xyY_blue[0] + t * (xyY_red[0] - xyY_blue[0]);
y_t = xyY_blue[1] + t * (xyY_red[1] - xyY_blue[1]);
}
else if(t_2 == CLAMP(t_2, 0, 1))
{
const float t = (D65_xyY[1] - xyY_red[1] + tan_angle * (xyY_red[0] - D65_xyY[0]))
/ (xyY_green[1] - xyY_red[1] + tan_angle * (xyY_red[0] - xyY_green[0]));
x_t = xyY_red[0] + t * (xyY_green[0] - xyY_red[0]);
y_t = xyY_red[1] + t * (xyY_green[1] - xyY_red[1]);
}
else if(t_3 == CLAMP(t_3, 0, 1))
{
const float t = (D65_xyY[1] - xyY_green[1] + tan_angle * (xyY_green[0] - D65_xyY[0]))
/ (xyY_blue[1] - xyY_green[1] + tan_angle * (xyY_green[0] - xyY_blue[0]));
x_t = xyY_green[0] + t * (xyY_blue[0] - xyY_green[0]);
y_t = xyY_green[1] + t * (xyY_blue[1] - xyY_green[1]);
}

// Convert to darktable UCS
dt_aligned_pixel_t xyY = { x_t, y_t, 1.f, 0.f };
float UV_star_prime[2];
xyY_to_dt_UCS_UV(xyY, UV_star_prime);

// Get the hue angle in darktable UCS
const float hue = atan2f(UV_star_prime[1], UV_star_prime[0]);
int index = roundf((LUT_ELEM - 1) * (hue + M_PI_F) / (2.f * M_PI_F));
index += (index < 0) ? LUT_ELEM : 0;
index -= (index >= LUT_ELEM) ? LUT_ELEM : 0;
// Warning: we store M², the square of the colorfulness

gamut_LUT[index] += UV_star_prime[0] * UV_star_prime[0] + UV_star_prime[1] * UV_star_prime[1];
sampler[index] += 1.0f;
}
for(size_t k = 0; k < LUT_ELEM; k++)
gamut_LUT[k] = gamut_LUT[k] / fmaxf(1.0f, sampler[k]);
}
dt_UCS_22_build_gamut_LUT(input_matrix, gamut_LUT);

d->lut_inited = TRUE;
dt_free_align(sampler);
}
}

Expand Down

0 comments on commit 0094614

Please sign in to comment.