color: Handle negative values in all transfer functions

Make sure that for all eotfs/oetfs, eotf(x) == -eotf(-x)

In particular, don't pass negative values to pow() and cause undefined
behavior.
This commit is contained in:
Benjamin Otte 2024-08-13 20:45:30 +02:00
parent b1995d0d77
commit 79c2df8392
2 changed files with 17 additions and 16 deletions

View File

@ -53,8 +53,8 @@ output_color_alpha (vec4 color,
float
srgb_eotf (float v)
{
if (v >= 0.04045)
return pow (((v + 0.055) / (1.0 + 0.055)), 2.4);
if (abs (v) >= 0.04045)
return sign (v) * pow (((abs (v) + 0.055) / (1.0 + 0.055)), 2.4);
else
return v / 12.92;
}
@ -62,8 +62,8 @@ srgb_eotf (float v)
float
srgb_oetf (float v)
{
if (v > 0.0031308)
return 1.055 * pow (v, 1.0 / 2.4) - 0.055;
if (abs (v) > 0.0031308)
return 1.055 * sign (v) * pow (abs (v), 1.0 / 2.4) - 0.055;
else
return 12.92 * v;
}
@ -77,9 +77,10 @@ pq_eotf (float v)
const float c2 = 2413.0 / 128.0;
const float c3 = 2392.0 / 128.0;
float x = pow (max ((pow (v, minv) - c1), 0.0) / (c2 - (c3 * (pow (v, minv)))), ninv);
float x = pow (abs (v), minv);
x = pow (max (x - c1, 0.0) / (c2 - (c3 * x)), ninv);
return x * 10000.0 / 203.0;
return sign (v) * x * 10000.0 / 203.0;
}
float
@ -91,9 +92,9 @@ pq_oetf (float v)
const float c2 = 2413.0 / 128.0;
const float c3 = 2392.0 / 128.0;
float x = v * 203.0 / 10000.0;
float x = pow (abs (v) * 203.0 / 10000.0, n);
return pow (((c1 + (c2 * pow (x, n))) / (1.0 + (c3 * pow (x, n)))), m);
return sign (v) * pow (((c1 + (c2 * x)) / (1.0 + (c3 * x))), m);
}
/* Note that these matrices are transposed from the C version */

View File

@ -161,43 +161,43 @@ run (out vec2 pos)
float
bt709_eotf (float v)
{
if (v < 0.081)
if (abs (v) < 0.081)
return v / 4.5;
else
return pow ((v + 0.099) / 1.099, 1.0/0.45);
return sign (v) * pow ((abs (v) + 0.099) / 1.099, 1.0/0.45);
}
float
bt709_oetf (float v)
{
if (v < 0.081)
if (abs (v) < 0.081)
return v * 4.5;
else
return 1.099 * pow (v, 0.45) - 0.099;
return 1.099 * sign (v) * pow (abs (v), 0.45) - 0.099;
}
float
gamma22_oetf (float v)
{
return pow (v, 1.0 / 2.2);
return sign (v) * pow (abs (v), 1.0 / 2.2);
}
float
gamma22_eotf (float v)
{
return pow (v, 2.2);
return sign (v) * pow (abs (v), 2.2);
}
float
gamma28_oetf (float v)
{
return pow (v, 1.0 / 2.8);
return sign (v) * pow (abs (v), 1.0 / 2.8);
}
float
gamma28_eotf (float v)
{
return pow (v, 2.8);
return sign (v) * pow (abs (v), 2.8);
}
float