最近个人项目需要用到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. nginx-web身份验证

    1.配置文件设置: server { listen 80; server_name www.longshuai.com www1.longshuai.com; location / { root /w ...

  2. ELK填坑总结和优化过程

    做了几周的测试,踩了无数的坑,总结一下,全是干货,给大家分享~ 一.elk 实用知识点总结 1.编码转换问题(主要就是中文乱码) (1)input 中的codec => plain 转码 cod ...

  3. linux系统,服务器与服务器拷贝文件

    服务器与服务器拷贝文件命令 scp -P (服务器端口)-r 拷贝文件名称列表    远程服务器用户@远程服务器ip :(文件放置目录) 1.将本地home目录下的apache-tomcat-8.0. ...

  4. 容器101:Docker基础

    Docker如此受欢迎的一个原因是它提供了“一次开发,随处运行”的承诺.Docker提供了一种将应用程序及其运行时依赖性打包到单个容器中的简单方法.它还提供了一个运行时抽象,使容器能够跨不同版本的Li ...

  5. [转贴]LTP--linux稳定性测试 linux性能测试 ltp压力测试 ---IBM 的 linux test project

    https://blog.csdn.net/melody157398/article/details/24354415   LTP--linux稳定性测试 linux性能测试 ltp压力测试 ---I ...

  6. spring整合kafka(配置文件方式 消费者)

    Kafka官方文档有   https://docs.spring.io/spring-kafka/reference/htmlsingle/ 这里是配置文件实现的方式 先引入依赖 <depend ...

  7. python页面解析_beautifulsoup试玩

      最近玩爬虫,先把python解析器 beautifulsoup 练练 这个 tainiu.html 是从百度网盘里拷贝一段html from bs4 importBeautifulSoup wit ...

  8. nc6 用业务插件注册来跑按钮事件

    在实际开发中,有些需求是要求系统单据,编辑或者触发其他按钮来回写其他模块单据 这时候就能用业务插件方式来触发其他模块的按钮事件,而不用去模块找对应的按钮编辑事件类 package hz.bs.hzct ...

  9. JVM 字节码(四)静态方法、构造代码、this 以及 synchronized 关键字

    JVM 字节码(四)静态方法.构造代码.this 以及 synchronized 关键字 一.静态代码 public class ByteCodeStatic { private static fin ...

  10. POJ 1328 Radar Installation 贪心 A

    POJ 1328 Radar Installation https://vjudge.net/problem/POJ-1328 题目: Assume the coasting is an infini ...