WPF调色盘(1):绘制三色轮

(有小修改!)        

计算机对颜色的表示,有很多种方式。如RGB模式、HSB(HSV)模式、CMYK模式等。这里重点讲如何用C#语言,生成一个RGB模式的调色盘。

先看效果图:

WPF调色盘(1):绘制三色轮_第1张图片

        在计算机中,一个像素点的颜色,由三种颜色构成:红色(R),蓝色(B)和绿色(G)构成。每种颜色的最大值为255,最亮,最小值为0,最暗。因此,构建一张这样的图片,重点就在于三种颜色如何进行混合。

        因为有三种颜色,首先很容易想到,将一个圆三等份,每一份表示一种颜色,其颜色值为255,这就构成了基本的调试盘。例如在-60°~60°这个区间内,所有像素的颜色值,R = 255, G =0, B =0。如下图所示:

WPF调色盘(1):绘制三色轮_第2张图片

        有了这一个调色盘之后,就需要将各种颜色,向相邻的区域进行扩散。如何扩散,是调色盘绘制的关键。

        颜色的扩散,有两个方向:

  1. 圆周扩散:从一个颜色的边缘,沿着圆周向相邻区域扩散;
  2. 径向扩散:从圆心沿半径向外围扩散。

        那么扩散的范围呢?通常的做法如下:

  1. 圆周的扩散范围是60°。例如红色,在60°~120°、-60°~-120°的区间内,圆周上各像素点的R值,从255按比例减少至0。在120°~180°、-120°~-180°区间内,圆周上各像素点的R值均为0;
  2. 径向扩散的范围是60度。例如红色,在60°~120°、-60°~-120°的区间内。先计算某个点到圆心的向量与颜色边界线的夹角(例如红色,边界线是60°和-60°),然后计算该向量与圆周向交点的颜色值。最后根据该点在[交点颜色值,255]之间的占比,计算该点最终的值。

如下图所示:

WPF调色盘(1):绘制三色轮_第3张图片

 

有了这两条规则,就可以计算出每一个点的颜色值。

核心代码如下:

        /// 
        /// 计算坐标点的颜色值。注意,以左上角定点为坐标原点,向右为正X轴,向下为Y轴。
        /// 
        /// x坐标
        /// y坐标
        /// 色轮的半径
        public Color GetColor(int x, int y, int radius)
        {

            // radius为圆的半径
            // 已圆心为坐标原点,水平向右为起始向量
            Vector o = new Vector(radius, 0);

            // r,g,b为三个原色分量
            byte r, g, b;

            // 点(x,y)到圆心的距离
            double distance = Math.Sqrt(Math.Pow(x - radius, 2) + Math.Pow(y - radius, 2));


            // 距离大于半径,说明点在圆的外面,不用计算器颜色
            if (distance > radius) return new Color() { R = 255, G = 255, B = 255, A = 0 };


            // 将(x,y)换算成已圆心为坐标原点的坐标,并计算向量(x1,y1)与起始向量的夹角
            Vector v1 = new Vector(x - radius, radius - y);
            double angel = Vector.AngleBetween(o, v1);

            if (angel <= -60)
            {
                // 落在蓝色区间
                r = CalculateSpread(distance, -angel - 60, radius);
                g = CalculateSpread(distance, 180 + angel, radius);
                b = 255;
            }
            else if (angel <= 60)
            {
                // 落在红色区间
                r = 255;
                g = CalculateSpread(distance, 60 - angel, radius);
                b = CalculateSpread(distance, 60 + angel, radius);
            }
            else
            {
                // 落在绿色区间
                r = CalculateSpread(distance, angel - 60, radius);
                g = 255;
                b = CalculateSpread(distance, 180 - angel, radius);
            }
            return new Color() { R = r, G = g, B = b, A = 255 };
        }


        // 计算某个颜色的分量。
        // distance为点到圆心的距离;
        // angel为点与圆心的连线,与颜色的边界之间的夹角
        private byte CalculateSpread(double distance, double angel, int radius)
        {
            // 计算圆周分量:如果两个向量的夹角大于60度,则圆周分量为0;否则,计算比例递减
            double circum = angel > 60 ? 0 : 255 - (angel / 60 * 255);
            return (byte)(255 - distance / radius * (255 - circum));
        }

关于控件的制作,下回讲解

你可能感兴趣的:(WPF学习,wpf,着色器)