28#ifndef DT_COMMON_COLORSPACES_INLINE_CONVERSIONS_H
29#define DT_COMMON_COLORSPACES_INLINE_CONVERSIONS_H
34static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
44 const dt_aligned_pixel_simd_t vin = dt_load_simd_aligned(in);
46 dt_colormatrix_row_to_simd(
matrix, 1),
47 dt_colormatrix_row_to_simd(
matrix, 2)));
53 uint32_t *
const p = (uint32_t *)&
f;
54 *
p = *
p / 3 + 709921077;
61 const float a3 = a * a * a;
62 const float b = a * (a3 +
R +
R) / (a3 + a3 +
R);
67static inline
float lab_f(const
float x)
69 const float epsilon = 216.0f / 24389.0f;
70 const float kappa = 24389.0f / 27.0f;
83 Lab[0] = 116.0f *
f[1] - 16.0f;
84 Lab[1] = 500.0f * (
f[0] -
f[1]);
85 Lab[2] = 200.0f * (
f[1] -
f[2]);
91 const float epsilon = 0.20689655172413796f;
92 const float kappa = 24389.0f / 27.0f;
93 return (
x > epsilon) ?
x *
x *
x : (116.0f *
x - 16.0f) / kappa;
100 const float fy = (
Lab[0] + 16.0f) / 116.0f;
101 const float fx =
Lab[1] / 500.0f + fy;
102 const float fz = fy -
Lab[2] / 200.0f;
112 const float sum =
XYZ[0] +
XYZ[1] +
XYZ[2];
119dt_XYZ_to_xyY_simd(
const dt_aligned_pixel_simd_t
XYZ)
121 const float sum =
XYZ[0] +
XYZ[1] +
XYZ[2];
122 return (dt_aligned_pixel_simd_t){
XYZ[0] / sum,
XYZ[1] / sum,
XYZ[1], 0.f };
134static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
135dt_xyY_to_XYZ_simd(
const dt_aligned_pixel_simd_t
xyY)
137 const float y_over_x =
xyY[2] /
xyY[1];
138 return (dt_aligned_pixel_simd_t){ y_over_x *
xyY[0],
xyY[2], y_over_x * (1.f -
xyY[0] -
xyY[1]), 0.f };
151 const float denominator = -2.f *
xyY[0] + 12.f *
xyY[1] + 3.f;
152 uvY[0] = 4.f *
xyY[0] / denominator;
153 uvY[1] = 9.f *
xyY[1] / denominator;
158static inline
float cbf(const
float x)
181 Luv[1] = 13.f *
Luv[0] * (
uvY[0] - D50[0]);
182 Luv[2] = 13.f *
Luv[0] * (
uvY[1] - D50[1]);
214 const float denominator = 6.0f *
uvY[0] - 16.f *
uvY[1] + 12.0f;
215 xyY[0] = 9.f *
uvY[0] / denominator;
216 xyY[1] = 4.f *
uvY[1] / denominator;
236 static const float D50[2]
DT_ALIGNED_PIXEL = { 0.20915914598542354f, 0.488075320769787f };
237 uvY[0] =
Luv[1] / (
Luv[0] * 13.f) + D50[0];
238 uvY[1] =
Luv[2] / (
Luv[0] * 13.f) + D50[1];
264 { { 3.1338561f, -0.9787684f, 0.0719453f, 0.0f },
265 { -1.6168667f, 1.9161415f, -0.2289914f, 0.0f },
266 { -0.4906146f, 0.0334540f, 1.4052427f, 0.0f } };
280 { 3.2404542f, -0.9692660f, 0.0556434f, 0.0f },
281 { -1.5371385f, 1.8760108f, -0.2040259f, 0.0f },
282 { -0.4985314f, 0.0415560f, 1.0572252f, 0.0f },
297 for(
size_t c = 0; c < 3; c++)
298 sRGB[c] =
rgb[c] <= 0.0031308f ? 12.92f *
rgb[c] : (1.0f + 0.055f) * powf(
rgb[c], 1.0f / 2.4f) - 0.055f;
320 { 0.4360747f, 0.2225045f, 0.0139322f, 0.0f },
321 { 0.3850649f, 0.7168786f, 0.0971045f, 0.0f },
322 { 0.1430804f, 0.0606169f, 0.7141733f, 0.0f }
330 for(
int c = 0; c < 3; c++)
331 RGB[c] =
sRGB[c] <= 0.04045f ?
sRGB[c] / 12.92f : powf((
sRGB[c] + 0.055f) / (1.0f + 0.055f), 2.4f);
348 { 1.3459433f, -0.5445989f, 0.0000000f, 0.0f },
349 { -0.2556075f, 1.5081673f, 0.0000000f, 0.0f },
350 { -0.0511118f, 0.0205351f, 1.2118128f, 0.0f }
361 { 0.7976749f, 0.2880402f, 0.0000000f, 0.0f },
362 { 0.1351917f, 0.7118741f, 0.0000000f, 0.0f },
363 { 0.0313534f, 0.0000857f, 0.8252100f, 0.0f }
370 { { 0.4360747f, 0.3850649f, 0.1430804f },
371 { 0.2225045f, 0.7168786f, 0.0606169f },
372 { 0.0139322f, 0.0971045f, 0.7141733f } };
376 { { 0.4360747f, 0.2225045f, 0.0139322f },
377 { 0.3850649f, 0.7168786f, 0.0971045f },
378 { 0.1430804f, 0.0606169f, 0.7141733f } };
387 { { 3.1338561f, -1.6168667f, -0.4906146f },
388 { -0.9787684f, 1.9161415f, 0.0334540f },
389 { 0.0719453f, -0.2289914f, 1.4052427f } };
393 { { 3.1338561f, -0.9787684f, 0.0719453f },
394 { -1.6168667f, 1.9161415f, -0.2289914f },
395 { -0.4906146f, 0.0334540f, 1.4052427f } };
432 if(hue < 0.0f) hue += 1.0f;
433 if(hue > 1.0f) hue -= 1.0f;
440 const float h =
H * 6.0f;
441 const float i = floorf(h);
442 const float f = h -
i;
520 const float L =
HSL[2];
525 C = (1.0f -
L) *
HSL[1];
541 if(fabsf(
max) > 1e-6f && fabsf(
delta) > 1e-6f)
561 const float C =
HSV[1] *
HSV[2];
562 const float m =
HSV[2] -
C;
577 if(fabsf(
max) > 1e-6f && fabsf(
delta) > 1e-6f)
620 return (
rgb[0] * 0.2225045f +
rgb[1] * 0.7168786f +
rgb[2] * 0.0606169f);
628 { 0.9555766f, -0.0230393f, 0.0631636f, 0.0f },
629 { -0.0282895f, 1.0099416f, 0.0210077f, 0.0f },
630 { 0.0122982f, -0.0204830f, 1.3299098f, 0.0f },
634 { 0.9555766f, -0.0282895f, 0.0122982f, 0.0f },
635 { -0.0230393f, 1.0099416f, -0.0204830f, 0.0f },
636 { 0.0631636f, 0.0210077f, 1.3299098f, 0.0f },
648 { 1.0478112f, 0.0228866f, -0.0501270f, 0.0f },
649 { 0.0295424f, 0.9904844f, -0.0170491f, 0.0f },
650 { -0.0092345f, 0.0150436f, 0.7521316f, 0.0f },
654 { 1.0478112f, 0.0295424f, -0.0092345f, 0.0f },
655 { 0.0228866f, 0.9904844f, 0.0150436f, 0.0f },
656 { -0.0501270f, -0.0170491f, 0.7521316f, 0.0f },
674 const float b = 1.15f;
675 const float g = 0.66f;
676 const float c1 = 0.8359375f;
677 const float c2 = 18.8515625f;
678 const float c3 = 18.6875f;
679 const float n = 0.159301758f;
680 const float p = 134.034375f;
681 const float d = -0.56f;
682 const float d0 = 1.6295499532821566e-11f;
684 { 0.41478972f, 0.579999f, 0.0146480f, 0.0f },
685 { -0.2015100f, 1.120649f, 0.0531008f, 0.0f },
686 { -0.0166008f, 0.264800f, 0.6684799f, 0.0f },
690 { 0.5f, 0.5f, 0.0f, 0.0f },
691 { 3.524000f, -4.066708f, 0.542708f, 0.0f },
692 { 0.199076f, 1.096799f, -1.295875f, 0.0f },
696 { 0.5f, 3.524000f, 0.199076f, 0.0f },
697 { 0.5f, -4.066708f, 1.096799f, 0.0f },
698 { 0.0f, 0.542708f, -1.295875f, 0.0f },
711 for(int
i = 0;
i < 3;
i++)
714 LMS[
i] = powf(fmaxf(
LMS[
i] / 10000.f, 0.0f),
n);
725static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
726dt_XYZ_2_JzAzBz_simd(
const dt_aligned_pixel_simd_t
XYZ_D65)
728 const float b = 1.15f;
729 const float g = 0.66f;
730 const float c1 = 0.8359375f;
731 const float c2 = 18.8515625f;
732 const float c3 = 18.6875f;
733 const float n = 0.159301758f;
734 const float p = 134.034375f;
735 const float d = -0.56f;
736 const float d0 = 1.6295499532821566e-11f;
738 { 0.41478972f, -0.2015100f, -0.0166008f, 0.0f },
739 { 0.5799990f, 1.1206490f, 0.2648000f, 0.0f },
740 { 0.0146480f, 0.0531008f, 0.6684799f, 0.0f },
743 { 0.5f, 3.524000f, 0.199076f, 0.0f },
744 { 0.5f, -4.066708f, 1.096799f, 0.0f },
745 { 0.0f, 0.542708f, -1.295875f, 0.0f },
748 const dt_aligned_pixel_simd_t
XYZ = {
755 dt_aligned_pixel_simd_t
LMS = dt_mat3x4_mul_vec4(
XYZ,
756 dt_colormatrix_row_to_simd(M_transposed, 0),
757 dt_colormatrix_row_to_simd(M_transposed, 1),
758 dt_colormatrix_row_to_simd(M_transposed, 2));
759 for(
int i = 0;
i < 3;
i++)
761 LMS[
i] = powf(fmaxf(
LMS[
i] / 10000.f, 0.0f),
n);
765 dt_aligned_pixel_simd_t
JzAzBz = dt_mat3x4_mul_vec4(
LMS,
794 const float b = 1.15f;
795 const float g = 0.66f;
796 const float c1 = 0.8359375f;
797 const float c2 = 18.8515625f;
798 const float c3 = 18.6875f;
799 const float n_inv = 1.0f / 0.159301758f;
800 const float p_inv = 1.0f / 134.034375f;
801 const float d = -0.56f;
802 const float d0 = 1.6295499532821566e-11f;
804 { 1.9242264357876067f, -1.0047923125953657f, 0.0376514040306180f, 0.0f },
805 { 0.3503167620949991f, 0.7264811939316552f, -0.0653844229480850f, 0.0f },
806 { -0.0909828109828475f, -0.3127282905230739f, 1.5227665613052603f, 0.0f },
809 { 1.0f, 0.1386050432715393f, 0.0580473161561189f, 0.0f },
810 { 1.0f, -0.1386050432715393f, -0.0580473161561189f, 0.0f },
811 { 1.0f, -0.0960192420263190f, -0.8118918960560390f, 0.0f },
825 for(int
i = 0;
i < 3;
i++)
843 { 1.9242264357876067f, 0.3503167620949991f, -0.0909828109828475f, 0.0f },
844 { -1.0047923125953657f, 0.7264811939316552f, -0.3127282905230739f, 0.0f },
845 { 0.0376514040306180f, -0.0653844229480850f, 1.5227665613052603f, 0.0f },
848 { 1.0f, 1.0f, 1.0f, 0.0f },
849 { 0.1386050432715393f, -0.1386050432715393f, -0.0960192420263190f, 0.0f },
850 { 0.0580473161561189f, -0.0580473161561189f, -0.8118918960560390f, 0.0f },
853static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
854dt_JzAzBz_2_XYZ_simd(
const dt_aligned_pixel_simd_t
JzAzBz)
856 const float b = 1.15f;
857 const float g = 0.66f;
858 const float c1 = 0.8359375f;
859 const float c2 = 18.8515625f;
860 const float c3 = 18.6875f;
861 const float n_inv = 1.0f / 0.159301758f;
862 const float p_inv = 1.0f / 134.034375f;
863 const float d = -0.56f;
864 const float d0 = 1.6295499532821566e-11f;
871 dt_aligned_pixel_simd_t
LMS = dt_mat3x4_mul_vec4(
IzAzBz,
872 dt_colormatrix_row_to_simd(AI_transposed, 0),
873 dt_colormatrix_row_to_simd(AI_transposed, 1),
874 dt_colormatrix_row_to_simd(AI_transposed, 2));
875 for(
int i = 0;
i < 3;
i++)
881 const dt_aligned_pixel_simd_t
XYZ = dt_mat3x4_mul_vec4(
LMS,
882 dt_colormatrix_row_to_simd(MI_transposed, 0),
883 dt_colormatrix_row_to_simd(MI_transposed, 1),
884 dt_colormatrix_row_to_simd(MI_transposed, 2));
886 return (dt_aligned_pixel_simd_t){
888 (
XYZ[1] + (
g - 1.0f) * ((
XYZ[0] + (b - 1.0f) *
XYZ[2]) / b)) /
g,
903 = { { 0.257085f, 0.859943f, -0.031061f, 0.f },
904 { -0.394427f, 1.175800f, 0.106423f, 0.f },
905 { 0.064856f, -0.076250f, 0.559067f, 0.f } };
908 = { { 1.80794659f, -1.29971660f, 0.34785879f, 0.f },
909 { 0.61783960f, 0.39595453f, -0.04104687f, 0.f },
910 { -0.12546960f, 0.20478038f, 1.74274183f, 0.f } };
916 dot_product(
XYZ, XYZ_D65_to_LMS_2006_D65,
LMS);
919static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
920XYZ_to_LMS_simd(
const dt_aligned_pixel_simd_t
XYZ)
923 { 0.257085f, -0.394427f, 0.064856f, 0.f },
924 { 0.859943f, 1.175800f, -0.076250f, 0.f },
925 { -0.031061f, 0.106423f, 0.559067f, 0.f },
927 return dt_mat3x4_mul_vec4(
XYZ,
928 dt_colormatrix_row_to_simd(XYZ_D65_to_LMS_2006_D65_transposed, 0),
929 dt_colormatrix_row_to_simd(XYZ_D65_to_LMS_2006_D65_transposed, 1),
930 dt_colormatrix_row_to_simd(XYZ_D65_to_LMS_2006_D65_transposed, 2));
936 dot_product(
LMS, LMS_2006_D65_to_XYZ_D65,
XYZ);
939static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
940LMS_to_XYZ_simd(
const dt_aligned_pixel_simd_t
LMS)
943 { 1.80794659f, 0.61783960f, -0.12546960f, 0.f },
944 { -1.29971660f, 0.39595453f, 0.20478038f, 0.f },
945 { 0.34785879f, -0.04104687f, 1.74274183f, 0.f },
947 return dt_mat3x4_mul_vec4(
LMS,
948 dt_colormatrix_row_to_simd(LMS_2006_D65_to_XYZ_D65_transposed, 0),
949 dt_colormatrix_row_to_simd(LMS_2006_D65_to_XYZ_D65_transposed, 1),
950 dt_colormatrix_row_to_simd(LMS_2006_D65_to_XYZ_D65_transposed, 2));
961 = { { 0.95f, 0.38f, 0.00f, 0.f },
962 { 0.05f, 0.62f, 0.03f, 0.f },
963 { 0.00f, 0.00f, 0.97f, 0.f } };
966 = { { 1.0877193f, -0.66666667f, 0.02061856f, 0.f },
967 { -0.0877193f, 1.66666667f, -0.05154639f, 0.f },
968 { 0.f, 0.f, 1.03092784f, 0.f } };
973 dot_product(
RGB, filmlightRGB_D65_to_LMS_D65,
LMS);
976static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
977gradingRGB_to_LMS_simd(
const dt_aligned_pixel_simd_t
RGB)
980 = { { 0.95f, 0.05f, 0.00f, 0.f },
981 { 0.38f, 0.62f, 0.00f, 0.f },
982 { 0.00f, 0.03f, 0.97f, 0.f } };
983 return dt_mat3x4_mul_vec4(
RGB,
984 dt_colormatrix_row_to_simd(filmlightRGB_D65_to_LMS_D65_transposed, 0),
985 dt_colormatrix_row_to_simd(filmlightRGB_D65_to_LMS_D65_transposed, 1),
986 dt_colormatrix_row_to_simd(filmlightRGB_D65_to_LMS_D65_transposed, 2));
992 dot_product(
LMS, LMS_D65_to_filmlightRGB_D65,
RGB);
995static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
996LMS_to_gradingRGB_simd(
const dt_aligned_pixel_simd_t
LMS)
999 = { { 1.0877193f, -0.0877193f, 0.f, 0.f },
1000 { -0.66666667f, 1.66666667f, 0.f, 0.f },
1001 { 0.02061856f, -0.05154639f, 1.03092784f, 0.f } };
1002 return dt_mat3x4_mul_vec4(
LMS,
1003 dt_colormatrix_row_to_simd(LMS_D65_to_filmlightRGB_D65_transposed, 0),
1004 dt_colormatrix_row_to_simd(LMS_D65_to_filmlightRGB_D65_transposed, 1),
1005 dt_colormatrix_row_to_simd(LMS_D65_to_filmlightRGB_D65_transposed, 2));
1017 const float Y = 0.68990272f *
LMS[0] + 0.34832189f *
LMS[1];
1033static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
1034LMS_to_Yrg_simd(
const dt_aligned_pixel_simd_t
LMS)
1036 const float Y = 0.68990272f *
LMS[0] + 0.34832189f *
LMS[1];
1038 const float inv_a = (
a == 0.f) ? 0.f : 1.f /
a;
1039 const dt_aligned_pixel_simd_t
lms = {
LMS[0] * inv_a,
LMS[1] * inv_a,
LMS[2] * inv_a, 0.f };
1040 const dt_aligned_pixel_simd_t
rgb = LMS_to_gradingRGB_simd(lms);
1041 return (dt_aligned_pixel_simd_t){
Y,
rgb[0],
rgb[1], 0.f };
1047 const float Y =
Yrg[0];
1050 const float r =
Yrg[1];
1051 const float g =
Yrg[2];
1052 const float b = 1.f -
r -
g;
1060 const float denom = (0.68990272f *
lms[0] + 0.34832189f *
lms[1]);
1061 const float a = (denom == 0.f) ? 0.f :
Y / denom;
1065static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
1066Yrg_to_LMS_simd(
const dt_aligned_pixel_simd_t Yrg)
1068 const dt_aligned_pixel_simd_t
rgb = {
Yrg[1],
Yrg[2], 1.f -
Yrg[1] -
Yrg[2], 0.f };
1069 const dt_aligned_pixel_simd_t
lms = gradingRGB_to_LMS_simd(
rgb);
1070 const float denom = 0.68990272f *
lms[0] + 0.34832189f *
lms[1];
1071 const float a = (denom == 0.f) ? 0.f :
Yrg[0] / denom;
1072 return (dt_aligned_pixel_simd_t){
lms[0] *
a,
lms[1] *
a,
lms[2] *
a, 0.f };
1082 const float Y =
Yrg[0];
1087 const float r =
Yrg[1] - 0.21902143f;
1088 const float g =
Yrg[2] - 0.54371398f;
1089 const float c = hypotf(
g,
r);
1090 const float h = atan2f(
g,
r);
1096static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
1097Yrg_to_Ych_simd(
const dt_aligned_pixel_simd_t Yrg)
1099 const float r =
Yrg[1] - 0.21902143f;
1100 const float g =
Yrg[2] - 0.54371398f;
1101 return (dt_aligned_pixel_simd_t){
Yrg[0], hypotf(
g,
r), atan2f(
g,
r), 0.f };
1107 const float Y = Ych[0];
1108 const float c = Ych[1];
1109 const float h = Ych[2];
1110 const float r =
c * cosf(h) + 0.21902143f;
1111 const float g =
c * sinf(h) + 0.54371398f;
1117static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
1118Ych_to_Yrg_simd(
const dt_aligned_pixel_simd_t Ych)
1120 return (dt_aligned_pixel_simd_t){
1122 Ych[1] * cosf(Ych[2]) + 0.21902143f,
1123 Ych[1] * sinf(Ych[2]) + 0.54371398f,
1142static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
1143Ych_to_gradingRGB_simd(
const dt_aligned_pixel_simd_t Ych)
1145 return LMS_to_gradingRGB_simd(Yrg_to_LMS_simd(Ych_to_Yrg_simd(Ych)));
1159static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
1160gradingRGB_to_Ych_simd(
const dt_aligned_pixel_simd_t
RGB)
1162 return Yrg_to_Ych_simd(LMS_to_Yrg_simd(gradingRGB_to_LMS_simd(
RGB)));
1177static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
1178XYZ_to_Ych_simd(
const dt_aligned_pixel_simd_t
XYZ)
1180 return Yrg_to_Ych_simd(LMS_to_Yrg_simd(XYZ_to_LMS_simd(
XYZ)));
1195static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
1196Ych_to_XYZ_simd(
const dt_aligned_pixel_simd_t Ych)
1198 return LMS_to_XYZ_simd(Yrg_to_LMS_simd(Ych_to_Yrg_simd(Ych)));
1214 const float D65_r = 0.21902143f;
1215 const float D65_g = 0.54371398f;
1217 float max_c = Ych[1];
1218 const float cos_h = cosf(Ych[2]);
1219 const float sin_h = sinf(Ych[2]);
1223 max_c = fminf(-D65_r / cos_h, max_c);
1227 max_c = fminf(-D65_g / sin_h, max_c);
1229 if(Yrg[1] + Yrg[2] > 1.f)
1231 max_c = fminf((1.f - D65_r - D65_g) / (cos_h + sin_h), max_c);
1238static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
1239gamut_check_Yrg_simd(
const dt_aligned_pixel_simd_t Ych)
1241 const dt_aligned_pixel_simd_t
Yrg = Ych_to_Yrg_simd(Ych);
1242 const float cos_h = cosf(Ych[2]);
1243 const float sin_h = sinf(Ych[2]);
1244 float max_c = Ych[1];
1246 if(Yrg[1] < 0.f) max_c = fminf(-0.21902143f / cos_h, max_c);
1247 if(Yrg[2] < 0.f) max_c = fminf(-0.54371398f / sin_h, max_c);
1248 if(Yrg[1] + Yrg[2] > 1.f) max_c = fminf((1.f - 0.21902143f - 0.54371398f) / (cos_h + sin_h), max_c);
1250 return (dt_aligned_pixel_simd_t){ Ych[0], max_c, Ych[2], 0.f };
1264 const float Y_hat = powf(Y, 0.631651345306265f);
1265 return 2.098883786377f * Y_hat / (Y_hat + 1.12426773749357f);
1271 return powf((1.12426773749357f * L_star / (2.098883786377f - L_star)), 1.5831518565279648f);
1279 const dt_aligned_pixel_t x_factors = { -0.783941002840055f, 0.745273540913283f, 0.318707282433486f, 0.f };
1280 const dt_aligned_pixel_t y_factors = { 0.277512987809202f, -0.205375866083878f, 2.16743692732158f, 0.f };
1281 const dt_aligned_pixel_t offsets = { 0.153836578598858f, -0.165478376301988f, 0.291320554395942f, 0.f };
1285 UVD[
c] = x_factors[
c] *
xyY[0] + y_factors[
c] *
xyY[1] + offsets[
c];
1290 float UV_star[2] = { 0.f };
1291 const float factors[2] = { 1.39656225667f, 1.4513954287f };
1292 const float half_values[2] = { 1.49217352929f, 1.52488637914f };
1293 for(
int c = 0;
c < 2;
c++)
1294 UV_star[c] = factors[c] * UVD[c] / (fabsf(UVD[c]) + half_values[c]);
1297 UV_star_prime[0] = -1.124983854323892f * UV_star[0] - 0.980483721769325f * UV_star[1];
1298 UV_star_prime[1] = 1.86323315098672f * UV_star[0] + 1.971853092390862f * UV_star[1];
1303static inline
void dt_UCS_LUV_to_JCH(const float L_star, const float L_white, const float UV_star_prime[2],
dt_aligned_pixel_t JCH)
1305 const float M2 = UV_star_prime[0] * UV_star_prime[0] + UV_star_prime[1] * UV_star_prime[1];
1308 JCH[0] = L_star / L_white;
1309 JCH[1] = 15.932993652962535f * powf(L_star, 0.6523997524738018f) * powf(M2, 0.6007557017508491f) / L_white;
1310 JCH[2] = atan2f(UV_star_prime[1], UV_star_prime[0]);
1326 float UV_star_prime[2];
1331static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
1332xyY_to_dt_UCS_JCH_simd(
const dt_aligned_pixel_simd_t
xyY,
const float L_white)
1337 return dt_load_simd_aligned(JCH);
1354 const float L_star = JCH[0] * L_white;
1355 const float M = powf(JCH[1] * L_white / (15.932993652962535f * powf(L_star, 0.6523997524738018f)), 0.8322850678616855f);
1357 const float U_star_prime =
M * cosf(JCH[2]);
1358 const float V_star_prime =
M * sinf(JCH[2]);
1361 const float UV_star[2] = { -5.037522385190711f * U_star_prime - 2.504856328185843f * V_star_prime,
1362 4.760029407436461f * U_star_prime + 2.874012963239247f * V_star_prime };
1364 float UV[2] = { 0.f };
1365 const float factors[2] = { 1.39656225667f, 1.4513954287f };
1366 const float half_values[2] = { 1.49217352929f, 1.52488637914f };
1367 for(
int c = 0;
c < 2;
c++)
1368 UV[c] = -half_values[c] * UV_star[c] / (fabsf(UV_star[c]) - factors[c]);
1370 const dt_aligned_pixel_t U_factors = { 0.167171472114775f, -0.150959086409163f, 0.940254742367256f, 0.f };
1371 const dt_aligned_pixel_t V_factors = { 0.141299802443708f, -0.155185060382272f, 1.000000000000000f, 0.f };
1372 const dt_aligned_pixel_t offsets = { -0.00801531300850582f, -0.00843312433578007f, -0.0256325967652889f, 0.f };
1376 xyD[
c] = U_factors[
c] * UV[0] + V_factors[
c] * UV[1] + offsets[
c];
1378 xyY[0] = xyD[0] / xyD[2];
1379 xyY[1] = xyD[1] / xyD[2];
1383static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
1384dt_UCS_JCH_to_xyY_simd(
const dt_aligned_pixel_simd_t JCH,
const float L_white)
1389 return dt_load_simd_aligned(
xyY);
1395 HSB[2] = JCH[0] * (powf(JCH[1], 1.33654221029386f) + 1.f);
1396 HSB[1] = (HSB[2] > 0.f) ? JCH[1] / HSB[2] : 0.f;
1400static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
1401dt_UCS_JCH_to_HSB_simd(
const dt_aligned_pixel_simd_t JCH)
1403 const float brightness = JCH[0] * (powf(JCH[1], 1.33654221029386f) + 1.f);
1404 return (dt_aligned_pixel_simd_t){ JCH[2], (brightness > 0.f) ? JCH[1] / brightness : 0.f, brightness, 0.f };
1411 JCH[1] = HSB[1] * HSB[2];
1412 JCH[0] = HSB[2] / (powf(JCH[1], 1.33654221029386f) + 1.f);
1415static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
1416dt_UCS_HSB_to_JCH_simd(
const dt_aligned_pixel_simd_t HSB)
1418 const float chroma = HSB[1] * HSB[2];
1419 return (dt_aligned_pixel_simd_t){
1420 HSB[2] / (powf(chroma, 1.33654221029386f) + 1.f),
1430 HCB[2] = JCH[0] * (powf(JCH[1], 1.33654221029386f) + 1.f);
1435static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
1436dt_UCS_JCH_to_HCB_simd(
const dt_aligned_pixel_simd_t JCH)
1438 return (dt_aligned_pixel_simd_t){
1441 JCH[0] * (powf(JCH[1], 1.33654221029386f) + 1.f),
1451 JCH[0] = HCB[2] / (powf(HCB[1], 1.33654221029386f) + 1.f);
1454static inline __attribute__((always_inline)) dt_aligned_pixel_simd_t
1455dt_UCS_HCB_to_JCH_simd(
const dt_aligned_pixel_simd_t HCB)
1457 return (dt_aligned_pixel_simd_t){
1458 HCB[2] / (powf(HCB[1], 1.33654221029386f) + 1.f),
1468 HPW[2] = sqrtf(HSB[1] * HSB[1] + HSB[2] * HSB[2]);
1469 HPW[1] = (HPW[2] > 0.f) ? HSB[1] / HPW[2] : 0.f;
1477 HSB[1] = HPW[1] * HPW[2];
1478 HSB[2] = fmaxf(sqrtf(HPW[2] * HPW[2] - HSB[1] * HSB[1]), 0.f);
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
static float dt_camera_rgb_luminance(const float4 rgb)
static float4 dt_UCS_JCH_to_HCB(const float4 JCH)
static float4 dt_xyY_to_XYZ(const float4 xyY)
static float4 dt_UCS_HSB_to_JCH(const float4 HSB)
static float4 gradingRGB_to_LMS(const float4 RGB)
static void xyY_to_dt_UCS_UV(const float4 xyY, float UV_star_prime[2])
static float4 gamut_check_Yrg(float4 Ych)
static float4 LMS_to_XYZ(const float4 LMS)
static float4 Yrg_to_Ych(const float4 Yrg)
static float4 Ych_to_Yrg(const float4 Ych)
static float4 LMS_to_gradingRGB(const float4 LMS)
static float4 dt_UCS_JCH_to_HSB(const float4 JCH)
static float dt_UCS_L_star_to_Y(const float L_star)
static float4 dt_UCS_JCH_to_xyY(const float4 JCH, const float L_white)
static float4 Yrg_to_LMS(const float4 Yrg)
static float4 LMS_to_Yrg(const float4 LMS)
static float Y_to_dt_UCS_L_star(const float Y)
static float4 xyY_to_dt_UCS_JCH(const float4 xyY, const float L_white)
static float4 dt_XYZ_to_xyY(const float4 XYZ)
static float4 XYZ_to_LMS(const float4 XYZ)
static float4 dt_UCS_HCB_to_JCH(const float4 HCB)
static dt_aligned_pixel_t xyY
static dt_aligned_pixel_t HSV
dt_prophotorgb_to_XYZ(rgb, XYZ)
dt_sRGB_to_linear_sRGB(sRGB, rgb)
const dt_aligned_pixel_t f
static dt_aligned_pixel_t rgb
dt_XYZ_to_Rec709_D50(XYZ, rgb)
static float cbrt_5f(float f)
_dt_Hue_2_RGB(RGB, HSL[0], 2.0f *C, m)
dt_apply_transposed_color_matrix(XYZ, xyz_to_srgb_matrix_transposed, sRGB)
static dt_aligned_pixel_t LCH
static float cbrta_halleyf(const float a, const float R)
static dt_aligned_pixel_t HCV
dt_XYZ_to_sRGB(XYZ, result)
static dt_aligned_pixel_t uvY
static const dt_colormatrix_t sRGB_to_xyz_transposed
const float D50[2] DT_ALIGNED_PIXEL
static const dt_colormatrix_t A_transposed
dt_XYZ_to_prophotorgb(XYZ, rgb)
static const dt_aligned_pixel_t d50
static dt_aligned_pixel_t HSL
static float cbf(const float x)
static const float const float const float min
const dt_colormatrix_t MI
static dt_aligned_pixel_t XYZ
static float lab_f(const float x)
static dt_aligned_pixel_t sRGB
static float lab_f_inv(const float x)
dt_aligned_pixel_t IzAzBz
static dt_aligned_pixel_t XYZ_D65
static dt_aligned_pixel_t Lab
static dt_aligned_pixel_t XYZ_D50
const dt_colormatrix_t AI
const dt_colormatrix_t dt_aligned_pixel_t out
dt_Rec709_to_XYZ_D50(rgb, XYZ)
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 const float const float C
static const dt_colormatrix_t xyz_to_srgb_transposed
for(size_t c=0;c< 3;c++) sRGB[c]
static dt_aligned_pixel_t JzAzBz
static dt_aligned_pixel_t Luv
static float _dt_RGB_2_Hue(const dt_aligned_pixel_t RGB, const float max, const float delta)
static dt_aligned_pixel_t RGB
static dt_aligned_pixel_t linearRGB
const dt_colormatrix_t matrix
static dt_aligned_pixel_t Lch
static const dt_colormatrix_t M
float DT_ALIGNED_ARRAY dt_colormatrix_t[4][4]
#define __OMP_SIMD__(...)
#define __OMP_DECLARE_SIMD__(...)
DT_ALIGNED_PIXEL float dt_aligned_pixel_t[4]
#define for_each_channel(_var,...)
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Apply one channel's tone curve to each of the three colour channels, or pass the channel through unto...
#define for_four_channels(_var,...)