最近个人项目需要用到ColorPicker,但是适用于WinRT和Win10的基本没用,所以只能自己造轮子了。

平台环境

  1. Windows 10
  2. Visual Studio 2015

思路

确定需求后,我查找了各方信息,发现PhotoShop的ColorPicker最符合我的需求,这里我们实现的仿PhotoShop HSB取色器,样式如下图。

确定目标后,则需要研究具体的调色原理了。我们都知道,程序使用的一般都是RGB颜色,而这里使用的则是HSB颜色。顾名思义,HSB分别是指色相(Hue)纯度(Saturation)明度(Brightness),这三个参数构成了HSB颜色,这比RGB颜色更易于选取,能够同时提供的颜色种类最多,对应HSV。色相可以通过色环来表示,HSB三个参数均和RGB保持着数学上的关系。详细信息可见于维基百科:https://en.wikipedia.org/wiki/HSL_and_HSV

这里计算流程为先计算色相,然后固定亮度,最后计算饱和度。首先对于色相,计算相对简单,分析色环,即可发现处于不同度数区间对应的RGB值也是有规律的。

具体来说假定HSB值为(H,100%,100%)条件下,RGB值对应关系如下:

H         Color     Value

-----------------------------

0-60         G       0->255

60-120      R       255->0

120-180    B       0->255

180-240    G       255->0

240-360    R       0->255

300-360    B       255->0

接下来根据饱和度S来进一步计算出RGB,此时假定条件为(H,S,100%),计算公式如下:

r"= r'+ (255 - r') * s

g"= g'+ (255 - g') * s
b"= b'+ (255 - b') * s

其中r',g',b'分别为第一步计算出的RGB结果。

最后一步,亮度L值与RGB关系最简单,RGB只需要分别乘以亮度即可。

实现代码

核心计算类CWColorService

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI; namespace CWColorPicker.Core
{
public class CWColorService
{
/// <summary>
/// Convert HSB value to RGB value
/// </summary>
/// <param name="hsb">HSB value</param>
/// <returns>RGB value</returns>
public static int[] HSBToRGB(float[] hsb)
{
var rgb = new float[];
var hValue = hsb[];
/*
Firstly, we need to calculate RGB value, when the HSB value is (h,100%,100%).
H Color Value
----------------------------
0-60 G 0->255
60-120 R 255->0
120-180 B 0->255
180-240 G 255->0
240-360 R 0->255
300-360 B 255->0
*/
if (hValue <= )
{
rgb[] = ;
rgb[] = hValue / 60.0f * ;
}
else if (hValue <= )
{
hValue -= ;
rgb[] = ;
rgb[] = ( - hValue / 60.0f) * ;
}
else if (hValue <= )
{
hValue -= ;
rgb[] = ;
rgb[] = hValue / 60.0f * ;
}
else if (hValue <= )
{
rgb[] = ;
hValue -= ;
rgb[] = ( - hValue / 60.0f) * ;
}
else if (hValue <= )
{
rgb[] = ;
hValue -= ;
rgb[] = hValue / 60.0f * ;
}
else
{
hValue -= ;
rgb[] = ;
rgb[] = ( - hValue / 60.0f) * ;
}
/*
Secondly, acorrding to the value of staturation, we can calculate the rgb value, when the value of hsb is (h,s,100%)
-------------------------
r"= r'+ (255 - r') * s
g"= g'+ (255 - g') * s
b"= b'+ (255 - b') * s
*/
for (int i = ; i < ; i++)
{
rgb[i] += ( - rgb[i]) * hsb[];
}
var result = new int[];
/*
Finally, we need to calculate the real value of rgb, according to the value of brightness
r = r" * br
g = g" * br
b = g" * br
*/
for (int i = ; i < ; i++)
{
rgb[i] *= hsb[];
result[i] = (int)(rgb[i] + 0.5);
}
return result;
} /// <summary>
/// Convert RGB value to HSB value
/// </summary>
/// <param name="rgb">RGB Value</param>
/// <returns></returns>
public static float[] RGBToHSB(int[] rgb)
{
var result = new float[];
return result;
} /// <summary>
/// get color from rgb value
/// </summary>
/// <param name="r"></param>
/// <param name="g"></param>
/// <param name="b"></param>
/// <returns></returns>
public static Color ColorFromRGB(int r,int g,int b)
{
var color = Color.FromArgb(, (byte)r, (byte)g, (byte)b);
return color;
}
public static Color ColorFromRGB(int[] rgb)
{
var color = ColorFromRGB(rgb[], rgb[], rgb[]);
return color;
}
}
}

