95 { 0.37208f, 0.37529f },
96 { 0.40910f, 0.39430f },
97 { 0.44018f, 0.40329f },
98 { 0.31379f, 0.34531f },
99 { 0.37790f, 0.38835f },
100 { 0.31292f, 0.32933f },
101 { 0.34588f, 0.35875f },
102 { 0.37417f, 0.37281f },
103 { 0.34609f, 0.35986f },
104 { 0.38052f, 0.37713f },
105 { 0.43695f, 0.40441f } };
117 { 0.4357f, 0.4012f },
118 { 0.3756f, 0.3723f },
119 { 0.3422f, 0.3502f },
120 { 0.3118f, 0.3236f },
121 { 0.4474f, 0.4066f },
122 { 0.4557f, 0.4211f },
123 { 0.4560f, 0.4548f },
124 { 0.3781f, 0.3775f }};
133 const float n = (
x - 0.3366f)/(y - 0.1735f);
134 return -949.86315f + 6253.80338f * expf(-
n / 0.92159f) + 28.70599f * expf(-
n / 0.20039f) + 0.00004f * expf(-
n / 0.07125f);
145 if(
t >= 4000.f &&
t <= 7000.0f)
146 x_temp = ((-4.6070e9f /
t + 2.9678e6f) /
t + 0.09911e3f) /
t + 0.244063f;
147 else if(
t > 7000.f &&
t <= 25000.f)
148 x_temp = ((-2.0064e9f /
t + 1.9018e6f) /
t + 0.24748e3f) /
t + 0.237040f;
150 y_temp = (-3.f * x_temp + 2.87f) * x_temp - 0.275f;
164 if(
t >= 1667.f &&
t <= 4000.f)
165 x_temp = ((-0.2661239e9f /
t - 0.2343589e6f) /
t + 0.8776956e3f) /
t + 0.179910f;
166 else if(
t > 4000.f &&
t <= 25000.f)
167 x_temp = ((-3.0258469e9f /
t + 2.1070379e6f) /
t + 0.2226347e3f) /
t + 0.240390f;
169 if(
t >= 1667.f &&
t <= 2222.f)
170 y_temp = ((-1.1063814f * x_temp - 1.34811020f) * x_temp + 2.18555832f) * x_temp - 0.20219683f;
171 else if(
t > 2222.f &&
t <= 4000.f)
172 y_temp = ((-0.9549476f * x_temp - 1.37418593f) * x_temp + 2.09137015f) * x_temp - 0.16748867f;
173 else if(
t > 4000.f &&
t <= 25000.f)
174 y_temp = (( 3.0817580f * x_temp - 5.87338670f) * x_temp + 3.75112997f) * x_temp - 0.37001483f;
186 XYZ[2] = (1.f -
x - y) / y;
202 const float max_RGB = fmaxf(fmaxf(
RGB[0],
RGB[1]),
RGB[2]);
203 for(
int c = 0; c < 3; c++)
RGB[c] = fmaxf(
RGB[c] / max_RGB, 0.f);
222 float *chroma_x,
float *chroma_y);
228 float *x_out,
float *y_out,
289 if(y != 0.f &&
x != 0.f)
break;
297 if(y != 0.f &&
x != 0.f)
break;
315 if(
x != 0.f && y != 0.f)
333 XYZ[0] = CAM_to_XYZ[0][0] / WB[0] + CAM_to_XYZ[1][0] / WB[1] + CAM_to_XYZ[2][0] / WB[2];
334 XYZ[1] = CAM_to_XYZ[0][1] / WB[0] + CAM_to_XYZ[1][1] / WB[1] + CAM_to_XYZ[2][1] / WB[2];
335 XYZ[2] = CAM_to_XYZ[0][2] / WB[0] + CAM_to_XYZ[1][2] / WB[1] + CAM_to_XYZ[2][2] / WB[2];
339 const float p = powf(1.088932f / 0.818155f, 0.0834f);
359 for(
int i = 0;
i < 3;
i++)
361 for(
int j = 0; j < 6; j++)
362 work[
i][j] = j ==
i+3;
363 for(
int j = 0; j < 3; j++)
365 work[
i][j] += in[
k][
i] * in[
k][j];
367 for(
int i = 0;
i < 3;
i++)
369 float num = work[
i][
i];
370 for(
int j = 0; j < 6; j++)
372 for(
int k = 0;
k < 3;
k++)
376 for(
int j = 0; j < 6; j++)
377 work[
k][j] -= work[
i][j] * num;
381 for(
int j = 0; j < 3; j++)
384 for(
int k = 0;
k < 3;
k++)
385 out[
i][j] += work[j][
k+3] * in[
i][
k];
391 float *chroma_x,
float *chroma_y)
396 int has_valid_coeffs =
TRUE;
400 for(
int k = 0; has_valid_coeffs &&
k < num_coeffs;
k++)
403 if(!has_valid_coeffs)
return FALSE;
411 for(
size_t k = 0;
k < 4;
k++) WB[
k] *= custom_wb[
k];
414 float XYZ_to_CAM[4][3];
415 XYZ_to_CAM[0][0] = NAN;
435 for(
int k=0;
k<4;
k++)
436 for(
int i=0;
i<3;
i++)
440 if(isnan(XYZ_to_CAM[0][0]))
return FALSE;
444 float CAM_to_XYZ[4][3];
445 CAM_to_XYZ[0][0] = NAN;
447 if(isnan(CAM_to_XYZ[0][0]))
return FALSE;
465 if(
t >= 1667.f &&
t <= 2222.f)
466 n = (-3.3191442f *
x - 2.69622040f) *
x + 2.18555832f;
467 else if(
t > 2222.f &&
t <= 4000.f)
468 n = (-2.8648428f *
x - 2.74837186f) *
x + 2.09137015f;
469 else if(
t > 4000.f &&
t < 25000.f)
470 n = (9.2452740f *
x - 11.7467734f) *
x + 3.75112997f;
477 float *x_out,
float *y_out)
481 const float norm = sqrtf(1.f +
n *
n);
482 *x_out =
x + tint *
n / norm;
483 *y_out = y - tint / norm;
492 const float norm = sqrtf(1.f +
n *
n);
495 const float tint = -(y - y_bb) * norm;
501static inline
void xy_to_uv(const
float xy[2],
float uv[2])
505 const float denom = 12.f * xy[1] - 1.882f * xy[0] + 2.9088f;
506 uv[0] = 5.5932f * xy[0] + 1.9116 * xy[1];
507 uv[1] = 7.8972f * xy[1];
533 if(
n.radius <
r.radius)
return n;
539#pragma omp declare reduction(pairmin:struct pair:omp_out=pair_min(omp_out,omp_in)) \
540 initializer(omp_priv = { FLT_MAX, 0.0f })
549 static const float T_min = 1667.f;
550 static const float T_max = 25000.f;
551 static const float T_range = T_max - T_min;
552 static const size_t LUT_samples = 1<<16;
554 struct pair min_radius = { FLT_MAX, 0.0f };
556#if !(defined(__apple_build_version__) && __apple_build_version__ < 11030000)
559 for(
size_t i = 0;
i < LUT_samples;
i++)
562 const float step = powf((
float)
i / (
float)(LUT_samples - 1), 4.0f);
565 const float T = T_min + step * T_range;
576 const pair radius_tmp = { dt_fast_hypotf((x_bb -
x), (y_bb - y)), T };
579 min_radius =
pair_min(min_radius, radius_tmp);
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
static const dt_aligned_pixel_simd_t illuminant
static float4 convert_XYZ_to_bradford_LMS(const float4 XYZ)
static void bradford_adapt_D50(float4 *lms_in, const float4 origin_illuminant, const float p, const int full)
static float4 convert_bradford_LMS_to_XYZ(const float4 LMS)
dt_XYZ_to_Rec709_D50(XYZ, rgb)
static dt_aligned_pixel_t XYZ
const dt_colormatrix_t dt_aligned_pixel_t out
dt_store_simd_aligned(out, dt_mat3x4_mul_vec4(vin, dt_colormatrix_row_to_simd(matrix, 0), dt_colormatrix_row_to_simd(matrix, 1), dt_colormatrix_row_to_simd(matrix, 2)))
static dt_aligned_pixel_t RGB
gboolean dt_image_is_matrix_correction_supported(const dt_image_t *img)
#define __OMP_DECLARE_SIMD__(...)
#define __OMP_PARALLEL_FOR__(...)
#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 illuminant_to_xy(const dt_illuminant_t illuminant, const dt_image_t *img, const dt_aligned_pixel_t custom_wb, float *x_out, float *y_out, const float t, const dt_illuminant_fluo_t fluo, const dt_illuminant_led_t iled)
@ DT_ILLUMINANT_DETECT_EDGES
@ DT_ILLUMINANT_DETECT_SURFACES
static void WB_coeffs_to_illuminant_xy(const float CAM_to_XYZ[4][3], const dt_aligned_pixel_t WB, float *x, float *y)
static void illuminant_CCT_to_RGB(const float t, dt_aligned_pixel_t RGB)
static void illuminant_xy_to_RGB(const float x, const float y, dt_aligned_pixel_t RGB)
static void illuminant_xy_to_XYZ(const float x, const float y, dt_aligned_pixel_t XYZ)
static float xy_to_CCT(const float x, const float y)
static void CCT_to_xy_daylight(const float t, float *x, float *y)
static float CCT_reverse_lookup(const float x, const float y)
static float get_tint_from_tinted_xy(const float x, const float y, const float t)
static float planckian_normal(const float x, const float t)
static int find_temperature_from_raw_coeffs(const dt_image_t *img, const dt_aligned_pixel_t custom_wb, float *chroma_x, float *chroma_y)
static void CCT_to_xy_blackbody(const float t, float *x, float *y)
static float fluorescent[DT_ILLUMINANT_FLUO_LAST][2]
static void matrice_pseudoinverse(float(*in)[3], float(*out)[3], int size)
@ DT_ILLUMINANT_FLUO_LAST
static void blackbody_xy_to_tinted_xy(const float x, const float y, const float t, const float tint, float *x_out, float *y_out)
static void xy_to_uv(const float xy[2], float uv[2])
static float led[DT_ILLUMINANT_LED_LAST][2]
struct pair pair_min(struct pair r, struct pair n)
float *const restrict const size_t k
float dt_aligned_pixel_t[4]
float d65_color_matrix[9]
float adobe_XYZ_to_CAM[4][3]
dt_aligned_pixel_t wb_coeffs