Example #1
0
        public static Color LabToRgb(Lab lab)
        {
            XYZ   xyz  = LabToXyz(lab);
            Color rgba = XyzToRgb(xyz);

            return(rgba);
        }
Example #2
0
        public static Lab RgbToLab(Color rgba)
        {
            XYZ xyz = RgbToXyz(rgba);
            Lab lab = XyzToLab(xyz);

            return(lab);
        }
Example #3
0
        public static XYZ LabToXyz(Lab lab)
        {
            float y = (lab.L + 16f) / 116f;
            float x = lab.A / 500f + y;
            float z = y - lab.B / 200f;

            float f = 16f / 116f;

            y = (Mathf.Pow(y, 3f) > 0.008856f) ? Mathf.Pow(y, 3f) : (y - f) / 7.787f;
            x = (Mathf.Pow(x, 3f) > 0.008856f) ? Mathf.Pow(x, 3f) : (x - f) / 7.787f;
            z = (Mathf.Pow(z, 3f) > 0.008856f) ? Mathf.Pow(z, 3f) : (z - f) / 7.787f;

            XYZ xyz = new XYZ
            {
                X     = xyzWhiteRef.X * x,
                Y     = xyzWhiteRef.Y * y,
                Z     = xyzWhiteRef.Z * z,
                Alpha = lab.Alpha
            };

            return(xyz);
        }
Example #4
0
        public static Lab XyzToLab(XYZ xyz)
        {
            float x = xyz.X / xyzWhiteRef.X;
            float y = xyz.Y / xyzWhiteRef.Y;
            float z = xyz.Z / xyzWhiteRef.Z;

            float p = 1f / 3f;
            float f = 16f / 116f;

            x = (x > 0.008856f) ? Mathf.Pow(x, p) : (7.787f * x) + f;
            y = (y > 0.008856f) ? Mathf.Pow(y, p) : (7.787f * y) + f;
            z = (z > 0.008856f) ? Mathf.Pow(z, p) : (7.787f * z) + f;

            Lab lab = new Lab
            {
                L     = (116f * y) - 16f,
                A     = 500f * (x - y),
                B     = 200f * (y - z),
                Alpha = xyz.Alpha
            };

            return(lab);
        }
Example #5
0
        private static LCh LabToLCh(Lab lab)
        {
            LCh lch = new LCh();

            lch.l = lab.L;

            lch.c = Mathf.Sqrt(lab.A * lab.A + lab.B * lab.B);

            float h = Mathf.Rad2Deg * Mathf.Atan2(lab.B, lab.A);

            if (h < 0)
            {
                h += 360f;
            }
            else if (h >= 360)
            {
                h -= 360f;
            }
            lch.h = h;

            lch.alpha = lab.Alpha;

            return(lch);
        }
