[UWP]使用Writeable​Bitmap創建HSV色輪

来源:http://www.cnblogs.com/dino623/archive/2017/09/15/HSV.html
-Advertisement-
Play Games

1. HSV 1.1 HSV的定義 HSV都是一種將RGB色彩模型中的點在圓柱坐標系中的表示法,這種表示法試圖做到比RGB基於笛卡爾坐標系的幾何結構更加直觀。HSV即色相、飽和度、明度(英語:Hue, Saturation, Value),又稱HSB,其中B即英語:Brightness。 色相(H) ...


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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 作者: "zyl910" 一、緣由 最近遇到了一個奇怪的問題——明明已經在VS2017里裝好了 .NET Core 2.0 SDK,且測試過新建一個 .NET Core 2.0控制台項目能成功使用。但是在項目目錄中實際使用新建.NET Core 2.0控制台項目時,會遇到不支持 .NET Core ...
  • 1.異常捕獲 trt-catch ①程式中經常出現各種各樣的異常,如果想要程式更堅強一點,在代碼中要經常用try-catch來進行異常捕獲 ②try-catch之間不能有其他代碼。 ③如果try中的程式沒有異常,則catch中的代碼不執行。如果try中的程式出異常了,哪怕這行代碼後面還有100行代碼 ...
  • 大學畢業對MVC的概念還不是很清晰,總覺得MVC是和三層一樣的,是同一級別的架構。其實不然,三層架構是:BLL(業務邏輯層),DAL(資料庫訪問層),UI(頁面顯示層),而MVC僅僅是屬於三層架構UI層。可以說MVC就是為了更好的展示數據,如果把三層架構比作一個完整的人,那麼MVC就是這個人的臉,用 ...
  • 1.類型的變數不相容string 與 intstring 與 double使用convert的轉換工廠進行轉換。string str = "123456";int nums= Convert.ToInt32(str); 2.前++與後++,前--與後--1)不論是前++還是後++,最終的結果都是給這 ...
  • 1、轉義符表示一個'\' + 一個特殊字元,組成一個具有特殊意義的字元\n 表示換行\" 表示一個英文半形的雙引號\t 表示一個tab鍵的空格\b 表示一個退格鍵,放在字元串兩邊沒有效果。\r\n windows操作系統不能用\n,只能用\r\n\\ 表示一個\ 2、@符號①取消\在字元串中的轉義作 ...
  • 發射調用System.Environment.Exit(0)示例: System.Reflection.Assembly ass = System.Reflection.Assembly.LoadFile(AppDomain.CurrentDomain.BaseDirectory+"\\xxx.dl ...
  • 1.Serialize JSON(序列化json) 2.Deserialize JSON(反序列化json) 3.LINQ to JSON ...
  • 今天測試提了一個BUG,說是消息提醒的時機不對,設置的提前2小時,還沒到就提醒了。 看了下代碼 執行 結果是55,按道理應該是170 執行 結果是169.89568451 最後把代碼修改為 BUG解決 總結: 1.Minutes的計算只限於分鐘部分,類型Int,(-59到59) https://ms ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...