コード例 #1
0
        private static MunsellDat FindMunsell(MunsellHue hue, double value, double chroma, bool retry = false)
        {
            var rec = Table.Where(x => x.H == hue && Math.Abs(x.V - value) < float.Epsilon && Math.Abs(x.C - chroma) < float.Epsilon).FirstOrDefault();

            if (rec != null)
            {
                return(rec.Clone());
            }
            else
            {
                if (!retry)
                {
                    return(null);
                }
                //見つからなかった場合は彩度を下げて再検索
                for (var i = chroma - 2.0; i >= 2.0; i -= 2.0)
                {
                    var m = Table.Where(x => x.H == hue && Math.Abs(x.V - value) < float.Epsilon && Math.Abs(x.C - i) < float.Epsilon).FirstOrDefault();
                    if (m != null)
                    {
                        return(m.Clone());
                    }
                }
                return(null);
            }
        }
コード例 #2
0
        private static MunsellDat FindMunsell(MunsellHue hue, double value, double chroma, bool retry = false)
        {
            var rec = Table.Where(x => x.H.Base == hue.Base && x.H.Number == hue.Number && x.V == value && x.C == chroma).FirstOrDefault();

            if (rec != null)
            {
                return(rec.Clone());
            }
            else
            {
                if (!retry)
                {
                    return(null);
                }
                //見つからなかった場合は彩度を下げて再検索
                for (var i = chroma - 2.0; i >= 2.0; i -= 2.0)
                {
                    var m = Table.Where(x => x.H == hue && x.V == value && x.C == i).FirstOrDefault();
                    if (m != null)
                    {
                        return(m.Clone());
                    }
                }
                return(null);
            }
        }
コード例 #3
0
        private static Lch ConvertLch(IMunsell item, MunsellHue hue)
        {
            //見込み明度
            var tmpV = Math.Round(item.V, MidpointRounding.AwayFromZero);

            if (Math.Abs(tmpV) < float.Epsilon)
            {
                tmpV = 1.0d;
            }
            if (Math.Abs(tmpV - 10.0) < float.Epsilon)
            {
                tmpV = 9.0d;
            }
            //彩度max min
            var c = Table.Where(x => x.H == hue && Math.Abs(x.V - tmpV) < float.Epsilon)
                    .GroupBy(x => x.V).Select(x => new { min = x.Min(y => y.C), max = x.Max(y => y.C) }).First();

            Lch lch;

            //彩度の範囲内
            if (c.min <= item.C && item.C <= c.max)
            {
                //2刻みの値ならテーブル値を取得
                if (Enumerable.Range((int)c.min, (int)c.max)
                    .Where(x => x % 2 == 0).Select(x => (double)x).Contains(item.C))
                {
                    lch = FindMunsell(hue, tmpV, item.C).Lch;
                }
                //上記以外は両隣の彩度を基準とする
                else
                {
                    var lowC  = Math.Floor(item.C / 2d) * 2d;
                    var highC = Math.Ceiling(item.C / 2d) * 2d;

                    var lowLch  = FindMunsell(hue, tmpV, lowC).Lch;
                    var highLch = FindMunsell(hue, tmpV, highC).Lch;
                    //補完値計算
                    lch = GetInterpolatedValue(item, lowLch, highLch);
                }
            }
            //彩度の範囲外
            else
            {
                var tmpC = item.C > c.max ? c.max : c.min;
                lch = FindMunsell(hue, tmpV, tmpC).Lch;
                //補完値
                lch.C = lch.C / tmpC * item.C;
            }

            lch.L -= ConvertVtoL(tmpV - item.V);
            return(lch);
        }
コード例 #4
0
 private static bool CloseEnough(MunsellHue a, MunsellHue b)
 {
     if (a.Base == b.Base)
     {
         return(Math.Abs(a.Number - b.Number) <= 1.5);
     }
     else if ((a.Base == b.Base - 1 || a.Base - 1 == b.Base) ||
              (a.Base == HueBase.R && b.Base == HueBase.RP) ||
              (a.Base == HueBase.RP && b.Base == HueBase.R))
     {
         return(Math.Abs(a.Number % 10 - b.Number % 10) <= 1.5);
     }
     else
     {
         return(false);
     }
 }
