原文:[UWP]使用Writeable?Bitmap创建HSV色轮

1. HSV

1.1 HSV的定义

HSV都是一种将RGB色彩模型中的点在圆柱坐标系中的表示法,这种表示法试图做到比RGB基于笛卡尔坐标系的几何结构更加直观。HSV即色相、饱和度、明度(英语:Hue, Saturation, Value),又称HSB,其中B即英语:Brightness。

  • 色相(H)是色彩的基本属性,就是平常所说的颜色名称,如红色、黄色等,取值0-360。红色是0,绿色是120,蓝色为240。
  • 饱和度(S)是指色彩的纯度,越高色彩越纯,低则逐渐变灰,取0-100%的数值。
  • 明度(V),数值越低越接近黑色。,取0-100%。

1.2 HSV与RGB

HSV在数学上定义为在RGB空间中的颜色的R, G和B的坐标的变换。

1.2.1 从RGB到HSL或HSV的转换

(r, g, b)分别是一个颜色的红、绿和蓝坐标,它们的值是在0到1之间的实数。设max等价于r, g和b中的最大者。设min等于这些值中的最小者:

1.2.2 从HSV到RGB的转换

给定在HSV中 (h, s, v)值定义的一个颜色,带有如上的h,和分别表示饱和度和明度的s和v变化于0到1之间,在RGB空间中对应的 (r, g, b)三原色可以计算为(R,G,B变化于0到1之间):

对于每个颜色向量 (r, g, b),

1.3 HSV的应用

HSV模型通常用于计算机图形应用中。在用户必须选择一个颜色应用于特定图形元素各种应用环境中,经常使用HSV 色轮。

另外,由于HSV对用户来说是一种直观的颜色模型,所以常用于调整图片,下图为Paint.Net中调整图片:


下图为UWPCommunityToolkit中通过Saturation调整图片:

1.4 HSV与色轮

很多设计方面的书籍都有介绍使用色轮为UI配色,由于篇幅较大这里就不在论述了,具体可以参考以下链接:网页设计中怎么配色

2. WriteableBitmap

WriteableBitmap 提供可写入并可更新的 BitmapSource。也就是说, 你可动态更改图像,然后重新呈现更新的图像。使用WinRTXamlToolkit可以轻松完成这个操作,代码如下:

var diameter = 100;
var source = new WriteableBitmap(diameter, diameter);
var pixels = source.PixelBuffer.GetPixels();
for (var i = 0; i < diameter * diameter; i++)
{var color = Color.FromArgb(255, 255, 255, 255);pixels.Bytes[i * 4] = color.B;pixels.Bytes[i * 4 + 1] = color.G;pixels.Bytes[i * 4 + 2] = color.R;pixels.Bytes[i * 4 + 3] = color.A;
}
pixels.UpdateFromBytes();
source.Invalidate();
_imageElement.Source = source;