自定义Xaml控件

<UserControl
x:Class="CWColorPicker.UI.CWColorPicker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CWColorPicker.UI"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="150"
d:DesignWidth="150"> <Grid x:Name="ColorPanel">
<Image x:Name="ColorImage" Source="ms-appx:///Resource/color-pan.png" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" PointerPressed="ColorImage_PointerPressed" Margin="0"></Image>
</Grid>
</UserControl>
namespace CWColorPicker.UI
{
public sealed partial class CWColorPicker : UserControl
{ /// <summary>
/// current selected color
/// </summary>
public Color Color
{
get { return (Color)GetValue(ColorProperty); }
set { SetValue(ColorProperty, value); }
} // Using a DependencyProperty as the backing store for Color. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ColorProperty =
DependencyProperty.Register("Color", typeof(Color), typeof(CWColorPicker), new PropertyMetadata()); /// <summary>
/// current ponit in color picker
/// </summary>
public Point ColorPoint
{
get { return (Point)GetValue(ColorPointProperty); }
set { SetValue(ColorPointProperty, value); }
} // Using a DependencyProperty as the backing store for ColorPoint. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ColorPointProperty =
DependencyProperty.Register("ColorPoint", typeof(Point), typeof(CWColorPicker), new PropertyMetadata()); /// <summary>
/// ColorSelected Event
/// </summary>
public event EventHandler<CWColorSelectedArgs> ColorSelected; private void ColorChange(float[] hsb)
{
if (ColorSelected != null)
{
ColorSelected(this, new CWColorSelectedArgs(CWColorService.ColorFromRGB(CWColorService.HSBToRGB(hsb))));
}
} private void ColorChange(Color color)
{
if (ColorSelected != null)
{
ColorSelected(this, new CWColorSelectedArgs(color));
}
} public CWColorPicker()
{
this.InitializeComponent();
initPanelImage(); } /// <summary>
/// load resource image from dll
/// </summary>
private async void initPanelImage()
{
var panel = new BitmapImage();
var imageStream = Assembly.Load(new AssemblyName("CWColorPicker")).GetManifestResourceStream("CWColorPicker.Resource.color-pan.png");
await panel.SetSourceAsync(imageStream.AsRandomAccessStream());
this.ColorImage.Source = panel;
} /// <summary>
/// calculate the color according to the touch point
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ColorImage_PointerPressed(object sender, PointerRoutedEventArgs e)
{
// Debug.WriteLine("pressed");
// Debug.WriteLine(e.GetCurrentPoint(this.ColorPanel).Position); var position = e.GetCurrentPoint(this.ColorImage).Position;
var hsb = new float[];
hsb[] = 1.0f;
hsb[] = (float)(int)(position.X / this.ColorImage.ActualWidth * );
hsb[] = float.Parse((position.Y / this.ColorImage.ActualHeight).ToString("0.00"));
this.Color = CWColorService.ColorFromRGB(CWColorService.HSBToRGB(hsb));
this.ColorPoint = position;
ColorChange(this.Color);
} }
}

其他代码及完整项目可以在Github上获取,地址:https://github.com/ChangweiZhang/CWColorPicker

实现效果