Example #6
0
        /// <summary>
        /// Tips: 0.5f (really high contrast shapes, maybe 10+ bit monitors), 1f (high-quality monitors, indoors) 2.0f (else).
        /// </summary>
        public static float DeltaEmpfindung00(Lab lab1, Lab lab2, DeltaEWeightType weight = DeltaEWeightType.Graphic)
        {
            // Lab to LCh
            LCh lch1 = LabToLCh(lab1);
            LCh lch2 = LabToLCh(lab2);
            // Weight Factors
            DeltaEWeight weightFactors = Convert.ToBoolean((int)weight) ? weightGraphic : weightTextile;

            float CX = (lch1.c + lch2.c) / 2f;
            float GX = 0.5f * (1f - Mathf.Sqrt(Mathf.Pow(CX, 7f) / (Mathf.Pow(CX, 7f) + Mathf.Pow(25f, 7f))));

            float NN = (1f + GX) * lab1.A;

            lch1.c = Mathf.Sqrt(NN * NN + lab1.B * lab1.B);

            float hue1 = LabToHue(NN, lab1.B);

            NN     = (1f + GX) * lab2.A;
            lch2.c = Mathf.Sqrt(NN * NN + lab2.B * lab2.B);

            float hue2           = LabToHue(NN, lab2.B);
            float deltaLightness = lch2.l - lch1.l;
            float deltaChroma    = lch2.c - lch1.c;
            float deltaHue;

            if ((lch1.c * lch2.c) == 0f)
            {
                deltaHue = 0f;
            }
            else
            {
                NN = Mathf.Round((hue2 - hue1) * 1000f) / 1000f;
                if (Mathf.Abs(NN) <= 180f)
                {
                    deltaHue = hue2 - hue1;
                }
                else
                {
                    if (NN > 180f)
                    {
                        deltaHue = hue2 - hue1 - 360f;
                    }
                    else
                    {
                        deltaHue = hue2 - hue1 + 360f;
                    }
                }
            }
            deltaHue = 2f * Mathf.Sqrt(lch1.c * lch2.c) * Mathf.Sin((deltaHue / 2f) * Mathf.Deg2Rad);

            float lightnessAverage = (lch1.l + lch2.l) / 2f;
            float chromaAverage    = (lch1.c + lch2.c) / 2f;

            float hueNeutralsCompensation;

            if ((lch1.c * lch2.c) == 0f)
            {
                hueNeutralsCompensation = hue1 + hue2;
            }
            else
            {
                NN = Mathf.Abs(Mathf.Round((hue1 - hue2) * 1000f) / 1000f);
                if (NN > 180f)
                {
                    if ((hue2 + hue1) < 360f)
                    {
                        hueNeutralsCompensation = hue1 + hue2 + 360f;
                    }
                    else
                    {
                        hueNeutralsCompensation = hue1 + hue2 - 360f;
                    }
                }
                else
                {
                    hueNeutralsCompensation = hue1 + hue2;
                }
                hueNeutralsCompensation /= 2f;
            }

            float T = 1f
                      - 0.17f * Mathf.Cos((hueNeutralsCompensation - 30f) * Mathf.Deg2Rad)
                      + 0.24f * Mathf.Cos((2f * hueNeutralsCompensation) * Mathf.Deg2Rad)
                      + 0.32f * Mathf.Cos((3f * hueNeutralsCompensation + 6f) * Mathf.Deg2Rad)
                      - 0.20f * Mathf.Cos((4f * hueNeutralsCompensation - 63f) * Mathf.Deg2Rad);

            // Compensations
            float lightnessCompensation = 1f + ((0.015f * ((lightnessAverage - 50f) * (lightnessAverage - 50f))) / Mathf.Sqrt(20f + ((lightnessAverage - 50f) * (lightnessAverage - 50f))));
            float chromaCompensation    = 1f + weightFactors.kC * chromaAverage;
            float hueCompensation       = 1f + weightFactors.kH * chromaAverage * T;
            // Rotation
            float PH           = 30f * Mathf.Exp(-((hueNeutralsCompensation - 275f) / 25f) * ((hueNeutralsCompensation - 275f) / 25f));
            float RC           = 2f * Mathf.Sqrt(Mathf.Pow(chromaAverage, 7f) / (Mathf.Pow(chromaAverage, 7f) + Mathf.Pow(25f, 7f)));
            float rotationTerm = -Mathf.Sin((2f * PH) * Mathf.Deg2Rad) * RC;
            // Weights Constants
            float weightFactorChroma = 1f;
            float weightFactorHue    = 1f;

            // Corrections
            deltaLightness = deltaLightness / (weightFactors.kL * lightnessCompensation);
            deltaChroma    = deltaChroma / (weightFactorChroma * chromaCompensation);
            deltaHue       = deltaHue / (weightFactorHue * hueCompensation);

            float distance = Mathf.Sqrt(Mathf.Pow(deltaLightness, 2f) + Mathf.Pow(deltaChroma, 2f) + Mathf.Pow(deltaHue, 2f) + rotationTerm * deltaChroma * deltaHue);

            return(distance);
        }