Пример #1
0
        private static ProfileCurve curveFromParameters(double a, double b, double c, double d, double e, double f, double g)
        {
            if (
                g.IsRoughlyEqualTo(2.4) &&
                d.IsRoughlyEqualTo(0.04045) &&
                a.IsRoughlyEqualTo(1.000 / 1.055) &&
                b.IsRoughlyEqualTo(0.055 / 1.055) &&
                c.IsRoughlyEqualTo(1.000 / 12.92)
                )
            {
                return(sRGB.Curve);
            }

            var igt = new float[LookupTables.InverseGammaLength];

            for (int i = 0; i < igt.Length; i++)
            {
                double val = (double)i / LookupTables.InverseGammaScale;
                if (val >= d)
                {
                    val = Math.Pow(val * a + b, g) + c + e;
                }
                else
                {
                    val = val * c + f;
                }

                igt[i] = (float)val;
            }

            g = 1d / g;

            var gt = new float[LookupTables.GammaLengthFloat];

            for (int i = 0; i < gt.Length; i++)
            {
                double val = (double)i / LookupTables.GammaScaleFloat;
                if (val > (c * d + f))
                {
                    val = (Math.Pow(val - c - e, g) - b) / a;
                }
                else
                {
                    val = c == 0f ? 0f : ((val - f) / c);
                }

                gt[i] = (float)val;
            }

            LookupTables.Fixup(gt, LookupTables.GammaScaleFloat);
            LookupTables.Fixup(igt, LookupTables.InverseGammaScale);

            return(new ProfileCurve(gt, igt));
        }
Пример #2
0
        private static ProfileCurve curveFromPower(double gamma)
        {
            var igt = new float[LookupTables.InverseGammaLength];

            for (int i = 0; i < igt.Length; i++)
            {
                igt[i] = (float)Math.Pow((double)i / LookupTables.InverseGammaScale, gamma);
            }

            gamma = 1d / gamma;

            var gt = new float[LookupTables.GammaLengthFloat];

            for (int i = 0; i < gt.Length; i++)
            {
                gt[i] = (float)Math.Pow((double)i / LookupTables.GammaScaleFloat, gamma);
            }

            LookupTables.Fixup(gt, LookupTables.GammaScaleFloat);
            LookupTables.Fixup(igt, LookupTables.InverseGammaScale);

            return(new ProfileCurve(gt, igt));
        }
Пример #3
0
        private static ProfileCurve curveFromPoints(ReadOnlySpan <ushort> points, bool inverse)
        {
            int buffLen = points.Length * sizeof(double);

            using var buff = MemoryPool <byte> .Shared.Rent(buffLen);

            var    curve = MemoryMarshal.Cast <byte, double>(buff.Memory.Span.Slice(0, buffLen));
            double cscal = curve.Length - 1;

            for (int i = 0; i < curve.Length; i++)
            {
                curve[i] = (double)points[i] / ushort.MaxValue;
            }

            var igt = new float[LookupTables.InverseGammaLength];

            for (int i = 0; i <= LookupTables.InverseGammaScale; i++)
            {
                double val = (double)i / LookupTables.InverseGammaScale;
                double pos = val * cscal;

                int idx = Math.Min((int)pos, curve.Length - 2);
                igt[i] = (float)Lerp(curve[idx], curve[idx + 1], pos - idx);
            }

            if (lutInvertsTo(igt, LookupTables.SrgbGamma))
            {
                return(sRGB.Curve);
            }

            if (inverse)
            {
                curve.Reverse();
            }

            var gt = new float[LookupTables.GammaLengthFloat];

            for (int i = 0; i <= LookupTables.GammaScaleFloat; i++)
            {
                double val = (double)i / LookupTables.GammaScaleFloat;
                int    idx = curve.BinarySearch(val);

                double pos;
                if (idx >= 0)
                {
                    pos = idx;
                }
                else
                {
                    idx = ~idx;
                    if (idx == 0)
                    {
                        pos = 0;
                    }
                    else if (idx == curve.Length)
                    {
                        pos = curve.Length - 1;
                    }
                    else
                    {
                        double vh = curve[idx];
                        double vl = curve[idx - 1];
                        if (vl == vh)
                        {
                            pos = idx;
                        }
                        else
                        {
                            pos = idx - 1 + (val - vl) / (vh - vl);
                        }
                    }
                }

                gt[i] = (float)(pos / (curve.Length - 1));
            }

            if (inverse)
            {
                Array.Reverse(gt, 0, LookupTables.GammaScaleFloat + 1);
            }

            LookupTables.Fixup(gt, LookupTables.GammaScaleFloat);
            LookupTables.Fixup(igt, LookupTables.InverseGammaScale);

            return(new ProfileCurve(gt, igt));
        }
Пример #4
0
 public WideningImpl(bool videoRange = false)
 {
     scale      = 1f / (videoRange ? VideoLumaScale : byte.MaxValue);
     offset     = videoRange ? VideoLumaMin : 0f;
     valueTable = videoRange ? LookupTables.MakeVideoInverseGamma(LookupTables.Alpha) : LookupTables.Alpha;
 }