コード例 #5
0
        internal static IRgb ToColor(IMunsell item)
        {
            //明度max or minは白黒で返す
            if (item.V <= 0.0d)
            {
                return new Rgb {
                           R = 0, G = 0, B = 0
                }
            }
            ;
            if (item.V >= 10.0d)
            {
                return new Rgb {
                           R = 255, G = 255, B = 255
                }
            }
            ;
            if (item.H.Base == HueBase.N)
            {
                return(ConvertAchromatic(item));
            }

            //2.5刻み値ジャストならマンセル検索→Lab値変換
            if (System.Linq.Enumerable.Range(1, 4).Select(x => x * 2.5d).Contains(item.H.Number))
            {
                return(ConvertLch(item, item.H).To <Rgb>());
            }

            //2.5刻み値以外は両隣の色相から補完値を計算
            var lowH  = new MunsellHue(Math.Floor(item.H.Number / 2.5d) * 2.5d, item.H.Base);
            var highH = new MunsellHue(Math.Ceiling(item.H.Number / 2.5d) * 2.5d, item.H.Base);
            var rate  = (item.H.Number % 2.5d) / 2.5d;   //2.5の間の割合
                                                         //両隣の色相の補完値同士の補完値を求める
            var lch = GetInterpolatedValue(item, ConvertLch(item, lowH), ConvertLch(item, highH), rate);

            return(lch.To <Rgb>());
        }
コード例 #6
0
        internal static void ToColorSpace(IRgb color, IMunsell item)
        {
            if ((int)Math.Round(color.R, 0) == (int)Math.Round(color.G, 0) && (int)Math.Round(color.G, 0) == (int)Math.Round(color.B, 0))
            {
                var lab = color.To <Lab>();
                item.H = new MunsellHue {
                    Base = HueBase.N
                };
                item.V = Math.Round(ConvertLtoV(lab.L), 1);
                return;
            }

            var lch = color.To <Lch>();

            var q = Table.Select(x => new {
                diff = Math.Abs(x.Lch.L - lch.L) + Math.Abs(x.Lch.C - lch.C) + Math.Abs(x.Lch.H - lch.H),
                self = x
            });
            var min     = q.Min(x => x.diff);
            var munsell = q.Where(x => Math.Abs(x.diff - min) < float.Epsilon).FirstOrDefault().self;

            if (min < 3.0d)
            {
                item.H = munsell.H;
                item.V = munsell.V;
                item.C = munsell.C;
                return;
            }

            var hue = new MunsellHue {
                Base = munsell.H.Base, Number = munsell.H.Number
            };
            MunsellHue newHue;

            if (munsell.Lch.H > lch.H)
            {
                hue.Number -= 2.5d;
                newHue      = new MunsellHue {
                    Base = hue.Base, Number = hue.Number
                };
            }
            else
            {
                hue.Number += 2.5d;
                newHue      = new MunsellHue {
                    Base = munsell.H.Base, Number = munsell.H.Number
                };
            }
            var munsellX = FindMunsell(hue, munsell.V, munsell.C, true);

            newHue.Number += Math.Round((lch.H - Math.Min(munsell.Lch.H, munsellX.Lch.H))
                                        / Math.Abs(munsell.Lch.H - munsellX.Lch.H) * 2.5d, 1, MidpointRounding.AwayFromZero);


            double newChroma;
            //彩度max min
            var c = Table.Where(x => x.H == munsell.H && Math.Abs(x.V - munsell.V) < float.Epsilon)
                    .GroupBy(x => x.V).Select(x => new { min = x.Min(y => y.C), max = x.Max(y => y.C) }).First();

            if (c.min < munsell.C && munsell.C < c.max)
            {
                var chroma   = munsell.Lch.C > lch.C ? munsell.C - 2.0d : munsell.C + 2.0d;
                var munsellY = FindMunsell(munsell.H, munsell.V, chroma);
                newChroma = Math.Round(Math.Min(munsell.C, munsellY.C) + (lch.C - Math.Min(munsell.Lch.C, munsellY.Lch.C))
                                       / Math.Abs(munsell.Lch.C - munsellY.Lch.C) * 2.0d, 1, MidpointRounding.AwayFromZero);
            }
            else
            {
                newChroma = Math.Round(munsell.C / munsell.Lch.C * lch.C, 1, MidpointRounding.AwayFromZero);
            }

            var newValue = Math.Round(ConvertLtoV(lch.L), 1, MidpointRounding.AwayFromZero);

            item.H = newHue;
            item.C = newChroma;
            item.V = newValue;
        }
