最近个人项目需要用到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. 安装SourceTree工具,无需注册就可以正常使用SourceTree

    1. 下载SourceTree安装包 2. 双击安装包进行安装,默认会直接安装在系统盘,此时桌面就会SourceTree的快捷键 3. 双击打开桌面的SourceTree,就会提示让你安装授权,那么接 ...

  2. sys、os 模块

    sys 模块常见函数 sys.argv           #命令行参数List,第一个元素是程序本身路径 sys.exit(n)        #退出程序,正常退出时exit(0) sys.vers ...

  3. java_16Arrays类

    1sort():对数组进行升序排列 public static void main(String[] args) { int[] arr= {2,43,6,7}; Arrays.sort(arr); ...

  4. c++ 计算cpu占用率

    计算CPU占用率就是获取系统总的内核时间 用户时间及空闲时间 其中空闲时间就是内核空转 所以内核时间包含空闲时间 然后计算 运行时间 = 内核时间 加 用户时间 减去 空闲时间 间隔时间 =  内核时 ...

  5. linux python 安装到用户目录

    在公司服务器中,python可能存在多个版本,而且python中的包也有多个不同版本,由于不同猿的需求不同,经常会引起程序冲突,影响工作效率.因此,给大家分享一个在没有root权限时,将python安 ...

  6. javaScript 字符串

    var name = '小明'; var age = 20; var message = '你好, ' + name + ', 你今年' + age + '岁了!'; alert(message) 要 ...

  7. Android 软件退出系统方法重写

    Android 软件退出系统按键方法重写 //针对Andriod软件退出系统按键方法重写 ;//key down time @Override public boolean onKeyDown(int ...

  8. SAS 逻辑库

    SAS逻辑库 SAS逻辑库是一个或多个SAS文件的集合,用于组织.查找和管理 SAS文件.SAS逻辑库管理的SAS文件包括SAS数据集.SAS目录.已编 译的SAS程序,以及多维数据库文件等. 1.逻 ...

  9. HashMap、HashTable

    HashMap 初始长度:1>>4   2^4=16 最大长度:1>>30   2^30 扩容时机:容量 >= 0.75f 扩容倍数:2倍 1.K可以为null 2.pu ...

  10. 项目部署到服务器上之后request.getRemoteAddr()为什么获取的都是本地地址

    获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了.如 ...