上面的代码将一个尺寸在100*100的WriteableBitmap中所有像素都设为白色,然后设置为图片的Source。在这里像素数据的格式为BitmapPixelFormat.Bgra8,即用四个Byte分别表示颜色的RGRA(通常颜色表示成ARGB,如#FFFF0000即Alpha:255,Red:255,Green:0,Blue:0)。

还可以将WriteableBitmap保存成文件,同样使用WinRTXamlToolkit实现:

await source.SaveAsync(KnownFolders.PicturesLibrary, "Wheel.png");

3. 使用WriteableBitmap创建HSV色轮

前面介绍了Hsv色轮,也介绍了如何使用WriteableBitmap,那么用WriteableBitmap实现一个HSV色轮是一件很简单的事,只需要计算每个像素点距离中心点的角度(Hue)和距离(Saturation)得出HsvColor,再转换成ArgbColor填入WriteableBitmap就实现了。具体代码如下:

var diameter = width < height ? width : height;
var radius = diameter / 2;
var source = new WriteableBitmap(diameter, diameter);
var pixels = source.PixelBuffer.GetPixels();
var array = new double[diameter, diameter];
for (var i = 0; i < diameter * diameter; i++)
{var x = i % diameter;var y = i / diameter;var distance = Math.Sqrt(Math.Pow(radius - x, 2) + Math.Pow(radius - y, 2));var saturation = distance / radius;array[x, y] = saturation;if (saturation >= 1){pixels.Bytes[i * 4] = 0;pixels.Bytes[i * 4 + 1] = 0;pixels.Bytes[i * 4 + 2] = 0;pixels.Bytes[i * 4 + 3] = 0;}else{var distanceOfX = x - radius;var distanceOfY = y - radius;var theta = Math.Atan2(distanceOfY, distanceOfX);if (theta < 0)theta += 2 * Math.PI;var hue = theta / (Math.PI * 2) * 360.0;var color = ColorHelper.FromHsv(hue, saturation, 1);pixels.Bytes[i * 4] = color.B;pixels.Bytes[i * 4 + 1] = color.G;pixels.Bytes[i * 4 + 2] = color.R;pixels.Bytes[i * 4 + 3] = 255;}
}
pixels.UpdateFromBytes();
source.Invalidate();

有个小问题,即使不仔细看也能看到圆形的边缘锯齿很严重。当然可以在上面的代码里加入高斯模糊的算法处理这些锯齿,但毕竟这篇文章不打算讨论到这么深入。可以简单地使用WriteableBitmapEx对整个WriteableBitmap进行高斯模糊:

source.Convolute(WriteableBitmapExtensions.KernelGaussianBlur5x5);

The WriteableBitmapEx library is a collection of extension methods for the WriteableBitmap. The WriteableBitmap class is available for all XAML flavors including Windows Phone, WPF, WinRT Windows Store XAML, (Windows 10) UWP and Silverlight.

这样看起来就好很多了。

4. HSV转RGB的陷阱

上面代码中RGB和HSV互换使用了UWPCommunityToolkit中的ColorHelper,ColorHelper的介绍是这样的:

The Colors Helper lets users convert colors from text names, HTML hex, HSV, or HSL to Windows UI Colors (and back again of course).

但是这里有个陷阱。以下代码将一个RGB color转换成HSV color,再转换回RGB color,看起来没什么问题:

var color = Color.FromArgb(255, 255, 20, 200);
var hsv = ColorHelper.ToHsv(color);
Debug.WriteLine(string.Format("H:{0}  S:{1}  V:{2}", hsv.H,hsv.S , hsv.V));
color = ColorHelper.FromHsv(hsv.H, hsv.S , hsv.V );
Debug.WriteLine(string.Format("R:{0}  G:{1}  B:{2}", color.R, color.G, color.B));

但是看输出就能发现转回来的RBG color改变了:

H:314.042553191489  S:0.92156862745098  V:1
R:255  G:19  B:199

造成这个问题的原因在于RGB能表示的颜色范围有限,只是256 * 256 * 256=16777216种颜色。而HSV如果使用int值,只能表示360 * 100 * 100=3600000种颜色,如果用double则几乎有无数种组合,这样两种颜色模型间就不匹配了。这种情况下只能折衷一下限制HSV的精度了,改成下面的代码能解决上面的问题:

color = ColorHelper.FromHsv(Math.Round(hsv.H), Math.Round(hsv.S, 2), Math.Round(hsv.V, 2));

5. 参考

HSL and HSV - Wikipedia
WriteableBitmap Class

6. 源码

HsvColorWheel for UWP

[UWP]使用Writeable?Bitmap创建HSV色轮相关推荐

  1. [UWP]分享一个基于HSV色轮的调色板应用

    原文:[UWP]分享一个基于HSV色轮的调色板应用 1. 前言 上一篇文章介绍了HSV色轮,这次分享一个基于HSV色轮的调色板应用,应用地址:ColorfulBox - Microsoft Store ...

  2. matlab绘制hsv色轮图

    % 生成网格 tList=linspace(0,2.*pi,300); rList=linspace(0,1,100); [theta,R]=meshgrid(tList,rList);% 角度及半径 ...

  3. IOS 仿Android色轮代码

    IOS 仿Android色轮代码 在android中做色轮相对比较容易,因为Android中有一个角度渐变着色器函数SweepGradient能够很轻松的完成圆环的环形着色绘制工作,在利用Paint的 ...

  4. LVGL V8学习之colorwheel色轮

    这一篇来研究下LVGL V8下colorwheel色轮的使用,这个色轮是HSV样式的,下面的代码通过创建色轮对象,然后添加对象事件处理,移动旋钮,显示对应的颜色和RGB值 还是通过codeblock来 ...

  5. 第4章第13节:创建漂亮的色轮旋转动画 [SwiftUI快速入门到实战]

    本节课演示如何制作一个彩色的圆环,进而创建漂亮的色轮旋转动画. 首先添加一个布尔类型的属性,标识是否开始播放动画. 添加一个ZStack视图,作为子视图的容器.接着创建一个简单的圆形图形. 给圆形设置 ...

  6. autojs自定义控件色轮

    牙叔教程 简单易懂 效果展示 视频效果 缘起 你想要比别人的界面更漂亮吗? 你想要做自己专用的色彩工具吗? 想要自己的专属功能, 深度定制, 自定义控件可以满足你的要求, 比被人的更好看, 功能更多, ...

  7. 《超越平凡的平面设计: 版式设计原理与应用》—色轮

    本节书摘来自异步社区<超越平凡的平面设计: 版式设计原理与应用>一书中的色轮,作者[美]John McWade,更多章节内容可以访问云栖社区"异步社区"公众号查看. 色 ...

  8. ps插件Coolorus for mac(photoshop色轮插件)

    coolorus是一款非常好用的Photoshop色轮插件,这款插件可以给你的ps软件增加一个色环配色面板,选择颜色更加方便.coolorus插件可以帮你轻松的获取所选区域的RGB值,可以添加到ps中 ...

  9. android 屏幕坐标色彩,android – 将RGB值转换为色轮坐标

    我正在尝试在我的iOS应用程序using CIFilter中实现颜色选择器,并且必须解决同样的问题. 我发现给定颜色的HSV值非常适合该色轮: >色调是车轮周围的角度. 0或1是0或2pi弧度, ...

最新文章

  1. R语言可视化包ggplot2包设置轴断点位置实战(Axis Breaks)、即自定义X轴和Y轴的数值标记位置
  2. 报名 | AI TIME 6 论道机器翻译——离我们还有多远?
  3. Docker容器运行后退出,怎么才能一直运行?
  4. Flink 1.11 SQL 十余项革新大揭秘,哪些演变在便捷你的使用体验?
  5. web前端之框架(frameset)
  6. AI大一统:阿里达摩院发布多任务、多模态统一模型OFA
  7. Python 下载文件并保存文件到本地
  8. POJ 2182 Lost Cows (线段树)
  9. DOM学习之获取元素及事件基础(附实例、源码)
  10. 数据库习题(填空题二)
  11. keil4 c语言标准,求助!关于KEIL4和C语言
  12. [渝粤教育] 宁波财经学院 金融工程学 参考 资料
  13. CCNP-OSPF中SPF(最短路径树)算法剖析,建树过程示例
  14. 【21.00%】【vijos P1018】智破连环阵
  15. 「力扣数据库」183. 从不订购的客户(第五天)
  16. [影评]电影《喜剧之王》评论两篇(1、喜剧之王:永不退缩的人生 2、努力!奋斗!——再看《喜剧之王》)
  17. 睿智的法杖v8.28ti
  18. (转)使用Wireshark抓包软件提示The NPF driver isn’t running解决办法
  19. 前端工程化、模块化、组件化
  20. Linux lds 文件格式分析(一)

热门文章

  1. vscode开发vue最常用快捷键,最常用的组件
  2. echarts-----树状图(基础参数)
  3. 计算机学院与软件学院区别,计算机学院和软件学院的专业上有什么区别?
  4. Android会员卡充值方案的实现
  5. nuxt 引入富文本编辑器wangEditor,刷新就会报错?试试这个
  6. 传球游戏【NOIP2008普及组】
  7. VS2017如何显示新建网站选项
  8. 那些生命不能承受之感动
  9. 7-18 花生换核桃
  10. 如何优雅地记录操作日志?