コード例 #7
0
        /// <summary>
        /// RGBカラーからMUNSELLカラースベースへ変換する
        /// </summary>
        /// <param name="rgb">RGBカラー</param>
        /// <returns>MUNSELLカラースベース</returns>
        internal static Munsell ToColor(Rgb rgb)
        {
            Munsell item = new Munsell();

            Lch lch = LchConverter.ToColor(rgb);

            if (rgb.R == rgb.G && rgb.G == rgb.B)
            {
                Lab lab = LabConverter.ToColor(rgb);
                item.H = new MunsellHue {
                    Base = HueBase.N
                };
                item.V = Math.Round(ConvertLtoV(lab.L), 1);
                return(item);
            }

            var q = Table.Select(x => new {
                diff = Math.Abs(x.Lch.L - lch.L) + Math.Abs(x.Lch.C - lch.C) + Math.Abs(x.Lch.H - lch.H),
                self = x
            });
            var min     = q.Min(x => x.diff);
            var munsell = q.Where(x => x.diff == min).FirstOrDefault().self;

            if (min < 3.0)
            {
                item.H = munsell.H;
                item.V = munsell.V;
                item.C = munsell.C;
                return(item);
            }

            var hue = new MunsellHue {
                Base = munsell.H.Base, Number = munsell.H.Number
            };
            MunsellHue newHue;

            if (munsell.Lch.H > lch.H)
            {
                hue.Number -= 2.5;
                newHue      = new MunsellHue {
                    Base = hue.Base, Number = hue.Number
                };
            }
            else
            {
                hue.Number += 2.5;
                newHue      = new MunsellHue {
                    Base = munsell.H.Base, Number = munsell.H.Number
                };
            }
            var munsellX = FindMunsell(hue, munsell.V, munsell.C, true);

            newHue.Number += Math.Round((lch.H - Math.Min(munsell.Lch.H, munsellX.Lch.H))
                                        / Math.Abs(munsell.Lch.H - munsellX.Lch.H) * 2.5, 1, MidpointRounding.AwayFromZero);


            double newChroma;
            //彩度max min
            var c = Table.Where(x => x.H == munsell.H && x.V == munsell.V)
                    .GroupBy(x => x.V).Select(x => new { min = x.Min(y => y.C), max = x.Max(y => y.C) }).First();

            if (c.min < munsell.C && munsell.C < c.max)
            {
                var chroma   = munsell.Lch.C > lch.C ? munsell.C - 2.0 : munsell.C + 2.0;
                var munsellY = FindMunsell(munsell.H, munsell.V, chroma);
                newChroma = Math.Round(Math.Min(munsell.C, munsellY.C) + (lch.C - Math.Min(munsell.Lch.C, munsellY.Lch.C))
                                       / Math.Abs(munsell.Lch.C - munsellY.Lch.C) * 2.0, 1, MidpointRounding.AwayFromZero);
            }
            else
            {
                newChroma = Math.Round(munsell.C / munsell.Lch.C * lch.C, 1, MidpointRounding.AwayFromZero);
            }

            var newValue = Math.Round(ConvertLtoV(lch.L), 1, MidpointRounding.AwayFromZero);

            item.H = newHue;
            item.C = newChroma;
            item.V = newValue;

            return(item);
        }