[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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...