Win10手记-取色器ColorPicker的实现的更多相关文章

  1. powerpoint取色器有什么用|ppt取色器使用教程

    在使用powerpoint过程中常常发现一些功能我们很少用到,其实是自己不会用的原因,关于powerpoint取色器有什么用呢?接下来我们一起来学一下ppt取色器使用教程. powerpoint取色器 ...

  2. TakeColor 屏幕取色器 8.0 中文绿色版

    软件名称: TakeColor 屏幕取色器软件语言: 简体中文授权方式: 免费软件运行环境: Win8 / Win7 / Vista / WinXP软件大小: 210KB图片预览: 软件简介:使用方便 ...

  3. C#取色器

    闲来无事,就写了一个取色器.原理其实很简单,只需要两步, 获取鼠标光标的位置, 获取当前鼠标光标的位置的RGB颜色值. 获取鼠标光标的位置: System.Drawing.Point p = Mous ...

  4. 恢复Win10照片查看器

    批处理文件: @echo off&cd\&color 0a&cls echo 恢复Win10照片查看器 reg add "HKLM\SOFTWARE\Microsof ...

  5. ColorPix——到目前为止最好用的屏幕取色器

    分享一个颜色取色器网页.PPT.EXCEL配色不再烦恼 简单易用 大家做商业.企业报告的时候是不是经常遇到要调色的困扰呢?PPT.EXCEL等颜色选取会对报告有质的影响!!要更专业要更有美感!给大家分 ...

  6. Arava: 用 swing 写一个取色器

    备哥以前发我了一个小工具,TakeColor 取色器.来复刻一个吧. 分析一下:顶部是菜单,左侧框显示当前鼠标所在的颜色(下面显示当前坐标和颜色值,默认RGB),中间框显示鼠标周围区域,右侧显示取色的 ...

  7. 设置Win10文件资源管理器默认打开“这台电脑”

    当Windows系统进入Win7之后,任务栏默认的文件资源管理器图标功能是“库”:Win8/Win8.1的这一按钮打开的是“这台电脑”.进入Win10之后,目前这一功能默认变为“快速访问”(曾经被称为 ...

  8. win10 Qt 调试器未设置

    安装win10后一直用vs调试,没有用qt调试,这次启动调试,发现提示调试器未设置. 解决办法: 需要重新安装wdk 10 https://developer.microsoft.com/zh-cn/ ...

  9. win10照片查看器不能看jpg等格式图片

    1.首先,我们需要使用注册表编辑器来开启Win10系统照片查看器功能,因为其实这个功能是被隐藏了,那么按下Windows徽标键+R键,打开运行命令窗口,输入“regedit”命令. 2.打开注册表编辑 ...

随机推荐

  1. jQuery 新添加元素事件绑定无效

    jQuery中事件绑定,大多使用on就足够了. 但是对于新添加的元素 on 的绑定事件 会不起作用. 因为 append 中的 节点是在整个文档加载之后才添加的,页面并不会为未来的元素初始化添加点击事 ...

  2. Quartz基础知识了解(一)

    一.QuartZ是什么? 二.获取 三.核心接口 Scheduler - 与调度程序交互的主要API. Job - 由希望由调度程序执行的组件实现的接口. JobDetail - 用于定义作业的实例. ...

  3. 十三 re模块

    一:什么是正则? 正则就是用一些具有特殊含义的符号组合到一起(称为正则表达式)来描述字符或者字符串的方法.或者说:正则就是用来描述一类事物的规则.(在Python中)它内嵌在Python中,并通过 r ...

  4. m3u8文件什么合成便于播放的MP4的方法

    先大家要知道M3U8文件不是一个视频文件,里面全是一些路径,说白了就是一个目录而已,所以要看视频,要找到对应存放视频的文件夹.如果不知道怎么找,可以使用文本格式打开M3U8文件,里面会有路径提示.   ...

  5. 整数中1出现的次数(从1到n整数中1出现的次数)(python)

    题目描述 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1.10.11.12.13因此共出现6次,但是对于后面问题他就没辙了. ...

  6. Git 基础 - 删除暂存区的文件

    1 直接删除文件 这个文件会有两个操作:已暂存的修改.未暂存的删除 2 直接删除文件 + 记录删除操作 先在工作目录中删除文件,再使用git rm命令记录此次移除文件的操作(删除暂存区中该文件的修改快 ...

  7. [leetcode]29. Divide Two Integers两整数相除

      Given two integers dividend and divisor, divide two integers without using multiplication, divisio ...

  8. stark组件开发之列表页面自定义函数扩展

    对于展示页面, 可能需要显示一些. 数据库中,没有的字段. 比如, 删除按钮, 编辑按钮.  这个数据库,是没有的. 所以,可能就需要, 添加一个这个东西.  比如我在渲染的时候, 给他添加两个函数进 ...

  9. spring boot项目升级到2.0.1,提示java.lang.ClassNotFoundException: org.apache.log4j.Logger错误

    首先肯定是版本出现了一点兼容问题 所以我就进入项目,查看依赖树,cd到项目目录下,mvn dependency:tree 我看到我的项目原先是1.5.9和现在2.0.1的区别在于org.slf4j的依 ...

  10. How Xtuner E3 works for BMW 520d Diagnosis and initialization of CBS service

    Using Xtuner E3 to perform BMW 520d Diagnosis and initialization of CBS service in step by step proc ...