diff options
Diffstat (limited to 'Software/Visual_Studio/PPC/Modules/Tango.PPC.JobsV2/Models/VisualOffsetModel.cs')
| -rw-r--r-- | Software/Visual_Studio/PPC/Modules/Tango.PPC.JobsV2/Models/VisualOffsetModel.cs | 407 |
1 files changed, 407 insertions, 0 deletions
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.JobsV2/Models/VisualOffsetModel.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.JobsV2/Models/VisualOffsetModel.cs new file mode 100644 index 000000000..042350cb0 --- /dev/null +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.JobsV2/Models/VisualOffsetModel.cs @@ -0,0 +1,407 @@ +using ColorMine.ColorSpaces; +using Colourful; +using Colourful.Conversion; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Media; +using Tango.Core.Commands; +using Tango.SharedUI; + +namespace Tango.PPC.Jobs.Models +{ + + public class VisualOffsetModel : ViewModel + { + public enum TypeColorCorrection + { + Lightness = 1, + Chroma = 2, + Hue = 3, + } + + public class VisualLCHOffset : ViewModel + { + public TypeColorCorrection ColorType { get; set; } + + public int Offset { get; set; } + + public double L { get; set; } + public double C { get; set; } + public double H { get; set; } + + public SolidColorBrush ColorBrush + { + get + { + Lch lch = new Lch() { L = L, C = C, H = H }; + IRgb RGB = lch.ToRgb(); + return new SolidColorBrush() { Color = Color.FromRgb(System.Convert.ToByte(RGB.R), System.Convert.ToByte(RGB.G), System.Convert.ToByte(RGB.B)) }; + } + } + + private bool _isVisible; + + public bool IsVisible + { + get { return _isVisible; } + set + { + _isVisible = value; + RaisePropertyChangedAuto(); + } + } + + + public VisualLCHOffset(TypeColorCorrection colorType, int offset) + { + ColorType = colorType; + Offset = offset; + } + + public void Init(Lch lch) + { + L = lch.L; + C = lch.C; + H = lch.H; + RaisePropertyChanged( nameof(ColorBrush)); + } + } + + #region Property + + + private double _l; + public double L + { + get { return _l; } + set + { + if (_l != value) + { + _l = value; + RaisePropertyChangedAuto(); + } + } + } + private double _a; + public double A + { + get { return _a; } + set + { + if (_a != value) + { + _a = value; + RaisePropertyChangedAuto(); + } + } + } + private double _b; + public double B + { + get { return _b; } + set + { + if (_b != value) + { + _b = value; + RaisePropertyChangedAuto(); + } + } + } + + public double C { get; set; } + public double H { get; set; } + + private double _sourcel; + public double SourceL + { + get { return _sourcel; } + set { + if(_sourcel != value) + { + _sourcel = value; + RaisePropertyChangedAuto(); + ManualCorrection(LightnessOffset, ChromaOffset, HueOffset); + } + } + } + + private double _sourcea; + public double SourceA + { + get { return _sourcea; } + set + { + if (_sourcea != value) + { + _sourcea = value; + RaisePropertyChangedAuto(); + ManualCorrection(LightnessOffset, ChromaOffset, HueOffset); + } + } + } + + private double _sourceb; + public double SourceB + { + get { return _sourceb; } + set + { + if (_sourceb != value) + { + _sourceb = value; + RaisePropertyChangedAuto(); + ManualCorrection(LightnessOffset, ChromaOffset, HueOffset); + } + } + } + + private double _sourceh; + public double SourceH + { + get { return _sourceh; } + set + { + if (_sourceh != value) + { + _sourceh = value; + RaisePropertyChangedAuto(); + } + } + } + + private double _sourcec; + public double SourceC + { + get { return _sourcec; } + set + { + if (_sourcec != value) + { + _sourcec = value; + RaisePropertyChangedAuto(); + } + } + } + + public double LightnessOffset { get; set; } + public double ChromaOffset { get; set; } + public double HueOffset { get; set; } + + + + public VisualLCHOffset MinLightness { get; set; } + public VisualLCHOffset MaxLightness { get; set; } + public VisualLCHOffset MinChroma { get; set; } + public VisualLCHOffset MaxChroma { get; set; } + public VisualLCHOffset MinHue { get; set; } + public VisualLCHOffset MaxHue { get; set; } + + public SolidColorBrush SourceColorBrush + { + get + { + //Lch lch = new Lch() { L = L, C = C, H = H }; + //IRgb RGB = lch.ToRgb(); + Lab lab = new Lab(SourceL, SourceA, SourceB); + Rgb rgb = new Rgb(lab.ToRgb()); + return new SolidColorBrush() { Color = Color.FromRgb((byte)rgb.R, (byte)rgb.G, (byte)rgb.B) }; + } + } + + public SolidColorBrush ManualColorBrush + { + get + { + //Lch lch = new Lch() { L = L, C = C, H = H }; + //IRgb rgb = lch.ToRgb(); + if(LightnessOffset == 0 && ChromaOffset == 0 && HueOffset == 0) + { + return SourceColorBrush; + } + Lab lab = new Lab(L, A, B); + Rgb rgb = new Rgb(lab.ToRgb()); + return new SolidColorBrush() { Color = Color.FromRgb((byte)rgb.R, (byte)rgb.G, (byte)rgb.B) }; + } + } + + #endregion + + public VisualOffsetModel() + { + MinLightness = new VisualLCHOffset(TypeColorCorrection.Lightness, -1); + MaxLightness = new VisualLCHOffset(TypeColorCorrection.Lightness, 1); + MinChroma = new VisualLCHOffset(TypeColorCorrection.Chroma, -1); + MaxChroma = new VisualLCHOffset(TypeColorCorrection.Chroma, 1); + MinHue = new VisualLCHOffset(TypeColorCorrection.Hue, -1); + MaxHue = new VisualLCHOffset(TypeColorCorrection.Hue, 1); + + } + + public void InitLAB(double l, double a, double b, double c, double h) + { + L = l; + A = a; + B = b; + C = c; + H = h; + LightnessOffset = ChromaOffset = HueOffset = 0; + + _sourcel = l; + RaisePropertyChanged(nameof(SourceL)); + _sourcea = a; + RaisePropertyChanged(nameof(SourceA)); + _sourceb = b; + RaisePropertyChanged(nameof(SourceB)); + _sourcec = c; + RaisePropertyChanged(nameof(SourceC)); + _sourceh = h; + RaisePropertyChanged(nameof(SourceH)); + + Lch lch = Correction(-6, 0, 0); + MinLightness.Init(lch); + lch = Correction(6, 0, 0); + MaxLightness.Init(lch); + lch = Correction(0, -6, 0); + MinChroma.Init(lch); + lch = Correction(0, 6, 0); + MaxChroma.Init(lch); + lch = Correction(0, 0, -6); + MinHue.Init(lch); + lch = Correction(0, 0, 6); + MaxHue.Init(lch); + + RaisePropertyChanged(nameof(SourceColorBrush)); + RaisePropertyChanged(nameof(ManualColorBrush)); + } + + public void UpdateSourceLAB(double l, double a, double b) + { + LabColor labColor = new LabColor(l, a, b); + var converter = new ColourfulConverter { WhitePoint = Illuminants.D65 }; + var last_LCH = converter.ToLChab(labColor); + SourceL = l; + SourceA = a; + SourceB = b; + SourceC = last_LCH.C; + SourceH = last_LCH.h; + } + + public void UpdateManualColors() + { + Lch lch = Correction(-6, 0, 0); + MinLightness.Init(lch); + lch = Correction(6, 0, 0); + MaxLightness.Init(lch); + lch = Correction(0, -6, 0); + MinChroma.Init(lch); + lch = Correction(0, 6, 0); + MaxChroma.Init(lch); + lch = Correction(0, 0, -6); + MinHue.Init(lch); + lch = Correction(0, 0, 6); + MaxHue.Init(lch); + + RaisePropertyChanged(nameof(SourceColorBrush)); + RaisePropertyChanged(nameof(ManualColorBrush)); + } + + /// <summary> + /// Manuals the correction. During change lightnessOffset, chromaOffset or hueOffset in app caused to change LAB of visual correction. + /// </summary> + /// <param name="lightnessOffset">The lightness offset.</param> + /// <param name="chromaOffset">The chroma offset.</param> + /// <param name="hueOffset">The hue offset.</param> + public void ManualCorrection(double lightnessOffset, double chromaOffset, double hueOffset) + { + Lch lch = Correction(lightnessOffset, chromaOffset, hueOffset); + + L = lch.L; + A = lch.C * Math.Cos(lch.H * (Math.PI / 180)); + B = lch.C * Math.Sin(lch.H * (Math.PI / 180)); + RaisePropertyChanged(nameof(SourceColorBrush)); + RaisePropertyChanged(nameof(ManualColorBrush)); + + } + + /// <summary> + /// Calculate Lch on the specified lightness offset. + /// </summary> + /// <param name="lightnessOffset">The lightness offset.</param> + /// <param name="chromaOffset">The chroma offset.</param> + /// <param name="hueOffset">The hue offset.</param> + /// <returns></returns> + public Lch Correction( double lightnessOffset, double chromaOffset, double hueOffset) + { + //LightnessOffset = lightnessOffset; + //ChromaOffset = chromaOffset; + //HueOffset = hueOffset; + + double L1 = SourceL; + double C1 = SourceC; + double H1 = SourceH; + if (H1 < 0) + H1 += 360; + double refX_C = C1; + ///lightness + double SL = 0; + if (L <= 16) + SL = 0.511; + else + SL = L1 * 0.040975 / (1 + 0.01765 * L1); + L1 += lightnessOffset * 2 * SL; + if(L1 > 100) + L1 = 100; + if(L1 < 0) + L1 = 0; + + double SC = (0.638 + 0.0638 * refX_C / (1 + 0.0131 * refX_C)); + C1 += chromaOffset * SC; + if (C1 > 128) + L1 = 128; + if (C1 < 0) + C1 = 0; + + //double h1 = H1; + //if (h1 < 0) + // h1 = h1 + 360; + double refX_CQ = Math.Pow(refX_C, 4); + double refX_H = H1; + double refX_F = Math.Sqrt(refX_CQ / (refX_CQ + 1900)); + double refX_T = 0; + if ((refX_H > 164) & (refX_H < 345)) + refX_T = 0.56 + Math.Abs(0.2 * Math.Cos(Math.PI * (refX_H + 168) / 180)); + else if ((refX_H >= 345) | (refX_H <= 164)) + refX_T = 0.36 + Math.Abs(0.4 * Math.Cos(Math.PI * (refX_H + 35) / 180)); + + double refX_SC = (0.638 + 0.0638 * refX_C / (1 + 0.0131 * refX_C)); + double refX_SH = refX_SC * (refX_T * refX_F + 1 - refX_F); + if(C1 != 0) + { + var argum = 1 - (refX_SH * refX_SH * hueOffset * hueOffset / (2 * C1 * C1)); + if(argum < -1) + argum = -1; + if (argum > 1) + argum = 1; + + double tmp = (180 / Math.PI) * Math.Acos(argum); + if (hueOffset < 0)//? + tmp *= -1; + H1 += tmp; + } + Lch lch = new Lch() { L = L1, C = C1, H = H1 }; + return lch; + + } + + + #region Converter + + + #endregion + } +} |
