1. 程式人生 > >Win10手記-取色器ColorPicker的實現

Win10手記-取色器ColorPicker的實現

最近個人專案需要用到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[3];
            var hValue = hsb[0];
            /*
            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 <= 60)
            {
                rgb[0] = 255;
                rgb[1] = hValue / 60.0f * 255;
            }
            else if (hValue <= 120)
            {
                hValue -= 60;
                rgb[1] = 255;
                rgb[0] = (1 - hValue / 60.0f) * 255;
            }
            else if (hValue <= 180)
            {
                hValue -= 120;
                rgb[1] = 255;
                rgb[2] = hValue / 60.0f * 255;
            }
            else if (hValue <= 240)
            {
                rgb[2] = 255;
                hValue -= 180;
                rgb[1] = (1 - hValue / 60.0f) * 255;
            }
            else if (hValue <= 300)
            {
                rgb[2] = 255;
                hValue -= 240;
                rgb[0] = hValue / 60.0f * 255;
            }
            else
            {
                hValue -= 300;
                rgb[0] = 255;
                rgb[2] = (1 - hValue / 60.0f) * 255;
            }
            /*
            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 = 0; i < 3; i++)
            {
                rgb[i] += (255 - rgb[i]) * hsb[1];
            }
            var result = new int[3];
            /*
            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 = 0; i < 3; i++)
            {
                rgb[i] *= hsb[2];
                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[3];
            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(255, (byte)r, (byte)g, (byte)b);
            return color;
        }
        public static Color ColorFromRGB(int[] rgb)
        {
            var color = ColorFromRGB(rgb[0], rgb[1], rgb[2]);
            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(0));



        /// <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(0));




        /// <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[3];
            hsb[2] = 1.0f;
            hsb[0] = (float)(int)(position.X / this.ColorImage.ActualWidth * 360);
            hsb[1] = float.Parse((position.Y / this.ColorImage.ActualHeight).ToString("0.00"));
            this.Color = CWColorService.ColorFromRGB(CWColorService.HSBToRGB(hsb));
            this.ColorPoint = position;
            ColorChange(this.Color);
        }


    }
}
複製程式碼

實現效果


相關推薦

Win10手記ColorPicker實現

最近個人專案需要用到ColorPicker,但是適用於WinRT和Win10的基本沒用,所以只能自己造輪子了。 平臺環境 Windows 10Visual Studio 2015 思路 確定需求後,我查找了各方資訊,發現PhotoShop的ColorPicke

【Android自定義View】仿PhotoshopColorPicker(三)

ColorPicker 一款基於HSV顏色空間的仿Photoshop取色器的Android版顏色拾取器。 前言 注: - 1 如果你對HSV顏色空間和RGB顏色空間不夠熟悉的話,請參看該系列的第一篇文章——仿Photoshop取色器Colo

【Android自定義View】仿PhotoshopColorPicker(四)完結篇

ColorPicker 一款基於HSV顏色空間的仿Photoshop取色器的Android版顏色拾取器。 前言 注: - 1 如果你對HSV顏色空間和RGB顏色空間不夠熟悉的話,請參看該系列的第一篇文章——仿Photoshop取色器Colo

用Java實現顏色的功能

前幾天同事給了用java實現顏色拾取器的一段程式碼,覺得很不錯。儲存下來。 public static void main(String[] args) { while (true) { Point mousepoint = MouseInfo.getPoint

一個很好用的桌面和一個線上

有時候不只是美工會用到取色器,平時很多時候都會用到取色器,其中有線上取色器,但是使用內網的時候往往是沒法使用線上取色器這時候就需要使用安裝桌面版取色器。下面是經過多次查詢獲取的比較好用的取色器,一款線上一款應用: 線上取色器:以羅列出本地圖片上所有出現的顏色,可在指定區域點選左上角顯示出

iOS轉場彈窗、網易雲音樂動效、圓環、Loading效果等原始碼

iOS精選原始碼 view controller transition and popover (控制器轉場和彈窗) UITableView頭部懸停+UITableView側滑巢狀 一行程式碼整合時間選擇器 iOS仿滴滴時間選擇picker BMMusic

推薦一個免費的螢幕,滑鼠放到的位置自動顯示RGB

因為工作需要,我需要一個軟體,能夠顯示滑鼠所在區域畫素點的RGB值。 網上找了一些資源,居然需要CSDN積分才能下載,囧。 最後找到一個好用的免費軟體,ColorPix,分享給大家。 使用非常簡單,執

最好用的,顏色轉換

  你有沒有遇到過這樣的情況,瀏覽網頁或者瀏覽圖片或者工作中,突然看到一個顏色,特別想拿到這個RGB顏色或者16進位制顏色。(然後解決的方法就是截圖存下來,拿到PS裡去檢視顏色。)     你還有沒有遇到過這樣的情況,只有一個RGB顏色或者16進位制顏色,卻無法轉換。(然後解決的方法就是截圖存下

輕量級 js JSColor

該檔案下載連結 http://jscolor.com/release/jscolor-1.4.5.zip 或者  http://download.csdn.net/detail/bibihaha/9125863 使用方法 下載下來的檔案以及圖片 進行下配置, 然後再HT

分享一款好用的外掛

Spectrum是一個jQuery拾色器外掛,可能包含了你正在尋找的所有功能。只用到CSS+JS實現,不需要圖片。 支援調色盤儲存/顯示你選擇的顏色,可以設定預設選中的顏色,也可以配置為只顯示預先定義好的一些顏色的調色盤。 具體檔案和用法參照官網:點選開啟連結

C#製作的螢幕

  1using System;  2using System.Collections.Generic;  3using System.ComponentModel;  4using System.Data;  5using System.Drawing;  6using 

程式設計小工具總結(一)

在程式設計過程中,經常會使用到取色器,這裡簡單介紹兩種取色方式: 方式1 : 使用AndroidStudio自帶的調色盤 步驟: 在XML佈局檔案中,任意寫出一個控制元件,控制元件中隨意定義一個顏色

opengl相機通過shader修改片斷著色實現,改,膚色檢測等特殊效果

1.嘴脣檢測並改掉色,不準確時可能和相同有關,關於嘴脣顏色檢測參考文章 https://blog.csdn.net/Trent1985/article/details/46330847  private static final String CAMERA_INPUT_FRAGME

Android 資料抓——線上音樂播放實現

前言: 相信很多同學學習android都開做過播放器一類的小玩意吧,但是苦於沒有伺服器提供資料,因而只能做個本地播放器,今天,這篇文章就是通過資料抓取,實現沒有伺服器,依然可以線上搜尋和播放音樂! 首先,貼上我的最終實現效果: 因為資料是從蝦米搜尋頁抓過

jQuery選擇----------jquery實現select下拉框的值與賦值,設定選中的方法大全

// 1.判斷select選項中 是否存在Value="paraValue"的Item function jsSelectIsExitItem(objSelect, objItemValue) { var isExit = false; for (var i = 0; i < objSelect.opt

GIMP使用 二 實現圖片的抓圖,裁剪,

一,抓圖 執行GIMP,點選 File -----> Create -----> Sreenshot 。選擇需要抓圖的螢幕區域,第一項“take a sreenshot of a single window” 為抓取整個螢幕,第三項“select a regio

連續分段累計FPGA實現的探討

img .cn alt 分段 images ges com blog pga 連續分段累計器FPGA實現的探討

Prim算法:最小生成樹貪心算法的實現

http lin eai article log jre details otn 最小生成樹 算法圖解: http://baike.baidu.com/link?url=hGNkWIOLRJ_LDWMJRECxCPKUw7pI3s8AH5kj-944RwgeBSa9hGpT

JAVAEE——struts2_04:自定義攔截、struts2標簽、登陸功能和校驗登陸攔截實現

strac htm logs transacti 標識 area 返回 ftw jsp 一、自定義攔截器   1.架構      2.攔截器創建 //攔截器:第一種創建方式 //攔截器生命周期:隨項目的啟動而創建,隨項目關閉而銷毀 public class MyInt

01_網頁源碼查看基本實現

alt host 基本實現 手機 com 技術分享 流量 基本 查看 安卓上面敲127.0.0.1或者是localhost是不行的,安卓上面的localhost/127.0.0.1默認是10.0.2.2.有些第三方的模擬器可能不是這個值。安卓自帶的模擬器