static double FromLinear(double cLinear)
if (cLinear <= 0.0031308)
return 1.055*Math.Pow(cLinear,1/2.4)-0.055;
static double FromGamma(double cGamma)
return Math.Pow((cGamma+0.055)/1.055, 2.4);
static int ToInt(double v)
return (int)(Math.Round(v*255.0));
static int TrueC(int c, int a)
var mult = FromGamma(c/255.0) * (a/255.0);
return (int)(Math.Clamp(Math.Round(mult*65535),0,65535));
static void Test(int c, int a, int bits)
int cL = (c>>bits)<<bits;
int aL = (a>>bits)<<bits;
var c01 = TrueC(cL,aL+mask);
var c10 = TrueC(cL+mask,aL);
var c11 = TrueC(cL+mask,aL+mask);
var bX = 1-(double)cF/mask;
var bY = 1-(double)aF/mask;
var v1 = c00 * bX + c10 * (1-bX);
var v2 = c01 * bX + c11 * (1-bX);
var v3 = (int)(Math.Round(v1 * bY + v2 * (1-bY)));
var v1 = c00 * bX + c10 * (mask-bX);
var v2 = c01 * bX + c11 * (mask-bX);
var vA = v1 * bY + v2 * (mask-bY);
var v3 = (vA+mask*mask)/(mask*mask) - 192;
var err = Math.Abs(v4-v3);
Console.WriteLine($"{c} {a} => {v3-v4} {v3} , {v4}");
public static void Main()
for (int a = 0; a <= 255; ++a)
for (int c = 0; c <= 255; ++c)
double cg = FromGamma(cd);
double c2 = FromLinear(cg);
if (ToInt(c2) != ToInt(cd) || ToInt(cd) != c)
Console.WriteLine($"C err {c}" );
Console.WriteLine("Done");