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)); }
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)); }
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)); }
public WideningImpl(bool videoRange = false) { scale = 1f / (videoRange ? VideoLumaScale : byte.MaxValue); offset = videoRange ? VideoLumaMin : 0f; valueTable = videoRange ? LookupTables.MakeVideoInverseGamma(LookupTables.Alpha) : LookupTables.Alpha; }